From 1628bf01304e9a63bbd8a34fea74a68e37788be1 Mon Sep 17 00:00:00 2001 From: "lucas.lra@gmail.com" <1uc45@GITH> Date: Fri, 20 Nov 2015 20:23:54 -0200 Subject: [PATCH 001/588] - Included some Clojure Extensions - Included one Powershell Extension - Included some Csharp Keywords - Reorganization of the language.main.js define call (To match the folders order) --- extensions/clojure/syntaxes/Clojure.tmLanguage | 3 +++ extensions/powershell/syntaxes/PowershellSyntax.tmLanguage | 1 + src/vs/editor/standalone-languages/csharp.ts | 2 +- src/vs/languages/languages.main.js | 6 +++--- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/extensions/clojure/syntaxes/Clojure.tmLanguage b/extensions/clojure/syntaxes/Clojure.tmLanguage index bf864640fd1..a94b2dcd1fb 100644 --- a/extensions/clojure/syntaxes/Clojure.tmLanguage +++ b/extensions/clojure/syntaxes/Clojure.tmLanguage @@ -7,6 +7,9 @@ clj cljs clojure + cljc + cljx + edn foldingStartMarker \(\s*$ diff --git a/extensions/powershell/syntaxes/PowershellSyntax.tmLanguage b/extensions/powershell/syntaxes/PowershellSyntax.tmLanguage index d9e7c46b125..fb213a2f3df 100644 --- a/extensions/powershell/syntaxes/PowershellSyntax.tmLanguage +++ b/extensions/powershell/syntaxes/PowershellSyntax.tmLanguage @@ -7,6 +7,7 @@ ps1 psm1 psd1 + ps1xml name PowerShell diff --git a/src/vs/editor/standalone-languages/csharp.ts b/src/vs/editor/standalone-languages/csharp.ts index 4e8d11d72bd..d145275864a 100644 --- a/src/vs/editor/standalone-languages/csharp.ts +++ b/src/vs/editor/standalone-languages/csharp.ts @@ -51,7 +51,7 @@ export var language = { 'internal', 'private', 'abstract', 'sealed', 'static', 'struct', 'readonly', 'volatile', 'virtual', 'override', 'params', 'get', 'set', 'add', 'remove', 'operator', 'true', 'false', 'implicit', 'explicit', 'interface', 'enum', - 'null', 'async', 'await' + 'null', 'async', 'await','fixed','sizeof','stackalloc','unsafe' ], namespaceFollows: [ diff --git a/src/vs/languages/languages.main.js b/src/vs/languages/languages.main.js index 761d6a32517..dd015518489 100644 --- a/src/vs/languages/languages.main.js +++ b/src/vs/languages/languages.main.js @@ -8,13 +8,13 @@ define([ "vs/languages/html/common/html.contribution", "vs/languages/javascript/common/javascript.contribution", "vs/languages/json/common/json.contribution", + "vs/languages/less/common/less.contribution", "vs/languages/markdown/common/markdown.contribution", "vs/languages/php/common/php.contribution", "vs/languages/plaintext/common/plaintext.contribution", "vs/languages/razor/common/razor.contribution", - "vs/languages/typescript/common/typescript.contribution", - "vs/languages/less/common/less.contribution", - "vs/languages/sass/common/sass.contribution" + "vs/languages/sass/common/sass.contribution", + "vs/languages/typescript/common/typescript.contribution" ], function() { "use strict"; }); \ No newline at end of file From a25963846cebec475b8552191a97a82327111724 Mon Sep 17 00:00:00 2001 From: "lucas.lra@gmail.com" <1uc45@GITH> Date: Fri, 20 Nov 2015 20:46:26 -0200 Subject: [PATCH 002/588] Included Edge UserAgent --- src/vs/base/browser/browser.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/base/browser/browser.ts b/src/vs/base/browser/browser.ts index 31038fa56dc..f7d735d9916 100644 --- a/src/vs/base/browser/browser.ts +++ b/src/vs/base/browser/browser.ts @@ -48,6 +48,7 @@ var globals = (typeof self === 'object' ? self : global); // IE: "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; MS-RTC LM 8; InfoPath.3; Zune 4.7)" // Opera: "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.9.168 Version/11.52" // FF: "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:8.0) Gecko/20100101 Firefox/8.0" +// Edge: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246" // LINUX: // chrome: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36" From 1733650c6b249be9af6fe2e407c03ca4f5cbea8e Mon Sep 17 00:00:00 2001 From: Arkady Shapkin Date: Sat, 21 Nov 2015 23:53:11 +0300 Subject: [PATCH 003/588] .editorconfig added --- .editorconfig | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000000..361c815c1a7 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Tab indentation (no size specified) +[*] +indent_style = tab + +[{.travis.yml,npm-shrinkwrap.json}] +indent_style = space +indent_size = 2 From 464487d90b921a6a67279aa3a3907a583a641e4d Mon Sep 17 00:00:00 2001 From: "lucas.lra@gmail.com" <1uc45@GITH> Date: Sun, 22 Nov 2015 17:11:53 -0200 Subject: [PATCH 004/588] Changes based in @aeschli comments --- extensions/clojure/package.json | 40 ++++++++++++------ .../clojure/syntaxes/Clojure.tmLanguage | 3 -- extensions/powershell/package.json | 42 +++++++++++++------ .../syntaxes/PowershellSyntax.tmLanguage | 1 - 4 files changed, 58 insertions(+), 28 deletions(-) diff --git a/extensions/clojure/package.json b/extensions/clojure/package.json index 3a67d006621..4ade95c084e 100644 --- a/extensions/clojure/package.json +++ b/extensions/clojure/package.json @@ -2,18 +2,34 @@ "name": "clojure", "version": "0.1.0", "publisher": "vscode", - "engines": { "vscode": "*" }, + "engines": { + "vscode": "*" + }, "contributes": { - "languages": [{ - "id": "clojure", - "aliases": ["Clojure", "clojure"], - "extensions": [".clj", ".cljs", ".cljx", ".clojure", ".edn"], - "configuration": "./clojure.configuration.json" - }], - "grammars": [{ - "language": "clojure", - "scopeName": "source.clojure", - "path": "./syntaxes/Clojure.tmLanguage" - }] + "languages": [ + { + "id": "clojure", + "aliases": [ + "Clojure", + "clojure" + ], + "extensions": [ + ".clj", + ".cljs", + ".cljc", + ".cljx", + ".clojure", + ".edn" + ], + "configuration": "./clojure.configuration.json" + } + ], + "grammars": [ + { + "language": "clojure", + "scopeName": "source.clojure", + "path": "./syntaxes/Clojure.tmLanguage" + } + ] } } \ No newline at end of file diff --git a/extensions/clojure/syntaxes/Clojure.tmLanguage b/extensions/clojure/syntaxes/Clojure.tmLanguage index a94b2dcd1fb..bf864640fd1 100644 --- a/extensions/clojure/syntaxes/Clojure.tmLanguage +++ b/extensions/clojure/syntaxes/Clojure.tmLanguage @@ -7,9 +7,6 @@ clj cljs clojure - cljc - cljx - edn foldingStartMarker \(\s*$ diff --git a/extensions/powershell/package.json b/extensions/powershell/package.json index 7fee9af3e24..febba83d727 100644 --- a/extensions/powershell/package.json +++ b/extensions/powershell/package.json @@ -2,18 +2,36 @@ "name": "powershell", "version": "0.1.0", "publisher": "vscode", - "engines": { "vscode": "*" }, + "engines": { + "vscode": "*" + }, "contributes": { - "languages": [{ - "id": "powershell", - "extensions": [ ".ps1", ".psm1", ".psd1", ".pssc", ".psrc" ], - "aliases": [ "PowerShell", "powershell", "ps", "ps1" ], - "configuration": "./powershell.configuration.json" - }], - "grammars": [{ - "language": "powershell", - "scopeName": "source.powershell", - "path": "./syntaxes/PowershellSyntax.tmLanguage" - }] + "languages": [ + { + "id": "powershell", + "extensions": [ + ".ps1", + ".psm1", + ".psd1", + ".pssc", + ".psrc", + ".ps1xml" + ], + "aliases": [ + "PowerShell", + "powershell", + "ps", + "ps1" + ], + "configuration": "./powershell.configuration.json" + } + ], + "grammars": [ + { + "language": "powershell", + "scopeName": "source.powershell", + "path": "./syntaxes/PowershellSyntax.tmLanguage" + } + ] } } \ No newline at end of file diff --git a/extensions/powershell/syntaxes/PowershellSyntax.tmLanguage b/extensions/powershell/syntaxes/PowershellSyntax.tmLanguage index fb213a2f3df..d9e7c46b125 100644 --- a/extensions/powershell/syntaxes/PowershellSyntax.tmLanguage +++ b/extensions/powershell/syntaxes/PowershellSyntax.tmLanguage @@ -7,7 +7,6 @@ ps1 psm1 psd1 - ps1xml name PowerShell From 98cc590065cbccb4ba68e56b4d7f64770df602af Mon Sep 17 00:00:00 2001 From: Lucas Araujo Date: Mon, 23 Nov 2015 07:59:03 -0200 Subject: [PATCH 005/588] Undoing some changes --- extensions/clojure/package.json | 40 +++++++++------------------- extensions/powershell/package.json | 42 +++++++++--------------------- src/vs/base/browser/browser.ts | 1 - src/vs/languages/languages.main.js | 6 ++--- 4 files changed, 27 insertions(+), 62 deletions(-) diff --git a/extensions/clojure/package.json b/extensions/clojure/package.json index 4ade95c084e..3a67d006621 100644 --- a/extensions/clojure/package.json +++ b/extensions/clojure/package.json @@ -2,34 +2,18 @@ "name": "clojure", "version": "0.1.0", "publisher": "vscode", - "engines": { - "vscode": "*" - }, + "engines": { "vscode": "*" }, "contributes": { - "languages": [ - { - "id": "clojure", - "aliases": [ - "Clojure", - "clojure" - ], - "extensions": [ - ".clj", - ".cljs", - ".cljc", - ".cljx", - ".clojure", - ".edn" - ], - "configuration": "./clojure.configuration.json" - } - ], - "grammars": [ - { - "language": "clojure", - "scopeName": "source.clojure", - "path": "./syntaxes/Clojure.tmLanguage" - } - ] + "languages": [{ + "id": "clojure", + "aliases": ["Clojure", "clojure"], + "extensions": [".clj", ".cljs", ".cljx", ".clojure", ".edn"], + "configuration": "./clojure.configuration.json" + }], + "grammars": [{ + "language": "clojure", + "scopeName": "source.clojure", + "path": "./syntaxes/Clojure.tmLanguage" + }] } } \ No newline at end of file diff --git a/extensions/powershell/package.json b/extensions/powershell/package.json index febba83d727..7fee9af3e24 100644 --- a/extensions/powershell/package.json +++ b/extensions/powershell/package.json @@ -2,36 +2,18 @@ "name": "powershell", "version": "0.1.0", "publisher": "vscode", - "engines": { - "vscode": "*" - }, + "engines": { "vscode": "*" }, "contributes": { - "languages": [ - { - "id": "powershell", - "extensions": [ - ".ps1", - ".psm1", - ".psd1", - ".pssc", - ".psrc", - ".ps1xml" - ], - "aliases": [ - "PowerShell", - "powershell", - "ps", - "ps1" - ], - "configuration": "./powershell.configuration.json" - } - ], - "grammars": [ - { - "language": "powershell", - "scopeName": "source.powershell", - "path": "./syntaxes/PowershellSyntax.tmLanguage" - } - ] + "languages": [{ + "id": "powershell", + "extensions": [ ".ps1", ".psm1", ".psd1", ".pssc", ".psrc" ], + "aliases": [ "PowerShell", "powershell", "ps", "ps1" ], + "configuration": "./powershell.configuration.json" + }], + "grammars": [{ + "language": "powershell", + "scopeName": "source.powershell", + "path": "./syntaxes/PowershellSyntax.tmLanguage" + }] } } \ No newline at end of file diff --git a/src/vs/base/browser/browser.ts b/src/vs/base/browser/browser.ts index f7d735d9916..31038fa56dc 100644 --- a/src/vs/base/browser/browser.ts +++ b/src/vs/base/browser/browser.ts @@ -48,7 +48,6 @@ var globals = (typeof self === 'object' ? self : global); // IE: "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; MS-RTC LM 8; InfoPath.3; Zune 4.7)" // Opera: "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.9.168 Version/11.52" // FF: "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:8.0) Gecko/20100101 Firefox/8.0" -// Edge: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246" // LINUX: // chrome: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36" diff --git a/src/vs/languages/languages.main.js b/src/vs/languages/languages.main.js index dd015518489..761d6a32517 100644 --- a/src/vs/languages/languages.main.js +++ b/src/vs/languages/languages.main.js @@ -8,13 +8,13 @@ define([ "vs/languages/html/common/html.contribution", "vs/languages/javascript/common/javascript.contribution", "vs/languages/json/common/json.contribution", - "vs/languages/less/common/less.contribution", "vs/languages/markdown/common/markdown.contribution", "vs/languages/php/common/php.contribution", "vs/languages/plaintext/common/plaintext.contribution", "vs/languages/razor/common/razor.contribution", - "vs/languages/sass/common/sass.contribution", - "vs/languages/typescript/common/typescript.contribution" + "vs/languages/typescript/common/typescript.contribution", + "vs/languages/less/common/less.contribution", + "vs/languages/sass/common/sass.contribution" ], function() { "use strict"; }); \ No newline at end of file From 092944b7df72255ae9a4f4688e32813ff1df0da5 Mon Sep 17 00:00:00 2001 From: Kewin Dousse Date: Mon, 23 Nov 2015 15:20:20 +0100 Subject: [PATCH 006/588] Implementing configurable cursor blinking --- .../browser/viewParts/viewCursors/viewCursors.ts | 11 ++++++++++- src/vs/editor/common/config/commonEditorConfig.ts | 8 ++++++++ src/vs/editor/common/config/defaultConfig.ts | 1 + src/vs/editor/common/editorCommon.ts | 7 +++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts index d9ab47b0be4..9bdc63d49f9 100644 --- a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts +++ b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts @@ -172,7 +172,16 @@ export class ViewCursors extends ViewPart { private _getRenderType(): RenderType { if (this._editorHasFocus) { if (this._primaryCursor.getIsInEditableRange() && !this._context.configuration.editor.readOnly) { - return RenderType.Blink; + switch (this._context.configuration.editor.cursorBlinking) { + case ("blink"): + return RenderType.Blink; + case ("visible"): + return RenderType.Visible; + case ("hidden"): + return RenderType.Hidden; + default: + return RenderType.Blink; + } } return RenderType.Visible; } diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index bed0d3b74f5..b36b57d5ce6 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -141,6 +141,7 @@ class InternalEditorOptionsHelper { readOnly: toBoolean(opts.readOnly), scrollbar: scrollbar, overviewRulerLanes: toInteger(opts.overviewRulerLanes, 0, 3), + cursorBlinking: opts.cursorBlinking, hideCursorInOverviewRuler: toBoolean(opts.hideCursorInOverviewRuler), scrollBeyondLastLine: toBoolean(opts.scrollBeyondLastLine), wrappingIndent: opts.wrappingIndent, @@ -236,6 +237,7 @@ class InternalEditorOptionsHelper { readOnly: (prevOpts.readOnly !== newOpts.readOnly), scrollbar: (!this._scrollbarOptsEqual(prevOpts.scrollbar, newOpts.scrollbar)), overviewRulerLanes: (prevOpts.overviewRulerLanes !== newOpts.overviewRulerLanes), + cursorBlinking: (prevOpts.cursorBlinking !== newOpts.cursorBlinking), hideCursorInOverviewRuler: (prevOpts.hideCursorInOverviewRuler !== newOpts.hideCursorInOverviewRuler), scrollBeyondLastLine: (prevOpts.scrollBeyondLastLine !== newOpts.scrollBeyondLastLine), wrappingIndent: (prevOpts.wrappingIndent !== newOpts.wrappingIndent), @@ -794,6 +796,12 @@ configurationRegistry.registerConfiguration({ 'default': 3, 'description': nls.localize('overviewRulerLanes', "Controls the number of decorations that can show up at the same position in the overview ruler") }, + 'editor.cursorBlinking' : { + 'type': 'string', + 'enum': ['blink', 'visible', 'hidden'], + 'default': DefaultConfig.editor.cursorBlinking, + 'description': nls.localize('cursorBlinking', "Controls the cursor blinking animation.") + }, 'editor.hideCursorInOverviewRuler' : { 'type': 'boolean', 'default': DefaultConfig.editor.hideCursorInOverviewRuler, diff --git a/src/vs/editor/common/config/defaultConfig.ts b/src/vs/editor/common/config/defaultConfig.ts index 0cdadde9ddf..28748ec4868 100644 --- a/src/vs/editor/common/config/defaultConfig.ts +++ b/src/vs/editor/common/config/defaultConfig.ts @@ -33,6 +33,7 @@ class ConfigClass implements IConfiguration { horizontalHasArrows: false }, overviewRulerLanes: 2, + cursorBlinking: 'blink', hideCursorInOverviewRuler: false, scrollBeyondLastLine: true, automaticLayout: false, diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index b204985b86c..cfb4334e15d 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -333,6 +333,11 @@ export interface ICommonEditorOptions { * Defaults to 2. */ overviewRulerLanes?:number; + /** + * Control the cursor blinking animation. + * Defaults to 'blink'. + */ + cursorBlinking?:string; /** * Should the cursor be hidden in the overview ruler. * Defaults to false. @@ -577,6 +582,7 @@ export interface IInternalEditorOptions { readOnly:boolean; scrollbar:IInternalEditorScrollbarOptions; overviewRulerLanes:number; + cursorBlinking:string; hideCursorInOverviewRuler:boolean; scrollBeyondLastLine:boolean; wrappingIndent: string; @@ -667,6 +673,7 @@ export interface IConfigurationChangedEvent { readOnly:boolean; scrollbar:boolean; overviewRulerLanes:boolean; + cursorBlinking:boolean; hideCursorInOverviewRuler:boolean; scrollBeyondLastLine:boolean; wrappingIndent:boolean; From 5568b5625aef1ee8e069d759333b1185ded229e6 Mon Sep 17 00:00:00 2001 From: Kewin Dousse Date: Mon, 23 Nov 2015 15:47:58 +0100 Subject: [PATCH 007/588] Updating cursor blink on config change --- src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts index 9bdc63d49f9..92efce34b39 100644 --- a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts +++ b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts @@ -136,6 +136,7 @@ export class ViewCursors extends ViewPart { } public onConfigurationChanged(e:EditorCommon.IConfigurationChangedEvent): boolean { this._primaryCursor.onConfigurationChanged(e); + this._updateBlinking(); for (var i = 0, len = this._secondaryCursors.length; i < len; i++) { this._secondaryCursors[i].onConfigurationChanged(e); } From d66f6f47efd501f380fb49effd0b89eb570b53f2 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 23 Nov 2015 17:42:39 +0100 Subject: [PATCH 008/588] add the "Sync" command to the command palette as global command --- .../parts/git/browser/gitActions.contribution.ts | 8 +++++--- src/vs/workbench/parts/git/browser/gitActions.ts | 5 +++-- .../parts/git/browser/views/changes/changesView.ts | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/parts/git/browser/gitActions.contribution.ts b/src/vs/workbench/parts/git/browser/gitActions.contribution.ts index 96d6de21c00..6442cf9abf5 100644 --- a/src/vs/workbench/parts/git/browser/gitActions.contribution.ts +++ b/src/vs/workbench/parts/git/browser/gitActions.contribution.ts @@ -31,7 +31,7 @@ import {IFileService, IFileStat} from 'vs/platform/files/common/files'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import wbar = require('vs/workbench/browser/actionRegistry'); import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; -import { OpenChangeAction } from './gitActions'; +import { OpenChangeAction, SyncAction } from './gitActions'; import Severity from 'vs/base/common/severity'; function getStatus(gitService: IGitService, contextService: IWorkspaceContextService, input: WorkbenchEditorCommon.IFileEditorInput): IFileStatus { @@ -432,5 +432,7 @@ actionBarRegistry.registerActionBarContributor(abr.Scope.EDITOR, GitWorkingTreeD let workbenchActionRegistry = ( platform.Registry.as(wbar.Extensions.WorkbenchActions)); -// Register Action to Open Viewlet -workbenchActionRegistry.registerWorkbenchAction(new SyncActionDescriptor(GlobalOpenChangeAction, GlobalOpenChangeAction.ID, GlobalOpenChangeAction.LABEL), nls.localize('git', "Git")); +// Register Actions +const category = nls.localize('git', "Git"); +workbenchActionRegistry.registerWorkbenchAction(new SyncActionDescriptor(GlobalOpenChangeAction, GlobalOpenChangeAction.ID, GlobalOpenChangeAction.LABEL), category); +workbenchActionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SyncAction, SyncAction.ID, SyncAction.LABEL), category); diff --git a/src/vs/workbench/parts/git/browser/gitActions.ts b/src/vs/workbench/parts/git/browser/gitActions.ts index 4f633bb51c3..7d1bb989a76 100644 --- a/src/vs/workbench/parts/git/browser/gitActions.ts +++ b/src/vs/workbench/parts/git/browser/gitActions.ts @@ -941,9 +941,10 @@ export abstract class BaseSyncAction extends GitAction { export class SyncAction extends BaseSyncAction { static ID = 'workbench.action.sync'; + static LABEL = nls.localize('sync', "Sync"); - constructor(@IGitService gitService: IGitService) { - super(SyncAction.ID, nls.localize('sync', "Sync"), 'git-action sync', gitService); + constructor(id: string, label: string, @IGitService gitService: IGitService) { + super(id, label, 'git-action sync', gitService); } } diff --git a/src/vs/workbench/parts/git/browser/views/changes/changesView.ts b/src/vs/workbench/parts/git/browser/views/changes/changesView.ts index bcb9a31521c..f454db50a1b 100644 --- a/src/vs/workbench/parts/git/browser/views/changes/changesView.ts +++ b/src/vs/workbench/parts/git/browser/views/changes/changesView.ts @@ -246,7 +246,7 @@ export class ChangesView extends EventEmitter.EventEmitter implements GitView.IV public getSecondaryActions(): Actions.IAction[] { if (!this.secondaryActions) { this.secondaryActions = [ - this.instantiationService.createInstance(GitActions.SyncAction), + this.instantiationService.createInstance(GitActions.SyncAction, GitActions.SyncAction.ID, GitActions.SyncAction.LABEL), this.instantiationService.createInstance(GitActions.PullAction), this.instantiationService.createInstance(GitActions.PushAction), new ActionBar.Separator(), From 418a76fa1600f6ff0556b409858dc4a1c0dfea16 Mon Sep 17 00:00:00 2001 From: Mahmoud Ali Date: Mon, 23 Nov 2015 21:15:00 -0300 Subject: [PATCH 009/588] Add "Show Extensions Updates" command Shows all installed extensions that have updates available. Can also be accessed by "ext update" --- .../electron-browser/extensionsActions.ts | 23 ++++++ .../electron-browser/extensionsQuickOpen.ts | 74 +++++++++++++++++++ .../extensionsWorkbenchExtension.ts | 14 +++- 3 files changed, 110 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts index debc3b13e36..8b039896ab8 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts @@ -54,3 +54,26 @@ export class InstallExtensionAction extends Action { return true; } } + +export class ListExtensionsUpdatesAction extends Action { + + static ID = 'workbench.extensions.action.listExtensionsUpdates'; + static LABEL = nls.localize('showExtensionsUpdates', "Show Extensions Updates"); + + constructor( + id: string, + label: string, + @IExtensionsService private extensionsService: IExtensionsService, + @IQuickOpenService private quickOpenService: IQuickOpenService + ) { + super(id, label, null, true); + } + + public run(): Promise { + return this.quickOpenService.show('ext update '); + } + + protected isEnabled(): boolean { + return true; + } +} diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen.ts index 8001df22395..5743ad36582 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen.ts @@ -469,6 +469,80 @@ export class GalleryExtensionsHandler extends QuickOpenHandler { return nls.localize('noExtensionsToInstall', "No extensions found"); } + getAutoFocus(searchValue: string): IAutoFocus { + return { autoFocusFirstEntry: true }; + } +} + +class ExtensionsUpdateModel implements IModel { + + public dataSource = new DataSource(); + public renderer: IRenderer; + public runner: IRunner; + public entries: IExtensionEntry[]; + + constructor( + private galleryExtensions: IExtension[], + private localExtensions: IExtension[], + @IInstantiationService instantiationService: IInstantiationService + ) { + this.renderer = instantiationService.createInstance(Renderer); + this.runner = instantiationService.createInstance(InstallRunner); + this.entries = []; + } + + public set input(input: string) { + this.entries = this.galleryExtensions + .map(extension => ({ extension, highlights: getHighlights(input, extension) })) + .filter(({ extension, highlights }) => { + const local = this.localExtensions.filter(local => extensionEquals(local, extension))[0]; + return local && local.version < extension.version && !!highlights; + }) + .map(({ extension, highlights }: { extension: IExtension, highlights: IHighlights }) => { + return { + extension, + highlights, + state: ExtensionState.Outdated + }; + }) + .sort((a, b) => a.extension.name.localeCompare(b.extension.name)); + } +} + +export class ExtensionsUpdateHandler extends QuickOpenHandler { + + private modelPromise: TPromise; + + constructor( + @IInstantiationService private instantiationService: IInstantiationService, + @IExtensionsService private extensionsService: IExtensionsService, + @IGalleryService private galleryService: IGalleryService, + @ITelemetryService private telemetryService: ITelemetryService + ) { + super(); + } + + getResults(input: string): TPromise> { + if (!this.modelPromise) { + this.telemetryService.publicLog('extensionGallery:open'); + this.modelPromise = TPromise.join([this.galleryService.query(), this.extensionsService.getInstalled()]) + .then(result => this.instantiationService.createInstance(ExtensionsUpdateModel, result[0], result[1])); + } + + return this.modelPromise.then(model => { + model.input = input; + return model; + }); + } + + onClose(canceled: boolean): void { + this.modelPromise = null; + } + + getEmptyLabel(input: string): string { + return nls.localize('noOutdatedExtensions', "No outdated extensions found"); + } + getAutoFocus(searchValue: string): IAutoFocus { return { autoFocusFirstEntry: true }; } diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension.ts index 38cd43e9351..44326bc574b 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension.ts @@ -16,7 +16,7 @@ import { IWorkspaceContextService } from 'vs/workbench/services/workspace/common import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions'; import wbaregistry = require('vs/workbench/browser/actionRegistry'); import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; -import { ListExtensionsAction, InstallExtensionAction } from './extensionsActions'; +import { ListExtensionsAction, InstallExtensionAction, ListExtensionsUpdatesAction } from './extensionsActions'; import { IQuickOpenRegistry, Extensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen'; import ipc = require('ipc'); @@ -67,6 +67,18 @@ export class ExtensionsWorkbenchExtension implements IWorkbenchContribution { true ) ); + + actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ListExtensionsUpdatesAction, ListExtensionsUpdatesAction.ID, ListExtensionsUpdatesAction.LABEL), extensionsCategory); + + (platform.Registry.as(Extensions.Quickopen)).registerQuickOpenHandler( + new QuickOpenHandlerDescriptor( + 'vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen', + 'ExtensionsUpdateHandler', + 'ext update ', + nls.localize('extensionsUpdateCommands', "Extensions Update Commands"), + true + ) + ); } } From 2a04b4713670556ff33d403ea49bee75a14a33c6 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Tue, 24 Nov 2015 07:49:44 +0700 Subject: [PATCH 010/588] Fix typo in comment in sample tasks.json. --- src/vs/workbench/parts/tasks/common/taskSampleConfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/tasks/common/taskSampleConfig.json b/src/vs/workbench/parts/tasks/common/taskSampleConfig.json index d232911d534..1f312158d75 100644 --- a/src/vs/workbench/parts/tasks/common/taskSampleConfig.json +++ b/src/vs/workbench/parts/tasks/common/taskSampleConfig.json @@ -156,7 +156,7 @@ } */ // A task runner example that defines a problemMatcher inline instead of using -// a predfined one. +// a predefined one. /* { "version": "0.1.0", From 2ad838560b79c275a24ad8974af6b3fca0fb955f Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Tue, 24 Nov 2015 07:52:21 +0700 Subject: [PATCH 011/588] Fix typos in LineCommentCommand comments. --- src/vs/editor/contrib/comment/common/lineCommentCommand.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/contrib/comment/common/lineCommentCommand.ts b/src/vs/editor/contrib/comment/common/lineCommentCommand.ts index 3b591d5a045..714eecbacd2 100644 --- a/src/vs/editor/contrib/comment/common/lineCommentCommand.ts +++ b/src/vs/editor/contrib/comment/common/lineCommentCommand.ts @@ -104,7 +104,7 @@ export class LineCommentCommand implements EditorCommon.ICommand { /** * Analyze lines and decide which lines are relevant and what the toggle should do. - * Also, build up several offsets and lengths usefull in the generation of editor operations. + * Also, build up several offsets and lengths useful in the generation of editor operations. */ public static _analyzeLines(type:Type, model:ISimpleModel, lines:ILinePreflightData[], startLineNumber:number): IPreflightData { var lineData: ILinePreflightData, @@ -206,7 +206,7 @@ export class LineCommentCommand implements EditorCommon.ICommand { } /** - * Given a succesfull analysis, execute either insert line comments, either remove line comments + * Given a successful analysis, execute either insert line comments, either remove line comments */ private _executeLineComments(model:ISimpleModel, builder:EditorCommon.IEditOperationBuilder, data:IPreflightData, s:EditorCommon.IEditorSelection): void { @@ -267,7 +267,7 @@ export class LineCommentCommand implements EditorCommon.ICommand { } /** - * Given an unsuccesfull analysis, delegate to the block comment command + * Given an unsuccessful analysis, delegate to the block comment command */ private _executeBlockComment(model:EditorCommon.ITokenizedModel, builder:EditorCommon.IEditOperationBuilder, s:EditorCommon.IEditorSelection): void { var commentsSupport = model.getModeAtPosition(s.startLineNumber, s.startColumn).commentsSupport; From c1abaae2493cd63d1001bc16fa5fcff044a62a8c Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Tue, 24 Nov 2015 07:53:09 +0700 Subject: [PATCH 012/588] Fix typo: return value of AbstractProcess::terminate. --- src/vs/base/node/processes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/node/processes.ts b/src/vs/base/node/processes.ts index 10dcefcea83..7bda74d0eed 100644 --- a/src/vs/base/node/processes.ts +++ b/src/vs/base/node/processes.ts @@ -329,7 +329,7 @@ export abstract class AbstractProcess { } return result; }, (err) => { - return { sucess: true }; + return { success: true }; }); } From 3f2b4ba9a686ef537eafb865efdfe0062d7bd89d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2015 07:00:06 +0100 Subject: [PATCH 013/588] npm install vscode-api-tests and some polish --- extensions/vscode-api-tests/.vscodeignore | 3 --- extensions/vscode-api-tests/README.md | 14 -------------- extensions/vscode-api-tests/package.json | 7 ++----- package.json | 2 +- 4 files changed, 3 insertions(+), 23 deletions(-) delete mode 100644 extensions/vscode-api-tests/README.md diff --git a/extensions/vscode-api-tests/.vscodeignore b/extensions/vscode-api-tests/.vscodeignore index bf8da5ca33e..d9d9698a317 100644 --- a/extensions/vscode-api-tests/.vscodeignore +++ b/extensions/vscode-api-tests/.vscodeignore @@ -1,9 +1,6 @@ .vscode/** typings/** -out/test/** -test/** **/*.ts **/*.map .gitignore tsconfig.json -vsc-extension-quickstart.md diff --git a/extensions/vscode-api-tests/README.md b/extensions/vscode-api-tests/README.md deleted file mode 100644 index 7263e355bc6..00000000000 --- a/extensions/vscode-api-tests/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# README -## This is the README for your extension "vscode-api-tests" -------------------- -You can author your README using Visual Studio Code. Here are some useful editor keyboard shortcuts: - -* Split the editor (`Cmd+\` on OSX or `Ctrl+\` on Windows and Linux) -* Toggle preview (`Shift+CMD+V` on OSX or `Shift+Ctrl+V` on Windows and Linux) -* Press `Ctrl+Space` (Windows, Linux) or `Cmd+Space` (OSX) to see a list of Markdown snippets - -### For more information -* [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown) -* [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/) - -** Enjoy!** diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index 0b1021c72d3..e69be343c0e 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -1,14 +1,11 @@ { "name": "vscode-api-tests", - "description": "", + "description": "API tests for VS Code", "version": "0.0.1", - "publisher": "vscode", + "private": true, "engines": { "vscode": "*" }, - "scripts": { - "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../gulpfile.plugins.js compile-plugin:vscode-api-tests ./tsconfig.json" - }, "devDependencies": { "vscode": "next" } diff --git a/package.json b/package.json index 8d66870c809..f546c788b1e 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ }, "scripts": { "test": "node node_modules/mocha/bin/_mocha", - "postinstall": "npm --prefix extensions/csharp-o/ install extensions/csharp-o/" + "postinstall": "npm --prefix extensions/csharp-o/ install extensions/csharp-o/ && npm --prefix extensions/vscode-api-tests/ install extensions/vscode-api-tests/" }, "dependencies": { "applicationinsights": "0.15.6", From 222b089f8ae011946b83e254ba29cf00ce2980dc Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2015 07:01:53 +0100 Subject: [PATCH 014/588] vscode api tests: add back publisher --- extensions/vscode-api-tests/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index e69be343c0e..0407ee75e73 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -2,6 +2,7 @@ "name": "vscode-api-tests", "description": "API tests for VS Code", "version": "0.0.1", + "publisher": "vscode", "private": true, "engines": { "vscode": "*" From 303b02eeac5b35947155181cea668e2be2e7ccb3 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2015 07:18:27 +0100 Subject: [PATCH 015/588] restore vscode:prepublish to compile tests properly --- extensions/vscode-api-tests/package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index 0407ee75e73..20e6ba7de8d 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -7,6 +7,9 @@ "engines": { "vscode": "*" }, + "scripts": { + "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../gulpfile.plugins.js compile-plugin:vscode-api-tests ./tsconfig.json" + }, "devDependencies": { "vscode": "next" } From debe0292dd463f632224c8c43e21de978aa93d1c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2015 07:42:41 +0100 Subject: [PATCH 016/588] allow to run plugin tests through the command line --- src/vs/workbench/electron-main/env.ts | 3 +++ src/vs/workbench/electron-main/lifecycle.ts | 3 ++- src/vs/workbench/electron-main/windows.ts | 21 +++++++++++++++++-- .../thread/electron-browser/threadService.ts | 14 ++++++++++--- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/electron-main/env.ts b/src/vs/workbench/electron-main/env.ts index 2fe6dd85146..25fe30ea7f3 100644 --- a/src/vs/workbench/electron-main/env.ts +++ b/src/vs/workbench/electron-main/env.ts @@ -106,6 +106,9 @@ if (!fs.existsSync(userPluginsHome)) { fs.mkdirSync(userPluginsHome); } +// Helper to identify if we have plugin tests to run from the command line without debugger +export const isTestingFromCli = cliArgs.pluginTestsPath && !cliArgs.debugBrkPluginHost; + export function log(...a: any[]): void { if (cliArgs.verboseLogging) { console.log.apply(null, a); diff --git a/src/vs/workbench/electron-main/lifecycle.ts b/src/vs/workbench/electron-main/lifecycle.ts index b25bdc9678a..831415103a5 100644 --- a/src/vs/workbench/electron-main/lifecycle.ts +++ b/src/vs/workbench/electron-main/lifecycle.ts @@ -67,7 +67,8 @@ export class Lifecycle { // Windows/Linux: we quit when all windows have closed // Mac: we only quit when quit was requested - if (this.quitRequested || process.platform !== 'darwin') { + // Tests: we always quit + if (this.quitRequested || process.platform !== 'darwin' || env.isTestingFromCli) { app.quit(); } }); diff --git a/src/vs/workbench/electron-main/windows.ts b/src/vs/workbench/electron-main/windows.ts index 5a829094fc7..81dd55b071c 100644 --- a/src/vs/workbench/electron-main/windows.ts +++ b/src/vs/workbench/electron-main/windows.ts @@ -85,6 +85,11 @@ export interface IOpenedPathsList { files: string[]; } +interface ILogEntry { + severity: string; + arguments: any; +} + export class WindowsManager { public static autoSaveDelayStorageKey = 'autoSaveDelay'; @@ -121,7 +126,7 @@ export class WindowsManager { } private registerListeners(): void { - app.on('activate', (event:Event, hasVisibleWindows:boolean) => { + app.on('activate', (event: Event, hasVisibleWindows: boolean) => { env.log('App#activate'); // Mac only event: reopen last window when we get activated @@ -247,7 +252,19 @@ export class WindowsManager { if (broadcast.channel && broadcast.payload) { this.sendToAll('vscode:broadcast', broadcast, [windowId]); } - }) + }); + + ipc.on('vscode:log', (event: Event, logEntry: ILogEntry) => { + let args = []; + try { + let parsed = JSON.parse(logEntry.arguments); + args.push(...Object.getOwnPropertyNames(parsed).map(o => parsed[o])); + } catch (error) { + args.push(logEntry.arguments); + } + + console[logEntry.severity].apply(console, args); + }); UpdateManager.on('update-downloaded', (update: IUpdate) => { this.sendToFocused('vscode:telemetry', { eventName: 'update:downloaded', data: { version: update.version } }); diff --git a/src/vs/workbench/services/thread/electron-browser/threadService.ts b/src/vs/workbench/services/thread/electron-browser/threadService.ts index ae62bf25074..fe946ab0837 100644 --- a/src/vs/workbench/services/thread/electron-browser/threadService.ts +++ b/src/vs/workbench/services/thread/electron-browser/threadService.ts @@ -107,6 +107,7 @@ class PluginHostProcessManager { public startPluginHostProcess(onPluginHostMessage: (msg: any) => void): void { let config = this.contextService.getConfiguration(); let isDev = !config.env.isBuilt || !!config.env.pluginDevelopmentPath; + let isTestingFromCli = !!config.env.pluginTestsPath && !config.env.debugBrkPluginHost; let opts: any = { env: objects.mixin(objects.clone(process.env), { AMD_ENTRYPOINT: 'vs/workbench/node/pluginHostProcess', PIPE_LOGGING: 'true', VERBOSE_LOGGING: true }) @@ -184,11 +185,18 @@ class PluginHostProcessManager { consoleArgs = ['%c[Plugin Host]', 'color: blue', ...args]; } - // Send to local console - console[logEntry.severity].apply(console, consoleArgs); + // Send to local console unless we run tests from cli + if (!isTestingFromCli) { + console[logEntry.severity].apply(console, consoleArgs); + } + + // Log on main side if running tests from cli + if (isTestingFromCli) { + ipc.send('vscode:log', logEntry); + } // Broadcast to other windows if we are in development mode - if (isDev) { + else if (isDev) { this.windowService.broadcast({ channel: PLUGIN_LOG_BROADCAST_CHANNEL, payload: logEntry From f043b26dc213ae31bbe94aa594846f5ca567ef8d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2015 07:43:13 +0100 Subject: [PATCH 017/588] run integration tests as part of build --- test/run.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/run.sh b/test/run.sh index 7a8a3924426..93ac3073d55 100755 --- a/test/run.sh +++ b/test/run.sh @@ -7,6 +7,7 @@ else ROOT=$(dirname $(dirname $(readlink -f $0))) fi +# Unit Tests if [[ "$OSTYPE" == "darwin"* ]]; then cd $ROOT ; ulimit -n 4096 ; ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 \ ../Electron-Build/Electron.app/Contents/MacOS/Electron \ @@ -16,3 +17,6 @@ else ../Electron-Build/electron \ node_modules/mocha/bin/_mocha $* fi + +# Integration Tests +./scripts/code.sh $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out \ No newline at end of file From 31f876f6c433fbaa84a03376a0c31b3e7653dffe Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2015 07:53:05 +0100 Subject: [PATCH 018/588] try to enable display for linux --- test/run.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/run.sh b/test/run.sh index 93ac3073d55..c33c03ac96c 100755 --- a/test/run.sh +++ b/test/run.sh @@ -19,4 +19,9 @@ else fi # Integration Tests +if [[ "$OSTYPE" == "linux" ]]; then + export DISPLAY=:99.0 + sh -e /etc/init.d/xvfb start + sleep 3 +fi ./scripts/code.sh $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out \ No newline at end of file From 6505ab448bde46d72f9b8565035e6f56cc0ae55d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2015 08:20:58 +0100 Subject: [PATCH 019/588] tests: make sure to set proper exit codes --- src/vs/workbench/electron-main/lifecycle.ts | 2 +- src/vs/workbench/electron-main/windows.ts | 4 ++++ src/vs/workbench/node/pluginHostMain.ts | 12 ++++++------ .../thread/electron-browser/threadService.ts | 7 ++++++- test/run.sh | 16 +++++++++------- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/electron-main/lifecycle.ts b/src/vs/workbench/electron-main/lifecycle.ts index 831415103a5..4d0cbc3f5f6 100644 --- a/src/vs/workbench/electron-main/lifecycle.ts +++ b/src/vs/workbench/electron-main/lifecycle.ts @@ -68,7 +68,7 @@ export class Lifecycle { // Windows/Linux: we quit when all windows have closed // Mac: we only quit when quit was requested // Tests: we always quit - if (this.quitRequested || process.platform !== 'darwin' || env.isTestingFromCli) { + if (this.quitRequested || process.platform !== 'darwin') { app.quit(); } }); diff --git a/src/vs/workbench/electron-main/windows.ts b/src/vs/workbench/electron-main/windows.ts index 81dd55b071c..0d1d2ab0f0f 100644 --- a/src/vs/workbench/electron-main/windows.ts +++ b/src/vs/workbench/electron-main/windows.ts @@ -266,6 +266,10 @@ export class WindowsManager { console[logEntry.severity].apply(console, args); }); + ipc.on('vscode:exit', (event: Event, code: number) => { + process.exit(code); + }); + UpdateManager.on('update-downloaded', (update: IUpdate) => { this.sendToFocused('vscode:telemetry', { eventName: 'update:downloaded', data: { version: update.version } }); diff --git a/src/vs/workbench/node/pluginHostMain.ts b/src/vs/workbench/node/pluginHostMain.ts index cdd8c531459..6364e96aa43 100644 --- a/src/vs/workbench/node/pluginHostMain.ts +++ b/src/vs/workbench/node/pluginHostMain.ts @@ -99,7 +99,7 @@ export function createServices(remoteCom: IPluginsIPC, initData: IInitData, shar } interface ITestRunner { - run(testsRoot:string, clb: (error:Error) => void): void; + run(testsRoot:string, clb: (error:Error, failures?: number) => void): void; } export class PluginHostMain { @@ -235,7 +235,7 @@ export class PluginHostMain { // Execute the runner if it follows our spec if (testRunner && typeof testRunner.run === 'function') { return new TPromise((c, e) => { - testRunner.run(env.pluginTestsPath, (error) => { + testRunner.run(env.pluginTestsPath, (error, failures) => { if (error) { e(error.toString()); } else { @@ -243,22 +243,22 @@ export class PluginHostMain { } // after tests have run, we shutdown the host - this.gracefulExit(); + this.gracefulExit(failures && failures > 0 ? 1 /* ERROR */ : 0 /* OK */); }); }); } // Otherwise make sure to shutdown anyway even in case of an error else { - this.gracefulExit(); + this.gracefulExit(1 /* ERROR */); } return TPromise.wrapError(requireError ? requireError.toString() : nls.localize('pluginTestError', "Path {0} does not point to a valid extension test runner.", env.pluginTestsPath)); } - private gracefulExit(): void { + private gracefulExit(code: number): void { // to give the PH process a chance to flush any outstanding console // messages to the main process, we delay the exit() by some time - setTimeout(() => exit(), 500); + setTimeout(() => exit(code), 500); } } \ No newline at end of file diff --git a/src/vs/workbench/services/thread/electron-browser/threadService.ts b/src/vs/workbench/services/thread/electron-browser/threadService.ts index fe946ab0837..6c365c26e68 100644 --- a/src/vs/workbench/services/thread/electron-browser/threadService.ts +++ b/src/vs/workbench/services/thread/electron-browser/threadService.ts @@ -237,9 +237,14 @@ class PluginHostProcessManager { } // Expected development plugin termination: When the plugin host goes down we also shutdown the window - else { + else if (!isTestingFromCli) { this.windowService.getWindow().close(); } + + // When CLI testing make sure to exit with proper exit code + else { + ipc.send('vscode:exit', code); + } } }); }); diff --git a/test/run.sh b/test/run.sh index c33c03ac96c..8a94edda3a1 100755 --- a/test/run.sh +++ b/test/run.sh @@ -18,10 +18,12 @@ else node_modules/mocha/bin/_mocha $* fi -# Integration Tests -if [[ "$OSTYPE" == "linux" ]]; then - export DISPLAY=:99.0 - sh -e /etc/init.d/xvfb start - sleep 3 -fi -./scripts/code.sh $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out \ No newline at end of file +# Integration Tests (currently not enabled for linux because of missing display) +# if [[ "$OSTYPE" == "linux" ]]; then +# export DISPLAY=:99.0 +# sh -e /etc/init.d/xvfb start +# sleep 3 +# fi +if [[ "$OSTYPE" == "darwin"* ]]; then +./scripts/code.sh $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out +fi \ No newline at end of file From 807f38ea806f73b4b76866c90f07dfac796ead4b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2015 08:30:31 +0100 Subject: [PATCH 020/588] try to enable integration tests for linux --- .travis.yml | 4 +++- test/run.sh | 9 +-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7588dfb3d1d..a18fdb63af4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,9 @@ before_install: - npm config set python `which python` - npm install -g gulp - if [ $TRAVIS_OS_NAME == "linux" ]; then - export CXX="g++-4.9" CC="gcc-4.9"; + export CXX="g++-4.9" CC="gcc-4.9" DISPLAY=:99.0; + sh -e /etc/init.d/xvfb start; + sleep 3; fi install: diff --git a/test/run.sh b/test/run.sh index 8a94edda3a1..24147939853 100755 --- a/test/run.sh +++ b/test/run.sh @@ -19,11 +19,4 @@ else fi # Integration Tests (currently not enabled for linux because of missing display) -# if [[ "$OSTYPE" == "linux" ]]; then -# export DISPLAY=:99.0 -# sh -e /etc/init.d/xvfb start -# sleep 3 -# fi -if [[ "$OSTYPE" == "darwin"* ]]; then -./scripts/code.sh $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out -fi \ No newline at end of file +./scripts/code.sh $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out \ No newline at end of file From 60c987e871aefad782be1a35639e11d0ec8b5194 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 24 Nov 2015 10:07:53 +0100 Subject: [PATCH 021/588] fix broken style, one file, one style --- .../api/browser/extHostOutputService.ts | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/api/browser/extHostOutputService.ts b/src/vs/workbench/api/browser/extHostOutputService.ts index 2fed91fe4a1..3e7f2cfcb18 100644 --- a/src/vs/workbench/api/browser/extHostOutputService.ts +++ b/src/vs/workbench/api/browser/extHostOutputService.ts @@ -77,32 +77,34 @@ export class ExtHostOutputService { @Remotable.MainContext('MainThreadOutputService') export class MainThreadOutputService { - constructor( - @IOutputService private outputService: IOutputService, - @IWorkbenchEditorService private editorService: IWorkbenchEditorService - ) { + private _outputService: IOutputService; + private _editorService: IWorkbenchEditorService; + + constructor( @IOutputService outputService: IOutputService, @IWorkbenchEditorService editorService: IWorkbenchEditorService) { + this._outputService = outputService; + this._editorService = editorService; } 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_EDITOR_INPUT_ID) { - this.editorService.closeEditor(editor).done(null, onUnexpectedError); + this._editorService.closeEditor(editor).done(null, onUnexpectedError); return undefined; } } From 36783391a72c87a774a71c38ae0d04c3a18215b2 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 24 Nov 2015 11:03:17 +0100 Subject: [PATCH 022/588] debug: show debug environment picker in more situations. fixes #458 --- .../parts/debug/electron-browser/debugService.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 44c0b90bbb2..a1b9f8b4c95 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -337,10 +337,14 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService public openConfigFile(sideBySide: boolean): Promise { const resource = uri.file(paths.join(this.contextService.getWorkspace().resource.fsPath, '/.vscode/launch.json')); - return this.fileService.resolveContent(resource).then(content => content, err => - this.getInitialConfigFileContent().then(content => - this.fileService.updateContent(resource, content)) - ).then(() => { + return this.fileService.resolveContent(resource).then(content => { + const globalConfig = JSON.parse(content.value); + if (!globalConfig || !globalConfig.configurations || globalConfig.configurations.length === 0) { + return this.createInitialConfigFile(resource); + } + }, err => this.createInitialConfigFile(resource)) + + .then(() => { this.telemetryService.publicLog('debugConfigure'); return this.editorService.openEditor({ resource: resource, @@ -391,7 +395,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService }); } - private getInitialConfigFileContent(): TPromise { + private createInitialConfigFile(resource: uri): Promise { return this.quickOpenService.pick(this.adapters, { placeHolder: nls.localize('selectDebug', "Select Debug Environment") }) .then(adapter => this.massageInitialConfigurations(adapter).then(() => @@ -400,7 +404,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService configurations: adapter && adapter.initialConfigurations ? adapter.initialConfigurations : [] }, null, '\t') ) - ); + ).then(content => this.fileService.updateContent(resource, content)); } private massageInitialConfigurations(adapter: Adapter): Promise { From c5d0d0d78686d5fbb8378cc89ce12499b7a031b1 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 24 Nov 2015 11:19:48 +0100 Subject: [PATCH 023/588] debug: polish initial launch.json generation. --- .../debug/electron-browser/debugService.ts | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index a1b9f8b4c95..509e35f76ac 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -338,11 +338,15 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService const resource = uri.file(paths.join(this.contextService.getWorkspace().resource.fsPath, '/.vscode/launch.json')); return this.fileService.resolveContent(resource).then(content => { - const globalConfig = JSON.parse(content.value); + let globalConfig = null; + try { + globalConfig = JSON.parse(content.value); + } catch (e) { } + if (!globalConfig || !globalConfig.configurations || globalConfig.configurations.length === 0) { - return this.createInitialConfigFile(resource); + return this.createInitialConfigFile(resource, content.value); } - }, err => this.createInitialConfigFile(resource)) + }, err => this.createInitialConfigFile(resource, null)) .then(() => { this.telemetryService.publicLog('debugConfigure'); @@ -395,15 +399,19 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService }); } - private createInitialConfigFile(resource: uri): Promise { + private createInitialConfigFile(resource: uri, previousContent: string): Promise { return this.quickOpenService.pick(this.adapters, { placeHolder: nls.localize('selectDebug', "Select Debug Environment") }) .then(adapter => - this.massageInitialConfigurations(adapter).then(() => - JSON.stringify({ + this.massageInitialConfigurations(adapter).then(() => { + if (previousContent && !adapter) { + return previousContent; + } + + return JSON.stringify({ version: '0.2.0', configurations: adapter && adapter.initialConfigurations ? adapter.initialConfigurations : [] }, null, '\t') - ) + }) ).then(content => this.fileService.updateContent(resource, content)); } From ff6c7a2306a0ccf9f3263e5661e5f7c27e77f011 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 24 Nov 2015 10:20:58 +0100 Subject: [PATCH 024/588] validate BUILD_SOURCEVERSION --- build/gulpfile.editor.js | 2 +- build/gulpfile.vscode.js | 2 +- build/lib/util.js | 11 +++++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/build/gulpfile.editor.js b/build/gulpfile.editor.js index 6c6798c5a0a..f1bd8355b35 100644 --- a/build/gulpfile.editor.js +++ b/build/gulpfile.editor.js @@ -14,7 +14,7 @@ var util = require('./lib/util'); var common = require('./gulpfile.common'); var root = path.dirname(__dirname); -var commit = process.env['BUILD_SOURCEVERSION'] || require('./lib/git').getVersion(root); +var commit = util.getVersion(root); // Build diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index b3a0cb057d7..50eb15484d3 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -25,7 +25,7 @@ var util = require('./lib/util'); var buildfile = require('../src/buildfile'); var common = require('./gulpfile.common'); var root = path.dirname(__dirname); -var commit = process.env['BUILD_SOURCEVERSION'] || require('./lib/git').getVersion(root); +var commit = util.getVersion(root); var baseModules = [ 'app', 'applicationinsights', 'assert', 'auto-updater', 'browser-window', diff --git a/build/lib/util.js b/build/lib/util.js index 5bb82a71055..7424e8e6876 100644 --- a/build/lib/util.js +++ b/build/lib/util.js @@ -10,6 +10,7 @@ var _ = require('underscore'); var path = require('path'); var fs = require('fs'); var rimraf = require('rimraf'); +var git = require('./git'); var NoCancellationToken = { isCancellationRequested: function () { @@ -275,4 +276,14 @@ exports.downloadExtensions = function(extensions) { }); return es.merge(streams); +}; + +exports.getVersion = function (root) { + var version = process.env['BUILD_SOURCEVERSION']; + + if (!version || !/^[0-9a-f]{40}$/i.test(version)) { + version = git.getVersion(root); + } + + return version; }; \ No newline at end of file From 0d4396531e25d9f8489be5b106c09c06f49647b3 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Nov 2015 12:09:59 +0100 Subject: [PATCH 025/588] Webdav network drive not work (fixes #218) --- src/vs/base/node/extfs.ts | 22 +++++++++++++++---- .../electron-browser/snippetsTracker.ts | 3 ++- .../common/configurationService.ts | 9 ++++---- .../services/files/node/fileService.ts | 2 +- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/vs/base/node/extfs.ts b/src/vs/base/node/extfs.ts index 4fc46053e96..1c9ca2a1b19 100644 --- a/src/vs/base/node/extfs.ts +++ b/src/vs/base/node/extfs.ts @@ -27,7 +27,7 @@ export function readdir(path: string, callback: (error: Error, files: string[]) // Mac: uses NFD unicode form on disk, but we want NFC // See also https://github.com/nodejs/node/issues/2165 if (platform.isMacintosh) { - return fs.readdir(path, (error, children) => { + return readdirNormalize(path, (error, children) => { if (error) { return callback(error, null); } @@ -36,9 +36,23 @@ export function readdir(path: string, callback: (error: Error, files: string[]) }); } - return fs.readdir(path, callback); + return readdirNormalize(path, callback); }; +function readdirNormalize(path: string, callback: (error: Error, files: string[]) => void): void { + fs.readdir(path, (error, children) => { + if (error) { + return callback(error, null); + } + + // In some environments we get "." and ".." as entries from the call to readdir(). + // For example Sharepoint via WebDav on Windows includes them. We never want those + // entries in the result set though because they are not valid children of the folder + // for our concerns. + return callback(null, children.filter((c) => c !== '.' && c !== '..')); + }) +} + export function mkdirp(path: string, mode: number, callback: (error: Error) => void): void { fs.exists(path, (exists) => { if (exists) { @@ -91,7 +105,7 @@ export function copy(source: string, target: string, callback: (error: Error) => } mkdirp(target, stat.mode & 511, (err) => { - fs.readdir(source, (err, files) => { + readdir(source, (err, files) => { loop(files, (file: string, clb: (error: Error) => void) => { copy(paths.join(source, file), paths.join(target, file), clb, copiedSources); }, callback); @@ -204,7 +218,7 @@ function rmRecursive(path: string, callback: (error: Error) => void): void { fs.unlink(path, callback); } } else { - fs.readdir(path, (err, children) => { + readdir(path, (err, children) => { if (err || !children) { callback(err); } else if (children.length === 0) { diff --git a/src/vs/workbench/parts/snippets/electron-browser/snippetsTracker.ts b/src/vs/workbench/parts/snippets/electron-browser/snippetsTracker.ts index 730a715b1f5..61faf573bf3 100644 --- a/src/vs/workbench/parts/snippets/electron-browser/snippetsTracker.ts +++ b/src/vs/workbench/parts/snippets/electron-browser/snippetsTracker.ts @@ -12,6 +12,7 @@ import async = require('vs/base/common/async'); import Errors = require('vs/base/common/errors'); import URI from 'vs/base/common/uri'; import winjs = require('vs/base/common/winjs.base'); +import extfs = require('vs/base/node/extfs'); import lifecycle = require('vs/base/common/lifecycle'); import tmsnippets = require('vs/editor/node/textMate/TMSnippets'); import {IFileService} from 'vs/platform/files/common/files'; @@ -100,7 +101,7 @@ export class SnippetsTracker implements workbenchExt.IWorkbenchContribution { function readDir(path: string): winjs.TPromise { return new winjs.TPromise((c, e, p) => { - fs.readdir(path,(err, files) => { + extfs.readdir(path,(err, files) => { if (err) { return e(err); } diff --git a/src/vs/workbench/services/configuration/common/configurationService.ts b/src/vs/workbench/services/configuration/common/configurationService.ts index d15ada7e882..e30b091b837 100644 --- a/src/vs/workbench/services/configuration/common/configurationService.ts +++ b/src/vs/workbench/services/configuration/common/configurationService.ts @@ -11,6 +11,7 @@ import uri from 'vs/base/common/uri'; import strings = require('vs/base/common/strings'); import platform = require('vs/base/common/platform'); import paths = require('vs/base/common/paths'); +import extfs = require('vs/base/node/extfs'); import {IConfigFile} from 'vs/platform/configuration/common/model'; import objects = require('vs/base/common/objects'); import {IStat, IContent, ConfigurationService as CommonConfigurationService} from 'vs/platform/configuration/common/configurationService'; @@ -62,9 +63,9 @@ export class ConfigurationService extends CommonConfigurationService { protected resolveStat(resource: uri): TPromise { return new TPromise((c, e) => { - fs.readdir(resource.fsPath, (error, childs) => { + extfs.readdir(resource.fsPath, (error, childs) => { if (error) { - if (error.code === 'ENOTDIR') { + if ((error).code === 'ENOTDIR') { c({ resource: resource, isDirectory: false @@ -158,7 +159,7 @@ export class MigrationConfigurationService extends ConfigurationService { return c(null); // we never migrate more than once } - return fs.readdir(oldSettingsFolder, (error, children) => { + return extfs.readdir(oldSettingsFolder, (error, children) => { if (error) { return c(null); // old .settings folder does not exist or is a file } @@ -187,7 +188,7 @@ export class MigrationConfigurationService extends ConfigurationService { }, () => { this.messageService.show(severity.Info, nls.localize('settingsMigrated', "VSCode is now using a top level '.vscode' folder to store settings. We moved your existing settings files from the '.settings' folder.")); - return fs.readdir(oldSettingsFolder, (error, children) => { + return extfs.readdir(oldSettingsFolder, (error, children) => { if (error || children.length > 0) { return c(null); // done } diff --git a/src/vs/workbench/services/files/node/fileService.ts b/src/vs/workbench/services/files/node/fileService.ts index ef3be5934bc..8b041546825 100644 --- a/src/vs/workbench/services/files/node/fileService.ts +++ b/src/vs/workbench/services/files/node/fileService.ts @@ -678,7 +678,7 @@ export class StatResolver { fileStat = fsstat; if (fileStat.isDirectory()) { - fs.readdir(fileResource.fsPath, (error, result) => { + extfs.readdir(fileResource.fsPath, (error, result) => { this(null, result ? result.length : 0); }); } else { From 4aff6e8fda837a8fb0e7f06859ab09e23962ce8c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Nov 2015 12:26:04 +0100 Subject: [PATCH 026/588] fix issue with getting path label from root drive --- src/vs/base/common/labels.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/base/common/labels.ts b/src/vs/base/common/labels.ts index 80e8005d04f..fd30fb6ac1a 100644 --- a/src/vs/base/common/labels.ts +++ b/src/vs/base/common/labels.ts @@ -41,14 +41,14 @@ export function getPathLabel(arg1: uri|string, arg2?: uri|string|IWorkspaceProvi var absolutePath = getPath(arg1); if (basepath && paths.isEqualOrParent(absolutePath, basepath)) { - return paths.normalize(absolutePath.substr(basepath.length + 1 /* no leading slash/backslash */), platform.isNative); + return paths.normalize(strings.ltrim(absolutePath.substr(basepath.length), paths.nativeSep), true); } if (platform.isWindows && absolutePath[1] === ':') { - return paths.normalize(absolutePath.charAt(0).toUpperCase() + absolutePath.slice(1), platform.isNative); + return paths.normalize(absolutePath.charAt(0).toUpperCase() + absolutePath.slice(1), true); } - return paths.normalize(absolutePath, platform.isNative); + return paths.normalize(absolutePath, true); } function getPath(arg1: uri|string|IWorkspaceProvider): string { From b367216b91732eb4545adbc243f9406be544a8ae Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Nov 2015 12:31:58 +0100 Subject: [PATCH 027/588] improve initial progress reporting for slow loading file shares --- src/vs/workbench/browser/parts/editor/editorPart.ts | 4 ++-- .../workbench/browser/parts/sidebar/sidebarPart.ts | 12 +++++------- .../parts/files/browser/views/explorerView.ts | 4 +--- .../parts/files/browser/views/explorerViewer.ts | 4 +--- 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index eb6c62098d0..c2adde705cc 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -254,8 +254,8 @@ export class EditorPart extends Part implements IEditorPart { assert.ok(editorDescriptor, strings.format('Can not find a registered editor for the input {0}', input)); // Progress Indication - let loadingPromise: TPromise = TPromise.timeout(800).then(() => { - if (editorOpenToken === this.editorOpenToken[position] && this.partService.isCreated()) { + let loadingPromise: TPromise = TPromise.timeout(this.partService.isCreated() ? 800 : 3200 /* less ugly initial startup */).then(() => { + if (editorOpenToken === this.editorOpenToken[position]) { this.sideBySideControl.getProgressBar(position).infinite().getContainer().show(); this.sideBySideControl.setLoading(position, input); } diff --git a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts index e9e0c43feff..3bd38e70224 100644 --- a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts +++ b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts @@ -216,10 +216,8 @@ export class SidebarPart extends Part implements IViewletService { return viewlet; }); - // Report progress for slow loading promises if workbench is already created and thus this is user initiated - if (this.partService.isCreated()) { - progressService.showWhile(loaderPromise, 800); - } + // Report progress for slow loading viewlets + progressService.showWhile(loaderPromise, this.partService.isCreated() ? 800 : 3200 /* less ugly initial startup */); // Add to Promise Cache until Loaded this.viewletLoaderPromises[id] = loaderPromise; @@ -265,10 +263,10 @@ export class SidebarPart extends Part implements IViewletService { createViewletPromise = TPromise.as(null); } - // Report progress for slow loading promises (but only if we did not create the viewlet before already and only if this is user initiated) + // Report progress for slow loading viewlets (but only if we did not create the viewlet before already) let progressService = this.mapProgressServiceToViewlet[viewlet.getId()]; - if (progressService && !viewletContainer && this.partService.isCreated()) { - this.mapProgressServiceToViewlet[viewlet.getId()].showWhile(createViewletPromise, 800); + if (progressService && !viewletContainer) { + this.mapProgressServiceToViewlet[viewlet.getId()].showWhile(createViewletPromise, this.partService.isCreated() ? 800 : 3200 /* less ugly initial startup */); } // Fill Content and Actions diff --git a/src/vs/workbench/parts/files/browser/views/explorerView.ts b/src/vs/workbench/parts/files/browser/views/explorerView.ts index 50f7d27c02c..48430dc8461 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerView.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerView.ts @@ -682,9 +682,7 @@ export class ExplorerView extends CollapsibleViewletView { }); }, (e: any) => Promise.wrapError(e)); - if (this.partService.isCreated()) { - this.progressService.showWhile(promise, instantProgress ? 0 : 800); - } + this.progressService.showWhile(promise, instantProgress ? 0 : this.partService.isCreated() ? 800 : 3200 /* less ugly initial startup */); return promise; } diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 7011ebed01a..cdc4ec22f3e 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -98,9 +98,7 @@ export class FileDataSource implements Tree.IDataSource { return []; // we could not resolve any children because of an error }); - if (this.partService.isCreated()) { - this.progressService.showWhile(promise, 800); - } + this.progressService.showWhile(promise, this.partService.isCreated() ? 800 : 3200 /* less ugly initial startup */); return promise; } From 616b9ad9d8f24792a804c94187ae5805a68f16b6 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 24 Nov 2015 15:24:56 +0100 Subject: [PATCH 028/588] fixes #144 --- .../contrib/format/common/formatCommand.ts | 62 ++-- .../format/test/common/formatCommand.test.ts | 295 ++++++++++++++++++ .../common/model/editableTextModel.test.ts | 35 +++ 3 files changed, 363 insertions(+), 29 deletions(-) create mode 100644 src/vs/editor/contrib/format/test/common/formatCommand.test.ts diff --git a/src/vs/editor/contrib/format/common/formatCommand.ts b/src/vs/editor/contrib/format/common/formatCommand.ts index 65b1df24a17..37f0edce92c 100644 --- a/src/vs/editor/contrib/format/common/formatCommand.ts +++ b/src/vs/editor/contrib/format/common/formatCommand.ts @@ -23,8 +23,7 @@ export class EditOperationsCommand implements EditorCommon.ICommand { public getEditOperations(model: EditorCommon.ITokenizedModel, builder: EditorCommon.IEditOperationBuilder): void { this._edits // We know that this edit.range comes from the mirror model, so it should only contain \n and no \r's - .map((edit) => this.fixLineTerminators(edit, model) ) - .map((edit) => this.trimEdit(edit, model)) + .map((edit) => EditOperationsCommand.trimEdit(edit, model)) .filter((edit) => edit !== null) // produced above in case the edit.text is identical to the existing text .forEach((edit) => builder.addEditOperation(Range.lift(edit.range), edit.text)); @@ -50,9 +49,8 @@ export class EditOperationsCommand implements EditorCommon.ICommand { return helper.getTrackedSelection(this._selectionId); } - private fixLineTerminators(edit: EditorCommon.ISingleEditOperation, model: EditorCommon.ITokenizedModel) : EditorCommon.ISingleEditOperation { + static fixLineTerminators(edit: EditorCommon.ISingleEditOperation, model: EditorCommon.ITokenizedModel): void { edit.text = edit.text.replace(/\r\n|\r|\n/g, model.getEOL()); - return edit; } /** @@ -63,42 +61,48 @@ export class EditOperationsCommand implements EditorCommon.ICommand { * bug #15108. There the cursor was jumping since the tracked selection was in the middle of the range edit * and was lost. */ - private trimEdit(edit:EditorCommon.ISingleEditOperation, model: EditorCommon.ITokenizedModel): EditorCommon.ISingleEditOperation { + static trimEdit(edit:EditorCommon.ISingleEditOperation, model: EditorCommon.ITokenizedModel): EditorCommon.ISingleEditOperation { - var currentText = model.getValueInRange(edit.range); + this.fixLineTerminators(edit, model); + + return this._trimEdit(model.validateRange(edit.range), edit.text, edit.forceMoveMarkers, model); + } + + static _trimEdit(editRange:Range, editText:string, editForceMoveMarkers:boolean, model: EditorCommon.ITokenizedModel): EditorCommon.ISingleEditOperation { + + let currentText = model.getValueInRange(editRange); // Find the equal characters in the front - var commonPrefixLength = Strings.commonPrefixLength(edit.text, currentText); + let commonPrefixLength = Strings.commonPrefixLength(editText, currentText); - // If the two strings are identical, return no edit - if (commonPrefixLength === currentText.length && commonPrefixLength === edit.text.length) { + // If the two strings are identical, return no edit (no-op) + if (commonPrefixLength === currentText.length && commonPrefixLength === editText.length) { return null; } - // Only compute a common suffix if none of the strings is already fully contained in the prefix - var commonSuffixLength = 0; - if (commonPrefixLength !== currentText.length && commonPrefixLength !== edit.text.length) { - commonSuffixLength = Strings.commonSuffixLength(edit.text, currentText); + if (commonPrefixLength > 0) { + // Apply front trimming + let newStartPosition = model.modifyPosition(editRange.getStartPosition(), commonPrefixLength); + editRange = new Range(newStartPosition.lineNumber, newStartPosition.column, editRange.endLineNumber, editRange.endColumn); + editText = editText.substring(commonPrefixLength); + currentText = currentText.substr(commonPrefixLength); } - // Adjust start position - var newStartPosition = new Position(edit.range.startLineNumber, edit.range.startColumn); - newStartPosition = model.modifyPosition(newStartPosition, commonPrefixLength); + // Find the equal characters in the rear + let commonSuffixLength = Strings.commonSuffixLength(editText, currentText); - // Adjust end position - var newEndPosition = new Position(edit.range.endLineNumber, edit.range.endColumn); - newEndPosition = model.modifyPosition(newEndPosition, -commonSuffixLength); - - //Trim the text - var newText = edit.text.slice(commonPrefixLength, edit.text.length - commonSuffixLength); + if (commonSuffixLength > 0) { + // Apply rear trimming + let newEndPosition = model.modifyPosition(editRange.getEndPosition(), -commonSuffixLength); + editRange = new Range(editRange.startLineNumber, editRange.startColumn, newEndPosition.lineNumber, newEndPosition.column); + editText = editText.substring(0, editText.length - commonSuffixLength); + currentText = currentText.substring(0, currentText.length - commonSuffixLength); + } return { - text: newText, - range: { - startLineNumber:newStartPosition.lineNumber, - startColumn:newStartPosition.column, - endLineNumber:newEndPosition.lineNumber, - endColumn: newEndPosition.column - }}; + text: editText, + range: editRange, + forceMoveMarkers: editForceMoveMarkers + }; } } diff --git a/src/vs/editor/contrib/format/test/common/formatCommand.test.ts b/src/vs/editor/contrib/format/test/common/formatCommand.test.ts new file mode 100644 index 00000000000..897863c949c --- /dev/null +++ b/src/vs/editor/contrib/format/test/common/formatCommand.test.ts @@ -0,0 +1,295 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import assert = require('assert'); +import {Range} from 'vs/editor/common/core/range'; +import TU = require('vs/editor/test/common/commands/commandTestUtils'); +import {EditOperationsCommand} from 'vs/editor/contrib/format/common/formatCommand'; +import {Selection} from 'vs/editor/common/core/selection'; +import {Model} from 'vs/editor/common/model/model'; +import EditorCommon = require('vs/editor/common/editorCommon'); + +function editOp(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, text:string[]): EditorCommon.ISingleEditOperation { + return { + range: new Range(startLineNumber, startColumn, endLineNumber, endColumn), + text: text.join('\n'), + forceMoveMarkers: false + }; +} + +suite('FormatCommand.trimEdit', () => { + function testTrimEdit(lines: string[], edit:EditorCommon.ISingleEditOperation, expected:EditorCommon.ISingleEditOperation): void { + let model = new Model(lines.join('\n'), null); + let actual = EditOperationsCommand.trimEdit(edit, model); + assert.deepEqual(actual, expected); + model.dispose(); + } + + test('single-line no-op', () => { + testTrimEdit( + [ + 'some text', + 'some other text' + ], + editOp(1,1,1,10, [ + 'some text' + ]), + null + ) + }); + + test('multi-line no-op 1', () => { + testTrimEdit( + [ + 'some text', + 'some other text' + ], + editOp(1,1,2,16, [ + 'some text', + 'some other text' + ]), + null + ) + }); + + test('multi-line no-op 2', () => { + testTrimEdit( + [ + 'some text', + 'some other text' + ], + editOp(1,1,2,1, [ + 'some text', + '' + ]), + null + ) + }); + + test('simple prefix, no suffix', () => { + testTrimEdit( + [ + 'some text', + 'some other text' + ], + editOp(1,1,1,10, [ + 'some interesting thing' + ]), + editOp(1,6,1,10, [ + 'interesting thing' + ]) + ) + }); + + test('whole line prefix, no suffix', () => { + testTrimEdit( + [ + 'some text', + 'some other text' + ], + editOp(1,1,1,10, [ + 'some text', + 'interesting thing' + ]), + editOp(1,10,1,10, [ + '', + 'interesting thing' + ]) + ) + }); + + test('multi-line prefix, no suffix', () => { + testTrimEdit( + [ + 'some text', + 'some other text' + ], + editOp(1,1,2,16, [ + 'some text', + 'some other interesting thing' + ]), + editOp(2,12,2,16, [ + 'interesting thing' + ]) + ) + }); + + test('no prefix, simple suffix', () => { + testTrimEdit( + [ + 'some text', + 'some other text' + ], + editOp(1,1,1,10, [ + 'interesting text' + ]), + editOp(1,1,1,5, [ + 'interesting' + ]) + ) + }); + + test('no prefix, whole line suffix', () => { + testTrimEdit( + [ + 'some text', + 'some other text' + ], + editOp(1,1,1,10, [ + 'interesting thing', + 'some text' + ]), + editOp(1,1,1,1, [ + 'interesting thing', + '' + ]) + ) + }); + + test('no prefix, multi-line suffix', () => { + testTrimEdit( + [ + 'some text', + 'some other text' + ], + editOp(1,1,2,16, [ + 'interesting thing text', + 'some other text' + ]), + editOp(1,1,1,5, [ + 'interesting thing' + ]) + ) + }); + + test('no overlapping prefix & suffix', () => { + testTrimEdit( + [ + 'some cool text' + ], + editOp(1,1,1,15, [ + 'some interesting text' + ]), + editOp(1,6,1,10, [ + 'interesting' + ]) + ) + }); + + test('overlapping prefix & suffix 1', () => { + testTrimEdit( + [ + 'some cool text' + ], + editOp(1,1,1,15, [ + 'some cool cool text' + ]), + editOp(1,11,1,11, [ + 'cool ' + ]) + ) + }); + + test('overlapping prefix & suffix 2', () => { + testTrimEdit( + [ + 'some cool cool text' + ], + editOp(1,1,1,29, [ + 'some cool text' + ]), + editOp(1,11,1,16, [ + '' + ]) + ) + }); +}); + +suite('FormatCommand', () => { + function testFormatCommand(lines: string[], selection: Selection, edits:EditorCommon.ISingleEditOperation[], expectedLines: string[], expectedSelection: Selection): void { + TU.testCommand(lines, null, selection, (sel) => new EditOperationsCommand(edits, sel), expectedLines, expectedSelection); + } + + test('no-op', () => { + testFormatCommand( + [ + 'some text', + 'some other text' + ], + new Selection(2,1,2,5), + [ + editOp(1, 1, 2, 16, [ + 'some text', + 'some other text' + ]) + ], + [ + 'some text', + 'some other text' + ], + new Selection(2,1,2,5) + ); + }); + + test('trim beginning', () => { + testFormatCommand( + [ + 'some text', + 'some other text' + ], + new Selection(2,1,2,5), + [ + editOp(1, 1, 2, 16, [ + 'some text', + 'some new other text' + ]) + ], + [ + 'some text', + 'some new other text' + ], + new Selection(2,1,2,5) + ); + }); + + test('issue #144', () => { + testFormatCommand( + [ + 'package caddy', + '', + 'func main() {', + '\tfmt.Println("Hello World! :)")', + '}', + '' + ], + new Selection(1,1,1,1), + [ + editOp(1, 1, 6, 1, [ + 'package caddy', + '', + 'import "fmt"', + '', + 'func main() {', + '\tfmt.Println("Hello World! :)")', + '}', + '' + ]) + ], + [ + 'package caddy', + '', + 'import "fmt"', + '', + 'func main() {', + '\tfmt.Println("Hello World! :)")', + '}', + '' + ], + new Selection(1,1,1,1) + ); + }); + +}); \ No newline at end of file diff --git a/src/vs/editor/test/common/model/editableTextModel.test.ts b/src/vs/editor/test/common/model/editableTextModel.test.ts index eeae4109e0f..75c6088e86f 100644 --- a/src/vs/editor/test/common/model/editableTextModel.test.ts +++ b/src/vs/editor/test/common/model/editableTextModel.test.ts @@ -1139,6 +1139,41 @@ suite('EditorModel - EditableTextModel.applyEdits', () => { ); }); + test('issue #144', () => { + testApplyEdits( + [ + 'package caddy', + '', + 'func main() {', + '\tfmt.Println("Hello World! :)")', + '}', + '' + ], + [ + editOp(1, 1, 6, 1, [ + 'package caddy', + '', + 'import "fmt"', + '', + 'func main() {', + '\tfmt.Println("Hello World! :)")', + '}', + '' + ]) + ], + [ + 'package caddy', + '', + 'import "fmt"', + '', + 'func main() {', + '\tfmt.Println("Hello World! :)")', + '}', + '' + ] + ); + }); + function assertSyncedModels(text:string, callback:(model:EditableTextModel, assertMirrorModels:()=>void)=>void, setup:(model:EditableTextModel)=>void = null): void { var model = new EditableTextModel([], TextModel.toRawText(text), null); model.setEOL(EditorCommon.EndOfLineSequence.LF); From 3f7972116aac76ecf511a553ff6a675a7bb797da Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 24 Nov 2015 16:19:14 +0100 Subject: [PATCH 029/588] Fix #47, add support for comments and brackets for JSX --- extensions/javascript/javascript.configuration.json | 11 +++++++++++ extensions/javascript/package.json | 3 ++- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 extensions/javascript/javascript.configuration.json diff --git a/extensions/javascript/javascript.configuration.json b/extensions/javascript/javascript.configuration.json new file mode 100644 index 00000000000..da6ed547150 --- /dev/null +++ b/extensions/javascript/javascript.configuration.json @@ -0,0 +1,11 @@ +{ + "comments": { + "lineComment": "//", + "blockComment": [ "/*", "*/" ] + }, + "brackets": [ + ["{", "}"], + ["[", "]"], + ["(", ")"] + ] +} \ No newline at end of file diff --git a/extensions/javascript/package.json b/extensions/javascript/package.json index e9c2ed6a9a1..0b60a23412b 100644 --- a/extensions/javascript/package.json +++ b/extensions/javascript/package.json @@ -7,7 +7,8 @@ "languages": [{ "id": "javascriptreact", "aliases": ["JavaScript React","jsx"], - "extensions": [".jsx"] + "extensions": [".jsx"], + "configuration": "./javascript.configuration.json" }, { "id": "javascript", From c34f50f8049351708956c0ca36849bea58b94b7b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 24 Nov 2015 16:39:45 +0100 Subject: [PATCH 030/588] Let shouldAutotriggerSuggestImpl always return true, fixes #179 --- src/vs/editor/common/modes/abstractMode.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/common/modes/abstractMode.ts b/src/vs/editor/common/modes/abstractMode.ts index ab68df67cc6..211c8460392 100644 --- a/src/vs/editor/common/modes/abstractMode.ts +++ b/src/vs/editor/common/modes/abstractMode.ts @@ -178,7 +178,7 @@ export class AbstractMode implements Modes.IMode { } public shouldAutotriggerSuggestImpl(context:Modes.ILineContext, offset:number, triggeredByCharacter:string):boolean { - return false; + return true; } public shouldShowEmptySuggestionList():boolean { From f84a9013f35989dea57dbd76564aa0be00dac45f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2015 16:55:01 +0100 Subject: [PATCH 031/588] fix comment --- test/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/run.sh b/test/run.sh index 24147939853..93ac3073d55 100755 --- a/test/run.sh +++ b/test/run.sh @@ -18,5 +18,5 @@ else node_modules/mocha/bin/_mocha $* fi -# Integration Tests (currently not enabled for linux because of missing display) +# Integration Tests ./scripts/code.sh $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out \ No newline at end of file From 4163a8dcd553494ff78ac4991036b978e087cab3 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 24 Nov 2015 16:56:40 +0100 Subject: [PATCH 032/588] [json] add tm grammer, not yet enabled --- extensions/json/OSSREADME.json | 22 ++ extensions/json/package.json | 19 ++ extensions/json/syntaxes/JSON.tmLanguage | 264 +++++++++++++++++++++++ 3 files changed, 305 insertions(+) create mode 100644 extensions/json/OSSREADME.json create mode 100644 extensions/json/package.json create mode 100644 extensions/json/syntaxes/JSON.tmLanguage diff --git a/extensions/json/OSSREADME.json b/extensions/json/OSSREADME.json new file mode 100644 index 00000000000..2d12a69da84 --- /dev/null +++ b/extensions/json/OSSREADME.json @@ -0,0 +1,22 @@ +// ATTENTION - THIS DIRECTORY CONTAINS THIRD PARTY OPEN SOURCE MATERIALS: +[{ + "name": "textmate/json.tmbundle", + "version": "0.0.0", + "license": "TextMate Bundle License", + "repositoryURL": "https://github.com/textmate/json.tmbundle", + "licenseDetail": [ + "Copyright (c) textmate-json.tmbundle project authors", + "", + "If not otherwise specified (see below), files in this repository fall under the following license:", + "", + "Permission to copy, use, modify, sell and distribute this", + "software is granted. This software is provided \"as is\" without", + "express or implied warranty, and with no claim as to its", + "suitability for any purpose.", + "", + "An exception is made for files in readable text which contain their own license information,", + "or files where an accompanying file exists (in the same directory) with a \"-license\" suffix added", + "to the base-name name of the original file, and an extension of txt, html, or similar. For example", + "\"tidy\" is accompanied by \"tidy-license.txt\"." + ] +}] diff --git a/extensions/json/package.json b/extensions/json/package.json new file mode 100644 index 00000000000..b68380b554f --- /dev/null +++ b/extensions/json/package.json @@ -0,0 +1,19 @@ +{ + "name": "json", + "version": "0.1.0", + "publisher": "vscode", + "engines": { "vscode": "*" }, + "contributes": { + "languages": [{ + "id": "json", + "aliases": ["JSON", "json"], + "extensions": [".json", ".bowerrc", ".jshintrc", ".jscsrc", ".eslintrc"], + "mimetypes": ["application/json"] + }], + "grammars": [{ + // "language": "json" : commented out for now, will add once we have rule for comments + "scopeName": "source.json", + "path": "./syntaxes/JSON.tmLanguage" + }] + } +} \ No newline at end of file diff --git a/extensions/json/syntaxes/JSON.tmLanguage b/extensions/json/syntaxes/JSON.tmLanguage new file mode 100644 index 00000000000..b158162b2a7 --- /dev/null +++ b/extensions/json/syntaxes/JSON.tmLanguage @@ -0,0 +1,264 @@ + + + + + fileTypes + + json + + keyEquivalent + ^~J + name + JSON + patterns + + + include + #value + + + repository + + array + + begin + \[ + beginCaptures + + 0 + + name + punctuation.definition.array.begin.json + + + end + \] + endCaptures + + 0 + + name + punctuation.definition.array.end.json + + + name + meta.structure.array.json + patterns + + + include + #value + + + match + , + name + punctuation.separator.array.json + + + match + [^\s\]] + name + invalid.illegal.expected-array-separator.json + + + + constant + + match + \b(?:true|false|null)\b + name + constant.language.json + + number + + comment + handles integer and decimal numbers + match + (?x: # turn on extended mode + -? # an optional minus + (?: + 0 # a zero + | # ...or... + [1-9] # a 1-9 character + \d* # followed by zero or more digits + ) + (?: + (?: + \. # a period + \d+ # followed by one or more digits + )? + (?: + [eE] # an e character + [+-]? # followed by an option +/- + \d+ # followed by one or more digits + )? # make exponent optional + )? # make decimal portion optional + ) + name + constant.numeric.json + + object + + begin + \{ + beginCaptures + + 0 + + name + punctuation.definition.dictionary.begin.json + + + comment + a JSON object + end + \} + endCaptures + + 0 + + name + punctuation.definition.dictionary.end.json + + + name + meta.structure.dictionary.json + patterns + + + comment + the JSON object key + include + #string + + + begin + : + beginCaptures + + 0 + + name + punctuation.separator.dictionary.key-value.json + + + end + (,)|(?=\}) + endCaptures + + 1 + + name + punctuation.separator.dictionary.pair.json + + + name + meta.structure.dictionary.value.json + patterns + + + comment + the JSON object value + include + #value + + + match + [^\s,] + name + invalid.illegal.expected-dictionary-separator.json + + + + + match + [^\s\}] + name + invalid.illegal.expected-dictionary-separator.json + + + + string + + begin + " + beginCaptures + + 0 + + name + punctuation.definition.string.begin.json + + + end + " + endCaptures + + 0 + + name + punctuation.definition.string.end.json + + + name + string.quoted.double.json + patterns + + + match + (?x: # turn on extended mode + \\ # a literal backslash + (?: # ...followed by... + ["\\/bfnrt] # one of these characters + | # ...or... + u # a u + [0-9a-fA-F]{4} # and four hex digits + ) + ) + name + constant.character.escape.json + + + match + \\. + name + invalid.illegal.unrecognized-string-escape.json + + + + value + + comment + the 'value' diagram at http://json.org + patterns + + + include + #constant + + + include + #number + + + include + #string + + + include + #array + + + include + #object + + + + + scopeName + source.json + uuid + 0C3868E4-F96B-4E55-B204-1DCB5A20748B + + \ No newline at end of file From 62960334ae0cfe1d0cb3fbd69704496b75e6ab12 Mon Sep 17 00:00:00 2001 From: Francois Valdy Date: Tue, 24 Nov 2015 17:12:59 +0100 Subject: [PATCH 033/588] Typo fixes for src/vs/workbench/services --- .../parts/tasks/electron-browser/task.contribution.ts | 2 +- src/vs/workbench/parts/tasks/node/processRunnerSystem.ts | 4 ++-- .../services/configuration/common/configurationService.ts | 8 ++++---- src/vs/workbench/services/editor/common/editorService.ts | 4 ++-- .../services/files/electron-browser/fileService.ts | 2 +- src/vs/workbench/services/files/node/fileService.ts | 6 +++--- src/vs/workbench/services/files/node/watcher/common.ts | 2 +- .../workbench/services/message/browser/messageService.ts | 2 +- .../services/quickopen/browser/quickOpenService.ts | 2 +- src/vs/workbench/services/search/node/searchService.ts | 4 ++-- .../workbench/services/workspace/common/contextService.ts | 2 +- 11 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index 818660543da..be0c9d2dcab 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -861,7 +861,7 @@ if (Env.enableTasks) { }, 'location': { 'type': 'integer', - 'description': nls.localize('JsonSchema.pattern.location', 'The match group index of the problem\'s location. Valid location patterns are: (line), (line,column) and (startLine,startColumn,endLine,endColumn). If omitted line and colum is assumed.') + 'description': nls.localize('JsonSchema.pattern.location', 'The match group index of the problem\'s location. Valid location patterns are: (line), (line,column) and (startLine,startColumn,endLine,endColumn). If omitted line and column is assumed.') }, 'line': { 'type': 'integer', diff --git a/src/vs/workbench/parts/tasks/node/processRunnerSystem.ts b/src/vs/workbench/parts/tasks/node/processRunnerSystem.ts index 168d832d9d1..4e42eb7845d 100644 --- a/src/vs/workbench/parts/tasks/node/processRunnerSystem.ts +++ b/src/vs/workbench/parts/tasks/node/processRunnerSystem.ts @@ -50,7 +50,7 @@ export class ProcessRunnerSystem extends EventEmitter implements ITaskSystem { private childProcess: LineProcess; private activeTaskIdentifier: string; - constructor(fileConfig:FileConfig.ExternalTaskRunnerConfiguration, variables:SystemVariables, markerService:IMarkerService, modelService: IModelService, telemetryService: ITelemetryService, outputService:IOutputService, outputChannel:string, clearOuput: boolean = true) { + constructor(fileConfig:FileConfig.ExternalTaskRunnerConfiguration, variables:SystemVariables, markerService:IMarkerService, modelService: IModelService, telemetryService: ITelemetryService, outputService:IOutputService, outputChannel:string, clearOutput: boolean = true) { super(); this.fileConfig = fileConfig; this.variables = variables; @@ -65,7 +65,7 @@ export class ProcessRunnerSystem extends EventEmitter implements ITaskSystem { this.childProcess = null; this.activeTaskIdentifier = null; - if (clearOuput) { + if (clearOutput) { this.clearOutput(); } this.errorsShown = false; diff --git a/src/vs/workbench/services/configuration/common/configurationService.ts b/src/vs/workbench/services/configuration/common/configurationService.ts index e30b091b837..cac3b858ca0 100644 --- a/src/vs/workbench/services/configuration/common/configurationService.ts +++ b/src/vs/workbench/services/configuration/common/configurationService.ts @@ -63,7 +63,7 @@ export class ConfigurationService extends CommonConfigurationService { protected resolveStat(resource: uri): TPromise { return new TPromise((c, e) => { - extfs.readdir(resource.fsPath, (error, childs) => { + extfs.readdir(resource.fsPath, (error, children) => { if (error) { if ((error).code === 'ENOTDIR') { c({ @@ -77,7 +77,7 @@ export class ConfigurationService extends CommonConfigurationService { c({ resource: resource, isDirectory: true, - children: childs.map((child) => { + children: children.map((child) => { if (platform.isMacintosh) { child = strings.normalizeNFC(child); // Mac: uses NFD unicode form on disk, but we want NFC } @@ -109,7 +109,7 @@ export class ConfigurationService extends CommonConfigurationService { protected loadWorkspaceConfiguration(section?: string): TPromise<{ [relativeWorkspacePath: string]: IConfigFile }> { - // Return early if we dont have a workspace + // Return early if we don't have a workspace if (!this.contextService.getWorkspace()) { return Promise.as({}); } @@ -123,7 +123,7 @@ export class ConfigurationService extends CommonConfigurationService { let globalSettings = this.contextService.getOptions().globalSettings; return { contents: objects.mixin( - objects.clone(defaults.contents), // target: default values (but dont modify!) + objects.clone(defaults.contents), // target: default values (but don't modify!) globalSettings.settings, // source: global configured values true // overwrite ), diff --git a/src/vs/workbench/services/editor/common/editorService.ts b/src/vs/workbench/services/editor/common/editorService.ts index 4c065b61e26..27181d733dc 100644 --- a/src/vs/workbench/services/editor/common/editorService.ts +++ b/src/vs/workbench/services/editor/common/editorService.ts @@ -55,7 +55,7 @@ export interface IWorkbenchEditorService extends IEditorService { isVisible(input: IEditorInput, includeDiff: boolean): boolean; /** - * Opens an Editor on the given input with the provided options at the given position. If the input paramater + * Opens an Editor on the given input with the provided options at the given position. If the input parameter * is null, will cause the currently opened editor at the position to close. If sideBySide parameter is provided, * causes the editor service to decide in what position to open the input. */ @@ -94,7 +94,7 @@ export interface IWorkbenchEditorService extends IEditorService { closeEditors(othersOnly?: boolean): TPromise; /** - * Focus the editor at the provided position. If position is not provided, the current active editor is focussed. + * Focus the editor at the provided position. If position is not provided, the current active editor is focused. */ focusEditor(editor?: IEditor): TPromise; focusEditor(position?: Position): TPromise; diff --git a/src/vs/workbench/services/files/electron-browser/fileService.ts b/src/vs/workbench/services/files/electron-browser/fileService.ts index 956d93e40f4..e092a3313ce 100644 --- a/src/vs/workbench/services/files/electron-browser/fileService.ts +++ b/src/vs/workbench/services/files/electron-browser/fileService.ts @@ -48,7 +48,7 @@ export class FileService implements files.IFileService { encodingOverride.push({ resource: uri.file(paths.join(this.contextService.getWorkspace().resource.fsPath, '.vscode')), encoding: encoding.UTF8 }); } - let doNotWatch = ['**/.git/objects/**']; // this folder does the heavy duty for git and we dont need to watch it + let doNotWatch = ['**/.git/objects/**']; // this folder does the heavy duty for git and we don't need to watch it if (platform.isLinux) { doNotWatch.push('**/node_modules/**'); // Linux does not have a good watching implementation, so we exclude more } diff --git a/src/vs/workbench/services/files/node/fileService.ts b/src/vs/workbench/services/files/node/fileService.ts index 8b041546825..4df7d85922d 100644 --- a/src/vs/workbench/services/files/node/fileService.ts +++ b/src/vs/workbench/services/files/node/fileService.ts @@ -540,7 +540,7 @@ export class FileService implements files.IFileService { path: fsPath }); - // handle emit through delayer to accomodate for bulk changes + // handle emit through delayer to accommodate for bulk changes this.fileChangesWatchDelayer.trigger(() => { let buffer = this.undeliveredRawFileChangesEvents; this.undeliveredRawFileChangesEvents = []; @@ -639,7 +639,7 @@ export class StatResolver { // Load children this.resolveChildren(this.resource.fsPath, absoluteTargetPaths, options && options.resolveSingleChildDescendants, (children) => { - children = arrays.coalesce(children); // we dont want those null childs (could be permission denied when reading a child) + children = arrays.coalesce(children); // we don't want those null children (could be permission denied when reading a child) fileStat.hasChildren = children && children.length > 0; fileStat.children = children || []; @@ -714,7 +714,7 @@ export class StatResolver { // Continue resolving children based on condition if (resolveFolderChildren) { $this.resolveChildren(fileResource.fsPath, absoluteTargetPaths, resolveSingleChildDescendants, (children) => { - children = arrays.coalesce(children); // we dont want those null childs + children = arrays.coalesce(children); // we don't want those null children childStat.hasChildren = children && children.length > 0; childStat.children = children || []; diff --git a/src/vs/workbench/services/files/node/watcher/common.ts b/src/vs/workbench/services/files/node/watcher/common.ts index 7bc7e630c54..fb64223f00a 100644 --- a/src/vs/workbench/services/files/node/watcher/common.ts +++ b/src/vs/workbench/services/files/node/watcher/common.ts @@ -28,7 +28,7 @@ export function toFileChangesEvent(changes: IRawFileChange[]): FileChangesEvent } /** - * Given events that occured, applies some rules to normalize the events + * Given events that occurred, applies some rules to normalize the events */ export function normalize(changes: IRawFileChange[]): IRawFileChange[] { diff --git a/src/vs/workbench/services/message/browser/messageService.ts b/src/vs/workbench/services/message/browser/messageService.ts index 9d836c5abb1..9577c0b5788 100644 --- a/src/vs/workbench/services/message/browser/messageService.ts +++ b/src/vs/workbench/services/message/browser/messageService.ts @@ -74,7 +74,7 @@ export class WorkbenchMessageService implements IMessageService { } private onQuickOpenShowing(): void { - this.canShowMessages = false; // when quick open is open, dont show messages behind + this.canShowMessages = false; // when quick open is open, don't show messages behind this.handler.hide(); // hide messages when quick open is visible } diff --git a/src/vs/workbench/services/quickopen/browser/quickOpenService.ts b/src/vs/workbench/services/quickopen/browser/quickOpenService.ts index 9ac89b70d1c..ece782330ab 100644 --- a/src/vs/workbench/services/quickopen/browser/quickOpenService.ts +++ b/src/vs/workbench/services/quickopen/browser/quickOpenService.ts @@ -95,7 +95,7 @@ export interface IQuickOpenService { removeEditorHistoryEntry(input: IEditorInput): void; /** - * A convinient way to bring up quick open as a picker with custom elements. This bypasses the quick open handler + * A convenient way to bring up quick open as a picker with custom elements. This bypasses the quick open handler * registry and just leverages the quick open widget to select any kind of entries. * * Passing in a promise will allow you to resolve the elements in the background while quick open will show a diff --git a/src/vs/workbench/services/search/node/searchService.ts b/src/vs/workbench/services/search/node/searchService.ts index fbc9b7715b2..b235858242d 100644 --- a/src/vs/workbench/services/search/node/searchService.ts +++ b/src/vs/workbench/services/search/node/searchService.ts @@ -86,7 +86,7 @@ export class SearchService implements ISearchService { // Match if (progress.resource) { - if (typeof localResults[progress.resource.toString()] === 'undefined') { // dont override local results + if (typeof localResults[progress.resource.toString()] === 'undefined') { // don't override local results onProgress(progress); } } @@ -118,7 +118,7 @@ export class SearchService implements ISearchService { } } - // Dont support other resource schemes than files for now + // Don't support other resource schemes than files for now else if (resource.scheme !== 'file') { return; } diff --git a/src/vs/workbench/services/workspace/common/contextService.ts b/src/vs/workbench/services/workspace/common/contextService.ts index 2b6cda39fd8..738867aff1b 100644 --- a/src/vs/workbench/services/workspace/common/contextService.ts +++ b/src/vs/workbench/services/workspace/common/contextService.ts @@ -28,7 +28,7 @@ export interface IWorkspaceContextService extends IBaseWorkspaceContextService { updateOptions(key: string, value: any): void; /** - * Convinient way to check if auto save is enabled or not. + * Convenient way to check if auto save is enabled or not. */ isAutoSaveEnabled(): boolean; } From fea1ef3bfc8622c4d3556327e79593b1ef86254b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2015 17:33:35 +0100 Subject: [PATCH 034/588] polish --- src/vs/base/node/extfs.ts | 2 +- src/vs/workbench/node/pluginHostMain.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/base/node/extfs.ts b/src/vs/base/node/extfs.ts index 1c9ca2a1b19..d3393340d2d 100644 --- a/src/vs/base/node/extfs.ts +++ b/src/vs/base/node/extfs.ts @@ -49,7 +49,7 @@ function readdirNormalize(path: string, callback: (error: Error, files: string[] // For example Sharepoint via WebDav on Windows includes them. We never want those // entries in the result set though because they are not valid children of the folder // for our concerns. - return callback(null, children.filter((c) => c !== '.' && c !== '..')); + return callback(null, children.filter(c => c !== '.' && c !== '..')); }) } diff --git a/src/vs/workbench/node/pluginHostMain.ts b/src/vs/workbench/node/pluginHostMain.ts index 6364e96aa43..e1c1206ebb6 100644 --- a/src/vs/workbench/node/pluginHostMain.ts +++ b/src/vs/workbench/node/pluginHostMain.ts @@ -55,7 +55,7 @@ export interface IInitData { }; } -const nativeExit = process.exit; +const nativeExit = process.exit.bin(process); process.exit = function() { const err = new Error('An extension called process.exit() and this was prevented.'); console.warn((err).stack); From f21fd8f468ae76e99bda5ee8492da01bfd3a1b3c Mon Sep 17 00:00:00 2001 From: Francois Valdy Date: Tue, 24 Nov 2015 17:35:15 +0100 Subject: [PATCH 035/588] Typo fixes for src/vs/workbench/parts --- .../debug/browser/debugEditorModelManager.ts | 2 +- .../parts/debug/browser/debugHoverWidget.ts | 6 +++--- .../parts/debug/common/debugModel.ts | 2 +- .../parts/debug/common/debugProtocol.d.ts | 2 +- .../parts/emmet/node/editorAccessor.ts | 2 +- src/vs/workbench/parts/emmet/node/emmet.d.ts | 4 ++-- .../browser/editors/textFileEditorModel.ts | 2 +- .../parts/files/browser/fileActions.ts | 2 +- .../parts/files/browser/fileTracker.ts | 4 ++-- .../parts/files/browser/files.contribution.ts | 4 ++-- .../parts/files/browser/views/explorerView.ts | 10 +++++----- .../files/browser/views/explorerViewer.ts | 2 +- .../files/browser/views/workingFilesView.ts | 2 +- .../files/browser/views/workingFilesViewer.ts | 2 +- .../parts/files/browser/workingFilesModel.ts | 2 +- src/vs/workbench/parts/files/common/files.ts | 4 ++-- .../electron-browser/electronFileTracker.ts | 2 +- .../electron-browser/textFileServices.ts | 2 +- .../workbench/parts/git/browser/gitActions.ts | 2 +- .../workbench/parts/git/common/stageRanges.ts | 2 +- .../parts/git/test/common/stageRanges.test.ts | 6 +++--- .../lib/test/node/systemVariables.test.ts | 4 ++-- .../parts/output/browser/outputActions.ts | 4 ++-- .../search/browser/openAnythingHandler.ts | 2 +- .../parts/search/browser/openFileHandler.ts | 2 +- .../parts/search/browser/openSymbolHandler.ts | 2 +- .../parts/search/browser/searchViewlet.ts | 2 +- .../parts/tasks/common/problemCollectors.ts | 20 +++++++++---------- .../electron-browser/task.contribution.ts | 6 +++--- 29 files changed, 54 insertions(+), 54 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts b/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts index ecfcac5c456..7a55ae49eef 100644 --- a/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts +++ b/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts @@ -294,7 +294,7 @@ export class DebugEditorModelManager implements wbext.IWorkbenchContribution { stickiness: editorcommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges }; - // We need a seperate decoration for glyph margin, since we do not want it on each line of a multi line statement. + // We need a separate decoration for glyph margin, since we do not want it on each line of a multi line statement. private static TOP_STACK_FRAME_MARGIN: editorcommon.IModelDecorationOptions = { glyphMarginClassName: 'debug-top-stack-frame-glyph', stickiness: editorcommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges diff --git a/src/vs/workbench/parts/debug/browser/debugHoverWidget.ts b/src/vs/workbench/parts/debug/browser/debugHoverWidget.ts index d97cb32757b..27b841e9da6 100644 --- a/src/vs/workbench/parts/debug/browser/debugHoverWidget.ts +++ b/src/vs/workbench/parts/debug/browser/debugHoverWidget.ts @@ -47,8 +47,8 @@ export class DebugHoverWidget implements editorbrowser.IContentWidget { const pos = range.getStartPosition(); const wordAtPosition = this.editor.getModel().getWordAtPosition(pos); const hoveringOver = wordAtPosition ? wordAtPosition.word : null; - const focussedStackFrame = this.debugService.getViewModel().getFocusedStackFrame(); - if (!hoveringOver || !focussedStackFrame || (this.isVisible && hoveringOver === this.lastHoveringOver)) { + const focusedStackFrame = this.debugService.getViewModel().getFocusedStackFrame(); + if (!hoveringOver || !focusedStackFrame || (this.isVisible && hoveringOver === this.lastHoveringOver)) { return; } @@ -60,7 +60,7 @@ export class DebugHoverWidget implements editorbrowser.IContentWidget { namesToFind[0] = namesToFind[0].substring(namesToFind[0].lastIndexOf(' ') + 1); const variables: debug.IExpression[] = []; - focussedStackFrame.getScopes(this.debugService).done(scopes => { + focusedStackFrame.getScopes(this.debugService).done(scopes => { // flatten out scopes lists return scopes.reduce((accum, scopes) => { return accum.concat(scopes); }, []) diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index 002a98d3e3c..61f57fc6b2c 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -555,7 +555,7 @@ export class Model extends ee.EventEmitter implements debug.IModel { this.threads[data.threadId].callStack = data.callStack.map( (rsf, level) => { if (!rsf) { - return new StackFrame(data.threadId, 0, debug.Source.fromUri(uri.parse('unknown')), nls.localize('unkownStack', "Unknown stack location"), undefined, undefined); + return new StackFrame(data.threadId, 0, debug.Source.fromUri(uri.parse('unknown')), nls.localize('unknownStack', "Unknown stack location"), undefined, undefined); } return new StackFrame(data.threadId, rsf.id, rsf.source ? debug.Source.fromRawSource(rsf.source) : debug.Source.fromUri(uri.parse('unknown')), rsf.name, rsf.line, rsf.column); diff --git a/src/vs/workbench/parts/debug/common/debugProtocol.d.ts b/src/vs/workbench/parts/debug/common/debugProtocol.d.ts index c3ec89074f0..9ae5973e25b 100644 --- a/src/vs/workbench/parts/debug/common/debugProtocol.d.ts +++ b/src/vs/workbench/parts/debug/common/debugProtocol.d.ts @@ -65,7 +65,7 @@ declare module DebugProtocol { reason: string; /** The thread which was stopped. */ threadId?: number; - /** Additonal information. E.g. if reason is 'exception', text contains the exception name. */ + /** Additional information. E.g. if reason is 'exception', text contains the exception name. */ text?: string; }; } diff --git a/src/vs/workbench/parts/emmet/node/editorAccessor.ts b/src/vs/workbench/parts/emmet/node/editorAccessor.ts index 01a37311fa7..fc97c72cb8d 100644 --- a/src/vs/workbench/parts/emmet/node/editorAccessor.ts +++ b/src/vs/workbench/parts/emmet/node/editorAccessor.ts @@ -83,7 +83,7 @@ export class EditorAccessor implements emmet.Editor { } } - // shift colum by +1 since they are 1 based + // shift column by +1 since they are 1 based let range = new Range(startPosition.lineNumber, startPosition.column + 1, endPosition.lineNumber, endPosition.column + 1); let deletePreviousChars = 0; diff --git a/src/vs/workbench/parts/emmet/node/emmet.d.ts b/src/vs/workbench/parts/emmet/node/emmet.d.ts index 71cf3eb906e..5a5380d64b3 100644 --- a/src/vs/workbench/parts/emmet/node/emmet.d.ts +++ b/src/vs/workbench/parts/emmet/node/emmet.d.ts @@ -25,7 +25,7 @@ declare module 'emmet' { /** * Creates selection from start to end character - * indexes. If end is ommited, this method should place caret + * indexes. If end is omitted, this method should place caret * and start index * @param {Number} start * @param {Number} [end] @@ -133,4 +133,4 @@ declare module 'emmet' { */ export function run(action: string, editor: Editor): boolean; -} \ No newline at end of file +} diff --git a/src/vs/workbench/parts/files/browser/editors/textFileEditorModel.ts b/src/vs/workbench/parts/files/browser/editors/textFileEditorModel.ts index 76558cad4a4..c6abef3c064 100644 --- a/src/vs/workbench/parts/files/browser/editors/textFileEditorModel.ts +++ b/src/vs/workbench/parts/files/browser/editors/textFileEditorModel.ts @@ -703,7 +703,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements IEncodin } if (!this.preferredEncoding && this.contentEncoding === encoding) { - return false; // also return if we dont have a preferred encoding but the content encoding is already the same + return false; // also return if we don't have a preferred encoding but the content encoding is already the same } return true; diff --git a/src/vs/workbench/parts/files/browser/fileActions.ts b/src/vs/workbench/parts/files/browser/fileActions.ts index d518ba270e4..ef61435ce44 100644 --- a/src/vs/workbench/parts/files/browser/fileActions.ts +++ b/src/vs/workbench/parts/files/browser/fileActions.ts @@ -288,7 +288,7 @@ export abstract class BaseRenameAction extends BaseFileAction { name = getWellFormedFileName(name); let existingName = getWellFormedFileName(this.element.name); - // Return early if name is invalid or didnt change + // Return early if name is invalid or didn't change if (name === existingName || this.validateFileName(this.element.parent, name)) { return Promise.as(null); } diff --git a/src/vs/workbench/parts/files/browser/fileTracker.ts b/src/vs/workbench/parts/files/browser/fileTracker.ts index bbfa8325961..7b5a95fada3 100644 --- a/src/vs/workbench/parts/files/browser/fileTracker.ts +++ b/src/vs/workbench/parts/files/browser/fileTracker.ts @@ -87,7 +87,7 @@ export class FileTracker implements IWorkbenchContribution { this.emitInputStateChangeEvent(e.getAfter().resource); if (!this.contextService.isAutoSaveEnabled()) { - this.updateActivityBadge(); // no indication needed when auto save is turned off and we didnt show dirty + this.updateActivityBadge(); // no indication needed when auto save is turned off and we didn't show dirty } } @@ -182,7 +182,7 @@ export class FileTracker implements IWorkbenchContribution { this.handleMovedFileInVisibleEditors(before ? before.resource : null, after ? after.resource : null, after ? after.mime : null); } - // Dispose all known inputs pased on resource + // Dispose all known inputs passed on resource let oldFile = e.getBefore(); if ((e.gotMoved() || e.gotDeleted())) { this.disposeAll(oldFile.resource, this.quickOpenService.getEditorHistory()); diff --git a/src/vs/workbench/parts/files/browser/files.contribution.ts b/src/vs/workbench/parts/files/browser/files.contribution.ts index b0f4da1a033..6d6d295e59d 100644 --- a/src/vs/workbench/parts/files/browser/files.contribution.ts +++ b/src/vs/workbench/parts/files/browser/files.contribution.ts @@ -75,7 +75,7 @@ let openViewletKb: IKeybindings = { // Register file editors (Registry.as(EditorExtensions.Editors)).registerEditor( new FileEditorDescriptor( - TextFileEditor.ID, // explicit dependency because we dont want these editors lazy loaded + TextFileEditor.ID, // explicit dependency because we don't want these editors lazy loaded nls.localize('textFileEditor', "Text File Editor"), 'vs/workbench/parts/files/browser/editors/textFileEditor', 'TextFileEditor', @@ -95,7 +95,7 @@ let openViewletKb: IKeybindings = { (Registry.as(EditorExtensions.Editors)).registerEditor( new FileEditorDescriptor( - BinaryFileEditor.ID, // explicit dependency because we dont want these editors lazy loaded + BinaryFileEditor.ID, // explicit dependency because we don't want these editors lazy loaded nls.localize('binaryFileEditor', "Binary File Editor"), 'vs/workbench/parts/files/browser/editors/binaryFileEditor', 'BinaryFileEditor', diff --git a/src/vs/workbench/parts/files/browser/views/explorerView.ts b/src/vs/workbench/parts/files/browser/views/explorerView.ts index 48430dc8461..50d1b00c12c 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerView.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerView.ts @@ -150,7 +150,7 @@ export class ExplorerView extends CollapsibleViewletView { // During workbench startup, the editor area might restore more than one editor from a previous // session. When this happens there might be editor input changing events for side editors that - // dont have focus. In these cases we do not adjust explorer selection for non-focussed editors + // don't have focus. In these cases we do not adjust explorer selection for non-focused editors // because we only want to react for the editor that has focus. if (!this.partService.isCreated() && e.editorOptions && e.editorOptions.preserveFocus) { return; @@ -198,10 +198,10 @@ export class ExplorerView extends CollapsibleViewletView { public focus(): void { super.focus(); - // Open the focussed element in the editor if there is currently no file opened + // Open the focused element in the editor if there is currently no file opened let input = this.editorService.getActiveEditorInput(); if (!input || !(input instanceof FileEditorInput)) { - this.openFocussedElement(); + this.openFocusedElement(); } } @@ -247,13 +247,13 @@ export class ExplorerView extends CollapsibleViewletView { // Otherwise restore last used file: By Explorer selection return refreshPromise.then(() => { - this.openFocussedElement(); + this.openFocusedElement(); }); } }); } - private openFocussedElement(): boolean { + private openFocusedElement(): boolean { let stat: FileStat = this.explorerViewer.getFocus(); if (stat && !stat.isDirectory) { let editorInput = this.instantiationService.createInstance(FileEditorInput, stat.resource, stat.mime, void 0); diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index cdc4ec22f3e..0753d3dc286 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -84,7 +84,7 @@ export class FileDataSource implements Tree.IDataSource { // Convert to view model let modelDirStat = FileStat.create(dirStat); - // Add childs to folder + // Add children to folder for (let i = 0; i < modelDirStat.children.length; i++) { stat.addChild(modelDirStat.children[i]); } diff --git a/src/vs/workbench/parts/files/browser/views/workingFilesView.ts b/src/vs/workbench/parts/files/browser/views/workingFilesView.ts index d7fe22657fe..2945647ab47 100644 --- a/src/vs/workbench/parts/files/browser/views/workingFilesView.ts +++ b/src/vs/workbench/parts/files/browser/views/workingFilesView.ts @@ -150,7 +150,7 @@ export class WorkingFilesView extends AdaptiveCollapsibleViewletView { private onTextFileDirty(e: LocalFileChangeEvent): void { if (!this.contextService.isAutoSaveEnabled()) { - this.updateDirtyIndicator(); // no indication needed when auto save is turned off and we didnt show dirty + this.updateDirtyIndicator(); // no indication needed when auto save is turned off and we didn't show dirty } } diff --git a/src/vs/workbench/parts/files/browser/views/workingFilesViewer.ts b/src/vs/workbench/parts/files/browser/views/workingFilesViewer.ts index 4d6d820b592..9cac592301f 100644 --- a/src/vs/workbench/parts/files/browser/views/workingFilesViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/workingFilesViewer.ts @@ -134,7 +134,7 @@ export class WorkingFilesActionProvider extends ContributableActionProvider { return element instanceof WorkingFileEntry || super.hasActions(tree, element); } - // we dont call into super here because we put only one primary action to the left (Remove/Dirty Indicator) + // we don't call into super here because we put only one primary action to the left (Remove/Dirty Indicator) public getActions(tree: tree.ITree, element: WorkingFileEntry): TPromise { let actions: actions.IAction[] = []; diff --git a/src/vs/workbench/parts/files/browser/workingFilesModel.ts b/src/vs/workbench/parts/files/browser/workingFilesModel.ts index a3401d6b595..48bc1360730 100644 --- a/src/vs/workbench/parts/files/browser/workingFilesModel.ts +++ b/src/vs/workbench/parts/files/browser/workingFilesModel.ts @@ -87,7 +87,7 @@ export class WorkingFilesModel implements filesCommon.IWorkingFilesModel { private onTextFileDirty(e: filesCommon.LocalFileChangeEvent): void { if (!this.contextService.isAutoSaveEnabled()) { - this.updateDirtyState(e.getAfter().resource, true); // no indication needed when auto save is turned off and we didnt show dirty + this.updateDirtyState(e.getAfter().resource, true); // no indication needed when auto save is turned off and we didn't show dirty } else { this.addEntry(e.getAfter().resource); } diff --git a/src/vs/workbench/parts/files/common/files.ts b/src/vs/workbench/parts/files/common/files.ts index 5ccff56b211..9060c91d3e7 100644 --- a/src/vs/workbench/parts/files/common/files.ts +++ b/src/vs/workbench/parts/files/common/files.ts @@ -294,7 +294,7 @@ export interface ITextFileService extends IDisposable { isDirty(resource?: URI): boolean; /** - * Returs all resources that are currently dirty matching the provided resource or all dirty resources. + * Returns all resources that are currently dirty matching the provided resource or all dirty resources. * * @param resource the resource to check for being dirty. If it is not specified, will check for * all dirty resources. @@ -342,7 +342,7 @@ export interface ITextFileService extends IDisposable { revertAll(resources?: URI[], force?: boolean): TPromise; /** - * Brings up the confirm dialog to either save, dont save or cancel. + * Brings up the confirm dialog to either save, don't save or cancel. * * @param resource the resource of the file to ask for confirmation. */ diff --git a/src/vs/workbench/parts/files/electron-browser/electronFileTracker.ts b/src/vs/workbench/parts/files/electron-browser/electronFileTracker.ts index f7460d2fd33..4fc1ba4f9a6 100644 --- a/src/vs/workbench/parts/files/electron-browser/electronFileTracker.ts +++ b/src/vs/workbench/parts/files/electron-browser/electronFileTracker.ts @@ -161,7 +161,7 @@ export class FileTracker implements IWorkbenchContribution { private onTextFileDirty(e: LocalFileChangeEvent): void { if (!this.contextService.isAutoSaveEnabled() && !this.isDocumentedEdited) { - this.updateDocumentEdited(); // no indication needed when auto save is turned off and we didnt show dirty + this.updateDocumentEdited(); // no indication needed when auto save is turned off and we didn't show dirty } } diff --git a/src/vs/workbench/parts/files/electron-browser/textFileServices.ts b/src/vs/workbench/parts/files/electron-browser/textFileServices.ts index 7179263c8d4..823ebb6e3c4 100644 --- a/src/vs/workbench/parts/files/electron-browser/textFileServices.ts +++ b/src/vs/workbench/parts/files/electron-browser/textFileServices.ts @@ -233,7 +233,7 @@ export class TextFileService extends BrowserTextFileService { if (untitled) { let targetPath: string; - // Untitled with associated file path dont need to prompt + // Untitled with associated file path don't need to prompt if (this.untitledEditorService.hasAssociatedFilePath(untitled.getResource())) { targetPath = untitled.getResource().fsPath; } diff --git a/src/vs/workbench/parts/git/browser/gitActions.ts b/src/vs/workbench/parts/git/browser/gitActions.ts index 4f633bb51c3..640854afd15 100644 --- a/src/vs/workbench/parts/git/browser/gitActions.ts +++ b/src/vs/workbench/parts/git/browser/gitActions.ts @@ -406,7 +406,7 @@ export abstract class BaseUndoAction extends GitAction { }); }); }).then(null, (errors: any[]): Promise => { - console.error('One or more errors occured', errors); + console.error('One or more errors occurred', errors); return Promise.wrapError(errors[0]); }); } diff --git a/src/vs/workbench/parts/git/common/stageRanges.ts b/src/vs/workbench/parts/git/common/stageRanges.ts index 50720021c56..e34752e4a90 100644 --- a/src/vs/workbench/parts/git/common/stageRanges.ts +++ b/src/vs/workbench/parts/git/common/stageRanges.ts @@ -69,7 +69,7 @@ export function intersectChangeAndSelection(change:editorcommon.IChange, selecti } /** - * Returns all selected changes (there can be mulitple selections due to mulitple cursors). + * Returns all selected changes (there can be multiple selections due to multiple cursors). * If a change is partially selected, the selected part of the change will be returned. */ export function getSelectedChanges(changes:editorcommon.IChange[], selections:editorcommon.IEditorSelection[]):editorcommon.IChange[] { diff --git a/src/vs/workbench/parts/git/test/common/stageRanges.test.ts b/src/vs/workbench/parts/git/test/common/stageRanges.test.ts index bbaccf8a59c..0220b1c9666 100644 --- a/src/vs/workbench/parts/git/test/common/stageRanges.test.ts +++ b/src/vs/workbench/parts/git/test/common/stageRanges.test.ts @@ -87,7 +87,7 @@ suite('Git - Stage ranges', () => { changesEqual(result, expected); }); - test('Get selected changes test - mulitple changes selected with one selection', () => { + test('Get selected changes test - multiple changes selected with one selection', () => { var selections: IEditorSelection[] = []; selections.push(Selection.createSelection(2, 7, 7, 1)); var changes: IChange[] = []; @@ -119,7 +119,7 @@ suite('Git - Stage ranges', () => { changesEqual(result, expected); }); - test('Get selected changes test - mulitple changes partially selected with multiple selections', () => { + test('Get selected changes test - multiple changes partially selected with multiple selections', () => { var selections: IEditorSelection[] = []; selections.push(Selection.createSelection(3, 1, 9, 5), Selection.createSelection(115, 2, 129, 1)); var changes: IChange[] = []; @@ -130,7 +130,7 @@ suite('Git - Stage ranges', () => { changesEqual(result, expected); }); - test('Get selected changes test - mulitple changes selected with multiple selections. Multiple changes not selected', () => { + test('Get selected changes test - multiple changes selected with multiple selections. Multiple changes not selected', () => { var selections: IEditorSelection[] = []; selections.push(Selection.createSelection(33, 11, 79, 15), Selection.createSelection(155, 21, 189, 11)); var changes: IChange[] = []; diff --git a/src/vs/workbench/parts/lib/test/node/systemVariables.test.ts b/src/vs/workbench/parts/lib/test/node/systemVariables.test.ts index 8cb9b181347..debae512745 100644 --- a/src/vs/workbench/parts/lib/test/node/systemVariables.test.ts +++ b/src/vs/workbench/parts/lib/test/node/systemVariables.test.ts @@ -11,7 +11,7 @@ import * as Platform from 'vs/base/common/platform'; import { SystemVariables } from 'vs/workbench/parts/lib/node/systemVariables'; suite('SystemVariables tests', () => { - test('SytemVariables: subsitute one', () => { + test('SystemVariables: substitute one', () => { let systemVariables: SystemVariables = new SystemVariables(null, null, URI.parse('file:///VSCode/workspaceLocation')); if (Platform.isWindows) { assert.strictEqual(systemVariables.resolve('abc ${workspaceRoot} xyz'), 'abc \\VSCode\\workspaceLocation xyz'); @@ -20,7 +20,7 @@ suite('SystemVariables tests', () => { } }); - test('SytemVariables: subsitute many', () => { + test('SystemVariables: substitute many', () => { let systemVariables: SystemVariables = new SystemVariables(null, null, URI.parse('file:///VSCode/workspaceLocation')); if (Platform.isWindows) { assert.strictEqual(systemVariables.resolve('${workspaceRoot} - ${workspaceRoot}'), '\\VSCode\\workspaceLocation - \\VSCode\\workspaceLocation'); diff --git a/src/vs/workbench/parts/output/browser/outputActions.ts b/src/vs/workbench/parts/output/browser/outputActions.ts index 2e9b316845f..b07c6695955 100644 --- a/src/vs/workbench/parts/output/browser/outputActions.ts +++ b/src/vs/workbench/parts/output/browser/outputActions.ts @@ -63,7 +63,7 @@ export class GlobalShowOutputAction extends Action { channelToOpen = channels[0].getChannel(); } - // Fallback to any contributed channel otherwise if we dont have history + // Fallback to any contributed channel otherwise if we don't have history else { channelToOpen = (Registry.as(Extensions.OutputChannels)).getChannels()[0]; } @@ -191,7 +191,7 @@ export class SwitchOutputActionItem extends SelectActionItem { super(null, action, SwitchOutputActionItem.getChannels(outputService, input), SwitchOutputActionItem.getChannels(outputService, input).indexOf(input.getChannel())); this.input = input; - + this.outputService.onOutputChannel.add(this.onOutputChannel, this); } diff --git a/src/vs/workbench/parts/search/browser/openAnythingHandler.ts b/src/vs/workbench/parts/search/browser/openAnythingHandler.ts index 13fe0319a9c..8b04c1fcc1c 100644 --- a/src/vs/workbench/parts/search/browser/openAnythingHandler.ts +++ b/src/vs/workbench/parts/search/browser/openAnythingHandler.ts @@ -29,7 +29,7 @@ export class OpenAnythingHandler extends QuickOpenHandler { private static SYMBOL_SEARCH_INITIAL_TIMEOUT = 500; // Ignore symbol search after a timeout to not block search results private static SYMBOL_SEARCH_SUBSEQUENT_TIMEOUT = 100; - private static SEARCH_DELAY = 100; // This delay acommodates for the user typing a word and then stops typing to start searching + private static SEARCH_DELAY = 100; // This delay accommodates for the user typing a word and then stops typing to start searching private openSymbolHandler: _OpenSymbolHandler; private openFileHandler: OpenFileHandler; diff --git a/src/vs/workbench/parts/search/browser/openFileHandler.ts b/src/vs/workbench/parts/search/browser/openFileHandler.ts index 042b49c4573..9c3287e7477 100644 --- a/src/vs/workbench/parts/search/browser/openFileHandler.ts +++ b/src/vs/workbench/parts/search/browser/openFileHandler.ts @@ -84,7 +84,7 @@ export class FileEntry extends EditorQuickOpenEntry { export class OpenFileHandler extends QuickOpenHandler { - private static SEARCH_DELAY = 500; // This delay acommodates for the user typing a word and then stops typing to start searching + private static SEARCH_DELAY = 500; // This delay accommodates for the user typing a word and then stops typing to start searching private queryBuilder: QueryBuilder; private delayer: ThrottledDelayer; diff --git a/src/vs/workbench/parts/search/browser/openSymbolHandler.ts b/src/vs/workbench/parts/search/browser/openSymbolHandler.ts index da7a4ec68f7..9ba6d686ae4 100644 --- a/src/vs/workbench/parts/search/browser/openSymbolHandler.ts +++ b/src/vs/workbench/parts/search/browser/openSymbolHandler.ts @@ -90,7 +90,7 @@ class SymbolEntry extends EditorQuickOpenEntry { export class OpenSymbolHandler extends QuickOpenHandler { private static SUPPORTED_OPEN_TYPES = ['class', 'interface', 'enum', 'function', 'method']; - private static SEARCH_DELAY = 500; // This delay acommodates for the user typing a word and then stops typing to start searching + private static SEARCH_DELAY = 500; // This delay accommodates for the user typing a word and then stops typing to start searching private delayer: ThrottledDelayer; private isStandalone: boolean; diff --git a/src/vs/workbench/parts/search/browser/searchViewlet.ts b/src/vs/workbench/parts/search/browser/searchViewlet.ts index 27d68d45479..5cdd1f5f4ef 100644 --- a/src/vs/workbench/parts/search/browser/searchViewlet.ts +++ b/src/vs/workbench/parts/search/browser/searchViewlet.ts @@ -929,7 +929,7 @@ export class SearchViewlet extends Viewlet { this.viewModel.toggleHighlights(visible); } - // Open focussed element from results in case the editor area is otherwise empty + // Open focused element from results in case the editor area is otherwise empty if (visible && !this.editorService.getActiveEditorInput()) { let focus = this.tree.getFocus(); if (focus) { diff --git a/src/vs/workbench/parts/tasks/common/problemCollectors.ts b/src/vs/workbench/parts/tasks/common/problemCollectors.ts index 95c7e86b725..bc2db5ae711 100644 --- a/src/vs/workbench/parts/tasks/common/problemCollectors.ts +++ b/src/vs/workbench/parts/tasks/common/problemCollectors.ts @@ -204,12 +204,12 @@ export class StartStopProblemCollector extends AbstractProblemCollector implemen this.currentResource = resource; this.currentResourceAsString = resourceAsString; } - let markerDatas = this.markers[owner]; - if (!markerDatas) { - markerDatas = []; - this.markers[owner] = markerDatas; + let markerData = this.markers[owner]; + if (!markerData) { + markerData = []; + this.markers[owner] = markerData; } - markerDatas.push(markerMatch.marker); + markerData.push(markerMatch.marker); } else { this.reportedResourcesWithMarkers[owner][resourceAsString] = resource; } @@ -316,12 +316,12 @@ export class WatchingProblemCollector extends AbstractProblemCollector implement this.currentResource = resource; this.currentResourceAsString = resourceAsString; } - let markerDatas = this.markers[owner]; - if (!markerDatas) { - markerDatas = []; - this.markers[owner] = markerDatas; + let markerData = this.markers[owner]; + if (!markerData) { + markerData = []; + this.markers[owner] = markerData; } - markerDatas.push(markerMatch.marker); + markerData.push(markerMatch.marker); } else { this.removeResourceToClean(owner, resourceAsString); } diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index 818660543da..83c0dd24ae4 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -1025,7 +1025,7 @@ if (Env.enableTasks) { 'isShellCommand': { 'type': 'boolean', 'default': true, - 'description': nls.localize('JsonSchema.shell', 'Specifies whether the command is a shell command or an external programm. Defaults to false if omitted.') + 'description': nls.localize('JsonSchema.shell', 'Specifies whether the command is a shell command or an external program. Defaults to false if omitted.') }, 'args': { 'type': 'array', @@ -1053,7 +1053,7 @@ if (Env.enableTasks) { }, 'showOutput': { '$ref': '#/definitions/showOutputType', - 'description': nls.localize('JsonSchema.showOuput', 'Controls whether the output of the running task is shown or not. If omitted \'always\' is used.') + 'description': nls.localize('JsonSchema.showOutput', 'Controls whether the output of the running task is shown or not. If omitted \'always\' is used.') }, 'isWatching': { 'type': 'boolean', @@ -1111,7 +1111,7 @@ if (Env.enableTasks) { }, 'showOutput': { '$ref': '#/definitions/showOutputType', - 'description': nls.localize('JsonSchema.tasks.showOuput', 'Controls whether the output of the running task is shown or not. If omitted the globally defined value is used.') + 'description': nls.localize('JsonSchema.tasks.showOutput', 'Controls whether the output of the running task is shown or not. If omitted the globally defined value is used.') }, 'echoCommand': { 'type': 'boolean', From 5d9a4f343494ae8969014a3224443b6d7ce5caf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 24 Nov 2015 17:46:28 +0100 Subject: [PATCH 036/588] remove reference to atom-shell-installer-assets --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index f546c788b1e..006319d9dd1 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,6 @@ }, "devDependencies": { "async": "^1.4.0", - "atom-shell-installer-assets": "^0.2.0", "azure-storage": "^0.3.1", "clone": "^1.0.2", "debounce": "^1.0.0", @@ -84,4 +83,4 @@ "bugs": { "url": "https://github.com/Microsoft/vscode/issues" } -} \ No newline at end of file +} From 1ef99fc7022652f48f2edcb53dd800cb390a102c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2015 18:00:33 +0100 Subject: [PATCH 037/588] bin => bind --- 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 e1c1206ebb6..5e7125e8e02 100644 --- a/src/vs/workbench/node/pluginHostMain.ts +++ b/src/vs/workbench/node/pluginHostMain.ts @@ -55,7 +55,7 @@ export interface IInitData { }; } -const nativeExit = process.exit.bin(process); +const nativeExit = process.exit.bind(process); process.exit = function() { const err = new Error('An extension called process.exit() and this was prevented.'); console.warn((err).stack); From 1419be89ab49a028b9e8ef5ed5705e109adadac5 Mon Sep 17 00:00:00 2001 From: Francois Valdy Date: Tue, 24 Nov 2015 18:04:53 +0100 Subject: [PATCH 038/588] Missed them typos --- .../parts/debug/browser/debugEditorModelManager.ts | 2 +- src/vs/workbench/parts/debug/browser/debugViewer.ts | 6 +++--- .../parts/tasks/electron-browser/task.contribution.ts | 2 +- src/vs/workbench/parts/tasks/node/processRunnerSystem.ts | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts b/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts index 7a55ae49eef..1e348e74514 100644 --- a/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts +++ b/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts @@ -325,7 +325,7 @@ export class DebugEditorModelManager implements wbext.IWorkbenchContribution { private static FOCUSED_STACK_FRAME_DECORATION: editorcommon.IModelDecorationOptions = { isWholeLine: true, - className: 'debug-focussed-stack-frame-line', + className: 'debug-focused-stack-frame-line', stickiness: editorcommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges }; } diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index e4166fab241..c911ced374f 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -857,15 +857,15 @@ export class BreakpointsController extends BaseDebugController { return this.doNotFocusExceptionBreakpoint(tree, super.onPageUp(tree, event)); } - private doNotFocusExceptionBreakpoint(tree: tree.ITree, upSucceded: boolean) : boolean { - if (upSucceded) { + private doNotFocusExceptionBreakpoint(tree: tree.ITree, upSucceeded: boolean) : boolean { + if (upSucceeded) { var focus = tree.getFocus(); if (focus instanceof model.ExceptionBreakpoint) { tree.focusNth(2); } } - return upSucceded; + return upSucceeded; } protected onDelete(tree: tree.ITree, event: keyboard.StandardKeyboardEvent): boolean { diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index 83c0dd24ae4..1e7426e830f 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -861,7 +861,7 @@ if (Env.enableTasks) { }, 'location': { 'type': 'integer', - 'description': nls.localize('JsonSchema.pattern.location', 'The match group index of the problem\'s location. Valid location patterns are: (line), (line,column) and (startLine,startColumn,endLine,endColumn). If omitted line and colum is assumed.') + 'description': nls.localize('JsonSchema.pattern.location', 'The match group index of the problem\'s location. Valid location patterns are: (line), (line,column) and (startLine,startColumn,endLine,endColumn). If omitted line and column is assumed.') }, 'line': { 'type': 'integer', diff --git a/src/vs/workbench/parts/tasks/node/processRunnerSystem.ts b/src/vs/workbench/parts/tasks/node/processRunnerSystem.ts index 168d832d9d1..4e42eb7845d 100644 --- a/src/vs/workbench/parts/tasks/node/processRunnerSystem.ts +++ b/src/vs/workbench/parts/tasks/node/processRunnerSystem.ts @@ -50,7 +50,7 @@ export class ProcessRunnerSystem extends EventEmitter implements ITaskSystem { private childProcess: LineProcess; private activeTaskIdentifier: string; - constructor(fileConfig:FileConfig.ExternalTaskRunnerConfiguration, variables:SystemVariables, markerService:IMarkerService, modelService: IModelService, telemetryService: ITelemetryService, outputService:IOutputService, outputChannel:string, clearOuput: boolean = true) { + constructor(fileConfig:FileConfig.ExternalTaskRunnerConfiguration, variables:SystemVariables, markerService:IMarkerService, modelService: IModelService, telemetryService: ITelemetryService, outputService:IOutputService, outputChannel:string, clearOutput: boolean = true) { super(); this.fileConfig = fileConfig; this.variables = variables; @@ -65,7 +65,7 @@ export class ProcessRunnerSystem extends EventEmitter implements ITaskSystem { this.childProcess = null; this.activeTaskIdentifier = null; - if (clearOuput) { + if (clearOutput) { this.clearOutput(); } this.errorsShown = false; From 7542b9a6afc5c1e243ce1eceec84703d9db3c50e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2015 18:06:50 +0100 Subject: [PATCH 039/588] move configuration service into correct execution environment --- src/vs/workbench/electron-browser/shell.ts | 2 +- src/vs/workbench/electron-main/sharedProcessMain.ts | 2 +- .../configuration/{common => node}/configurationService.ts | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/vs/workbench/services/configuration/{common => node}/configurationService.ts (100%) diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index cd3566cd7d5..bab8a2828e9 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -36,7 +36,7 @@ import {IWindowService, WindowService} from 'vs/workbench/services/window/electr import {MessageService} from 'vs/workbench/services/message/electron-browser/messageService'; import {RequestService} from 'vs/workbench/services/request/node/requestService'; import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; -import {MigrationConfigurationService} from 'vs/workbench/services/configuration/common/configurationService'; +import {MigrationConfigurationService} from 'vs/workbench/services/configuration/node/configurationService'; import {FileService} from 'vs/workbench/services/files/electron-browser/fileService'; import {SearchService} from 'vs/workbench/services/search/node/searchService'; import {LifecycleService} from 'vs/workbench/services/lifecycle/electron-browser/lifecycleService'; diff --git a/src/vs/workbench/electron-main/sharedProcessMain.ts b/src/vs/workbench/electron-main/sharedProcessMain.ts index 285d0b2f1ce..269d0e06d11 100644 --- a/src/vs/workbench/electron-main/sharedProcessMain.ts +++ b/src/vs/workbench/electron-main/sharedProcessMain.ts @@ -19,7 +19,7 @@ import { WorkspaceContextService } from 'vs/workbench/services/workspace/common/ import { IEventService } from 'vs/platform/event/common/event'; import { EventService } from 'vs/platform/event/common/eventService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ConfigurationService } from 'vs/workbench/services/configuration/common/configurationService'; +import { ConfigurationService } from 'vs/workbench/services/configuration/node/configurationService'; // Extra services import { IExtensionsService } from 'vs/workbench/parts/extensions/common/extensions'; diff --git a/src/vs/workbench/services/configuration/common/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts similarity index 100% rename from src/vs/workbench/services/configuration/common/configurationService.ts rename to src/vs/workbench/services/configuration/node/configurationService.ts From a34c71df93baa3f5f081e8ba883805b1ccea7594 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2015 18:11:42 +0100 Subject: [PATCH 040/588] remove some older migration code --- src/vs/workbench/electron-browser/shell.ts | 7 +- src/vs/workbench/electron-main/windows.ts | 13 ---- .../node/configurationService.ts | 78 +------------------ 3 files changed, 4 insertions(+), 94 deletions(-) diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index bab8a2828e9..c157c54a422 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -36,7 +36,7 @@ import {IWindowService, WindowService} from 'vs/workbench/services/window/electr import {MessageService} from 'vs/workbench/services/message/electron-browser/messageService'; import {RequestService} from 'vs/workbench/services/request/node/requestService'; import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; -import {MigrationConfigurationService} from 'vs/workbench/services/configuration/node/configurationService'; +import {ConfigurationService} from 'vs/workbench/services/configuration/node/configurationService'; import {FileService} from 'vs/workbench/services/files/electron-browser/fileService'; import {SearchService} from 'vs/workbench/services/search/node/searchService'; import {LifecycleService} from 'vs/workbench/services/lifecycle/electron-browser/lifecycleService'; @@ -249,10 +249,9 @@ export class WorkbenchShell { this.messageServiceInstance = new MessageService(contextServiceInstance, this.windowServiceInstance, telemetryServiceInstance, keybindingServiceInstance); keybindingServiceInstance.setMessageService(this.messageServiceInstance); - let configServiceInstance = new MigrationConfigurationService( + let configServiceInstance = new ConfigurationService( contextServiceInstance, - eventServiceInstance, - this.messageServiceInstance + eventServiceInstance ); let fileServiceInstance = new FileService( diff --git a/src/vs/workbench/electron-main/windows.ts b/src/vs/workbench/electron-main/windows.ts index 0d1d2ab0f0f..936dda2ab76 100644 --- a/src/vs/workbench/electron-main/windows.ts +++ b/src/vs/workbench/electron-main/windows.ts @@ -100,9 +100,6 @@ export class WindowsManager { private static windowsStateStorageKey = 'windowsState'; private static themeStorageKey = 'theme'; // TODO@Ben this key is only used to find out if a window can be shown instantly because of light theme, remove once we have support for bg color - private static legacyLastActiveOpenedFolderStorageKey = 'lastActiveOpenedPath'; - private static legacyLastActiveWindowStateStorageKey = 'windowUIState'; - private static WINDOWS: window.VSCodeWindow[] = []; private userEnv: IEnv; @@ -113,16 +110,6 @@ export class WindowsManager { this.userEnv = userEnv; this.windowsState = storage.getItem(WindowsManager.windowsStateStorageKey) || { openedFolders: [] }; - - // TODO@Ben migration: remove me in a couple of versions - if (!this.windowsState.lastActiveWindow) { - let lastActiveOpenedFolder = storage.getItem(WindowsManager.legacyLastActiveOpenedFolderStorageKey); - let lastActiveWindowState = storage.getItem(WindowsManager.legacyLastActiveWindowStateStorageKey); - - if (lastActiveOpenedFolder || lastActiveWindowState) { - this.windowsState.lastActiveWindow = { workspacePath: lastActiveOpenedFolder, uiState: lastActiveWindowState || window.defaultWindowState() }; - } - } } private registerListeners(): void { diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index cac3b858ca0..a6f29ebadc6 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -92,11 +92,6 @@ export class ConfigurationService extends CommonConfigurationService { }); } - // TODO@Ben migration: remove this code after some versions - protected migrateSettingsOnce(): TPromise { - return TPromise.as(null); - } - private registerListeners(): void { this.toDispose = this.eventService.addListener(EventType.WORKBENCH_OPTIONS_CHANGED, (e) => this.onOptionsChanged(e)); } @@ -115,7 +110,7 @@ export class ConfigurationService extends CommonConfigurationService { } // Migrate as needed (.settings => .vscode) - return this.migrateSettingsOnce().then(() => super.loadWorkspaceConfiguration(section)); + return super.loadWorkspaceConfiguration(section); } protected loadGlobalConfiguration(): TPromise<{ contents: any; parseErrors?: string[]; }> { @@ -135,75 +130,4 @@ export class ConfigurationService extends CommonConfigurationService { public dispose(): void { this.toDispose(); } -} - -export class MigrationConfigurationService extends ConfigurationService { - - protected messageService: IMessageService; - private settingsMigrationPromise: TPromise; - - constructor(contextService: IWorkspaceContextService, eventService: IEventService, messageService: IMessageService) { - super(contextService, eventService); - this.messageService = messageService; - } - - // TODO@Ben migration: remove this code after some versions - protected migrateSettingsOnce(): TPromise { - if (!this.settingsMigrationPromise) { - this.settingsMigrationPromise = new TPromise((c, e) => { - let newSettingsFolder = this.contextService.toResource(this.workspaceSettingsRootFolder).fsPath; - let oldSettingsFolder = this.contextService.toResource('.settings').fsPath; - - return fs.exists(newSettingsFolder, (exists) => { - if (exists) { - return c(null); // we never migrate more than once - } - - return extfs.readdir(oldSettingsFolder, (error, children) => { - if (error) { - return c(null); // old .settings folder does not exist or is a file - } - - let knownSettingsFiles = ['team.settings.json', 'settings.json', 'tasks.json', 'launch.json', 'team.tasks.json', 'team.launch.json']; - let filesToMove: string[] = []; - children.forEach(child => { - if (knownSettingsFiles.some(f => child === f)) { - filesToMove.push(child); - } - }); - - if (filesToMove.length === 0) { - return c(null); // .settings folder does not contain files we expect - } - - return fs.mkdir(newSettingsFolder, (error) => { - if (error) { - return c(null); // abort if we cannot create the new settings folder - } - - return flow.loop(filesToMove, (fileToMove, callback) => { - return fs.rename(paths.join(oldSettingsFolder, fileToMove), paths.join(newSettingsFolder, fileToMove), (error) => { - callback(null, null); // ignore any errors - }); - }, () => { - this.messageService.show(severity.Info, nls.localize('settingsMigrated', "VSCode is now using a top level '.vscode' folder to store settings. We moved your existing settings files from the '.settings' folder.")); - - return extfs.readdir(oldSettingsFolder, (error, children) => { - if (error || children.length > 0) { - return c(null); // done - } - - return fs.rmdir(oldSettingsFolder, () => { - return c(null); - }); - }); - }) - }); - }); - }); - }); - } - - return this.settingsMigrationPromise; - } } \ No newline at end of file From b232ee55606a3c8d44de66a6dc7450295e861e12 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 24 Nov 2015 18:36:02 +0100 Subject: [PATCH 041/588] Goto definition acts too early in some cases (fixes #189) --- .../browser/goToDeclaration.ts | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts index c468b874875..8b6b9370b5f 100644 --- a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts @@ -239,7 +239,8 @@ class GotoDefinitionWithMouseEditorContribution implements EditorCommon.IEditorC private decorations:string[]; private currentWordUnderMouse:EditorCommon.IWordAtPosition; private throttler:Async.Throttler; - private lastMouseEvent:EditorBrowser.IMouseEvent; + private lastMouseMoveEvent:EditorBrowser.IMouseEvent; + private hasTriggerKeyOnMouseDown:boolean; constructor(editor: EditorBrowser.ICodeEditor, @IRequestService requestService: IRequestService, @IMessageService messageService: IMessageService, @IEditorService editorService: IEditorService) { this.editorService = editorService; @@ -252,6 +253,7 @@ class GotoDefinitionWithMouseEditorContribution implements EditorCommon.IEditorC this.editor = editor; this.throttler = new Async.Throttler(); + this.toUnhook.push(this.editor.addListener(EditorCommon.EventType.MouseDown, (e:EditorBrowser.IMouseEvent) => this.onEditorMouseDown(e))); this.toUnhook.push(this.editor.addListener(EditorCommon.EventType.MouseUp, (e:EditorBrowser.IMouseEvent) => this.onEditorMouseUp(e))); this.toUnhook.push(this.editor.addListener(EditorCommon.EventType.MouseMove, (e:EditorBrowser.IMouseEvent) => this.onEditorMouseMove(e))); this.toUnhook.push(this.editor.addListener(EditorCommon.EventType.KeyDown, (e:Keyboard.StandardKeyboardEvent) => this.onEditorKeyDown(e))); @@ -263,7 +265,7 @@ class GotoDefinitionWithMouseEditorContribution implements EditorCommon.IEditorC } private onEditorMouseMove(mouseEvent: EditorBrowser.IMouseEvent, withKey?:Keyboard.StandardKeyboardEvent):void { - this.lastMouseEvent = mouseEvent; + this.lastMouseMoveEvent = mouseEvent; this.startFindDefinition(mouseEvent, withKey); } @@ -410,20 +412,28 @@ class GotoDefinitionWithMouseEditorContribution implements EditorCommon.IEditorC } private onEditorKeyDown(e:Keyboard.StandardKeyboardEvent):void { - if (e.keyCode === GotoDefinitionWithMouseEditorContribution.TRIGGER_KEY_VALUE && this.lastMouseEvent) { - this.startFindDefinition(this.lastMouseEvent, e); + if (e.keyCode === GotoDefinitionWithMouseEditorContribution.TRIGGER_KEY_VALUE && this.lastMouseMoveEvent) { + this.startFindDefinition(this.lastMouseMoveEvent, e); } else if (e[GotoDefinitionWithMouseEditorContribution.TRIGGER_MODIFIER]) { this.removeDecorations(); // remove decorations if user holds another key with ctrl/cmd to prevent accident goto declaration } } private resetHandler():void { - this.lastMouseEvent = null; + this.lastMouseMoveEvent = null; this.removeDecorations(); } + private onEditorMouseDown(mouseEvent: EditorBrowser.IMouseEvent):void { + // We need to record if we had the trigger key on mouse down because someone might select something in the editor + // holding the mouse down and then while mouse is down start to press Ctrl/Cmd to start a copy operation and then + // release the mouse button without wanting to do the navigation. + // With this flag we prevent goto definition if the mouse was down before the trigger key was pressed. + this.hasTriggerKeyOnMouseDown = !!mouseEvent.event[GotoDefinitionWithMouseEditorContribution.TRIGGER_MODIFIER]; + } + private onEditorMouseUp(mouseEvent: EditorBrowser.IMouseEvent):void { - if (this.isEnabled(mouseEvent)) { + if (this.isEnabled(mouseEvent) && this.hasTriggerKeyOnMouseDown) { this.gotoDefinition(mouseEvent.target, mouseEvent.event.altKey).done(()=>{ this.removeDecorations(); }, (error:Error)=>{ From f6e57602af185ed359da985ef6efcd6bca0d6c51 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 24 Nov 2015 18:24:37 +0100 Subject: [PATCH 042/588] fix whitespace --- src/vs/base/browser/globalMouseMoveMonitor.ts | 20 +++--- src/vs/base/browser/idleMonitor.ts | 50 +++++++------- src/vs/base/browser/iframe.ts | 20 +++--- src/vs/base/common/collections.ts | 20 +++--- src/vs/base/common/graph.ts | 26 +++---- src/vs/base/common/injector.ts | 38 +++++------ src/vs/base/common/remote.ts | 24 +++---- src/vs/base/common/worker/workerProtocol.ts | 12 ++-- .../editor/common/services/modeServiceImpl.ts | 2 +- .../common/viewModel/prefixSumComputer.ts | 42 ++++++------ src/vs/editor/contrib/hover/browser/hover.css | 4 +- .../languages/css/common/parser/cssErrors.ts | 2 +- .../languages/css/common/parser/cssSymbols.ts | 68 +++++++++---------- .../languages/css/common/services/browsers.js | 2 +- .../languages/typescript/common/typescript.ts | 4 +- .../platform/plugins/common/ipcRemoteCom.ts | 24 +++---- .../parts/output/browser/outputActions.ts | 2 +- .../node/appInsightsTelemetryAppender.test.ts | 2 +- .../files/test/node/fileService.test.ts | 2 +- 19 files changed, 182 insertions(+), 182 deletions(-) diff --git a/src/vs/base/browser/globalMouseMoveMonitor.ts b/src/vs/base/browser/globalMouseMoveMonitor.ts index bf6f02d77e4..de03d86bc42 100644 --- a/src/vs/base/browser/globalMouseMoveMonitor.ts +++ b/src/vs/base/browser/globalMouseMoveMonitor.ts @@ -38,45 +38,45 @@ export function standardMouseMoveMerger(lastEvent:IStandardMouseMoveEventData, c } export class GlobalMouseMoveMonitor implements Lifecycle.IDisposable { - + private hooks:Lifecycle.IDisposable[]; private mouseMoveEventMerger:IEventMerger; private mouseMoveCallback:IMouseMoveCallback; private onStopCallback:IOnStopCallback; - + constructor() { this.hooks = []; this.mouseMoveEventMerger = null; this.mouseMoveCallback = null; this.onStopCallback = null; } - + public dispose(): void { this.stopMonitoring(false); } - + public stopMonitoring(invokeStopCallback:boolean): void { if (!this.isMonitoring()) { // Not monitoring return; } - + // Unhook this.hooks = Lifecycle.disposeAll(this.hooks); this.mouseMoveEventMerger = null; this.mouseMoveCallback = null; var onStopCallback = this.onStopCallback; this.onStopCallback = null; - + if (invokeStopCallback) { onStopCallback(); } } - + public isMonitoring() { return this.hooks.length > 0; } - + public startMonitoring( mouseMoveEventMerger:IEventMerger, mouseMoveCallback:IMouseMoveCallback, @@ -89,7 +89,7 @@ export class GlobalMouseMoveMonitor implements Lifecycle.IDisposable { this.mouseMoveEventMerger = mouseMoveEventMerger; this.mouseMoveCallback = mouseMoveCallback; this.onStopCallback = onStopCallback; - + var windowChain = IframeUtils.getSameOriginWindowChain(); for (var i = 0; i < windowChain.length; i++) { this.hooks.push(DomUtils.addDisposableThrottledListener(windowChain[i].window.document, 'mousemove', @@ -98,7 +98,7 @@ export class GlobalMouseMoveMonitor implements Lifecycle.IDisposable { )); this.hooks.push(DomUtils.addDisposableListener(windowChain[i].window.document, 'mouseup', (e:MouseEvent) => this.stopMonitoring(true))); } - + if (IframeUtils.hasDifferentOriginAncestor()) { var lastSameOriginAncestor = windowChain[windowChain.length - 1]; // We might miss a mouse up if it happens outside the iframe diff --git a/src/vs/base/browser/idleMonitor.ts b/src/vs/base/browser/idleMonitor.ts index 5524eae01f7..f5637be62a8 100644 --- a/src/vs/base/browser/idleMonitor.ts +++ b/src/vs/base/browser/idleMonitor.ts @@ -17,7 +17,7 @@ export enum UserStatus { export var DEFAULT_IDLE_TIME = 60 * 60 * 1000; // 60 minutes export class IdleMonitor { - + private toDispose:Lifecycle.IDisposable[]; private lastActiveTime:number; private idleCheckTimeout:number; @@ -25,41 +25,41 @@ export class IdleMonitor { private eventEmitter:EventEmitter.EventEmitter; private instance:ReferenceCountedIdleMonitor; private idleTime:number; - + constructor(idleTime:number = DEFAULT_IDLE_TIME) { this.instance = ReferenceCountedIdleMonitor.INSTANCE; this.instance.increment(); - + this.status = null; this.idleCheckTimeout = -1; this.lastActiveTime = -1; this.idleTime = idleTime; - + this.toDispose = []; this.eventEmitter = new EventEmitter.EventEmitter(); this.toDispose.push(this.eventEmitter); this.toDispose.push({dispose: this.instance.addListener(() => this.onUserActive())}); this.onUserActive(); } - + public addOneTimeActiveListener(callback:()=>void): Lifecycle.IDisposable { return this.eventEmitter.addOneTimeDisposableListener('onActive', callback); } - + public addOneTimeIdleListener(callback:()=>void): Lifecycle.IDisposable { return this.eventEmitter.addOneTimeDisposableListener('onIdle', callback); } - + public getStatus(): UserStatus { return this.status; } - + public dispose(): void { this.cancelIdleCheck(); this.toDispose = Lifecycle.disposeAll(this.toDispose); this.instance.decrement(); } - + private onUserActive(): void { this.lastActiveTime = (new Date()).getTime(); if (this.status !== UserStatus.Active) { @@ -68,14 +68,14 @@ export class IdleMonitor { this.eventEmitter.emit('onActive'); } } - + private onUserIdle(): void { if (this.status !== UserStatus.Idle) { this.status = UserStatus.Idle; this.eventEmitter.emit('onIdle'); } } - + private scheduleIdleCheck(): void { if (this.idleCheckTimeout === -1) { var minimumTimeWhenUserCanBecomeIdle = this.lastActiveTime + this.idleTime; @@ -85,14 +85,14 @@ export class IdleMonitor { }, minimumTimeWhenUserCanBecomeIdle - (new Date()).getTime()); } } - + private cancelIdleCheck(): void { if (this.idleCheckTimeout !== -1) { clearTimeout(this.idleCheckTimeout); this.idleCheckTimeout = -1; } } - + private checkIfUserIsIdle(): void { var actualIdleTime = (new Date()).getTime() - this.lastActiveTime; if (actualIdleTime >= this.idleTime) { @@ -104,20 +104,20 @@ export class IdleMonitor { } class ReferenceCountedObject { - + private referenceCount:number; - + constructor() { this.referenceCount = 0; } - + public increment(): void { if (this.referenceCount === 0) { this.construct(); } this.referenceCount++; } - + public decrement(): void { if (this.referenceCount > 0) { this.referenceCount--; @@ -126,23 +126,23 @@ class ReferenceCountedObject { } } } - + public construct(): void { throw new Error('Implement me'); } - + public dispose(): void { throw new Error('Implement me'); } } class ReferenceCountedIdleMonitor extends ReferenceCountedObject { - + public static INSTANCE:ReferenceCountedIdleMonitor = new ReferenceCountedIdleMonitor(); - + private toDispose:Lifecycle.IDisposable[]; private eventEmitter:EventEmitter.EventEmitter; - + public construct(): void { this.toDispose = []; this.eventEmitter = new EventEmitter.EventEmitter(); @@ -151,15 +151,15 @@ class ReferenceCountedIdleMonitor extends ReferenceCountedObject { this.toDispose.push(DomUtils.addDisposableListener(BrowserService.getService().document, 'keydown', () => this.onUserActive())); this.onUserActive(); } - + public dispose(): void { this.toDispose = Lifecycle.disposeAll(this.toDispose); } - + private onUserActive(): void { this.eventEmitter.emit('onActive'); } - + public addListener(callback:()=>void):EventEmitter.ListenerUnbind { return this.eventEmitter.addListener('onActive', callback); } diff --git a/src/vs/base/browser/iframe.ts b/src/vs/base/browser/iframe.ts index 91a075e8861..d080ea4aeeb 100644 --- a/src/vs/base/browser/iframe.ts +++ b/src/vs/base/browser/iframe.ts @@ -25,7 +25,7 @@ function getParentWindowIfSameOrigin(w:Window): Window { if (!w.parent || w.parent === w) { return null; } - + // Cannot really tell if we have access to the parent window unless we try to access something in it try { var location = w.location; @@ -38,7 +38,7 @@ function getParentWindowIfSameOrigin(w:Window): Window { hasDifferentOriginAncestorFlag = true; return null; } - + return w.parent; } @@ -97,34 +97,34 @@ export function hasDifferentOriginAncestor(): boolean { * Returns the position of `childWindow` relative to `ancestorWindow` */ export function getPositionOfChildWindowRelativeToAncestorWindow(childWindow:Window, ancestorWindow:any) { - + if (!ancestorWindow || childWindow === ancestorWindow) { return { top: 0, left: 0 }; } - + var top = 0, left = 0; - + var windowChain = getSameOriginWindowChain(); - + for (var i = 0; i < windowChain.length; i++) { var windowChainEl = windowChain[i]; - + if (windowChainEl.window === ancestorWindow) { break; } - + if (!windowChainEl.iframeElement) { break; } - + var boundingRect = windowChainEl.iframeElement.getBoundingClientRect(); top += boundingRect.top; left += boundingRect.left; } - + return { top: top, left: left diff --git a/src/vs/base/common/collections.ts b/src/vs/base/common/collections.ts index dba6af36976..0fd34ece7f5 100644 --- a/src/vs/base/common/collections.ts +++ b/src/vs/base/common/collections.ts @@ -94,7 +94,7 @@ export function contains(from:any, what:any):boolean { export function keys(from:IStringDictionary):IIterable; export function keys(from:INumberDictionary):IIterable; export function keys(from:any):IIterable { - + return { every: function(callback:(element:any)=>boolean):boolean { for (var key in from) { @@ -174,7 +174,7 @@ export function groupBy(data: T[], groupFn: (element: T) => string): IStringD * compatible with the JavaScript array. */ export interface IIterable { - + /** * Iterates over every element in the array * as long as the callback does not return some @@ -273,33 +273,33 @@ interface ICacheRow { * removes the older elements as new ones are inserted. */ export class LimitedSizeCache { - + private cache: { [id: string]: ICacheRow }; private order: string[]; - + constructor(private size: number) { this.cache = Object.create(null); this.order = []; } - + public get(id: string): T { var result = this.cache[id]; return result && result.element; } - + public put(id: string, element: T, onRemove: ()=>void): void { var existing = this.cache[id]; var row: ICacheRow = { element: element, onRemove: onRemove }; - + this.cache[id] = row; - + if (!existing) { this.order.push(id); } - + this.swipe(); } - + private swipe(): void { while (this.order.length > this.size) { var id = this.order.shift(); diff --git a/src/vs/base/common/graph.ts b/src/vs/base/common/graph.ts index 2272ff58a62..d091ce92dca 100644 --- a/src/vs/base/common/graph.ts +++ b/src/vs/base/common/graph.ts @@ -22,13 +22,13 @@ export function newNode(data:T):Node { } export class Graph { - + private _nodes:{[key:string]:Node} = Object.create(null); - + constructor(private _hashFn:(element:T)=>string) { // empty } - + public roots():Node[] { var ret:Node[] = []; collections.forEach(this._nodes, entry => { @@ -38,7 +38,7 @@ export class Graph { }); return ret; } - + public traverse(start:T, inwards:boolean, callback:(data:T)=>void):void { var startNode = this.lookup(start); if(!startNode) { @@ -46,7 +46,7 @@ export class Graph { } this._traverse(startNode, inwards, {}, callback); } - + private _traverse(node:Node, inwards:boolean, seen:{[key:string]:boolean}, callback:(data:T)=>void):void { var key = this._hashFn(node.data); if(collections.contains(seen, key)) { @@ -57,15 +57,15 @@ export class Graph { var nodes = inwards ? node.outgoing : node.incoming; collections.forEach(nodes, (entry) => this._traverse(entry.value, inwards, seen, callback)); } - + public insertEdge(from:T, to:T):void { var fromNode = this.lookupOrInsertNode(from), toNode = this.lookupOrInsertNode(to); - + fromNode.outgoing[this._hashFn(to)] = toNode; toNode.incoming[this._hashFn(from)] = fromNode; } - + public removeNode(data:T):void { var key = this._hashFn(data); delete this._nodes[key]; @@ -74,23 +74,23 @@ export class Graph { delete entry.value.incoming[key]; }); } - + public lookupOrInsertNode(data:T):Node { var key = this._hashFn(data), node = collections.lookup(this._nodes, key); - + if(!node) { node = newNode(data); this._nodes[key] = node; } - + return node; } - + public lookup(data:T):Node { return collections.lookup(this._nodes, this._hashFn(data)); } - + public get length():number { return Object.keys(this._nodes).length; } diff --git a/src/vs/base/common/injector.ts b/src/vs/base/common/injector.ts index fb5f113ae95..0a180e9f97f 100644 --- a/src/vs/base/common/injector.ts +++ b/src/vs/base/common/injector.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ 'use strict'; - + import Assert = require('vs/base/common/assert'); import Types = require('vs/base/common/types'); @@ -11,32 +11,32 @@ var inject = 'inject'; var injectLen = inject.length; export class Container { - + private map:{[name:string]:any;}; private parent:Container; - + constructor() { this.map = {}; this.parent = null; } - + public setParent(parent:Container):void { this.parent = parent; } - + public registerService(target:string, service:any):any { Assert.ok(!Types.isUndefinedOrNull(target)); Assert.ok(!Types.isUndefinedOrNull(service)); - + this.map[target.toLowerCase()] = service; - + return service; } - + // injects the denoted services to the target public injectTo(target:any):boolean { Assert.ok(!Types.isUndefinedOrNull(target)); - + // Support arrays var didInjectAtLeastOnce = false; if (Types.isArray(target)) { @@ -45,48 +45,48 @@ export class Container { }); return didInjectAtLeastOnce; } - + // inject services one by one for (var key in target) { if(key.indexOf(inject) !== 0) { continue; } - + var element = target[key]; if(!Types.isFunction(element)) { continue; } - + key = key.substring(injectLen).toLowerCase(); var service = this.findService(key, target); if(Types.isUndefinedOrNull(service)) { continue; } - + // call inject function element.apply(target, [service]); didInjectAtLeastOnce = true; } - + return didInjectAtLeastOnce; } - + public createChild():Container { var childContainer = new Container(); childContainer.setParent(this); - + return childContainer; } - + public findService(key:string, target:any=null):any { var result = this.map[key]; if((Types.isUndefinedOrNull(result) || target === result) && this.parent !== null) { result = this.parent.findService(key, target); } - + return result; } - + public dispose():void { this.map = null; this.parent = null; diff --git a/src/vs/base/common/remote.ts b/src/vs/base/common/remote.ts index 5e90967b1fd..75e06166e22 100644 --- a/src/vs/base/common/remote.ts +++ b/src/vs/base/common/remote.ts @@ -51,63 +51,63 @@ export interface ISerializedProxy { } export class ProxiesMarshallingContribution implements marshalling.IMarshallingContribution { - + private _remoteCom:IProxyHelper; - + constructor(remoteCom:IProxyHelper) { this._remoteCom = remoteCom; } - + public canSerialize(obj:any): boolean { return (typeof obj.$__CREATE__PROXY__REQUEST === 'string'); } - + public serialize(obj:any, serialize:(obj:any)=>any): ISerializedProxy { var desc: IObjDescriptor = { methods: [], props: {} }; - + var keys = Object.keys(obj); for (var i = 0; i < keys.length; i++) { var key = keys[i]; - + if (typeof obj[key] === 'function') { desc.methods.push(key); } else { desc.props[key] = serialize(obj[key]); } } - + return { $isProxyDescriptor: true, proxyId: obj.$__CREATE__PROXY__REQUEST, desc: desc }; } - + public canDeserialize(obj:ISerializedProxy): boolean { return obj.$isProxyDescriptor === true; } - + public deserialize(obj:ISerializedProxy, deserialize:(obj:any)=>any): any { // this is an object var result: any = { $__IS_REMOTE_OBJ: true }; - + var methods = obj.desc.methods; for (var i = 0; i < methods.length; i++) { result[methods[i]] = createMethodProxy(this._remoteCom, obj.proxyId, methods[i]); } - + var props = obj.desc.props; for (var prop in props) { if (hasOwnProperty.call(props, prop)) { result[prop] = deserialize(props[prop]); } } - + return result; } } \ No newline at end of file diff --git a/src/vs/base/common/worker/workerProtocol.ts b/src/vs/base/common/worker/workerProtocol.ts index 07e2a846b49..dafaf7d0578 100644 --- a/src/vs/base/common/worker/workerProtocol.ts +++ b/src/vs/base/common/worker/workerProtocol.ts @@ -77,15 +77,15 @@ export interface IRequester { } export class RemoteCom implements remote.IRemoteCom { - + private _requester: IRequester; private _bigHandler: remote.IManyHandler; - + constructor(requester:IRequester) { this._requester = requester; this._bigHandler = null; } - + public callOnRemote(proxyId: string, path: string, args:any[]): winjs.Promise { return this._requester.request('_proxyObj', { proxyId: proxyId, @@ -93,18 +93,18 @@ export class RemoteCom implements remote.IRemoteCom { args: args }); } - + public registerBigHandler(handler:remote.IManyHandler): void { this._bigHandler = handler; } - + public handleMessage(msg: { proxyId: string; path: string; args: any[]; }): winjs.Promise { if (!this._bigHandler) { throw new Error('got message before big handler attached!'); } return this._invokeHandler(msg.proxyId, msg.path, msg.args); } - + private _invokeHandler(rpcId:string, method:string, args:any[]): winjs.Promise { try { return winjs.TPromise.as(this._bigHandler.handle(rpcId, method, args)); diff --git a/src/vs/editor/common/services/modeServiceImpl.ts b/src/vs/editor/common/services/modeServiceImpl.ts index afbd2763e6d..6de4ab3cb1d 100644 --- a/src/vs/editor/common/services/modeServiceImpl.ts +++ b/src/vs/editor/common/services/modeServiceImpl.ts @@ -190,7 +190,7 @@ export class ModeServiceImpl implements IModeService { var c, e; var promise = new TPromise((cc,ee,pp) => { c = cc; e = ee; }); this._activationPromises[modeId] = promise; - + this._createMode(modeId).then((mode) => { this._instantiatedModes[modeId] = mode; delete this._activationPromises[modeId]; diff --git a/src/vs/editor/common/viewModel/prefixSumComputer.ts b/src/vs/editor/common/viewModel/prefixSumComputer.ts index 986e35fcd9d..a43856fae48 100644 --- a/src/vs/editor/common/viewModel/prefixSumComputer.ts +++ b/src/vs/editor/common/viewModel/prefixSumComputer.ts @@ -10,22 +10,22 @@ export interface IPrefixSumIndexOfResult { } export class PrefixSumComputer { - + /** * values[i] is the value at index i */ private values:number[]; - + /** * prefixSum[i] = SUM(heights[j]), 0 <= j <= i */ private prefixSum:number[]; - + /** * prefixSum[i], 0 <= i <= prefixSumValidIndex can be trusted */ private prefixSumValidIndex:number; - + constructor(values:number[]) { this.values = values; this.prefixSum = []; @@ -34,11 +34,11 @@ export class PrefixSumComputer { } this.prefixSumValidIndex = -1; } - + public getCount(): number { return this.values.length; } - + public insertValue(insertIndex:number, value:number): void { this.values.splice(insertIndex, 0, value); this.prefixSum.splice(insertIndex, 0, 0); @@ -46,20 +46,20 @@ export class PrefixSumComputer { this.prefixSumValidIndex = insertIndex - 1; } } - + public insertValues(insertIndex: number, values: number[]): void { if (values.length === 0) { return; } - + this.values = this.values.slice(0, insertIndex).concat(values).concat(this.values.slice(insertIndex)); this.prefixSum = this.prefixSum.slice(0, insertIndex).concat(PrefixSumComputer._zeroArray(values.length)).concat(this.prefixSum.slice(insertIndex)); - + if (insertIndex - 1 < this.prefixSumValidIndex) { this.prefixSumValidIndex = insertIndex - 1; } } - + private static _zeroArray(count: number): number[] { var r: number[] = new Array(count); for (var i = 0; i < count; i++) { @@ -67,7 +67,7 @@ export class PrefixSumComputer { } return r; } - + public changeValue(index:number, value:number): void { if (this.values[index] === value) { return; @@ -77,7 +77,7 @@ export class PrefixSumComputer { this.prefixSumValidIndex = index - 1; } } - + public removeValues(startIndex:number, cnt:number): void { this.values.splice(startIndex, cnt); this.prefixSum.splice(startIndex, cnt); @@ -85,14 +85,14 @@ export class PrefixSumComputer { this.prefixSumValidIndex = startIndex - 1; } } - + public getTotalValue(): number { if (this.values.length === 0) { return 0; } return this.getAccumulatedValue(this.values.length - 1); } - + public getAccumulatedValue(index:number): number { if (index < 0) { return 0; @@ -100,37 +100,37 @@ export class PrefixSumComputer { if (index <= this.prefixSumValidIndex) { return this.prefixSum[index]; } - + var startIndex = this.prefixSumValidIndex + 1; if (startIndex === 0) { this.prefixSum[0] = this.values[0]; startIndex++; } - + if (index >= this.values.length) { index = this.values.length - 1; } - + for (var i = startIndex; i <= index; i++) { this.prefixSum[i] = this.prefixSum[i - 1] + this.values[i]; } this.prefixSumValidIndex = Math.max(this.prefixSumValidIndex, index); return this.prefixSum[index]; } - + public getIndexOf(accumulatedValue:number, result:IPrefixSumIndexOfResult): void { var low = 0, high = this.values.length - 1, mid:number, midStart:number, midStop:number; - + while (low <= high) { mid = low + ( (high-low)/2 ) | 0; - + midStop = this.getAccumulatedValue(mid); midStart = midStop - this.values[mid]; - + if (accumulatedValue < midStart) { high = mid - 1; } else if (accumulatedValue >= midStop) { diff --git a/src/vs/editor/contrib/hover/browser/hover.css b/src/vs/editor/contrib/hover/browser/hover.css index a0091b4a6d4..abab1994f41 100644 --- a/src/vs/editor/contrib/hover/browser/hover.css +++ b/src/vs/editor/contrib/hover/browser/hover.css @@ -18,14 +18,14 @@ -ms-animation-name: fadeIn; animation-duration: 0.15s; animation-name: fadeIn; - + -webkit-user-select: text; -ms-user-select: text; -khtml-user-select: text; -moz-user-select: text; -o-user-select: text; user-select: text; - + overflow: hidden; } diff --git a/src/vs/languages/css/common/parser/cssErrors.ts b/src/vs/languages/css/common/parser/cssErrors.ts index 111f1bc809e..c185d6ee869 100644 --- a/src/vs/languages/css/common/parser/cssErrors.ts +++ b/src/vs/languages/css/common/parser/cssErrors.ts @@ -10,7 +10,7 @@ import nodes = require('./cssNodes'); export class CSSIssueType implements nodes.IRule { id: string; message: string; - + public constructor(id:string, message: string) { this.id = id; this.message = message; diff --git a/src/vs/languages/css/common/parser/cssSymbols.ts b/src/vs/languages/css/common/parser/cssSymbols.ts index 391a9f4428a..61af2712a45 100644 --- a/src/vs/languages/css/common/parser/cssSymbols.ts +++ b/src/vs/languages/css/common/parser/cssSymbols.ts @@ -8,40 +8,40 @@ import nodes = require('./cssNodes'); import arrays = require('vs/base/common/arrays'); export class Scope { - + public parent:Scope; public children:Scope[]; - + public offset:number; public length:number; - + private symbols:Symbol[]; - + constructor(offset:number, length:number) { this.offset = offset; this.length = length; this.symbols = []; - + this.parent = null; this.children = []; } - + public addChild(scope:Scope):void { this.children.push(scope); scope.setParent(this); } - + public setParent(scope:Scope):void { this.parent = scope; } - + public findScope(offset:number, length:number=0):Scope { if (this.offset <= offset && this.offset + this.length > offset + length || this.offset === offset && this.length === length) { return this.findInScope(offset, length); } return null; } - + private findInScope(offset: number, length: number = 0): Scope { // find the first scope child that has an offset larger than offset + length var end = offset + length; @@ -50,18 +50,18 @@ export class Scope { // all scopes have offsets larger than our end return this; } - + var res = this.children[idx-1]; if (res.offset <= offset && res.offset + res.length >= offset + length) { return res.findInScope(offset, length); } return this; } - + public addSymbol(symbol:Symbol):void { this.symbols.push(symbol); } - + public getSymbol(name:string, type: nodes.ReferenceType):Symbol { for (var index = 0; index < this.symbols.length; index++) { var symbol = this.symbols[index]; @@ -71,14 +71,14 @@ export class Scope { } return null; } - + public getSymbols():Symbol[] { return this.symbols; } } export class GlobalScope extends Scope { - + constructor() { super(0, Number.MAX_VALUE); } @@ -87,11 +87,11 @@ export class GlobalScope extends Scope { export class Symbol { - + public name:string; public type:nodes.ReferenceType; public node:nodes.Node; - + constructor(name:string, node:nodes.Node, type: nodes.ReferenceType) { this.name = name; this.node = node; @@ -102,18 +102,18 @@ export class Symbol { export class ScopeBuilder implements nodes.IVisitor { public scope:Scope; - + constructor(scope:Scope) { this.scope = scope; } - + private addSymbol(node:nodes.Node, name:string, type: nodes.ReferenceType) : void { if (node.offset !== -1) { var current = this.scope.findScope(node.offset, node.length); current.addSymbol(new Symbol(name, node, type)); } } - + private addScope(node:nodes.Node) : Scope { if (node.offset !== -1) { var current = this.scope.findScope(node.offset, node.length); @@ -126,14 +126,14 @@ export class ScopeBuilder implements nodes.IVisitor { } return null; } - + private addSymbolToChildScope(scopeNode:nodes.Node, node:nodes.Node, name:string, type: nodes.ReferenceType): void { if (scopeNode && scopeNode.offset !== -1 ) { var current = this.addScope(scopeNode); // create the scope or gets the existing one current.addSymbol(new Symbol(name, node, type)); } } - + public visitNode(node:nodes.Node):boolean { switch (node.type) { case nodes.NodeType.Keyframe: @@ -171,7 +171,7 @@ export class ScopeBuilder implements nodes.IVisitor { } return true; } - + public visitRuleSet(node:nodes.RuleSet):boolean { var current = this.scope.findScope(node.offset, node.length); node.getSelectors().getChildren().forEach((node) => { @@ -187,14 +187,14 @@ export class ScopeBuilder implements nodes.IVisitor { export class Symbols { - + private global:Scope; - + constructor(node:nodes.Node) { this.global = new GlobalScope(); node.accept(new ScopeBuilder(this.global)); } - + public findSymbolsAtOffset(offset:number, referenceType: nodes.ReferenceType) : Symbol[] { var scope = this.global.findScope(offset, 0); var result : Symbol[] = []; @@ -212,7 +212,7 @@ export class Symbols { } return result; } - + private internalFindSymbol(node:nodes.Node, referenceTypes:nodes.ReferenceType[]): Symbol { var scopeNode = node; if (node.parent instanceof nodes.FunctionParameter && node.parent.getParent() instanceof nodes.BodyDeclaration) { @@ -244,7 +244,7 @@ export class Symbols { } return null; } - + private evaluateReferenceTypes(node: nodes.Node) : nodes.ReferenceType[] { if (node instanceof nodes.Identifier) { var referenceTypes = ( node).referenceTypes; @@ -274,7 +274,7 @@ export class Symbols { } return null; } - + public findSymbolFromNode(node: nodes.Node):Symbol { if (!node) { return null; @@ -282,14 +282,14 @@ export class Symbols { while (node.type === nodes.NodeType.Interpolation) { node = node.getParent(); } - + var referenceTypes = this.evaluateReferenceTypes(node); if (referenceTypes) { return this.internalFindSymbol(node, referenceTypes); } return null; } - + public matchesSymbol(node: nodes.Node, symbol: Symbol):boolean { if (!node) { return null; @@ -300,17 +300,17 @@ export class Symbols { if (symbol.name.length !== node.length || symbol.name !== node.getText()) { return false; } - + var referenceTypes = this.evaluateReferenceTypes(node); if (!referenceTypes || referenceTypes.indexOf(symbol.type) === -1) { return false; } - + var nodeSymbol = this.internalFindSymbol(node, referenceTypes); return nodeSymbol === symbol; } - - + + public findSymbol(name:string, type: nodes.ReferenceType, offset:number):Symbol { var scope = this.global.findScope(offset); while(scope) { diff --git a/src/vs/languages/css/common/services/browsers.js b/src/vs/languages/css/common/services/browsers.js index db363c7f33e..3742fce0850 100644 --- a/src/vs/languages/css/common/services/browsers.js +++ b/src/vs/languages/css/common/services/browsers.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. *--------------------------------------------------------------------------------------------*/ - + // file generated from css-schema.xml using css-exclude_generate_browserjs.js define(["require", "exports"], function(require, exports) { diff --git a/src/vs/languages/typescript/common/typescript.ts b/src/vs/languages/typescript/common/typescript.ts index ee48668f239..a7cef06f12c 100644 --- a/src/vs/languages/typescript/common/typescript.ts +++ b/src/vs/languages/typescript/common/typescript.ts @@ -64,7 +64,7 @@ export class DefaultProjectResolver implements IProjectResolver2 { files: [], options: undefined }; - + setConsumer(consumer: IProjectConsumer) { this._consumer = consumer; } @@ -91,7 +91,7 @@ export class DefaultProjectResolver implements IProjectResolver2 { let resource = filePath ? URI.file(filePath) : URI.create('extralib', undefined, Date.now().toString()); - + this._needsProjectUpdate = true; this._projectChange.files.push(resource); this._fileChanges.push({ kind: ChangeKind.Added, resource, content }); diff --git a/src/vs/platform/plugins/common/ipcRemoteCom.ts b/src/vs/platform/plugins/common/ipcRemoteCom.ts index 37e8069bd1a..4f4cb636265 100644 --- a/src/vs/platform/plugins/common/ipcRemoteCom.ts +++ b/src/vs/platform/plugins/common/ipcRemoteCom.ts @@ -23,7 +23,7 @@ var pendingRPCReplies: { [msgId: string]: IRPCReply; } = {}; function createRPC(serializeAndSend:(obj:any)=>void): IRPCFunc { var lastMessageId = 0; - + return function rpc(rpcId: string, method: string, args: any[]): winjs.TPromise { var req = String(++lastMessageId); var reply: IRPCReply = { @@ -61,7 +61,7 @@ export function create(send:(obj:string)=>void): IPluginsIPC { var rpc = createRPC(serializeAndSend); var bigHandler: remote.IManyHandler = null; var invokedHandlers: { [req: string]: winjs.TPromise; } = Object.create(null); - + var r: IPluginsIPC = { callOnRemote: rpc, registerBigHandler: (_bigHandler: remote.IManyHandler): void => { @@ -69,7 +69,7 @@ export function create(send:(obj:string)=>void): IPluginsIPC { }, handle: (rawmsg) => { var msg = marshalling.demarshallObject(rawmsg, proxiesMarshalling); - + if (msg.seq) { if (!pendingRPCReplies.hasOwnProperty(msg.seq)) { console.warn('Got reply to unknown seq'); @@ -93,22 +93,22 @@ export function create(send:(obj:string)=>void): IPluginsIPC { } return; } - + if (msg.err) { console.error(msg.err); return; } var rpcId = msg.rpcId; - + if (!bigHandler) { throw new Error('got message before big handler attached!'); } - + var req = msg.req; - + invokedHandlers[req] = invokeHandler(rpcId, msg.method, msg.args); - + invokedHandlers[req].then((r) => { delete invokedHandlers[req]; serializeAndSend({ @@ -124,13 +124,13 @@ export function create(send:(obj:string)=>void): IPluginsIPC { }); } }; - + var proxiesMarshalling = new remote.ProxiesMarshallingContribution(r); - + function serializeAndSend(msg:any): void { send(marshalling.marshallObject(msg, proxiesMarshalling)); } - + function invokeHandler(rpcId:string, method:string, args:any[]): winjs.TPromise { try { return winjs.TPromise.as(bigHandler.handle(rpcId, method, args)); @@ -138,7 +138,7 @@ export function create(send:(obj:string)=>void): IPluginsIPC { return winjs.TPromise.wrapError(err); } } - + return r; }; diff --git a/src/vs/workbench/parts/output/browser/outputActions.ts b/src/vs/workbench/parts/output/browser/outputActions.ts index 2e9b316845f..5f96cb8ef08 100644 --- a/src/vs/workbench/parts/output/browser/outputActions.ts +++ b/src/vs/workbench/parts/output/browser/outputActions.ts @@ -191,7 +191,7 @@ export class SwitchOutputActionItem extends SelectActionItem { super(null, action, SwitchOutputActionItem.getChannels(outputService, input), SwitchOutputActionItem.getChannels(outputService, input).indexOf(input.getChannel())); this.input = input; - + this.outputService.onOutputChannel.add(this.onOutputChannel, this); } diff --git a/src/vs/workbench/parts/telemetry/test/node/appInsightsTelemetryAppender.test.ts b/src/vs/workbench/parts/telemetry/test/node/appInsightsTelemetryAppender.test.ts index 69d19b70842..099bd31823d 100644 --- a/src/vs/workbench/parts/telemetry/test/node/appInsightsTelemetryAppender.test.ts +++ b/src/vs/workbench/parts/telemetry/test/node/appInsightsTelemetryAppender.test.ts @@ -159,7 +159,7 @@ suite('Telemetry - AppInsightsTelemetryAppender', () => { assert.equal(appInsightsMock.events.length, 2); assert.equal(appInsightsMock.events[0].eventName, NodeAppInsightsTelemetryAppender.EVENT_NAME_PREFIX+'testEvent'); - + // test vortex assert.equal(appInsightsMock.events[1].eventName, NodeAppInsightsTelemetryAppender.EVENT_NAME_PREFIX+'testEvent'); }); diff --git a/src/vs/workbench/services/files/test/node/fileService.test.ts b/src/vs/workbench/services/files/test/node/fileService.test.ts index db96506f327..e715e98c9f2 100644 --- a/src/vs/workbench/services/files/test/node/fileService.test.ts +++ b/src/vs/workbench/services/files/test/node/fileService.test.ts @@ -58,7 +58,7 @@ suite('FileService', () => { test('createFile', function(done: () => void) { this.timeout(10000); // test tends to need longer? - + let contents = 'Hello World'; service.createFile(uri.file(path.join(testDir, 'test.txt')), contents).done(s => { assert.equal(s.name, 'test.txt'); From 9b5899187d007aaa4c760ecbd3269cb93440d1e3 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 24 Nov 2015 19:09:31 +0100 Subject: [PATCH 043/588] gulp hygiene --- build/gulpfile.hygiene.js | 120 ++++++++++++++++++++++++++++++++++++++ build/lib/copyrights.js | 36 ------------ build/lib/style.js | 60 ------------------- gulpfile.js | 68 +-------------------- 4 files changed, 121 insertions(+), 163 deletions(-) create mode 100644 build/gulpfile.hygiene.js delete mode 100644 build/lib/copyrights.js delete mode 100644 build/lib/style.js diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js new file mode 100644 index 00000000000..27c3c4fc891 --- /dev/null +++ b/build/gulpfile.hygiene.js @@ -0,0 +1,120 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +var gulp = require('gulp'); +var filter = require('gulp-filter'); +var es = require('event-stream'); +var path = require('path'); + +var eolFilter = [ + 'build/**/*', + 'extensions/**/*', + 'scripts/**/*', + 'src/**/*', + 'test/**/*', + '!extensions/csharp-o/bin/**', + '!extensions/**/out/**', + '!**/node_modules/**', + '!**/fixtures/**', + '!**/*.{svg,exe,png,scpt,bat,cur,ttf,woff,eot}', +]; + +var indentationFilter = [ + '**', + '!**/lib/**', + '!**/*.d.ts', + '!extensions/typescript/server/**', + '!test/assert.js', + '!**/package.json', + '!**/octicons/**', + '!**/vs/languages/sass/test/common/example.scss', + '!**/vs/languages/less/common/parser/less.grammar.txt', + '!**/vs/languages/css/common/buildscripts/css-schema.xml', + '!**/vs/languages/markdown/common/raw.marked.js', + '!**/vs/base/common/winjs.base.raw.js', + '!**/vs/base/node/terminateProcess.sh', + '!extensions/csharp-o/gulpfile.js', + '!**/vs/base/node/terminateProcess.sh', + '!**/vs/text.js', + '!**/vs/nls.js', + '!**/vs/css.js', + '!**/vs/loader.js', + '!extensions/**/snippets/**', + '!extensions/**/syntaxes/**', + '!extensions/**/themes/**', +]; + +var copyrightFilterList = [ + '**', + '!**/*.json', + '!**/*.html', + '!**/test/**', + '!**/*.md', + '!**/*.sh', + '!**/*.txt', + '!src/vs/editor/standalone-languages/swift.ts', +]; + +var copyrightHeader = [ + '/*---------------------------------------------------------------------------------------------', + ' * Copyright (c) Microsoft Corporation. All rights reserved.', + ' * Licensed under the MIT License. See License.txt in the project root for license information.', + ' *--------------------------------------------------------------------------------------------*/' +].join('\n'); + +gulp.task('hygiene', function() { + var errorCount = 0; + + var eol = es.through(function (file) { + if (/\r\n?/g.test(file.contents.toString('utf8'))) { + console.error(file.path + ': Bad EOL found'); + errorCount++; + } + + this.emit('data', file); + }); + + var indentation = es.through(function (file) { + file.contents + .toString('utf8') + .split(/\r\n|\r|\n/) + .forEach(function(line, i) { + if (line.length === 0) { + // empty lines are OK + } else if (/^[\t]*[^\s]/.test(line)) { + // good indent + } else if (/^[\t]* \*/.test(line)) { + // block comment using an extra space + } else { + console.error(file.path + '(' + (i + 1) + ',1): Bad whitespace indentation'); + errorCount++; + } + }); + + this.emit('data', file); + }); + + var copyrights = es.through(function (file) { + if (file.contents.toString('utf8').indexOf(copyrightHeader) !== 0) { + console.error(file.path + ': Missing or bad copyright statement'); + errorCount++; + } + }); + + return gulp.src(eolFilter, { base: '.' }) + .pipe(filter(function (f) { return !f.stat.isDirectory(); })) + .pipe(eol) + .pipe(filter(indentationFilter)) + .pipe(indentation) + .pipe(filter(copyrightFilterList)) + .pipe(copyrights) + .pipe(es.through(null, function () { + if (errorCount > 0) { + this.emit('error', 'Hygiene failed with ' + errorCount + ' errors.\nCheck build/gulpfile.hygiene.js for the hygiene rules.'); + } else { + this.emit('end'); + } + })); +}); diff --git a/build/lib/copyrights.js b/build/lib/copyrights.js deleted file mode 100644 index b468398bc60..00000000000 --- a/build/lib/copyrights.js +++ /dev/null @@ -1,36 +0,0 @@ -var es = require('event-stream'); -var fs = require('fs'); -var path = require('path'); - -var copyright = [ - '/*---------------------------------------------------------------------------------------------', - ' * Copyright (c) Microsoft Corporation. All rights reserved.', - ' * Licensed under the MIT License. See License.txt in the project root for license information.', - ' *--------------------------------------------------------------------------------------------*/' -].join('\n'); - - -exports.copyrights = function () { - return es.mapSync(function (file) { - if (file.contents) { - var contents = file.contents.toString('utf8'); - - if (contents.indexOf(copyright) !== 0) { - throw new Error('File ' + file.path + ' does not contain copyright statement.'); - } - } - }); -}; - -exports.insertCopyrights = function() { - return es.mapSync(function (file) { - if (file.contents) { - var contents = file.contents.toString('utf8'); - - if (contents.indexOf(copyright) !== 0) { - contents = copyright + '\n\n' + contents; - fs.writeFileSync(file.path, contents, 'utf8'); - } - } - }); -} diff --git a/build/lib/style.js b/build/lib/style.js deleted file mode 100644 index d9d890d37ce..00000000000 --- a/build/lib/style.js +++ /dev/null @@ -1,60 +0,0 @@ -var es = require('event-stream'); -var path = require('path'); - -module.exports = function (opts) { - return es.mapSync(function (file) { - if (file.stat.isDirectory()) { - return file; - } - var contents = file.contents.toString('utf8'); - - if (opts.complain) { - if (contents.indexOf('\r\n') >= 0) { - console.log(file.path + ' uses \\r\\n'); - } - - if (opts.whitespace) { - var lines = contents.split(/\r\n|\r|\n/); - for (var i = 0, len = lines.length; i < len; i++) { - var line = lines[i]; - if (line.length === 0) { - // empty lines are OK - continue; - } - - if (/^[\t]*[^\s]/.test(line)) { - // good indent - continue; - } else if (/^[\t]* \*/.test(line)) { - // block comment using an extra space - continue; - } else if (/^[\t]+$/.test(line)) { - // empty line - continue; - } else { - console.log(file.path + '(' + (i + 1) + ',1): Mixed whitespace indentation'); - } - } - } - } else { - var lines = contents.split(/\r\n|\r|\n/); - - if (opts.whitespace) { - for (var i = 0, len = lines.length; i < len; i++) { - var line = lines[i]; - line = line.replace(/^\ {28}/, '\t\t\t\t\t\t\t'); - line = line.replace(/^\ {24}/, '\t\t\t\t\t\t'); - line = line.replace(/^\ {20}/, '\t\t\t\t\t'); - line = line.replace(/^\ {16}/, '\t\t\t\t'); - line = line.replace(/^\ {12}/, '\t\t\t'); - line = line.replace(/^\ {8}/, '\t\t'); - line = line.replace(/^\ {4}/, '\t'); - lines[i] = line; - } - } - - file.contents = new Buffer(lines.join('\n'), 'utf8'); - } - return file; - }); -}; diff --git a/gulpfile.js b/gulpfile.js index 429761cdbd8..2be8f89a9e2 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -13,8 +13,6 @@ var mocha = require('gulp-mocha'); var es = require('event-stream'); var watch = require('./build/lib/watch'); var nls = require('./build/lib/nls'); -var style = require('./build/lib/style'); -var copyrights = require('./build/lib/copyrights'); var util = require('./build/lib/util'); var reporter = require('./build/lib/reporter')(); var remote = require('gulp-remote-src'); @@ -115,71 +113,6 @@ gulp.task('clean', ['clean-client', 'clean-plugins']); gulp.task('compile', ['compile-client', 'compile-plugins']); gulp.task('watch', ['watch-client', 'watch-plugins']); -var LINE_FEED_FILES = [ - 'build/**/*', - 'extensions/**/*', - 'scripts/**/*', - 'src/**/*', - 'test/**/*', - '!extensions/csharp-o/bin/**', - '!extensions/**/out/**', - '!**/node_modules/**', - '!**/fixtures/**', - '!**/*.{svg,exe,png,scpt,bat,cur,ttf,woff,eot}', -]; - -gulp.task('eol-style', function() { - return gulp.src(LINE_FEED_FILES).pipe(style({complain:true})); -}); -gulp.task('fix-eol-style', function() { - return gulp.src(LINE_FEED_FILES, { base: '.' }).pipe(style({})).pipe(gulp.dest('.')); -}); -var WHITESPACE_FILES = LINE_FEED_FILES.concat([ - '!**/lib/**', - '!**/*.d.ts', - '!extensions/typescript/server/**', - '!test/assert.js', - '!**/octicons/**', - '!**/vs/languages/sass/test/common/example.scss', - '!**/vs/languages/less/common/parser/less.grammar.txt', - '!**/vs/languages/css/common/buildscripts/css-schema.xml', - '!**/vs/languages/markdown/common/raw.marked.js', - '!**/vs/base/common/winjs.base.raw.js', - '!**/vs/base/node/terminateProcess.sh', - '!extensions/csharp-o/gulpfile.js', - '!**/vs/base/node/terminateProcess.sh', - '!**/vs/text.js', - '!**/vs/nls.js', - '!**/vs/css.js', - '!**/vs/loader.js', - '!extensions/**/snippets/**', - '!extensions/**/syntaxes/**', - '!extensions/**/themes/**', -]); -gulp.task('whitespace-style', function() { - return gulp.src(WHITESPACE_FILES).pipe(style({complain:true, whitespace:true})); -}); -gulp.task('fix-whitespace-style', function() { - return gulp.src(WHITESPACE_FILES, { base: '.' }).pipe(style({whitespace:true})).pipe(gulp.dest('.')); -}); - -var COPYRIGHTS_FILES = WHITESPACE_FILES.concat([ - '!**/*.json', - '!**/*.html', - '!**/test/**', - '!**/*.md', - '!**/*.sh', - '!**/*.txt', - '!src/vs/editor/standalone-languages/swift.ts', -]); -gulp.task('copyrights', function() { - return gulp.src(COPYRIGHTS_FILES, { base: '.' }).pipe(copyrights.copyrights()); -}); - -gulp.task('insert-copyrights', function() { - return gulp.src(COPYRIGHTS_FILES, { base: '.' }).pipe(copyrights.insertCopyrights()); -}); - gulp.task('test', function () { return gulp.src('test/all.js') .pipe(mocha({ ui: 'tdd', delay: true })) @@ -215,6 +148,7 @@ gulp.task('mixin', function () { .pipe(gulp.dest('.')); }); +require('./build/gulpfile.hygiene'); require('./build/gulpfile.vscode'); require('./build/gulpfile.editor'); require('./build/gulpfile.plugins'); From 81d560b7cefc4b3034a78ea26e38aa09c58cf91a Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 24 Nov 2015 19:10:33 +0100 Subject: [PATCH 044/588] run gulp hygiene in travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index a18fdb63af4..4c5fbc362c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,6 +33,7 @@ before_install: install: - ./scripts/npm.sh install + - gulp hygiene - gulp electron compile script: From 62db5d86d0392660df955314c42b90e24267b42c Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 24 Nov 2015 19:37:47 +0100 Subject: [PATCH 045/588] damn these tabs --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4c5fbc362c2..27490784144 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,7 @@ before_install: install: - ./scripts/npm.sh install - - gulp hygiene + - gulp hygiene - gulp electron compile script: From cb259e1c4f1c1a3c9f746b471814baca8eb51a64 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 24 Nov 2015 19:43:35 +0100 Subject: [PATCH 046/588] use appveyor --- appveyor.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000000..f53b3ab2fd1 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,12 @@ +environment: + ATOM_SHELL_INTERNAL_RUN_AS_NODE: 1 + +install: + - npm install -g gulp mocha + +build_script: + - .\scripts\npm.bat install + - gulp electron compile + +test_script: + - mocha From 66051fc5f8d78f806d7f6a303ebe00ddb1440efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 24 Nov 2015 19:51:03 +0100 Subject: [PATCH 047/588] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5f405d9a8c2..a89dce5a1ec 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Visual Studio Code - Open Source -[![Build Status](https://travis-ci.org/Microsoft/vscode.svg?branch=master)](https://travis-ci.org/Microsoft/vscode) +[![Build Status](https://travis-ci.org/Microsoft/vscode.svg?branch=master)](https://travis-ci.org/Microsoft/vscode) [![Build status](https://ci.appveyor.com/api/projects/status/6x5o1u291yrvqouo?svg=true)](https://ci.appveyor.com/project/joaomoreno/vscode-6kam5) + [VS Code](http://code.visualstudio.com) is a new type of tool that combines the simplicity of a code editor with what developers need for their core edit-build-debug cycle. Code provides comprehensive editing and debugging support, an extensibility model, and lightweight integration with existing tools. @@ -28,4 +29,4 @@ Many of the core components and extensions to Code live in their own repositorie For a complete list, please see the [Related Projects](https://github.com/Microsoft/vscode/wiki/Related-Projects) page on our wiki. ## License -[MIT](LICENSE.txt) \ No newline at end of file +[MIT](LICENSE.txt) From f63c7a01d4cf8cc3cf073704579201fc72b8fc27 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Tue, 24 Nov 2015 22:45:47 +0100 Subject: [PATCH 048/588] update debug adapters --- extensions/mono-debug/mono-debug.azure.json | 2 +- extensions/node-debug/node-debug.azure.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/mono-debug/mono-debug.azure.json b/extensions/mono-debug/mono-debug.azure.json index 15c1cf4bfb6..087b6ff6123 100644 --- a/extensions/mono-debug/mono-debug.azure.json +++ b/extensions/mono-debug/mono-debug.azure.json @@ -1,6 +1,6 @@ { "account": "monacobuild", "container": "debuggers", - "zip": "757615d/mono-debug.zip", + "zip": "4d200e7/mono-debug.zip", "output": "" } diff --git a/extensions/node-debug/node-debug.azure.json b/extensions/node-debug/node-debug.azure.json index b0853e58a78..a19aae8176a 100644 --- a/extensions/node-debug/node-debug.azure.json +++ b/extensions/node-debug/node-debug.azure.json @@ -1,6 +1,6 @@ { "account": "monacobuild", "container": "debuggers", - "zip": "a7f6203/node-debug.zip", + "zip": "01cab6f/node-debug.zip", "output": "" } From 8a0f53baa4323a74314b046086d115aeda76e611 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 24 Nov 2015 22:47:41 +0100 Subject: [PATCH 049/588] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index a89dce5a1ec..24095f6f5c8 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # Visual Studio Code - Open Source -[![Build Status](https://travis-ci.org/Microsoft/vscode.svg?branch=master)](https://travis-ci.org/Microsoft/vscode) [![Build status](https://ci.appveyor.com/api/projects/status/6x5o1u291yrvqouo?svg=true)](https://ci.appveyor.com/project/joaomoreno/vscode-6kam5) - +[![Build Status](https://travis-ci.org/Microsoft/vscode.svg?branch=master)](https://travis-ci.org/Microsoft/vscode) [![Build status](https://ci.appveyor.com/api/projects/status/njqjjghtcsb3xhje?svg=true)](https://ci.appveyor.com/project/joaomoreno/vscode) [VS Code](http://code.visualstudio.com) is a new type of tool that combines the simplicity of a code editor with what developers need for their core edit-build-debug cycle. Code provides comprehensive editing and debugging support, an extensibility model, and lightweight integration with existing tools. From 4ea2714df890a538b5ecf226aafb044ae1d16582 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2015 08:44:13 +0100 Subject: [PATCH 050/588] add more meaningful api tests --- .../vscode-api-tests/src/editor.test.ts | 39 +++++++++++ extensions/vscode-api-tests/src/index.ts | 3 +- extensions/vscode-api-tests/src/utils.ts | 40 +++++++++++ .../vscode-api-tests/src/window.test.ts | 18 +++-- .../vscode-api-tests/src/workspace.test.ts | 66 +++++++++++++++---- src/vs/workbench/electron-main/main.ts | 9 +++ 6 files changed, 156 insertions(+), 19 deletions(-) create mode 100644 extensions/vscode-api-tests/src/editor.test.ts create mode 100644 extensions/vscode-api-tests/src/utils.ts diff --git a/extensions/vscode-api-tests/src/editor.test.ts b/extensions/vscode-api-tests/src/editor.test.ts new file mode 100644 index 00000000000..0e7bfaf05a0 --- /dev/null +++ b/extensions/vscode-api-tests/src/editor.test.ts @@ -0,0 +1,39 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as assert from 'assert'; +import * as fs from 'fs'; +import * as os from 'os'; +import {workspace, window, Position} from 'vscode'; +import {createRandomFile, deleteFile} from './utils'; +import {join} from 'path'; + +suite("editor tests", () => { + + test('make edit', (done) => { + createRandomFile().then(file => { + return workspace.openTextDocument(file).then(doc => { + return window.showTextDocument(doc).then((editor) => { + return editor.edit((builder) => { + builder.insert(new Position(0, 0), 'Hello World'); + }).then(applied => { + assert.ok(applied); + assert.equal(doc.getText(), 'Hello World'); + assert.ok(doc.isDirty); + + return doc.save().then(saved => { + assert.ok(saved); + assert.ok(!doc.isDirty); + + return deleteFile(file); + }); + }); + }); + }); + }).then(() => done(), (error) => done(error)); + }); +}); \ No newline at end of file diff --git a/extensions/vscode-api-tests/src/index.ts b/extensions/vscode-api-tests/src/index.ts index 84f3fc542f3..512c2794dd6 100644 --- a/extensions/vscode-api-tests/src/index.ts +++ b/extensions/vscode-api-tests/src/index.ts @@ -21,7 +21,8 @@ const testRunner = require('vscode/lib/testrunner'); // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info testRunner.configure({ ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.) - useColors: true // colored output from test results + useColors: true, // colored output from test results + timeout: 10000 }); export= testRunner; \ No newline at end of file diff --git a/extensions/vscode-api-tests/src/utils.ts b/extensions/vscode-api-tests/src/utils.ts new file mode 100644 index 00000000000..23e36c59b6b --- /dev/null +++ b/extensions/vscode-api-tests/src/utils.ts @@ -0,0 +1,40 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as vscode from 'vscode'; +import * as fs from 'fs'; +import * as os from 'os'; +import {join} from 'path'; + +function rndName() { + return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10); +} + +export function createRandomFile(contents = ''): Thenable { + return new Promise((resolve, reject) => { + const tmpFile = join(os.tmpdir(), rndName()); + fs.writeFile(tmpFile, contents, (error) => { + if (error) { + return reject(error); + } + + resolve(vscode.Uri.file(tmpFile)); + }); + }); +} + +export function deleteFile(file: vscode.Uri): Thenable { + return new Promise((resolve, reject) => { + fs.unlink(file.fsPath, (err) => { + if (err) { + reject(err); + } else { + resolve(true); + } + }); + }); +} \ No newline at end of file diff --git a/extensions/vscode-api-tests/src/window.test.ts b/extensions/vscode-api-tests/src/window.test.ts index 7b0a5142702..2de42113ce3 100644 --- a/extensions/vscode-api-tests/src/window.test.ts +++ b/extensions/vscode-api-tests/src/window.test.ts @@ -6,12 +6,18 @@ 'use strict'; import * as assert from 'assert'; -import {window, workspace} from 'vscode'; +import {workspace, window} from 'vscode'; +import {join} from 'path'; -suite("window namespace texts", () => { - - // test('open document fires event', (done) => { - - // }); +suite("window namespace tests", () => { + test('active text editor', (done) => { + workspace.openTextDocument(join(workspace.rootPath, './far.js')).then(doc => { + return window.showTextDocument(doc).then((editor) => { + const active = window.activeTextEditor; + assert.ok(active); + assert.equal(active.document.uri.fsPath, doc.uri.fsPath); + }); + }).then(() => done(), (error) => done(error)); + }); }); \ No newline at end of file diff --git a/extensions/vscode-api-tests/src/workspace.test.ts b/extensions/vscode-api-tests/src/workspace.test.ts index 4a89e6b278a..8b2a17b2af4 100644 --- a/extensions/vscode-api-tests/src/workspace.test.ts +++ b/extensions/vscode-api-tests/src/workspace.test.ts @@ -6,8 +6,15 @@ 'use strict'; import * as assert from 'assert'; -import {workspace, TextDocument} from 'vscode'; +import {workspace, TextDocument, window, Position} from 'vscode'; +import {createRandomFile, deleteFile} from './utils'; import {join} from 'path'; +import * as fs from 'fs'; +import * as os from 'os'; + +function rndName() { + return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10); +} suite('workspace-namespace', () => { @@ -38,17 +45,52 @@ suite('workspace-namespace', () => { }); }); - // test('createTextDocument', done => { + test('events: onDidOpenTextDocument, onDidChangeTextDocument, onDidSaveTextDocument', (done) => { + createRandomFile().then(file => { + let onDidOpenTextDocument = false; + workspace.onDidOpenTextDocument(e => { + assert.equal(e.uri.fsPath, file.fsPath); + onDidOpenTextDocument = true; + }); - // let text = 'Das Pferd isst keinen Reis.' + let onDidChangeTextDocument = false; + workspace.onDidChangeTextDocument(e => { + assert.equal(e.document.uri.fsPath, file.fsPath); + onDidChangeTextDocument = true; + }); - // workspace.createTextDocument(text).then(doc => { - // assert.equal(doc.getText(), text); - // assert.equal(doc.uri.scheme, 'untitled'); - // assert.equal(doc.languageId, 'plaintext'); - // done(); - // }, err => { - // done(err); - // }); - // }); + let onDidSaveTextDocument = false; + workspace.onDidSaveTextDocument(e => { + assert.equal(e.uri.fsPath, file.fsPath); + onDidSaveTextDocument = true; + }); + + return workspace.openTextDocument(file).then(doc => { + return window.showTextDocument(doc).then((editor) => { + return editor.edit((builder) => { + builder.insert(new Position(0, 0), 'Hello World'); + }).then(applied => { + return doc.save().then(saved => { + assert.ok(onDidOpenTextDocument); + assert.ok(onDidChangeTextDocument); + assert.ok(onDidSaveTextDocument); + + return deleteFile(file); + }); + }); + }); + }); + }).then(() => done(), (error) => done(error)); + }); + + test('findFiles', done => { + workspace.findFiles('*.js', null).then((res) => { + assert.equal(res.length, 1); + assert.equal(workspace.asRelativePath(res[0]), '/far.js'); + + done(); + }, err => { + done(err); + }); + }); }); \ No newline at end of file diff --git a/src/vs/workbench/electron-main/main.ts b/src/vs/workbench/electron-main/main.ts index e1f5ca381c5..cbea266a3ed 100644 --- a/src/vs/workbench/electron-main/main.ts +++ b/src/vs/workbench/electron-main/main.ts @@ -190,6 +190,15 @@ function setupIPC(): TPromise { // there's a running instance, let's connect to it return connect(env.mainIPCHandle).then( client => { + + // Tests from CLI require to be the only instance currently (TODO@Ben support multiple instances and output) + if (env.isTestingFromCli) { + const errorMsg = 'Running tests from the command line is currently only supported if no other instance of Code is running.'; + console.error(errorMsg); + + return Promise.wrapError(errorMsg); + } + env.log('Sending env to running instance...'); const service = client.getService('LaunchService', LaunchService); From 1736f67195e7bf4a5276e9a8d0c0d4b74447c4ec Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2015 09:17:58 +0100 Subject: [PATCH 051/588] Adopt latest loader --- src/vs/css.js | 18 ++++++++++++++---- src/vs/loader.js | 23 +++++++++++++++++------ src/vs/nls.js | 11 +++++++++++ src/vs/text.js | 15 +++++++++++++-- 4 files changed, 55 insertions(+), 12 deletions(-) diff --git a/src/vs/css.js b/src/vs/css.js index 7a02c971fee..d3650a5db86 100644 --- a/src/vs/css.js +++ b/src/vs/css.js @@ -2,14 +2,24 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + * Please make sure to make edits in the .ts file at https://github.com/Microsoft/vscode-loader/ + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------*/ /// /// 'use strict'; var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } - __.prototype = b.prototype; - d.prototype = new __(); + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var _cssPluginGlobal = this; var CSSLoaderPlugin; @@ -405,8 +415,8 @@ var CSSLoaderPlugin; CSSLoaderPlugin.Utilities = Utilities; (function () { var cssLoader = null; - var isAtomShell = (typeof process !== 'undefined' && typeof process.versions !== 'undefined' && typeof process.versions['electron'] !== 'undefined'); - if (typeof process !== 'undefined' && process.versions && !!process.versions.node && !isAtomShell) { + var isElectron = (typeof process !== 'undefined' && typeof process.versions !== 'undefined' && typeof process.versions['electron'] !== 'undefined'); + if (typeof process !== 'undefined' && process.versions && !!process.versions.node && !isElectron) { cssLoader = new NodeCSSLoader(); } else if (typeof navigator !== 'undefined' && navigator.userAgent.indexOf('MSIE 9') >= 0) { diff --git a/src/vs/loader.js b/src/vs/loader.js index 75b0afb92fb..5c3e03a7496 100644 --- a/src/vs/loader.js +++ b/src/vs/loader.js @@ -2,6 +2,17 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + * Please make sure to make edits in the .ts file at https://github.com/Microsoft/vscode-loader/ + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------*/ /// 'use strict'; // Limitation: To load jquery through the loader, always require 'jquery' and add a path for it in the loader configuration @@ -1717,7 +1728,7 @@ var AMDLoader; recorder.record(LoaderEventType.NodeBeginEvaluatingScript, scriptSrc); var vmScriptSrc = _this._path.normalize(scriptSrc); // Make the script src friendly towards electron - if (isAtomRenderer) { + if (isElectronRenderer) { var driveLetterMatch = vmScriptSrc.match(/^([a-z])\:(.*)/); if (driveLetterMatch) { vmScriptSrc = driveLetterMatch[1].toUpperCase() + ':' + driveLetterMatch[2]; @@ -1825,11 +1836,11 @@ var AMDLoader; }; return RequireFunc; })(); - var global = _amdLoaderGlobal, hasPerformanceNow = (global.performance && typeof global.performance.now === 'function'), isWebWorker, isAtomRenderer, isAtomMain, isNode, scriptLoader, moduleManager, loaderAvailableTimestamp; + var global = _amdLoaderGlobal, hasPerformanceNow = (global.performance && typeof global.performance.now === 'function'), isWebWorker, isElectronRenderer, isElectronMain, isNode, scriptLoader, moduleManager, loaderAvailableTimestamp; function initVars() { isWebWorker = (typeof global.importScripts === 'function'); - isAtomRenderer = (typeof process !== 'undefined' && typeof process.versions !== 'undefined' && typeof process.versions['electron'] !== 'undefined' && process.type === 'renderer'); - isAtomMain = (typeof process !== 'undefined' && typeof process.versions !== 'undefined' && typeof process.versions['electron'] !== 'undefined' && process.type === 'browser'); + isElectronRenderer = (typeof process !== 'undefined' && typeof process.versions !== 'undefined' && typeof process.versions['electron'] !== 'undefined' && process.type === 'renderer'); + isElectronMain = (typeof process !== 'undefined' && typeof process.versions !== 'undefined' && typeof process.versions['electron'] !== 'undefined' && process.type === 'browser'); isNode = (typeof module !== 'undefined' && !!module.exports); if (isWebWorker) { scriptLoader = new OnlyOnceScriptLoader(new WorkerScriptLoader()); @@ -1893,7 +1904,7 @@ var AMDLoader; global.nodeRequire = nodeRequire; RequireFunc.nodeRequire = nodeRequire; } - if (isNode && !isAtomRenderer) { + if (isNode && !isElectronRenderer) { module.exports = RequireFunc; // These two defs are fore the local closure defined in node in the case that the loader is concatenated define = function () { @@ -1906,7 +1917,7 @@ var AMDLoader; if (typeof global.require !== 'undefined' && typeof global.require !== 'function') { RequireFunc.config(global.require); } - if (!isAtomRenderer) { + if (!isElectronRenderer) { global.define = DefineFunc; } else { diff --git a/src/vs/nls.js b/src/vs/nls.js index d42263bc425..90214658a15 100644 --- a/src/vs/nls.js +++ b/src/vs/nls.js @@ -2,6 +2,17 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + * Please make sure to make edits in the .ts file at https://github.com/Microsoft/vscode-loader/ + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------*/ /// /// 'use strict'; diff --git a/src/vs/text.js b/src/vs/text.js index b363b799e4c..041a4615736 100644 --- a/src/vs/text.js +++ b/src/vs/text.js @@ -2,6 +2,17 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + * Please make sure to make edits in the .ts file at https://github.com/Microsoft/vscode-loader/ + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------*/ /// /// 'use strict'; @@ -164,8 +175,8 @@ var TextLoaderPlugin; TextLoaderPlugin.Utilities = Utilities; (function () { var textLoader = null; - var isAtomShell = (typeof process !== 'undefined' && typeof process.versions !== 'undefined' && typeof process.versions['electron'] !== 'undefined'); - if (typeof process !== 'undefined' && process.versions && !!process.versions.node && !isAtomShell) { + var isElectron = (typeof process !== 'undefined' && typeof process.versions !== 'undefined' && typeof process.versions['electron'] !== 'undefined'); + if (typeof process !== 'undefined' && process.versions && !!process.versions.node && !isElectron) { textLoader = new NodeTextLoader(); } else { From a1c4fd9bfe214252c9e52901bebb13ff4b6a8bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 25 Nov 2015 09:25:03 +0100 Subject: [PATCH 052/588] appveyor: split electron and compile tasks --- appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index f53b3ab2fd1..b8fd60c0062 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,7 +6,8 @@ install: build_script: - .\scripts\npm.bat install - - gulp electron compile + - gulp electron + - gulp compile test_script: - mocha From 916c5245595faba0c0e79f58df5d92b5392f47f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 25 Nov 2015 09:27:02 +0100 Subject: [PATCH 053/588] travis: split electron and compile tasks --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 27490784144..0f2564979cf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,8 @@ before_install: install: - ./scripts/npm.sh install - gulp hygiene - - gulp electron compile + - gulp electron + - gulp compile script: - ./test/run.sh From 52c9c102f8dd1319fe4b27c00d020769dfbcb6c5 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 25 Nov 2015 09:29:48 +0100 Subject: [PATCH 054/588] hygiene: emit file at end --- build/gulpfile.hygiene.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js index 27c3c4fc891..841e139b0ca 100644 --- a/build/gulpfile.hygiene.js +++ b/build/gulpfile.hygiene.js @@ -101,6 +101,8 @@ gulp.task('hygiene', function() { console.error(file.path + ': Missing or bad copyright statement'); errorCount++; } + + this.emit('data', file); }); return gulp.src(eolFilter, { base: '.' }) From 4e0b0b359f08c0acbe55aa9bcf3895672bba7f0d Mon Sep 17 00:00:00 2001 From: Francois Valdy Date: Wed, 25 Nov 2015 09:43:38 +0100 Subject: [PATCH 055/588] Make sure css is fixed as well --- .../parts/debug/browser/media/debug.contribution.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/media/debug.contribution.css b/src/vs/workbench/parts/debug/browser/media/debug.contribution.css index 8df0146cd9e..5f304c48e84 100644 --- a/src/vs/workbench/parts/debug/browser/media/debug.contribution.css +++ b/src/vs/workbench/parts/debug/browser/media/debug.contribution.css @@ -21,7 +21,7 @@ background: rgba(255, 255, 0, 0.7); } -.monaco-editor .debug-focussed-stack-frame-line { +.monaco-editor .debug-focused-stack-frame-line { background: rgba(206, 231, 206, 0.45); } @@ -247,7 +247,7 @@ color: #C586C0; } -.monaco-editor.vs-dark .debug-focussed-stack-frame-line { +.monaco-editor.vs-dark .debug-focused-stack-frame-line { background: rgba(122, 189, 122, 0.3); } From d113d85fd4556522602b4f3b0170c6879a471339 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 25 Nov 2015 09:47:15 +0100 Subject: [PATCH 056/588] fix hygiene --- build/gulpfile.hygiene.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js index 841e139b0ca..3427f3240d2 100644 --- a/build/gulpfile.hygiene.js +++ b/build/gulpfile.hygiene.js @@ -81,8 +81,8 @@ gulp.task('hygiene', function() { .toString('utf8') .split(/\r\n|\r|\n/) .forEach(function(line, i) { - if (line.length === 0) { - // empty lines are OK + if (/^\s*$/.test(line)) { + // empty or whitespace lines are OK } else if (/^[\t]*[^\s]/.test(line)) { // good indent } else if (/^[\t]* \*/.test(line)) { @@ -101,7 +101,7 @@ gulp.task('hygiene', function() { console.error(file.path + ': Missing or bad copyright statement'); errorCount++; } - + this.emit('data', file); }); From b7b97fd8ee625d5157dce808cc62044cad47e5da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 25 Nov 2015 09:49:27 +0100 Subject: [PATCH 057/588] Update .travis.yml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0f2564979cf..d03a3b77e7b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,9 +33,9 @@ before_install: install: - ./scripts/npm.sh install + +script: - gulp hygiene - gulp electron - gulp compile - -script: - ./test/run.sh From e5d7c7a919c9dd174a4cfd225107880961ae2c60 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2015 10:28:53 +0100 Subject: [PATCH 058/588] api tests: cleanup after test run --- .../vscode-api-tests/src/editor.test.ts | 6 +++- extensions/vscode-api-tests/src/utils.ts | 6 ++++ .../vscode-api-tests/src/window.test.ts | 5 ++++ .../vscode-api-tests/src/workspace.test.ts | 28 +++++++++++-------- 4 files changed, 33 insertions(+), 12 deletions(-) diff --git a/extensions/vscode-api-tests/src/editor.test.ts b/extensions/vscode-api-tests/src/editor.test.ts index 0e7bfaf05a0..38a9b1558ef 100644 --- a/extensions/vscode-api-tests/src/editor.test.ts +++ b/extensions/vscode-api-tests/src/editor.test.ts @@ -9,11 +9,15 @@ import * as assert from 'assert'; import * as fs from 'fs'; import * as os from 'os'; import {workspace, window, Position} from 'vscode'; -import {createRandomFile, deleteFile} from './utils'; +import {createRandomFile, deleteFile, cleanUp} from './utils'; import {join} from 'path'; suite("editor tests", () => { + teardown((done) => { + cleanUp().then(() => done(), (error) => done(error)); + }); + test('make edit', (done) => { createRandomFile().then(file => { return workspace.openTextDocument(file).then(doc => { diff --git a/extensions/vscode-api-tests/src/utils.ts b/extensions/vscode-api-tests/src/utils.ts index 23e36c59b6b..060c79d5580 100644 --- a/extensions/vscode-api-tests/src/utils.ts +++ b/extensions/vscode-api-tests/src/utils.ts @@ -37,4 +37,10 @@ export function deleteFile(file: vscode.Uri): Thenable { } }); }); +} + +export function cleanUp(): Thenable { + return vscode.commands.executeCommand('workbench.action.closeAllEditors').then(() => { + return vscode.commands.executeCommand('workbench.files.action.closeAllFiles'); + }); } \ No newline at end of file diff --git a/extensions/vscode-api-tests/src/window.test.ts b/extensions/vscode-api-tests/src/window.test.ts index 2de42113ce3..0f3ba712cd3 100644 --- a/extensions/vscode-api-tests/src/window.test.ts +++ b/extensions/vscode-api-tests/src/window.test.ts @@ -8,9 +8,14 @@ import * as assert from 'assert'; import {workspace, window} from 'vscode'; import {join} from 'path'; +import {cleanUp} from './utils'; suite("window namespace tests", () => { + teardown((done) => { + cleanUp().then(() => done(), (error) => done(error)); + }); + test('active text editor', (done) => { workspace.openTextDocument(join(workspace.rootPath, './far.js')).then(doc => { return window.showTextDocument(doc).then((editor) => { diff --git a/extensions/vscode-api-tests/src/workspace.test.ts b/extensions/vscode-api-tests/src/workspace.test.ts index 8b2a17b2af4..5925e579fbc 100644 --- a/extensions/vscode-api-tests/src/workspace.test.ts +++ b/extensions/vscode-api-tests/src/workspace.test.ts @@ -7,17 +7,17 @@ import * as assert from 'assert'; import {workspace, TextDocument, window, Position} from 'vscode'; -import {createRandomFile, deleteFile} from './utils'; +import {createRandomFile, deleteFile, cleanUp} from './utils'; import {join} from 'path'; import * as fs from 'fs'; import * as os from 'os'; -function rndName() { - return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10); -} - suite('workspace-namespace', () => { + teardown((done) => { + cleanUp().then(() => done(), (error) => done(error)); + }); + test('textDocuments', () => { assert.ok(Array.isArray(workspace.textDocuments)); assert.throws(() => workspace.textDocuments = null); @@ -47,23 +47,25 @@ suite('workspace-namespace', () => { test('events: onDidOpenTextDocument, onDidChangeTextDocument, onDidSaveTextDocument', (done) => { createRandomFile().then(file => { + let disposables = []; + let onDidOpenTextDocument = false; - workspace.onDidOpenTextDocument(e => { + disposables.push(workspace.onDidOpenTextDocument(e => { assert.equal(e.uri.fsPath, file.fsPath); onDidOpenTextDocument = true; - }); + })); let onDidChangeTextDocument = false; - workspace.onDidChangeTextDocument(e => { + disposables.push(workspace.onDidChangeTextDocument(e => { assert.equal(e.document.uri.fsPath, file.fsPath); onDidChangeTextDocument = true; - }); + })); let onDidSaveTextDocument = false; - workspace.onDidSaveTextDocument(e => { + disposables.push(workspace.onDidSaveTextDocument(e => { assert.equal(e.uri.fsPath, file.fsPath); onDidSaveTextDocument = true; - }); + })); return workspace.openTextDocument(file).then(doc => { return window.showTextDocument(doc).then((editor) => { @@ -75,6 +77,10 @@ suite('workspace-namespace', () => { assert.ok(onDidChangeTextDocument); assert.ok(onDidSaveTextDocument); + while (disposables.length) { + disposables.pop().dispose(); + } + return deleteFile(file); }); }); From 90ace5d47906974e16d82bcd5d471a89f37bb2ec Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2015 10:41:46 +0100 Subject: [PATCH 059/588] fixes #115 --- src/vs/editor/common/modes/lineStream.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vs/editor/common/modes/lineStream.ts b/src/vs/editor/common/modes/lineStream.ts index 608b5aad7ff..b340ab62cb5 100644 --- a/src/vs/editor/common/modes/lineStream.ts +++ b/src/vs/editor/common/modes/lineStream.ts @@ -40,15 +40,15 @@ export class LineStream implements IStream { } private actualStringToArray(str:string):boolean[] { - var maxCharCode = 0; - for (var i = 0; i < str.length; i++) { - maxCharCode = str.charCodeAt(i); + let maxCharCode = 0; + for (let i = 0; i < str.length; i++) { + maxCharCode = Math.max(maxCharCode, str.charCodeAt(i)); } - var r = []; - for (i = 0; i < maxCharCode; i++) { + let r:boolean[] = []; + for (let i = 0; i <= maxCharCode; i++) { r[i] = false; } - for (i = 0; i < str.length; i++) { + for (let i = 0; i < str.length; i++) { r[str.charCodeAt(i)] = true; } return r; From 53644525befb95f094c17681dcd4ce90a48b524f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 25 Nov 2015 10:45:28 +0100 Subject: [PATCH 060/588] use --force when running npm install on Appveyor --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index b8fd60c0062..a88d64c6161 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,7 +5,7 @@ install: - npm install -g gulp mocha build_script: - - .\scripts\npm.bat install + - .\scripts\npm.bat install --force - gulp electron - gulp compile From 7754743a7e0860d8b8e0096ef544a72371695c1d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2015 10:58:13 +0100 Subject: [PATCH 061/588] api tests: allow to run and debug them --- extensions/tsconfig.json | 3 +- .../vscode-api-tests/.vscode/launch.json | 17 +++++++++++ .../vscode-api-tests/.vscode/tasks.json | 30 +++++++++++++++++++ extensions/vscode-api-tests/package.json | 2 ++ 4 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 extensions/vscode-api-tests/.vscode/launch.json create mode 100644 extensions/vscode-api-tests/.vscode/tasks.json diff --git a/extensions/tsconfig.json b/extensions/tsconfig.json index 36f6ef5e85c..379cfd01b07 100644 --- a/extensions/tsconfig.json +++ b/extensions/tsconfig.json @@ -11,6 +11,7 @@ "typescript/src/lib", "typescript/out/lib", "jshint", - "csharp-o" + "csharp-o", + "vscode-api-tests/node_modules" ] } \ No newline at end of file diff --git a/extensions/vscode-api-tests/.vscode/launch.json b/extensions/vscode-api-tests/.vscode/launch.json new file mode 100644 index 00000000000..b6ed0f7a674 --- /dev/null +++ b/extensions/vscode-api-tests/.vscode/launch.json @@ -0,0 +1,17 @@ +// A launch configuration that compiles the extension and then opens it inside a new window +{ + "version": "0.1.0", + "configurations": [ + { + "name": "Launch Tests", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": ["${workspaceRoot}/../../", "${workspaceRoot}/testWorkspace", "--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out" ], + "stopOnEntry": false, + "sourceMaps": true, + "outDir": "out", + "preLaunchTask": "npm" + } + ] +} \ No newline at end of file diff --git a/extensions/vscode-api-tests/.vscode/tasks.json b/extensions/vscode-api-tests/.vscode/tasks.json new file mode 100644 index 00000000000..d31b15910ee --- /dev/null +++ b/extensions/vscode-api-tests/.vscode/tasks.json @@ -0,0 +1,30 @@ +// Available variables which can be used inside of strings. +// ${workspaceRoot}: the root folder of the team +// ${file}: the current opened file +// ${fileBasename}: the current opened file's basename +// ${fileDirname}: the current opened file's dirname +// ${fileExtname}: the current opened file's extension +// ${cwd}: the current working directory of the spawned process + +// A task runner that calls a custom npm script that compiles the extension. +{ + "version": "0.1.0", + + // we want to run npm + "command": "npm", + + // the command is a shell script + "isShellCommand": true, + + // show the output window only if unrecognized errors occur. + "showOutput": "silent", + + // we run the custom script "compile" as defined in package.json + "args": ["run", "compile", "--loglevel", "silent"], + + // The tsc compiler is started in watching mode + "isWatching": true, + + // use the standard tsc in watch mode problem matcher to find compile problems in the output. + "problemMatcher": "$tsc-watch" +} \ No newline at end of file diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index 20e6ba7de8d..8b6055b5822 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -8,9 +8,11 @@ "vscode": "*" }, "scripts": { + "compile": "node ./node_modules/vscode/bin/compile -watch -p ./", "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../gulpfile.plugins.js compile-plugin:vscode-api-tests ./tsconfig.json" }, "devDependencies": { + "typescript": "^1.6.2", "vscode": "next" } } \ No newline at end of file From 6ea319fa68201e80fb194b6cb41df95051bdc8ae Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2015 11:00:40 +0100 Subject: [PATCH 062/588] move the logic of getOutlineEntries into one place --- .../contrib/quickOpen/common/quickOpen.ts | 63 ++++++++++++++++++- .../workbench/api/common/languageFeatures.ts | 8 +-- .../quickopen/browser/gotoSymbolHandler.ts | 33 +--------- .../test/common/api/languageFeatures.test.ts | 14 ++--- 4 files changed, 75 insertions(+), 43 deletions(-) diff --git a/src/vs/editor/contrib/quickOpen/common/quickOpen.ts b/src/vs/editor/contrib/quickOpen/common/quickOpen.ts index cf5c24c299e..b4e2dc1c9ea 100644 --- a/src/vs/editor/contrib/quickOpen/common/quickOpen.ts +++ b/src/vs/editor/contrib/quickOpen/common/quickOpen.ts @@ -5,14 +5,73 @@ 'use strict'; +import {onUnexpectedError} from 'vs/base/common/errors'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {Range} from 'vs/editor/common/core/range'; +import {IModel} from 'vs/editor/common/editorCommon'; import {IOutlineEntry, IOutlineSupport} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; -const QuickOutineRegistry = new LanguageFeatureRegistry('outlineSupport'); +const OutlineRegistry = new LanguageFeatureRegistry('outlineSupport'); export { + OutlineRegistry, IOutlineEntry, IOutlineSupport } -export default QuickOutineRegistry; \ No newline at end of file +export function getOutlineEntries(model: IModel): TPromise<{ entries: IOutlineEntry[], outlineGroupLabel: { [n: string]: string;} }> { + + let resource = model.getAssociatedResource(); + let groupLabels: { [n: string]: string } = Object.create(null); + let entries: IOutlineEntry[] = []; + + let promises = OutlineRegistry.all(model).map(support => { + + if (support.outlineGroupLabel) { + for (var key in support.outlineGroupLabel) { + if (Object.prototype.hasOwnProperty.call(support.outlineGroupLabel, key)) { + groupLabels[key] = support.outlineGroupLabel[key]; + } + } + } + + return support.getOutline(resource).then(result => { + if (Array.isArray(result)) { + entries.push(...result); + } + }, err => { + onUnexpectedError(err); + }); + }); + + return TPromise.join(promises).then(() => { + let flatEntries: IOutlineEntry[] = []; + flatten(flatEntries, entries, ''); + flatEntries.sort(compareEntriesUsingStart); + + return { + entries: flatEntries, + outlineGroupLabel: groupLabels + } + }); +} + +function compareEntriesUsingStart(a: IOutlineEntry, b: IOutlineEntry): number{ + return Range.compareRangesUsingStarts(a.range, b.range); +} + +function flatten(bucket: IOutlineEntry[], entries: IOutlineEntry[], overrideContainerLabel: string): void { + for (let entry of entries) { + bucket.push({ + type: entry.type, + range: entry.range, + label: entry.label, + icon: entry.icon, + containerLabel: entry.containerLabel || overrideContainerLabel + }); + if (entry.children) { + flatten(bucket, entry.children, entry.label); + } + } +} diff --git a/src/vs/workbench/api/common/languageFeatures.ts b/src/vs/workbench/api/common/languageFeatures.ts index b5caf5ddbd2..4fa0fb5ffc7 100644 --- a/src/vs/workbench/api/common/languageFeatures.ts +++ b/src/vs/workbench/api/common/languageFeatures.ts @@ -27,7 +27,7 @@ import ExtraInfoRegistry from 'vs/editor/contrib/hover/common/hover'; import DocumentHighlighterRegistry from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; import ReferenceSearchRegistry from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; import QuickFixRegistry from 'vs/editor/contrib/quickFix/common/quickFix'; -import QuickOutlineRegistry, {IOutlineEntry, IOutlineSupport} from 'vs/editor/contrib/quickOpen/common/quickOpen'; +import {OutlineRegistry, IOutlineEntry, IOutlineSupport} from 'vs/editor/contrib/quickOpen/common/quickOpen'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import {NavigateTypesSupportRegistry, INavigateTypesSupport, ITypeBearing} from 'vs/workbench/parts/search/common/search' import {RenameRegistry} from 'vs/editor/contrib/rename/common/rename'; @@ -544,7 +544,7 @@ export class ExtensionHostDocumentSymbols extends AbstractExtensionHostFeature implements IOutlineSupport { constructor( @IThreadService threadService: IThreadService) { - super('vscode.executeDocumentSymbolProvider', QuickOutlineRegistry, threadService); + super('vscode.executeDocumentSymbolProvider', OutlineRegistry, threadService); } getOutline(resource: URI): TPromise{ @@ -1262,7 +1262,7 @@ export namespace LanguageFeatures { threadService.getRemotable(MainThreadReferenceSearch); threadService.getRemotable(MainThreadCodeActions); threadService.getRemotable(MainThreadCodeLens); - threadService.getRemotable(MainThreadDocumentSymbols); + // threadService.getRemotable(MainThreadDocumentSymbols); threadService.getRemotable(MainThreadWorkspaceSymbols); threadService.getRemotable(MainThreadRename); threadService.getRemotable(MainThreadFormatDocument); @@ -1280,7 +1280,7 @@ export namespace LanguageFeatures { referenceSearch: new ExtensionHostReferenceSearch(threadService), codeActions: new ExtensionHostCodeActions(threadService), codeLens: threadService.getRemotable(ExtensionHostCodeLens), - documentSymbols: new ExtensionHostDocumentSymbols(threadService), + // documentSymbols: new ExtensionHostDocumentSymbols(threadService), workspaceSymbols: new ExtensionHostWorkspaceSymbols(threadService), rename: new ExtensionHostRename(threadService), formatDocument: new ExtHostFormatDocument(threadService), diff --git a/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts b/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts index 046dd4cc8d6..576ce3f82c2 100644 --- a/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts +++ b/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts @@ -31,7 +31,7 @@ import {IQuickOpenService} from 'vs/workbench/services/quickopen/browser/quickOp import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {Position} from 'vs/platform/editor/common/editor'; import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; -import QuickOpenRegistry from 'vs/editor/contrib/quickOpen/common/quickOpen'; +import {OutlineRegistry, getOutlineEntries} from 'vs/editor/contrib/quickOpen/common/quickOpen'; const ACTION_ID = 'workbench.action.gotoSymbol'; const ACTION_LABEL = nls.localize('gotoSymbol', "Go to Symbol..."); @@ -432,7 +432,7 @@ export class GotoSymbolHandler extends QuickOpenHandler { if (model && types.isFunction((model).getMode)) { - canRun = QuickOpenRegistry.has( model); + canRun = OutlineRegistry.has( model); } } @@ -527,34 +527,7 @@ export class GotoSymbolHandler extends QuickOpenHandler { return TPromise.as(this.outlineToModelCache[modelId]); } - let groupLabels: { [n: string]: string } = Object.create(null); - let entries: IOutlineEntry[] = []; - let resource = (model).getAssociatedResource(); - let promises = QuickOpenRegistry.all(model).map(support => { - - if (support.outlineGroupLabel) { - for (var key in support.outlineGroupLabel) { - if (Object.prototype.hasOwnProperty.call(support.outlineGroupLabel, key)) { - groupLabels[key] = support.outlineGroupLabel[key]; - } - } - } - - return support.getOutline(resource).then(result => { - if (Array.isArray(result)) { - entries.push(...result); - } - }, err => { - errors.onUnexpectedError(err); - }); - }); - - return TPromise.join(promises).then(() => { - - let outline = { - entries, - outlineGroupLabel: groupLabels - }; + return getOutlineEntries(model).then(outline => { let model = new OutlineModel(outline, this.toQuickOpenEntries(outline)); diff --git a/src/vs/workbench/test/common/api/languageFeatures.test.ts b/src/vs/workbench/test/common/api/languageFeatures.test.ts index 5ea693041f9..bf6a92187e6 100644 --- a/src/vs/workbench/test/common/api/languageFeatures.test.ts +++ b/src/vs/workbench/test/common/api/languageFeatures.test.ts @@ -18,7 +18,7 @@ import * as LF from 'vs/workbench/api/common/languageFeatures'; import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; import {SyncDescriptor0} from 'vs/platform/instantiation/common/descriptors'; -import QuickOutlineRegistry from 'vs/editor/contrib/quickOpen/common/quickOpen'; +import {OutlineRegistry} from 'vs/editor/contrib/quickOpen/common/quickOpen'; import {LanguageSelector, ModelLike} from 'vs/editor/common/modes/languageSelector'; class ThreadService extends NullThreadService { @@ -85,17 +85,17 @@ suite('ExtHostLanguageFeatures', function() { // register - assert.equal(QuickOutlineRegistry.all(model).length, 0); + assert.equal(OutlineRegistry.all(model).length, 0); let disposable = extHost.register('far', { provideDocumentSymbols() { return []; } }); - assert.equal(QuickOutlineRegistry.all(model).length, 1); + assert.equal(OutlineRegistry.all(model).length, 1); // deregister disposable.dispose(); - assert.equal(QuickOutlineRegistry.all(model).length, 0); + assert.equal(OutlineRegistry.all(model).length, 0); // all extension host provider appear as one disposable = extHost.register('far', { @@ -108,12 +108,12 @@ suite('ExtHostLanguageFeatures', function() { return []; } }); - assert.equal(QuickOutlineRegistry.all(model).length, 1); + assert.equal(OutlineRegistry.all(model).length, 1); disposable.dispose(); - assert.equal(QuickOutlineRegistry.all(model).length, 1); + assert.equal(OutlineRegistry.all(model).length, 1); disposable2.dispose(); - assert.equal(QuickOutlineRegistry.all(model).length, 0); + assert.equal(OutlineRegistry.all(model).length, 0); }); test('DocumentSymbols, evil provider', function(done) { From b370792f68b5ea1b62932231f4643ce02db7b74b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2015 11:01:38 +0100 Subject: [PATCH 063/588] fix document symbol duplication each provider is represented as one support, have a provider to support adapter --- .../api/browser/pluginHost.api.impl.ts | 4 +- .../api/common/extHostLanguageFeatures.ts | 160 ++++++++++++++++++ src/vs/workbench/electron-browser/shell.ts | 2 + 3 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 src/vs/workbench/api/common/extHostLanguageFeatures.ts diff --git a/src/vs/workbench/api/browser/pluginHost.api.impl.ts b/src/vs/workbench/api/browser/pluginHost.api.impl.ts index 3364186808d..a7556ab7512 100644 --- a/src/vs/workbench/api/browser/pluginHost.api.impl.ts +++ b/src/vs/workbench/api/browser/pluginHost.api.impl.ts @@ -22,6 +22,7 @@ import {PluginHostMessageService} from 'vs/workbench/api/common/pluginHostMessag import {PluginHostTelemetryService} from 'vs/workbench/api/common/pluginHostTelemetry'; import {PluginHostEditors} from 'vs/workbench/api/common/pluginHostEditors'; import {ExtHostLanguages} from 'vs/workbench/api/common/extHostLanguages'; +import {ExtHostLanguageFeatures} from 'vs/workbench/api/common/extHostLanguageFeatures'; import * as extHostTypes from 'vs/workbench/api/common/pluginHostTypes'; import 'vs/workbench/api/common/pluginHostTypes.marshalling'; import {wrapAsWinJSPromise} from 'vs/base/common/async'; @@ -251,6 +252,7 @@ export class PluginHostAPIImplementation { const languages = new ExtHostLanguages(this._threadService); const pluginHostDiagnostics = new PluginHostDiagnostics(this._threadService); const features = LanguageFeatures.createExtensionHostInstances(this._threadService); + const languageFeatures = threadService.getRemotable(ExtHostLanguageFeatures); this.languages = { createDiagnosticCollection(name?: string): vscode.DiagnosticCollection { @@ -284,7 +286,7 @@ export class PluginHostAPIImplementation { return features.rename.register(selector, provider); }, registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable { - return features.documentSymbols.register(selector, provider); + return languageFeatures.registerDocumentSymbolProvider(selector, provider); }, registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable { return features.workspaceSymbols.register(provider); diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts new file mode 100644 index 00000000000..d99e870d0e5 --- /dev/null +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -0,0 +1,160 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import URI from 'vs/base/common/uri'; +import Event, {Emitter} from 'vs/base/common/event'; +import Severity from 'vs/base/common/severity'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {sequence} from 'vs/base/common/async'; +import {Range as EditorRange} from 'vs/editor/common/core/range'; +import {IDisposable} from 'vs/base/common/lifecycle'; +import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; +import {Remotable, IThreadService} from 'vs/platform/thread/common/thread'; +import * as vscode from 'vscode'; +import * as TypeConverters from 'vs/workbench/api/common/pluginHostTypeConverters'; +import {Position, Range, SymbolKind, DocumentHighlightKind, Disposable, Diagnostic, DiagnosticSeverity, Location, SignatureHelp, CompletionItemKind} from 'vs/workbench/api/common/pluginHostTypes'; +import {IPosition, IRange, ISingleEditOperation} from 'vs/editor/common/editorCommon'; +import * as modes from 'vs/editor/common/modes'; +import {CancellationTokenSource} from 'vs/base/common/cancellation'; +import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; +import {IMarkerService, IMarker} from 'vs/platform/markers/common/markers'; +import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; +import DeclarationRegistry from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; +import ExtraInfoRegistry from 'vs/editor/contrib/hover/common/hover'; +import DocumentHighlighterRegistry from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; +import ReferenceSearchRegistry from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; +import QuickFixRegistry from 'vs/editor/contrib/quickFix/common/quickFix'; +import {OutlineRegistry, IOutlineEntry, IOutlineSupport} from 'vs/editor/contrib/quickOpen/common/quickOpen'; +import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; +import {NavigateTypesSupportRegistry, INavigateTypesSupport, ITypeBearing} from 'vs/workbench/parts/search/common/search' +import {RenameRegistry} from 'vs/editor/contrib/rename/common/rename'; +import {FormatRegistry, FormatOnTypeRegistry} from 'vs/editor/contrib/format/common/format'; +import {CodeLensRegistry} from 'vs/editor/contrib/codelens/common/codelens'; +import {ParameterHintsRegistry} from 'vs/editor/contrib/parameterHints/common/parameterHints'; +import {SuggestRegistry} from 'vs/editor/contrib/suggest/common/suggest'; + +function isThenable(obj: any): obj is Thenable { + return obj && typeof obj['then'] === 'function'; +} + +function asWinJsPromise(callback: (token: vscode.CancellationToken) => T | Thenable): TPromise { + let source = new CancellationTokenSource(); + return new TPromise((resolve, reject) => { + let item = callback(source.token); + if (isThenable(item)) { + item.then(resolve, reject); + } else { + resolve(item); + } + }, () => { + source.cancel(); + }); +} + +// --- adapter + +class OutlineSupportAdapter implements IOutlineSupport { + + private _documents: PluginHostModelService; + private _provider: vscode.DocumentSymbolProvider; + + constructor(documents: PluginHostModelService, provider: vscode.DocumentSymbolProvider) { + this._documents = documents; + this._provider = provider; + } + + getOutline(resource: URI): TPromise { + let doc = this._documents.getDocument(resource); + return asWinJsPromise(token => this._provider.provideDocumentSymbols(doc, token)).then(value => { + if (Array.isArray(value)) { + return value.map(OutlineSupportAdapter._convertSymbolInfo); + } + }); + } + + private static _convertSymbolInfo(symbol: vscode.SymbolInformation): IOutlineEntry { + return { + type: TypeConverters.fromSymbolKind(symbol.kind), + range: TypeConverters.fromRange(symbol.location.range), + containerLabel: symbol.containerName, + label: symbol.name, + icon: undefined, + }; + } +} + +type Adapter = OutlineSupportAdapter; + +@Remotable.PluginHostContext('ExtHostLanguageFeatures') +export class ExtHostLanguageFeatures { + + private static _handlePool = 0; + + private _proxy: MainThreadLanguageFeatures; + private _documents: PluginHostModelService; + private _adapter: { [handle: number]: Adapter } = Object.create(null); + + constructor( @IThreadService threadService: IThreadService) { + this._proxy = threadService.getRemotable(MainThreadLanguageFeatures); + this._documents = threadService.getRemotable(PluginHostModelService); + } + + private _createDisposable(handle: number): Disposable { + return new Disposable(() => { + delete this._adapter[handle]; + this._proxy.$unregister(handle); + }); + } + + // --- outline + + registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable { + const handle = ExtHostLanguageFeatures._handlePool++; + this._proxy.$registerOutlineSupport(handle, selector); + this._adapter[handle] = new OutlineSupportAdapter(this._documents, provider); + return this._createDisposable(handle); + } + + $getOutline(handle: number, resource: URI): TPromise{ + let adapter = this._adapter[handle]; + if (adapter instanceof OutlineSupportAdapter) { + return adapter.getOutline(resource); + } + return TPromise.wrapError(new Error('no adapter found')); + } +} + +@Remotable.MainContext('MainThreadLanguageFeatures') +export class MainThreadLanguageFeatures { + + private _proxy: ExtHostLanguageFeatures; + private _disposables: { [handle: number]: IDisposable; } = Object.create(null); + + constructor( @IThreadService threadService: IThreadService) { + this._proxy = threadService.getRemotable(ExtHostLanguageFeatures); + } + + $unregister(handle: number): TPromise { + let d = this._disposables[handle]; + if (d) { + d.dispose(); + delete this._disposables[handle]; + } + return undefined; + } + + // --- outline + + $registerOutlineSupport(handle: number, selector: vscode.DocumentSelector): TPromise { + let disposable = OutlineRegistry.register(selector, { + getOutline: (resource: URI): TPromise => { + return this._proxy.$getOutline(handle, resource); + } + }); + this._disposables[handle] = disposable; + return undefined; + } +} \ No newline at end of file diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index cd3566cd7d5..67d448b965c 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -68,6 +68,7 @@ import {MainThreadEditors} from 'vs/workbench/api/common/pluginHostEditors'; import {MainThreadWorkspace} from 'vs/workbench/api/browser/pluginHostWorkspace'; import {MainThreadConfiguration} from 'vs/workbench/api/common/pluginHostConfiguration'; import {LanguageFeatures} from 'vs/workbench/api/common/languageFeatures'; +import {MainThreadLanguageFeatures} from 'vs/workbench/api/common/extHostLanguageFeatures'; import {EventService} from 'vs/platform/event/common/eventService'; import {IOptions} from 'vs/workbench/common/options'; import themes = require('vs/platform/theme/common/themes'); @@ -337,6 +338,7 @@ export class WorkbenchShell { this.threadServiceInstance.getRemotable(MainThreadWorkspace); this.threadServiceInstance.getRemotable(MainThreadEditors); this.threadServiceInstance.getRemotable(MainThreadStorage); + this.threadServiceInstance.getRemotable(MainThreadLanguageFeatures); LanguageFeatures.createMainThreadInstances(this.threadServiceInstance); } From c37136730f3eeddd091c43b0cff78f60a4fbe4b5 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 25 Nov 2015 11:09:23 +0100 Subject: [PATCH 064/588] [json] 'JSON with comments' text mate bundle --- extensions/json/OSSREADME.json | 21 +-- extensions/json/package.json | 2 +- extensions/json/syntaxes/JSON.tmLanguage | 159 +++++++++++++++++------ 3 files changed, 124 insertions(+), 58 deletions(-) diff --git a/extensions/json/OSSREADME.json b/extensions/json/OSSREADME.json index 2d12a69da84..aa2ec19ee33 100644 --- a/extensions/json/OSSREADME.json +++ b/extensions/json/OSSREADME.json @@ -1,22 +1,7 @@ // ATTENTION - THIS DIRECTORY CONTAINS THIRD PARTY OPEN SOURCE MATERIALS: [{ - "name": "textmate/json.tmbundle", + "name": "Benvie/JavaScriptNext.tmLanguage", "version": "0.0.0", - "license": "TextMate Bundle License", - "repositoryURL": "https://github.com/textmate/json.tmbundle", - "licenseDetail": [ - "Copyright (c) textmate-json.tmbundle project authors", - "", - "If not otherwise specified (see below), files in this repository fall under the following license:", - "", - "Permission to copy, use, modify, sell and distribute this", - "software is granted. This software is provided \"as is\" without", - "express or implied warranty, and with no claim as to its", - "suitability for any purpose.", - "", - "An exception is made for files in readable text which contain their own license information,", - "or files where an accompanying file exists (in the same directory) with a \"-license\" suffix added", - "to the base-name name of the original file, and an extension of txt, html, or similar. For example", - "\"tidy\" is accompanied by \"tidy-license.txt\"." - ] + "license": "MIT", + "repositoryURL": "https://github.com/Benvie/JavaScriptNext.tmLanguage" }] diff --git a/extensions/json/package.json b/extensions/json/package.json index b68380b554f..983a0480e4b 100644 --- a/extensions/json/package.json +++ b/extensions/json/package.json @@ -11,7 +11,7 @@ "mimetypes": ["application/json"] }], "grammars": [{ - // "language": "json" : commented out for now, will add once we have rule for comments + // "language": "json" : commented out for now "scopeName": "source.json", "path": "./syntaxes/JSON.tmLanguage" }] diff --git a/extensions/json/syntaxes/JSON.tmLanguage b/extensions/json/syntaxes/JSON.tmLanguage index b158162b2a7..539d1416cbd 100644 --- a/extensions/json/syntaxes/JSON.tmLanguage +++ b/extensions/json/syntaxes/JSON.tmLanguage @@ -1,15 +1,44 @@ - + fileTypes json + sublime-settings + sublime-menu + sublime-keymap + sublime-mousemap + sublime-theme + sublime-build + sublime-project + sublime-completions + foldingStartMarker + (?x) # turn on extended mode + ^ # a line beginning with + \s* # some optional space + [{\[] # the start of an object or array + (?! # but not followed by + .* # whatever + [}\]] # and the close of an object or array + ,? # an optional comma + \s* # some optional space + $ # at the end of the line + ) + | # ...or... + [{\[] # the start of an object or array + \s* # some optional space + $ # at the end of the line + foldingStopMarker + (?x) # turn on extended mode + ^ # a line beginning with + \s* # some optional space + [}\]] # and the close of an object or array keyEquivalent ^~J name - JSON + JSON (Javascript Next) patterns @@ -63,6 +92,58 @@ + comments + + patterns + + + begin + /\*\* + captures + + 0 + + name + punctuation.definition.comment.json + + + end + \*/ + name + comment.block.documentation.json + + + begin + /\* + captures + + 0 + + name + punctuation.definition.comment.json + + + end + \*/ + name + comment.block.json + + + captures + + 1 + + name + punctuation.definition.comment.json + + + match + (//).*$\n? + name + comment.line.double-slash.js + + + constant match @@ -72,29 +153,26 @@ number - comment - handles integer and decimal numbers match - (?x: # turn on extended mode - -? # an optional minus - (?: - 0 # a zero - | # ...or... - [1-9] # a 1-9 character - \d* # followed by zero or more digits - ) - (?: - (?: - \. # a period - \d+ # followed by one or more digits - )? - (?: - [eE] # an e character - [+-]? # followed by an option +/- - \d+ # followed by one or more digits - )? # make exponent optional - )? # make decimal portion optional - ) + (?x) # turn on extended mode + -? # an optional minus + (?: + 0 # a zero + | # ...or... + [1-9] # a 1-9 character + \d* # followed by zero or more digits + ) + (?: + (?: + \. # a period + \d+ # followed by one or more digits + )? + (?: + [eE] # an e character + [+-]? # followed by an option +/- + \d+ # followed by one or more digits + )? # make exponent optional + )? # make decimal portion optional name constant.numeric.json @@ -110,8 +188,6 @@ punctuation.definition.dictionary.begin.json - comment - a JSON object end \} endCaptures @@ -132,6 +208,10 @@ include #string + + include + #comments + begin : @@ -207,15 +287,13 @@ match - (?x: # turn on extended mode - \\ # a literal backslash - (?: # ...followed by... - ["\\/bfnrt] # one of these characters - | # ...or... - u # a u - [0-9a-fA-F]{4} # and four hex digits - ) - ) + (?x) # turn on extended mode + \\ # a literal backslash + (?: # ...followed by... + ["\\/bfnrt] # one of these characters + | # ...or... + u # a u + [0-9a-fA-F]{4}) # and four hex digits name constant.character.escape.json @@ -229,8 +307,6 @@ value - comment - the 'value' diagram at http://json.org patterns @@ -253,12 +329,17 @@ include #object + + include + #comments + scopeName source.json uuid - 0C3868E4-F96B-4E55-B204-1DCB5A20748B + 8f97457b-516e-48ce-83c7-08ae12fb327a - \ No newline at end of file + + From aba9d6bf3f8140d1f8cfe2eb06553ba696f83910 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 25 Nov 2015 11:55:52 +0100 Subject: [PATCH 065/588] better cleanup for api tests --- extensions/vscode-api-tests/src/utils.ts | 39 +++++++++++++++++-- .../vscode-api-tests/src/workspace.test.ts | 11 ++---- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/extensions/vscode-api-tests/src/utils.ts b/extensions/vscode-api-tests/src/utils.ts index 060c79d5580..3dbfdd77365 100644 --- a/extensions/vscode-api-tests/src/utils.ts +++ b/extensions/vscode-api-tests/src/utils.ts @@ -5,6 +5,7 @@ 'use strict'; +import * as assert from 'assert'; import * as vscode from 'vscode'; import * as fs from 'fs'; import * as os from 'os'; @@ -39,8 +40,40 @@ export function deleteFile(file: vscode.Uri): Thenable { }); } -export function cleanUp(): Thenable { - return vscode.commands.executeCommand('workbench.action.closeAllEditors').then(() => { - return vscode.commands.executeCommand('workbench.files.action.closeAllFiles'); +export function cleanUp(): Thenable { + return new Promise((c, e) => { + if (vscode.window.visibleTextEditors.length === 0) { + return c(); + } + + // TODO: the visibleTextEditors variable doesn't seem to be + // up to date after a onDidChangeActiveTextEditor event, not + // even using a setTimeout 0... so we MUST poll :( + const interval = setInterval(() => { + if (vscode.window.visibleTextEditors.length > 0) { + return; + } + + clearInterval(interval); + c(); + }, 10); + + vscode.commands.executeCommand('workbench.action.closeAllEditors') + .then(() => vscode.commands.executeCommand('workbench.files.action.closeAllFiles')) + .then(null, err => { + clearInterval(interval); + e(err); + }); + }).then(() => { + assert.equal(vscode.window.visibleTextEditors.length, 0); + assert(!vscode.window.activeTextEditor); + + // TODO: we can't yet make this assertion because when + // the phost creates a document and makes no changes to it, + // the main side doesn't know about it and the phost side + // assumes it exists. Calling closeAllFiles will not + // remove it from textDocuments array. :( + + // assert.equal(vscode.workspace.textDocuments.length, 0); }); } \ No newline at end of file diff --git a/extensions/vscode-api-tests/src/workspace.test.ts b/extensions/vscode-api-tests/src/workspace.test.ts index 5925e579fbc..06923761b40 100644 --- a/extensions/vscode-api-tests/src/workspace.test.ts +++ b/extensions/vscode-api-tests/src/workspace.test.ts @@ -14,9 +14,7 @@ import * as os from 'os'; suite('workspace-namespace', () => { - teardown((done) => { - cleanUp().then(() => done(), (error) => done(error)); - }); + teardown(cleanUp); test('textDocuments', () => { assert.ok(Array.isArray(workspace.textDocuments)); @@ -28,12 +26,9 @@ suite('workspace-namespace', () => { assert.throws(() => workspace.rootPath = 'farboo'); }); - test('openTextDocument', done => { - workspace.openTextDocument(join(workspace.rootPath, './far.js')).then(doc => { + test('openTextDocument', () => { + return workspace.openTextDocument(join(workspace.rootPath, './far.js')).then(doc => { assert.ok(doc); - done(); - }, err => { - done(err); }); }); From f924875c005e65766d7cb90b29131b73ca73a44a Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 25 Nov 2015 12:00:58 +0100 Subject: [PATCH 066/588] [json] improve text mate tokenizer, enable as default --- extensions/json/package.json | 2 +- extensions/json/syntaxes/JSON.tmLanguage | 44 +++++++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/extensions/json/package.json b/extensions/json/package.json index 983a0480e4b..224e446f8a0 100644 --- a/extensions/json/package.json +++ b/extensions/json/package.json @@ -11,7 +11,7 @@ "mimetypes": ["application/json"] }], "grammars": [{ - // "language": "json" : commented out for now + "language": "json", "scopeName": "source.json", "path": "./syntaxes/JSON.tmLanguage" }] diff --git a/extensions/json/syntaxes/JSON.tmLanguage b/extensions/json/syntaxes/JSON.tmLanguage index 539d1416cbd..9d6a24cc16a 100644 --- a/extensions/json/syntaxes/JSON.tmLanguage +++ b/extensions/json/syntaxes/JSON.tmLanguage @@ -206,7 +206,7 @@ comment the JSON object key include - #string + #objectkey include @@ -283,6 +283,48 @@ name string.quoted.double.json + patterns + + + include + #stringcontent + + + + objectkey + + begin + " + beginCaptures + + 0 + + name + punctuation.support.type.property-name.begin.json + + + end + " + endCaptures + + 0 + + name + punctuation.support.type.property-name.end.json + + + name + support.type.property-name.json + patterns + + + include + #stringcontent + + + + stringcontent + patterns From bd93ccb864fb2d0099cb14921d4ed2a822874286 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2015 12:02:15 +0100 Subject: [PATCH 067/588] add tests for the document symbol provider --- .../contrib/quickOpen/common/quickOpen.ts | 8 +- .../api/common/extHostLanguageFeatures.ts | 15 +- .../quickopen/browser/gotoSymbolHandler.ts | 5 +- .../api/extHostLanguageFeatures.test.ts | 142 ++++++++++++++ .../test/common/api/languageFeatures.test.ts | 177 ------------------ .../test/common/api/testThreadService.ts | 84 +++++++++ 6 files changed, 242 insertions(+), 189 deletions(-) create mode 100644 src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts delete mode 100644 src/vs/workbench/test/common/api/languageFeatures.test.ts create mode 100644 src/vs/workbench/test/common/api/testThreadService.ts diff --git a/src/vs/editor/contrib/quickOpen/common/quickOpen.ts b/src/vs/editor/contrib/quickOpen/common/quickOpen.ts index b4e2dc1c9ea..5894c18e632 100644 --- a/src/vs/editor/contrib/quickOpen/common/quickOpen.ts +++ b/src/vs/editor/contrib/quickOpen/common/quickOpen.ts @@ -11,6 +11,7 @@ import {Range} from 'vs/editor/common/core/range'; import {IModel} from 'vs/editor/common/editorCommon'; import {IOutlineEntry, IOutlineSupport} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; +import {ModelLike} from 'vs/editor/common/modes/languageSelector'; const OutlineRegistry = new LanguageFeatureRegistry('outlineSupport'); @@ -20,13 +21,12 @@ export { IOutlineSupport } -export function getOutlineEntries(model: IModel): TPromise<{ entries: IOutlineEntry[], outlineGroupLabel: { [n: string]: string;} }> { +export function getOutlineEntries(model: ModelLike): TPromise<{ entries: IOutlineEntry[], outlineGroupLabel: { [n: string]: string;} }> { - let resource = model.getAssociatedResource(); let groupLabels: { [n: string]: string } = Object.create(null); let entries: IOutlineEntry[] = []; - let promises = OutlineRegistry.all(model).map(support => { + let promises = OutlineRegistry.all(model).map(support => { if (support.outlineGroupLabel) { for (var key in support.outlineGroupLabel) { @@ -36,7 +36,7 @@ export function getOutlineEntries(model: IModel): TPromise<{ entries: IOutlineEn } } - return support.getOutline(resource).then(result => { + return support.getOutline( model.uri).then(result => { if (Array.isArray(result)) { entries.push(...result); } diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index d99e870d0e5..baa4d1e25b4 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -8,6 +8,7 @@ import URI from 'vs/base/common/uri'; import Event, {Emitter} from 'vs/base/common/event'; import Severity from 'vs/base/common/severity'; import {TPromise} from 'vs/base/common/winjs.base'; +import {onUnexpectedError} from 'vs/base/common/errors'; import {sequence} from 'vs/base/common/async'; import {Range as EditorRange} from 'vs/editor/common/core/range'; import {IDisposable} from 'vs/base/common/lifecycle'; @@ -113,8 +114,8 @@ export class ExtHostLanguageFeatures { registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable { const handle = ExtHostLanguageFeatures._handlePool++; - this._proxy.$registerOutlineSupport(handle, selector); this._adapter[handle] = new OutlineSupportAdapter(this._documents, provider); + this._proxy.$registerOutlineSupport(handle, selector); return this._createDisposable(handle); } @@ -131,17 +132,17 @@ export class ExtHostLanguageFeatures { export class MainThreadLanguageFeatures { private _proxy: ExtHostLanguageFeatures; - private _disposables: { [handle: number]: IDisposable; } = Object.create(null); + private _registrations: { [handle: number]: IDisposable; } = Object.create(null); constructor( @IThreadService threadService: IThreadService) { this._proxy = threadService.getRemotable(ExtHostLanguageFeatures); } $unregister(handle: number): TPromise { - let d = this._disposables[handle]; - if (d) { - d.dispose(); - delete this._disposables[handle]; + let registration = this._registrations[handle]; + if (registration) { + registration.dispose(); + delete this._registrations[handle]; } return undefined; } @@ -154,7 +155,7 @@ export class MainThreadLanguageFeatures { return this._proxy.$getOutline(handle, resource); } }); - this._disposables[handle] = disposable; + this._registrations[handle] = disposable; return undefined; } } \ No newline at end of file diff --git a/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts b/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts index 576ce3f82c2..a4f86a7bc11 100644 --- a/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts +++ b/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts @@ -527,7 +527,10 @@ export class GotoSymbolHandler extends QuickOpenHandler { return TPromise.as(this.outlineToModelCache[modelId]); } - return getOutlineEntries(model).then(outline => { + return getOutlineEntries({ + uri: ( model).getAssociatedResource(), + language: (model).getModeId() + }).then(outline => { let model = new OutlineModel(outline, this.toQuickOpenEntries(outline)); diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts new file mode 100644 index 00000000000..46a90608856 --- /dev/null +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts @@ -0,0 +1,142 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as assert from 'assert'; +import {setUnexpectedErrorHandler, errorHandler} from 'vs/base/common/errors'; +import {create} from 'vs/base/common/types'; +import URI from 'vs/base/common/uri'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {PluginHostDocument} from 'vs/workbench/api/common/pluginHostDocuments'; +import * as phTypes from 'vs/workbench/api/common/pluginHostTypes'; +import {Range as CodeEditorRange} from 'vs/editor/common/core/range'; +import * as EditorCommon from 'vs/editor/common/editorCommon'; +import threadService from './testThreadService' +import {ExtHostLanguageFeatures, MainThreadLanguageFeatures} from 'vs/workbench/api/common/extHostLanguageFeatures'; +import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; +import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; +import {SyncDescriptor0} from 'vs/platform/instantiation/common/descriptors'; +import {OutlineRegistry, getOutlineEntries} from 'vs/editor/contrib/quickOpen/common/quickOpen'; +import {LanguageSelector, ModelLike} from 'vs/editor/common/modes/languageSelector'; + + +let model: ModelLike; +let extHost: ExtHostLanguageFeatures; +let mainThread: MainThreadLanguageFeatures; +let disposables: vscode.Disposable[] = []; +let originalErrorHandler: (e: any) => any; + +suite('ExtHostLanguageFeatures', function() { + + suiteSetup(() => { + + originalErrorHandler = errorHandler.getUnexpectedErrorHandler(); + setUnexpectedErrorHandler(() => { }); + + model = { + language: 'far', + uri: URI.parse('far://testing/file.a') + }; + + threadService.getRemotable(PluginHostModelService)._acceptModelAdd({ + isDirty: false, + versionId: 1, + modeId: 'far', + url: model.uri, + value: { + EOL: '\n', + lines: [ + 'This is the first line', + 'This is the second line', + 'This is the third line', + ], + BOM: '', + length: -1 + }, + }) + + threadService.getRemotable(PluginHostCommands); + threadService.getRemotable(MainThreadCommands); + mainThread = threadService.getRemotable(MainThreadLanguageFeatures); + extHost = threadService.getRemotable(ExtHostLanguageFeatures); + }); + + suiteTeardown(() => { + setUnexpectedErrorHandler(originalErrorHandler); + }); + + teardown(function(done) { + while (disposables.length) { + disposables.pop().dispose(); + } + threadService.sync() + .then(() => done(), err => done(err)); + }); + + test('DocumentSymbols, register/deregister', function(done) { + assert.equal(OutlineRegistry.all(model).length, 0); + let d1 = extHost.registerDocumentSymbolProvider('far', { + provideDocumentSymbols() { + return []; + } + }); + + threadService.sync().then(() => { + assert.equal(OutlineRegistry.all(model).length, 1); + d1.dispose(); + threadService.sync().then(() => { + done(); + }); + }); + + }); + + test('DocumentSymbols, evil provider', function(done) { + disposables.push(extHost.registerDocumentSymbolProvider('far', { + provideDocumentSymbols(): any { + throw new Error('evil document symbol provider'); + } + })); + disposables.push(extHost.registerDocumentSymbolProvider('far', { + provideDocumentSymbols(): any { + return [new phTypes.SymbolInformation('test', phTypes.SymbolKind.Field, new phTypes.Range(0, 0, 0, 0))]; + } + })); + + threadService.sync().then(() => { + + getOutlineEntries(model).then(value => { + assert.equal(value.entries.length, 1); + done(); + }, err => { + done(err); + }); + }); + }); + + test('DocumentSymbols, data conversion', function(done) { + disposables.push(extHost.registerDocumentSymbolProvider('far', { + provideDocumentSymbols(): any { + return [new phTypes.SymbolInformation('test', phTypes.SymbolKind.Field, new phTypes.Range(0, 0, 0, 0))]; + } + })); + + threadService.sync().then(() => { + + getOutlineEntries(model).then(value => { + assert.equal(value.entries.length, 1); + + let entry = value.entries[0]; + assert.equal(entry.label, 'test'); + assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }); + done(); + + }, err => { + done(err); + }); + }); + }); +}); \ No newline at end of file diff --git a/src/vs/workbench/test/common/api/languageFeatures.test.ts b/src/vs/workbench/test/common/api/languageFeatures.test.ts deleted file mode 100644 index bf6a92187e6..00000000000 --- a/src/vs/workbench/test/common/api/languageFeatures.test.ts +++ /dev/null @@ -1,177 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import * as assert from 'assert'; -import {create} from 'vs/base/common/types'; -import URI from 'vs/base/common/uri'; -import {TPromise} from 'vs/base/common/winjs.base'; -import {PluginHostDocument} from 'vs/workbench/api/common/pluginHostDocuments'; -import * as phTypes from 'vs/workbench/api/common/pluginHostTypes'; -import {Range as CodeEditorRange} from 'vs/editor/common/core/range'; -import * as EditorCommon from 'vs/editor/common/editorCommon'; -import {NullThreadService} from 'vs/platform/test/common/nullThreadService' -import * as LF from 'vs/workbench/api/common/languageFeatures'; -import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; -import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; -import {SyncDescriptor0} from 'vs/platform/instantiation/common/descriptors'; -import {OutlineRegistry} from 'vs/editor/contrib/quickOpen/common/quickOpen'; -import {LanguageSelector, ModelLike} from 'vs/editor/common/modes/languageSelector'; - -class ThreadService extends NullThreadService { - - protected _registerAndInstantiateMainProcessActor(id: string, descriptor: SyncDescriptor0): T { - - let instance: any; - - return this._getOrCreateProxyInstance({ - callOnRemote: (proxyId: string, path: string, args: any[]): TPromise => { - if (!instance) { - instance = create(descriptor.ctor, this); - } - try { - let result = (instance[path]).apply(instance, args); - return TPromise.is(result) ? result : TPromise.as(result); - } catch (err) { - return TPromise.wrapError(err); - } - } - }, id, descriptor) - } - - protected _registerAndInstantiatePluginHostActor(id: string, descriptor: SyncDescriptor0): T { - return this._getOrCreateLocalInstance(id, descriptor); - } -} - -let threadService: ThreadService; -let model: ModelLike = { language: 'far', uri: URI.parse('far://testing/file.a') }; - -let extHost: LF.ExtensionHostDocumentSymbols; -let mainHost: LF.MainThreadDocumentSymbols; - -suite('ExtHostLanguageFeatures', function() { - - suiteSetup(() => { - threadService = new ThreadService(); - let documents = threadService.getRemotable(PluginHostModelService); - documents._acceptModelAdd({ - isDirty: false, - versionId: 1, - modeId: 'far', - url: model.uri, - value: { - EOL: '\n', - lines: [ - 'This is the first line', - 'This is the second line', - 'This is the third line', - ], - BOM: '', - length: -1 - }, - }) - threadService.getRemotable(PluginHostCommands); - threadService.getRemotable(MainThreadCommands); - threadService.getRemotable(LF.MainThreadDocumentSymbols); - extHost = new LF.ExtensionHostDocumentSymbols(threadService); - mainHost = threadService.getRemotable(LF.MainThreadDocumentSymbols); - }); - - test('DocumentSymbols, register/deregister', function() { - - - // register - assert.equal(OutlineRegistry.all(model).length, 0); - let disposable = extHost.register('far', { - provideDocumentSymbols() { - return []; - } - }); - assert.equal(OutlineRegistry.all(model).length, 1); - - // deregister - disposable.dispose(); - assert.equal(OutlineRegistry.all(model).length, 0); - - // all extension host provider appear as one - disposable = extHost.register('far', { - provideDocumentSymbols() { - return []; - } - }); - let disposable2 = extHost.register('far', { - provideDocumentSymbols() { - return []; - } - }); - assert.equal(OutlineRegistry.all(model).length, 1); - - disposable.dispose(); - assert.equal(OutlineRegistry.all(model).length, 1); - disposable2.dispose(); - assert.equal(OutlineRegistry.all(model).length, 0); - }); - - test('DocumentSymbols, evil provider', function(done) { - - - let disposable = extHost.register('far', { - provideDocumentSymbols():any { - throw new Error('ddd'); - } - }); - let disposable2 = extHost.register('far', { - provideDocumentSymbols():any { - return [ - new phTypes.SymbolInformation('boo', phTypes.SymbolKind.Field, new phTypes.Range(0, 0, 0, 0)) - ]; - } - }); - - mainHost.getOutline(model.uri).then(result => { - assert.equal(result.length, 1); - done(); - - disposable.dispose(); - disposable2.dispose(); - - }, err => { - done(err); - }); - }); - - test('DocumentSymbols, data conversion', function(done) { - - let d = extHost.register('far', { - provideDocumentSymbols():any { - return [ - new phTypes.SymbolInformation('boo', - phTypes.SymbolKind.Field, - new phTypes.Range(0, 0, 0, 0), - model.uri, - 'far') - ]; - } - }); - - mainHost.getOutline(model.uri).then(result => { - assert.equal(result.length, 1); - let entry = result[0]; - - assert.equal(entry.label, 'boo'); - assert.equal(entry.containerLabel, 'far'); - assert.equal(entry.children, undefined); - assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }); - d.dispose(); - done(); - - }, err => { - done(err); - }); - - }); -}); \ No newline at end of file diff --git a/src/vs/workbench/test/common/api/testThreadService.ts b/src/vs/workbench/test/common/api/testThreadService.ts new file mode 100644 index 00000000000..5b408734768 --- /dev/null +++ b/src/vs/workbench/test/common/api/testThreadService.ts @@ -0,0 +1,84 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import {NullThreadService} from 'vs/platform/test/common/nullThreadService'; +import {create} from 'vs/base/common/types'; +import {SyncDescriptor0} from 'vs/platform/instantiation/common/descriptors'; +import {TPromise} from 'vs/base/common/winjs.base'; + +export class TestThreadService extends NullThreadService { + + private _callCountValue: number = 0; + private _idle: TPromise; + private _completeIdle: Function; + + private get _callCount(): number { + return this._callCountValue; + } + + private set _callCount(value:number) { + this._callCountValue = value; + if (this._callCountValue === 0) { + this._completeIdle(); + this._idle = undefined; + } + } + + sync(): TPromise { + if (this._callCount === 0) { + return TPromise.as(undefined); + } + if (!this._idle) { + this._idle = new TPromise((c, e) => { + this._completeIdle = c; + }, function() { + // no cancel + }); + } + return this._idle; + } + + protected _registerAndInstantiateMainProcessActor(id: string, descriptor: SyncDescriptor0): T { + + let instance: any; + + return this._getOrCreateProxyInstance({ + callOnRemote: (proxyId: string, path: string, args: any[]): TPromise => { + + this._callCount++; + + return TPromise.timeout(0).then(() => { + if (!instance) { + instance = create(descriptor.ctor, this); + } + let p: TPromise; + try { + let result = (instance[path]).apply(instance, args); + p = TPromise.is(result) ? result : TPromise.as(result); + } catch (err) { + p = TPromise.wrapError(err); + } + + return p.then(result => { + this._callCount--; + return result; + }, err => { + this._callCount--; + return TPromise.wrapError(err); + }); + }); + } + }, id, descriptor) + } + + protected _registerAndInstantiatePluginHostActor(id: string, descriptor: SyncDescriptor0): T { + return this._getOrCreateLocalInstance(id, descriptor); + } +} + +const Instance = new TestThreadService(); +export default Instance; \ No newline at end of file From 052a1dc8a06869c6e219be8c4db41cd2c1727f0c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2015 12:04:21 +0100 Subject: [PATCH 068/588] api tests - more use of promises in mocha --- extensions/vscode-api-tests/src/editor.test.ts | 10 ++++------ extensions/vscode-api-tests/src/window.test.ts | 10 ++++------ extensions/vscode-api-tests/src/workspace.test.ts | 14 +++++--------- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/extensions/vscode-api-tests/src/editor.test.ts b/extensions/vscode-api-tests/src/editor.test.ts index 38a9b1558ef..e3bb24f42c2 100644 --- a/extensions/vscode-api-tests/src/editor.test.ts +++ b/extensions/vscode-api-tests/src/editor.test.ts @@ -14,12 +14,10 @@ import {join} from 'path'; suite("editor tests", () => { - teardown((done) => { - cleanUp().then(() => done(), (error) => done(error)); - }); + teardown(cleanUp); - test('make edit', (done) => { - createRandomFile().then(file => { + test('make edit', () => { + return createRandomFile().then(file => { return workspace.openTextDocument(file).then(doc => { return window.showTextDocument(doc).then((editor) => { return editor.edit((builder) => { @@ -38,6 +36,6 @@ suite("editor tests", () => { }); }); }); - }).then(() => done(), (error) => done(error)); + }); }); }); \ No newline at end of file diff --git a/extensions/vscode-api-tests/src/window.test.ts b/extensions/vscode-api-tests/src/window.test.ts index 0f3ba712cd3..3764c8feb9a 100644 --- a/extensions/vscode-api-tests/src/window.test.ts +++ b/extensions/vscode-api-tests/src/window.test.ts @@ -12,17 +12,15 @@ import {cleanUp} from './utils'; suite("window namespace tests", () => { - teardown((done) => { - cleanUp().then(() => done(), (error) => done(error)); - }); + teardown(cleanUp); - test('active text editor', (done) => { - workspace.openTextDocument(join(workspace.rootPath, './far.js')).then(doc => { + test('active text editor', () => { + return workspace.openTextDocument(join(workspace.rootPath, './far.js')).then(doc => { return window.showTextDocument(doc).then((editor) => { const active = window.activeTextEditor; assert.ok(active); assert.equal(active.document.uri.fsPath, doc.uri.fsPath); }); - }).then(() => done(), (error) => done(error)); + }); }); }); \ No newline at end of file diff --git a/extensions/vscode-api-tests/src/workspace.test.ts b/extensions/vscode-api-tests/src/workspace.test.ts index 06923761b40..bf457f5b6f4 100644 --- a/extensions/vscode-api-tests/src/workspace.test.ts +++ b/extensions/vscode-api-tests/src/workspace.test.ts @@ -40,8 +40,8 @@ suite('workspace-namespace', () => { }); }); - test('events: onDidOpenTextDocument, onDidChangeTextDocument, onDidSaveTextDocument', (done) => { - createRandomFile().then(file => { + test('events: onDidOpenTextDocument, onDidChangeTextDocument, onDidSaveTextDocument', () => { + return createRandomFile().then(file => { let disposables = []; let onDidOpenTextDocument = false; @@ -81,17 +81,13 @@ suite('workspace-namespace', () => { }); }); }); - }).then(() => done(), (error) => done(error)); + }); }); - test('findFiles', done => { - workspace.findFiles('*.js', null).then((res) => { + test('findFiles', () => { + return workspace.findFiles('*.js', null).then((res) => { assert.equal(res.length, 1); assert.equal(workspace.asRelativePath(res[0]), '/far.js'); - - done(); - }, err => { - done(err); }); }); }); \ No newline at end of file From 2c09792e1c3fb49d5d5d32c634ca594f56efba6e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2015 12:13:40 +0100 Subject: [PATCH 069/588] first commands test (disabled) --- .../vscode-api-tests/src/commands.test.ts | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 extensions/vscode-api-tests/src/commands.test.ts diff --git a/extensions/vscode-api-tests/src/commands.test.ts b/extensions/vscode-api-tests/src/commands.test.ts new file mode 100644 index 00000000000..6d9453f3510 --- /dev/null +++ b/extensions/vscode-api-tests/src/commands.test.ts @@ -0,0 +1,29 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as assert from 'assert'; +import * as fs from 'fs'; +import * as os from 'os'; +import {workspace, window, Position, commands} from 'vscode'; +import {createRandomFile, deleteFile, cleanUp} from './utils'; +import {join} from 'path'; + +suite("editor tests", () => { + + teardown(cleanUp); + + // test('calling command completes with the extension host updated properly', () => { + // return workspace.openTextDocument(join(workspace.rootPath, './far.js')).then(doc => { + // return window.showTextDocument(doc).then(editor => { + // assert.equal(window.visibleTextEditors.length, 1); + // return commands.executeCommand('workbench.action.closeAllEditors').then(() => { + // assert.equal(window.visibleTextEditors.length, 0); + // }); + // }); + // }); + // }); +}); \ No newline at end of file From 770ede158afea0293f4c66448e0effb8d2788a4b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2015 12:48:55 +0100 Subject: [PATCH 070/588] One code lens provider is one code lens support, fixes #360 --- .../contrib/codelens/browser/codelens.ts | 24 +-- .../contrib/codelens/common/codelens.ts | 27 ++- .../api/browser/pluginHost.api.impl.ts | 2 +- .../api/common/extHostLanguageFeatures.ts | 139 ++++++++++++- .../workbench/api/common/languageFeatures.ts | 184 ------------------ .../workbench/api/common/pluginHostTypes.ts | 2 +- .../api/extHostLanguageFeatures.test.ts | 84 +++++++- 7 files changed, 241 insertions(+), 221 deletions(-) diff --git a/src/vs/editor/contrib/codelens/browser/codelens.ts b/src/vs/editor/contrib/codelens/browser/codelens.ts index 84585d921fb..9ec540a9476 100644 --- a/src/vs/editor/contrib/codelens/browser/codelens.ts +++ b/src/vs/editor/contrib/codelens/browser/codelens.ts @@ -22,12 +22,8 @@ import {IModelService} from 'vs/editor/common/services/modelService'; import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; import {Range} from 'vs/editor/common/core/range'; -import {CodeLensRegistry} from '../common/codelens'; +import {CodeLensRegistry, ICodeLensData, getCodeLensData} from '../common/codelens'; -interface ICodeLensData { - symbol: Modes.ICodeLensSymbol; - support: Modes.ICodeLensSupport; -} class CodeLensViewZone implements EditorBrowser.IViewZone { @@ -428,22 +424,8 @@ export class CodeLensContribution implements EditorCommon.IEditorContribution { this._currentFindCodeLensSymbolsPromise.cancel(); } - let resource = model.getAssociatedResource(); - let symbols: ICodeLensData[] = []; - let promises = CodeLensRegistry.all(model).map(support => { - return support.findCodeLensSymbols(resource).then(result => { - if (!Array.isArray(result)) { - return; - } - for (let symbol of result) { - symbols.push({ symbol, support }); - } - }, err => { - errors.onUnexpectedError(err); - }); - }); - - this._currentFindCodeLensSymbolsPromise = TPromise.join(promises).then(() => symbols); + this._currentFindCodeLensSymbolsPromise = getCodeLensData(model.getAssociatedResource(), + model.getModeId()); var counterValue = ++this._modelChangeCounter; this._currentFindCodeLensSymbolsPromise.then((result) => { diff --git a/src/vs/editor/contrib/codelens/common/codelens.ts b/src/vs/editor/contrib/codelens/common/codelens.ts index cf84481f124..0392ab6a924 100644 --- a/src/vs/editor/contrib/codelens/common/codelens.ts +++ b/src/vs/editor/contrib/codelens/common/codelens.ts @@ -5,6 +5,7 @@ 'use strict'; +import {onUnexpectedError} from 'vs/base/common/errors'; import URI from 'vs/base/common/uri'; import {IAction, Action} from 'vs/base/common/actions'; import {TPromise} from 'vs/base/common/winjs.base'; @@ -13,6 +14,28 @@ import {Range} from 'vs/editor/common/core/range'; import {ICodeLensSupport, ICodeLensSymbol, ICommand} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; -const _registry = new LanguageFeatureRegistry('codeLensSupport'); +export const CodeLensRegistry = new LanguageFeatureRegistry('codeLensSupport'); -export {_registry as CodeLensRegistry} +export interface ICodeLensData { + symbol: ICodeLensSymbol; + support: ICodeLensSupport; +} + +export function getCodeLensData(resource: URI, modeId: string) { + + const symbols: ICodeLensData[] = []; + const promises = CodeLensRegistry.all({ uri: resource, language: modeId }).map(support => { + return support.findCodeLensSymbols(resource).then(result => { + if (!Array.isArray(result)) { + return; + } + for (let symbol of result) { + symbols.push({ symbol, support }); + } + }, err => { + onUnexpectedError(err); + }); + }); + + return TPromise.join(promises).then(() => symbols); +} \ No newline at end of file diff --git a/src/vs/workbench/api/browser/pluginHost.api.impl.ts b/src/vs/workbench/api/browser/pluginHost.api.impl.ts index a7556ab7512..1d4ce1101ed 100644 --- a/src/vs/workbench/api/browser/pluginHost.api.impl.ts +++ b/src/vs/workbench/api/browser/pluginHost.api.impl.ts @@ -268,7 +268,7 @@ export class PluginHostAPIImplementation { return features.codeActions.register(selector, provider); }, registerCodeLensProvider(selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable { - return features.codeLens.register(selector, provider); + return languageFeatures.registerCodeLensProvider(selector, provider); }, registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable { return features.definition.register(selector, provider); diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index baa4d1e25b4..953592ba9c5 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -57,7 +57,7 @@ function asWinJsPromise(callback: (token: vscode.CancellationToken) => T | Th // --- adapter -class OutlineSupportAdapter implements IOutlineSupport { +class OutlineAdapter implements IOutlineSupport { private _documents: PluginHostModelService; private _provider: vscode.DocumentSymbolProvider; @@ -71,7 +71,7 @@ class OutlineSupportAdapter implements IOutlineSupport { let doc = this._documents.getDocument(resource); return asWinJsPromise(token => this._provider.provideDocumentSymbols(doc, token)).then(value => { if (Array.isArray(value)) { - return value.map(OutlineSupportAdapter._convertSymbolInfo); + return value.map(OutlineAdapter._convertSymbolInfo); } }); } @@ -87,7 +87,78 @@ class OutlineSupportAdapter implements IOutlineSupport { } } -type Adapter = OutlineSupportAdapter; +class CodeLensAdapter implements modes.ICodeLensSupport { + + private _documents: PluginHostModelService; + private _provider: vscode.CodeLensProvider; + + private _cache: { [uri: string]: vscode.CodeLens[] } = Object.create(null); + + constructor(documents: PluginHostModelService, provider: vscode.CodeLensProvider) { + this._documents = documents; + this._provider = provider; + } + + findCodeLensSymbols(resource: URI): TPromise { + let doc = this._documents.getDocument(resource); + let key = resource.toString(); + + delete this._cache[key]; + + return asWinJsPromise(token => this._provider.provideCodeLenses(doc, token)).then(value => { + if (!Array.isArray(value)) { + return; + } + + this._cache[key] = value; + + return value.map((lens, i) => { + return { + id: String(i), + range: TypeConverters.fromRange(lens.range) + } + }); + }); + } + + resolveCodeLensSymbol(resource: URI, symbol: modes.ICodeLensSymbol): TPromise { + + let lenses = this._cache[resource.toString()]; + if (!lenses) { + return; + } + + let lens = lenses[Number(symbol.id)]; + if (!lens) { + return; + } + + let resolve: TPromise; + if (typeof this._provider.resolveCodeLens !== 'function' || lens.isResolved) { + resolve = TPromise.as(lens); + } else { + resolve = asWinJsPromise(token => this._provider.resolveCodeLens(lens, token)); + } + + return resolve.then(newLens => { + lens = newLens || lens; + let command = lens.command; + if (!command) { + command = { + title: '<>', + command: 'missing', + } + } + return { + id: command.command, + title: command.title, + arguments: command.arguments + } + }); + } +} + +type Adapter = OutlineAdapter | CodeLensAdapter; @Remotable.PluginHostContext('ExtHostLanguageFeatures') export class ExtHostLanguageFeatures { @@ -110,22 +181,59 @@ export class ExtHostLanguageFeatures { }); } + private _nextHandle(): number { + return ExtHostLanguageFeatures._handlePool++; + } + + private _noAdapter() { + return TPromise.wrapError(new Error('no adapter found')); + } + // --- outline registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable { - const handle = ExtHostLanguageFeatures._handlePool++; - this._adapter[handle] = new OutlineSupportAdapter(this._documents, provider); + const handle = this._nextHandle(); + this._adapter[handle] = new OutlineAdapter(this._documents, provider); this._proxy.$registerOutlineSupport(handle, selector); return this._createDisposable(handle); } $getOutline(handle: number, resource: URI): TPromise{ let adapter = this._adapter[handle]; - if (adapter instanceof OutlineSupportAdapter) { + if (adapter instanceof OutlineAdapter) { return adapter.getOutline(resource); + } else { + return this._noAdapter(); } - return TPromise.wrapError(new Error('no adapter found')); } + + // --- code lens + + registerCodeLensProvider(selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable { + const handle = this._nextHandle(); + this._adapter[handle] = new CodeLensAdapter(this._documents, provider); + this._proxy.$registerCodeLensSupport(handle, selector); + return this._createDisposable(handle); + } + + $findCodeLensSymbols(handle:number, resource: URI): TPromise { + let adapter = this._adapter[handle]; + if (adapter instanceof CodeLensAdapter) { + return adapter.findCodeLensSymbols(resource); + } else { + return this._noAdapter(); + } + } + + $resolveCodeLensSymbol(handle:number, resource: URI, symbol: modes.ICodeLensSymbol): TPromise { + let adapter = this._adapter[handle]; + if (adapter instanceof CodeLensAdapter) { + return adapter.resolveCodeLensSymbol(resource, symbol); + } else { + return this._noAdapter(); + } + } + } @Remotable.MainContext('MainThreadLanguageFeatures') @@ -150,12 +258,25 @@ export class MainThreadLanguageFeatures { // --- outline $registerOutlineSupport(handle: number, selector: vscode.DocumentSelector): TPromise { - let disposable = OutlineRegistry.register(selector, { + this._registrations[handle] = OutlineRegistry.register(selector, { getOutline: (resource: URI): TPromise => { return this._proxy.$getOutline(handle, resource); } }); - this._registrations[handle] = disposable; + return undefined; + } + + // --- code lens + + $registerCodeLensSupport(handle: number, selector: vscode.DocumentSelector): TPromise { + this._registrations[handle] = CodeLensRegistry.register(selector, { + findCodeLensSymbols: (resource: URI): TPromise => { + return this._proxy.$findCodeLensSymbols(handle, resource); + }, + resolveCodeLensSymbol: (resource: URI, symbol: modes.ICodeLensSymbol): TPromise => { + return this._proxy.$resolveCodeLensSymbol(handle, resource, symbol); + } + }); return undefined; } } \ No newline at end of file diff --git a/src/vs/workbench/api/common/languageFeatures.ts b/src/vs/workbench/api/common/languageFeatures.ts index 4fa0fb5ffc7..2d3a0fb57ea 100644 --- a/src/vs/workbench/api/common/languageFeatures.ts +++ b/src/vs/workbench/api/common/languageFeatures.ts @@ -480,78 +480,6 @@ export class MainThreadCodeActions extends AbstractMainThreadFeature { - - constructor( @IThreadService threadService: IThreadService) { - super(threadService.getRemotable(MainThreadDocumentSymbols), threadService); - } - - protected _runAsCommand(resource: URI): TPromise { - - if (!(resource instanceof URI)) { - return TPromise.wrapError('uri missing'); - } - - let symbols: vscode.SymbolInformation[] = []; - let document = this._models.getDocument(resource); - let candidate = { - language: document.languageId, - uri: document.uri - }; - let promises = this._registry.all(candidate).map(provider => { - return asWinJsPromise(token => { - return provider.provideDocumentSymbols(document, token); - }).then(result => { - if (Array.isArray(result)) { - symbols.push(...result); - } - }, err => { - console.log(err); - }); - }); - - return TPromise.join(promises).then(() => { - return symbols - .sort(ExtensionHostDocumentSymbols._compareByStart) - .map(ExtensionHostDocumentSymbols._convertSymbolInfo); - }); - } - - private static _compareByStart(a: vscode.SymbolInformation, b: vscode.SymbolInformation): number { - if (a.location.range.start.isBefore(b.location.range.start)) { - return -1; - } else if (b.location.range.start.isBefore(a.location.range.start)) { - return 1; - } else { - return 0; - } - } - - private static _convertSymbolInfo(symbol: vscode.SymbolInformation): IOutlineEntry { - return { - type: TypeConverters.fromSymbolKind(symbol.kind), - range: TypeConverters.fromRange(symbol.location.range), - containerLabel: symbol.containerName, - label: symbol.name, - icon: undefined, - }; - } -} - -@Remotable.MainContext('MainThreadDocumentSymbols2') -export class MainThreadDocumentSymbols extends AbstractMainThreadFeature implements IOutlineSupport { - - constructor( @IThreadService threadService: IThreadService) { - super('vscode.executeDocumentSymbolProvider', OutlineRegistry, threadService); - } - - getOutline(resource: URI): TPromise{ - return this._executeCommand(resource); - } -} - // -- Rename provider export class ExtensionHostRename extends AbstractExtensionHostFeature { @@ -1046,114 +974,6 @@ export class MainThreadCompletions extends AbstractMainThreadFeature { - - private static _idPool = 0; - private _lenses: { [id: string]: [string, vscode.CodeLensProvider, vscode.CodeLens] } = Object.create(null); - - constructor(@IThreadService threadService: IThreadService) { - super(threadService.getRemotable(MainThreadCodeLens), threadService); - this._models.onDidRemoveDocument(event => this._clearCache(event.uri)); - } - - _clearCache(resource: URI): void { - for (let key in this._lenses) { - if (this._lenses[key][0] === resource.toString()) { - delete this._lenses[key]; - } - } - } - - _runAsCommand(resource: URI): TPromise { - - let document = this._models.getDocument(resource); - let result: modes.ICodeLensSymbol[] = []; - let promises = this._getAllFor(document).map(provider => { - - let providerCanResolveLens = typeof provider.resolveCodeLens === 'function'; - - return asWinJsPromise(token => provider.provideCodeLenses(document, token)).then(lenses => { - - // new commands - this._clearCache(resource); - - if (!Array.isArray(lenses)) { - return; - } - for (let lens of lenses) { - - if (!providerCanResolveLens && !lens.isResolved) { - throw new Error('illegal state - code lens must be resolved or provider must implement resolveCodeLens-function'); - } - - let id = 'code_lense_#' + ExtensionHostCodeLens._idPool++; - this._lenses[id] = [resource.toString(), provider, lens]; - - result.push({ - id, - range: TypeConverters.fromRange(lens.range) - }); - } - }, err => { - console.error(err); - }); - }); - - return TPromise.join(promises).then(() => { - return result; - }); - } - - _resolveCodeLensSymbol(symbol: modes.ICodeLensSymbol): TPromise { - - if (!this._lenses[symbol.id]) { - return; - } - - let [, provider, lens] = this._lenses[symbol.id]; - let resolve: TPromise; - - if (typeof provider.resolveCodeLens !== 'function') { - resolve = TPromise.as(lens); - } else { - resolve = asWinJsPromise(token => provider.resolveCodeLens(lens, token)); - } - - return resolve.then(newLens => { - lens = newLens || lens; - if (lens.command) { - return { - id: lens.command.command, - title: lens.command.title, - arguments: lens.command.arguments - } - } - }); - } -} - -@Remotable.MainContext('MainThreadCodeLens') -export class MainThreadCodeLens extends AbstractMainThreadFeature implements modes.ICodeLensSupport { - - private _proxy: ExtensionHostCodeLens; - - constructor( @IThreadService threadService: IThreadService) { - super('vscode.executeCodeLensProvider', CodeLensRegistry, threadService); - this._proxy = threadService.getRemotable(ExtensionHostCodeLens); - } - - findCodeLensSymbols(resource: URI): TPromise { - return this._executeCommand(resource); - } - - resolveCodeLensSymbol(resource: URI, symbol: modes.ICodeLensSymbol): TPromise { - return this._proxy._resolveCodeLensSymbol(symbol); - } -} - // --- workspace symbols export class ExtensionHostWorkspaceSymbols { @@ -1261,8 +1081,6 @@ export namespace LanguageFeatures { threadService.getRemotable(MainThreadOccurrencesFeature); threadService.getRemotable(MainThreadReferenceSearch); threadService.getRemotable(MainThreadCodeActions); - threadService.getRemotable(MainThreadCodeLens); - // threadService.getRemotable(MainThreadDocumentSymbols); threadService.getRemotable(MainThreadWorkspaceSymbols); threadService.getRemotable(MainThreadRename); threadService.getRemotable(MainThreadFormatDocument); @@ -1279,8 +1097,6 @@ export namespace LanguageFeatures { documentHighlight: new ExtensionHostOccurrencesFeature(threadService), referenceSearch: new ExtensionHostReferenceSearch(threadService), codeActions: new ExtensionHostCodeActions(threadService), - codeLens: threadService.getRemotable(ExtensionHostCodeLens), - // documentSymbols: new ExtensionHostDocumentSymbols(threadService), workspaceSymbols: new ExtensionHostWorkspaceSymbols(threadService), rename: new ExtensionHostRename(threadService), formatDocument: new ExtHostFormatDocument(threadService), diff --git a/src/vs/workbench/api/common/pluginHostTypes.ts b/src/vs/workbench/api/common/pluginHostTypes.ts index f8e6803369d..ab1850230f7 100644 --- a/src/vs/workbench/api/common/pluginHostTypes.ts +++ b/src/vs/workbench/api/common/pluginHostTypes.ts @@ -509,7 +509,7 @@ export class CodeLens { constructor(range: Range, command?: vscode.Command) { this.range = range; - this.command; + this.command = command; } get isResolved(): boolean { diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts index 46a90608856..c4cd44d1a12 100644 --- a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts @@ -11,7 +11,7 @@ import {create} from 'vs/base/common/types'; import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; import {PluginHostDocument} from 'vs/workbench/api/common/pluginHostDocuments'; -import * as phTypes from 'vs/workbench/api/common/pluginHostTypes'; +import * as types from 'vs/workbench/api/common/pluginHostTypes'; import {Range as CodeEditorRange} from 'vs/editor/common/core/range'; import * as EditorCommon from 'vs/editor/common/editorCommon'; import threadService from './testThreadService' @@ -20,6 +20,7 @@ import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pl import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; import {SyncDescriptor0} from 'vs/platform/instantiation/common/descriptors'; import {OutlineRegistry, getOutlineEntries} from 'vs/editor/contrib/quickOpen/common/quickOpen'; +import {CodeLensRegistry, getCodeLensData} from 'vs/editor/contrib/codelens/common/codelens'; import {LanguageSelector, ModelLike} from 'vs/editor/common/modes/languageSelector'; @@ -76,6 +77,8 @@ suite('ExtHostLanguageFeatures', function() { .then(() => done(), err => done(err)); }); + // --- outline + test('DocumentSymbols, register/deregister', function(done) { assert.equal(OutlineRegistry.all(model).length, 0); let d1 = extHost.registerDocumentSymbolProvider('far', { @@ -102,7 +105,7 @@ suite('ExtHostLanguageFeatures', function() { })); disposables.push(extHost.registerDocumentSymbolProvider('far', { provideDocumentSymbols(): any { - return [new phTypes.SymbolInformation('test', phTypes.SymbolKind.Field, new phTypes.Range(0, 0, 0, 0))]; + return [new types.SymbolInformation('test', types.SymbolKind.Field, new types.Range(0, 0, 0, 0))]; } })); @@ -120,7 +123,7 @@ suite('ExtHostLanguageFeatures', function() { test('DocumentSymbols, data conversion', function(done) { disposables.push(extHost.registerDocumentSymbolProvider('far', { provideDocumentSymbols(): any { - return [new phTypes.SymbolInformation('test', phTypes.SymbolKind.Field, new phTypes.Range(0, 0, 0, 0))]; + return [new types.SymbolInformation('test', types.SymbolKind.Field, new types.Range(0, 0, 0, 0))]; } })); @@ -139,4 +142,79 @@ suite('ExtHostLanguageFeatures', function() { }); }); }); + + // --- code lens + + test('CodeLens, evil provider', function(done) { + + disposables.push(extHost.registerCodeLensProvider('far', { + provideCodeLenses():any { + throw new Error('evil') + } + })); + disposables.push(extHost.registerCodeLensProvider('far', { + provideCodeLenses() { + return [new types.CodeLens(new types.Range(0, 0, 0, 0))]; + } + })); + + threadService.sync().then(() => { + getCodeLensData(model.uri, model.language).then(value => { + assert.equal(value.length, 1); + done(); + }); + }); + }); + + test('CodeLens, do not resolve a resolved lens', function(done) { + + disposables.push(extHost.registerCodeLensProvider('far', { + provideCodeLenses():any { + return [new types.CodeLens( + new types.Range(0, 0, 0, 0), + { command: 'id', title: 'Title' })]; + }, + resolveCodeLens():any { + assert.ok(false, 'do not resolve'); + } + })); + + threadService.sync().then(() => { + + getCodeLensData(model.uri, model.language).then(value => { + assert.equal(value.length, 1); + let data = value[0]; + + data.support.resolveCodeLensSymbol(model.uri, data.symbol).then(command => { + assert.equal(command.id, 'id'); + assert.equal(command.title, 'Title'); + done(); + }); + }); + }); + }); + + test('CodeLens, missing command', function(done) { + + disposables.push(extHost.registerCodeLensProvider('far', { + provideCodeLenses() { + return [new types.CodeLens(new types.Range(0, 0, 0, 0))]; + } + })); + + threadService.sync().then(() => { + + getCodeLensData(model.uri, model.language).then(value => { + assert.equal(value.length, 1); + + let data = value[0]; + data.support.resolveCodeLensSymbol(model.uri, data.symbol).then(command => { + + assert.equal(command.id, 'missing'); + assert.equal(command.title, '<>'); + done(); + }); + }); + }); + }); }); \ No newline at end of file From 5ea34f9dba4d8d20e872c0a02d7a79d87baff5bc Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2015 12:51:24 +0100 Subject: [PATCH 071/588] return early from confirmSave when we are in extension development mode --- extensions/vscode-api-tests/src/workspace.test.ts | 1 + .../parts/files/electron-browser/textFileServices.ts | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/extensions/vscode-api-tests/src/workspace.test.ts b/extensions/vscode-api-tests/src/workspace.test.ts index bf457f5b6f4..4cbc96827da 100644 --- a/extensions/vscode-api-tests/src/workspace.test.ts +++ b/extensions/vscode-api-tests/src/workspace.test.ts @@ -29,6 +29,7 @@ suite('workspace-namespace', () => { test('openTextDocument', () => { return workspace.openTextDocument(join(workspace.rootPath, './far.js')).then(doc => { assert.ok(doc); + assert.equal(workspace.textDocuments.length, 1); }); }); diff --git a/src/vs/workbench/parts/files/electron-browser/textFileServices.ts b/src/vs/workbench/parts/files/electron-browser/textFileServices.ts index 7179263c8d4..78a8903a4f7 100644 --- a/src/vs/workbench/parts/files/electron-browser/textFileServices.ts +++ b/src/vs/workbench/parts/files/electron-browser/textFileServices.ts @@ -63,10 +63,6 @@ export class TextFileService extends BrowserTextFileService { public beforeShutdown(): boolean | TPromise { super.beforeShutdown(); - if (!!this.contextService.getConfiguration().env.pluginDevelopmentPath) { - return false; // no veto when we are in plugin dev mode because we want to reload often - } - // Dirty files need treatment on shutdown if (this.getDirty().length) { let confirm = this.confirmSave(); @@ -156,6 +152,10 @@ export class TextFileService extends BrowserTextFileService { } public confirmSave(resource?: URI): ConfirmResult { + if (!!this.contextService.getConfiguration().env.pluginDevelopmentPath) { + return ConfirmResult.DONT_SAVE; // no veto when we are in plugin dev mode because we cannot assum we run interactive (e.g. tests) + } + let resourcesToConfirm = this.getDirty(resource); if (resourcesToConfirm.length === 0) { return ConfirmResult.DONT_SAVE; From b57564d7fb4d2810dead7db42a5fca9fe4eace0a Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2015 13:21:46 +0100 Subject: [PATCH 072/588] fixes #177 --- src/vs/editor/common/editorCommon.ts | 12 + src/vs/editor/common/model/mirrorModel.ts | 65 ++-- .../common/model/textModelWithTokens.ts | 40 +- src/vs/editor/common/modes.ts | 5 + src/vs/editor/common/modes/abstractMode.ts | 86 +++++ src/vs/editor/common/modes/nullMode.ts | 4 + src/vs/editor/common/services/modelService.ts | 2 - .../common/services/modelServiceImpl.ts | 344 ++++++++---------- .../common/model/editableTextModel.test.ts | 9 +- .../test/common/model/mirrorModel.test.ts | 158 ++++---- .../common/modes/textToHtmlTokenizer.test.ts | 4 + .../test/common/modes/tokenization.test.ts | 8 + src/vs/editor/test/common/modesTestUtils.ts | 24 +- src/vs/editor/test/common/modesUtil.ts | 23 +- src/vs/editor/test/common/testModes.ts | 4 + .../test/common/projectResolver.test.ts | 1 - 16 files changed, 443 insertions(+), 346 deletions(-) diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index b204985b86c..8c467a9db3c 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -1452,6 +1452,18 @@ export interface ITokenizedModel extends ITextModel { * @param position The position at which to look for a bracket. */ matchBracket(position:IPosition, inaccurateResultAcceptable?:boolean): IMatchBracketResult; + + /** + * No mode supports allowed on this model because it is simply too large. + * (even tokenization would cause too much memory pressure) + */ + isTooLargeForHavingAMode(): boolean; + + /** + * Only basic mode supports allowed on this model because it is simply too large. + * (tokenization is allowed and other basic supports) + */ + isTooLargeForHavingARichMode(): boolean; } /** diff --git a/src/vs/editor/common/model/mirrorModel.ts b/src/vs/editor/common/model/mirrorModel.ts index 2240bde5959..5f2bd193bf5 100644 --- a/src/vs/editor/common/model/mirrorModel.ts +++ b/src/vs/editor/common/model/mirrorModel.ts @@ -16,6 +16,11 @@ import {IResourceService} from 'vs/editor/common/services/resourceService'; import {URL} from 'vs/base/common/network'; import {disposeAll} from 'vs/base/common/lifecycle'; +export interface IMirrorModelEvents { + contentChanged: EditorCommon.IModelContentChangedEvent[]; + propertiesChanged: EditorCommon.IModelPropertiesChangedEvent; +} + export class AbstractMirrorModel extends TextModelWithTokens implements EditorCommon.IMirrorModel { _lineStarts:PrefixSumComputer; @@ -453,51 +458,43 @@ export class MirrorModel extends AbstractMirrorModel implements EditorCommon.IMi return false; } - public onEvents(events:{ type:string; }[]) : boolean { + public onEvents(events:IMirrorModelEvents) : boolean { if (this._isDisposed) { throw new Error('MirrorModel.onEvents: Model is disposed'); } - var changed = false; - for (var i = 0, len = events.length; i < len; i++) { - var e = events[i]; - switch (e.type) { - case EditorCommon.EventType.ModelContentChanged: - var contentChangedEvent = e; + if (events.propertiesChanged) { + this._extraProperties = events.propertiesChanged.properties; + } - // Force recreating of line starts - this._lineStarts = null; + let changed = false; + for (let i = 0, len = events.contentChanged.length; i < len; i++) { + let contentChangedEvent = events.contentChanged[i]; - this._setVersionId(contentChangedEvent.versionId); - switch (contentChangedEvent.changeType) { - case EditorCommon.EventType.ModelContentChangedFlush: - this._onLinesFlushed(contentChangedEvent); - changed = true; - break; + // Force recreating of line starts + this._lineStarts = null; - case EditorCommon.EventType.ModelContentChangedLinesDeleted: - this._onLinesDeleted(contentChangedEvent); - changed = true; - break; - - case EditorCommon.EventType.ModelContentChangedLinesInserted: - this._onLinesInserted(contentChangedEvent); - changed = true; - break; - - case EditorCommon.EventType.ModelContentChangedLineChanged: - this._onLineChanged(contentChangedEvent); - changed = true; - break; - } + this._setVersionId(contentChangedEvent.versionId); + switch (contentChangedEvent.changeType) { + case EditorCommon.EventType.ModelContentChangedFlush: + this._onLinesFlushed(contentChangedEvent); + changed = true; break; - case EditorCommon.EventType.ModelPropertiesChanged: - this._extraProperties = (e).properties; + case EditorCommon.EventType.ModelContentChangedLinesDeleted: + this._onLinesDeleted(contentChangedEvent); + changed = true; break; - default: - console.warn('Unknown model event: ' + e.type); + case EditorCommon.EventType.ModelContentChangedLinesInserted: + this._onLinesInserted(contentChangedEvent); + changed = true; + break; + + case EditorCommon.EventType.ModelContentChangedLineChanged: + this._onLineChanged(contentChangedEvent); + changed = true; + break; } } diff --git a/src/vs/editor/common/model/textModelWithTokens.ts b/src/vs/editor/common/model/textModelWithTokens.ts index 5fe1014ad81..68bbe2e023f 100644 --- a/src/vs/editor/common/model/textModelWithTokens.ts +++ b/src/vs/editor/common/model/textModelWithTokens.ts @@ -185,7 +185,7 @@ export class TextModelWithTokens extends TextModel implements EditorCommon.IToke private static MODE_TOKENIZATION_FAILED_MSG = nls.localize('mode.tokenizationSupportFailed', "The mode has failed while tokenizing the input."); private static MODEL_SYNC_LIMIT = 5 * 1024 * 1024; // 5 MB - private static MODEL_TOKENIZATION_LIMIT = 50 * 1024 * 1024; // 50 MB + private static MODEL_TOKENIZATION_LIMIT = 20 * 1024 * 1024; // 20 MB private _shouldAutoTokenize:boolean; private _mode: Modes.IMode; @@ -262,12 +262,20 @@ export class TextModelWithTokens extends TextModel implements EditorCommon.IToke super.dispose(); } + public isTooLargeForHavingAMode(): boolean { + return this._shouldDenyMode; + } + + public isTooLargeForHavingARichMode(): boolean { + return this._shouldSimplifyMode; + } + private _massageMode(mode: Modes.IMode): Modes.IMode { - if (this._shouldDenyMode) { + if (this.isTooLargeForHavingAMode()) { return new NullMode(); } - if (this._shouldSimplifyMode) { - return new SimplifiedMode(mode); + if (this.isTooLargeForHavingARichMode()) { + return mode.toSimplifiedMode(); } return mode; } @@ -856,27 +864,3 @@ export class TextModelWithTokens extends TextModel implements EditorCommon.IToke return BracketsHelper.matchBracket(this, this.validatePosition(position), inaccurateResultAcceptable); } } - -class SimplifiedMode implements Modes.IMode { - - tokenizationSupport: Modes.ITokenizationSupport; - electricCharacterSupport: Modes.IElectricCharacterSupport; - commentsSupport: Modes.ICommentsSupport; - characterPairSupport: Modes.ICharacterPairSupport; - tokenTypeClassificationSupport: Modes.ITokenTypeClassificationSupport; - - private _id: string; - - constructor(sourceMode: Modes.IMode) { - this._id = 'vs.editor.modes.simplifiedMode:' + sourceMode.getId(); - this.tokenizationSupport = sourceMode.tokenizationSupport; - this.electricCharacterSupport = sourceMode.electricCharacterSupport; - this.commentsSupport = sourceMode.commentsSupport; - this.characterPairSupport = sourceMode.characterPairSupport; - this.tokenTypeClassificationSupport = sourceMode.tokenTypeClassificationSupport; - } - - public getId(): string { - return this._id; - } -} \ No newline at end of file diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 0b901ead07e..45a94068f00 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -197,6 +197,11 @@ export interface IMode { getId(): string; + /** + * Return a mode "similar" to this one that strips any "smart" supports. + */ + toSimplifiedMode(): IMode; + addSupportChangedListener?(callback: (e: EditorCommon.IModeSupportChangedEvent) => void): IDisposable; /** diff --git a/src/vs/editor/common/modes/abstractMode.ts b/src/vs/editor/common/modes/abstractMode.ts index 211c8460392..6dc61e14b12 100644 --- a/src/vs/editor/common/modes/abstractMode.ts +++ b/src/vs/editor/common/modes/abstractMode.ts @@ -49,6 +49,7 @@ export class AbstractMode implements Modes.IMode { // adapters end private _eventEmitter = new EventEmitter(); + private _simplifiedMode: Modes.IMode; constructor( descriptor:Modes.IModeDescriptor, @@ -73,6 +74,7 @@ export class AbstractMode implements Modes.IMode { this.tokenTypeClassificationSupport = this; this._workerPiecePromise = null; + this._simplifiedMode = null; } public getId(): string { @@ -86,6 +88,13 @@ export class AbstractMode implements Modes.IMode { } } + public toSimplifiedMode(): Modes.IMode { + if (!this._simplifiedMode) { + this._simplifiedMode = new SimplifiedMode(this); + } + return this._simplifiedMode; + } + private _getOrCreateWorker(): TPromise { if (!this._workerPiecePromise) { var workerDescriptor: AsyncDescriptor2 = this._getWorkerDescriptor(); @@ -236,7 +245,84 @@ export class AbstractMode implements Modes.IMode { } } +class SimplifiedMode implements Modes.IMode { + tokenizationSupport: Modes.ITokenizationSupport; + electricCharacterSupport: Modes.IElectricCharacterSupport; + commentsSupport: Modes.ICommentsSupport; + characterPairSupport: Modes.ICharacterPairSupport; + tokenTypeClassificationSupport: Modes.ITokenTypeClassificationSupport; + onEnterSupport: Modes.IOnEnterSupport; + + private _sourceMode: Modes.IMode; + private _eventEmitter: EventEmitter; + private _id: string; + + constructor(sourceMode: Modes.IMode) { + this._sourceMode = sourceMode; + this._eventEmitter = new EventEmitter(); + this._id = 'vs.editor.modes.simplifiedMode:' + sourceMode.getId(); + this._assignSupports(); + + if (this._sourceMode.addSupportChangedListener) { + this._sourceMode.addSupportChangedListener((e) => { + if (e.tokenizationSupport || e.electricCharacterSupport || e.commentsSupport || e.characterPairSupport || e.tokenTypeClassificationSupport || e.onEnterSupport) { + this._assignSupports(); + let newEvent = SimplifiedMode._createModeSupportChangedEvent(e); + this._eventEmitter.emit('modeSupportChanged', newEvent); + } + }) + } + } + + public getId(): string { + return this._id; + } + + public toSimplifiedMode(): Modes.IMode { + return this; + } + + private _assignSupports(): void { + this.tokenizationSupport = this._sourceMode.tokenizationSupport; + this.electricCharacterSupport = this._sourceMode.electricCharacterSupport; + this.commentsSupport = this._sourceMode.commentsSupport; + this.characterPairSupport = this._sourceMode.characterPairSupport; + this.tokenTypeClassificationSupport = this._sourceMode.tokenTypeClassificationSupport; + this.onEnterSupport = this._sourceMode.onEnterSupport; + } + + private static _createModeSupportChangedEvent(originalModeEvent:EditorCommon.IModeSupportChangedEvent): EditorCommon.IModeSupportChangedEvent { + var event = { + codeLensSupport: false, + tokenizationSupport: originalModeEvent.tokenizationSupport, + occurrencesSupport:false, + declarationSupport:false, + typeDeclarationSupport:false, + navigateTypesSupport:false, + referenceSupport:false, + suggestSupport:false, + parameterHintsSupport:false, + extraInfoSupport:false, + outlineSupport:false, + logicalSelectionSupport:false, + formattingSupport:false, + inplaceReplaceSupport:false, + diffSupport:false, + dirtyDiffSupport:false, + emitOutputSupport:false, + linkSupport:false, + configSupport:false, + electricCharacterSupport: originalModeEvent.electricCharacterSupport, + commentsSupport: originalModeEvent.commentsSupport, + characterPairSupport: originalModeEvent.characterPairSupport, + tokenTypeClassificationSupport: originalModeEvent.tokenTypeClassificationSupport, + quickFixSupport:false, + onEnterSupport: originalModeEvent.onEnterSupport + }; + return event; + } +} export var isDigit:(character:string, base:number)=>boolean = (function () { diff --git a/src/vs/editor/common/modes/nullMode.ts b/src/vs/editor/common/modes/nullMode.ts index 4e6c80f0846..36e82233517 100644 --- a/src/vs/editor/common/modes/nullMode.ts +++ b/src/vs/editor/common/modes/nullMode.ts @@ -91,6 +91,10 @@ export class NullMode implements Modes.IMode { return NullMode.ID; } + public toSimplifiedMode(): Modes.IMode { + return this; + } + public getWordDefinition():RegExp { return NullMode.DEFAULT_WORD_REGEXP; } diff --git a/src/vs/editor/common/services/modelService.ts b/src/vs/editor/common/services/modelService.ts index 28f98765657..880bc5f1e29 100644 --- a/src/vs/editor/common/services/modelService.ts +++ b/src/vs/editor/common/services/modelService.ts @@ -21,8 +21,6 @@ export interface IModelService { destroyModel(resource: URL): void; - removeModel(model: EditorCommon.IModel): void; - getModels(): EditorCommon.IModel[]; getModel(resource: URI): EditorCommon.IModel; diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index 3c985effdb7..ef7b5e1c5cf 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -7,7 +7,7 @@ import {IEmitterEvent} from 'vs/base/common/eventEmitter'; import {IModeService} from 'vs/editor/common/services/modeService'; import {IMarker, IMarkerService} from 'vs/platform/markers/common/markers'; -import {MirrorModel} from 'vs/editor/common/model/mirrorModel'; +import {IMirrorModelEvents, MirrorModel} from 'vs/editor/common/model/mirrorModel'; import {Range} from 'vs/editor/common/core/range'; import EditorCommon = require('vs/editor/common/editorCommon'); import Modes = require('vs/editor/common/modes'); @@ -21,7 +21,7 @@ import URI from 'vs/base/common/uri'; import {URL} from 'vs/base/common/network'; import Severity from 'vs/base/common/severity'; import {EventProvider} from 'vs/base/common/eventProvider'; -import {IDisposable} from 'vs/base/common/lifecycle'; +import {IDisposable, disposeAll} from 'vs/base/common/lifecycle'; import {TPromise} from 'vs/base/common/winjs.base'; import Errors = require('vs/base/common/errors'); import {anonymize} from 'vs/platform/telemetry/common/telemetry'; @@ -35,53 +35,69 @@ export interface IRawModelData { modeId:string; } -class BoundModel implements IDisposable { +function MODEL_ID(resource:URI): string { + return resource.toString(); +} - model:EditorCommon.IModel; - toUnbind:Function; - private _decorationIds: string[]; +class ModelData implements IDisposable { + model: EditorCommon.IModel; + isSyncedToWorkers: boolean; - constructor(model:EditorCommon.IModel) { + private _markerDecorations: string[]; + private _modelEventsListener: IDisposable; + + constructor(model: EditorCommon.IModel, eventsHandler:(modelData:ModelData, events:IEmitterEvent[])=>void) { this.model = model; - this.toUnbind = null; + this.isSyncedToWorkers = false; + + this._markerDecorations = []; + this._modelEventsListener = model.addBulkListener2((events) => eventsHandler(this, events)); } public dispose(): void { - - this._decorationIds = this.model.deltaDecorations(this._decorationIds, []); + this._markerDecorations = this.model.deltaDecorations(this._markerDecorations, []); + this._modelEventsListener.dispose(); + this._modelEventsListener = null; this.model = null; - - if (this.toUnbind) { - this.toUnbind(); - this.toUnbind = null; - } } - public deltaMarkers(markers:IMarker[]):void { + public getModelId(): string { + return MODEL_ID(this.model.getAssociatedResource()); + } + + public acceptMarkerDecorations(newDecorations:EditorCommon.IModelDeltaDecoration[]): void { + this._markerDecorations = this.model.deltaDecorations(this._markerDecorations, newDecorations); + } +} + +class ModelMarkerHandler { + + public static setMarkers(modelData:ModelData, markers:IMarker[]):void { // Limit to the first 500 errors/warnings markers = markers.slice(0, 500); - var newModelDecorations = markers.map(marker => { - return { - range: this._createDecorationRange(marker), + let newModelDecorations:EditorCommon.IModelDeltaDecoration[] = markers.map((marker) => { + return { + range: this._createDecorationRange(modelData.model, marker), options: this._createDecorationOption(marker) }; }); - this._decorationIds = this.model.deltaDecorations(this._decorationIds, newModelDecorations); + + modelData.acceptMarkerDecorations(newModelDecorations); } - private _createDecorationRange(rawMarker: IMarker): EditorCommon.IRange { - var marker = this.model.validateRange(new Range(rawMarker.startLineNumber, rawMarker.startColumn, rawMarker.endLineNumber, rawMarker.endColumn)); - var ret: EditorCommon.IEditorRange = new Range(marker.startLineNumber, marker.startColumn, marker.endLineNumber, marker.endColumn); + private static _createDecorationRange(model:EditorCommon.IModel, rawMarker: IMarker): EditorCommon.IRange { + let marker = model.validateRange(new Range(rawMarker.startLineNumber, rawMarker.startColumn, rawMarker.endLineNumber, rawMarker.endColumn)); + let ret: EditorCommon.IEditorRange = new Range(marker.startLineNumber, marker.startColumn, marker.endLineNumber, marker.endColumn); if (ret.isEmpty()) { - var word = this.model.getWordAtPosition(ret.getStartPosition()); + let word = model.getWordAtPosition(ret.getStartPosition()); if (word) { ret.startColumn = word.startColumn; ret.endColumn = word.endColumn; } else { - var maxColumn = this.model.getLineLastNonWhitespaceColumn(marker.startLineNumber) || - this.model.getLineMaxColumn(marker.startLineNumber); + let maxColumn = model.getLineLastNonWhitespaceColumn(marker.startLineNumber) || + model.getLineMaxColumn(marker.startLineNumber); if (maxColumn === 1) { // empty line @@ -96,7 +112,7 @@ class BoundModel implements IDisposable { } } } else if (rawMarker.endColumn === Number.MAX_VALUE && rawMarker.startColumn === 1 && ret.startLineNumber === ret.endLineNumber) { - var minColumn = this.model.getLineFirstNonWhitespaceColumn(rawMarker.startLineNumber); + let minColumn = model.getLineFirstNonWhitespaceColumn(rawMarker.startLineNumber); if (minColumn < ret.endColumn) { ret.startColumn = minColumn; rawMarker.startColumn = minColumn; @@ -105,7 +121,7 @@ class BoundModel implements IDisposable { return ret; } - private _createDecorationOption(marker:IMarker): EditorCommon.IModelDecorationOptions { + private static _createDecorationOption(marker:IMarker): EditorCommon.IModelDecorationOptions { let className: string; let color: string; @@ -151,14 +167,9 @@ class BoundModel implements IDisposable { } } -export interface IModelsEvents { - [url:string]: any[]; -} - export class ModelServiceImpl implements IModelService { public serviceId = IModelService; - private _models: {[modelId:string]:BoundModel;}; private _markerService: IMarkerService; private _markerServiceSubscription: IDisposable; private _threadService: IThreadService; @@ -167,9 +178,11 @@ export class ModelServiceImpl implements IModelService { private _onModelAdded: EventSource<(model: EditorCommon.IModel) => void>; private _onModelRemoved: EventSource<(model: EditorCommon.IModel) => void>; private _onModelModeChanged: EventSource<(model: EditorCommon.IModel, oldModeId:string) => void>; - private _accumulatedModelEvents: IModelsEvents; - private _lastSentModelEventsTime: number; - private _sendModelEventsTimerId: number; + + /** + * All the models known in the system. + */ + private _models: {[modelId:string]:ModelData;}; constructor(threadService: IThreadService, markerService: IMarkerService) { this._threadService = threadService; @@ -185,137 +198,75 @@ export class ModelServiceImpl implements IModelService { if(this._markerService) { this._markerServiceSubscription = this._markerService.onMarkerChanged(this._handleMarkerChange, this); } - - this._accumulatedModelEvents = {}; - this._lastSentModelEventsTime = -1; - this._sendModelEventsTimerId = -1; } public dispose(): void { if(this._markerServiceSubscription) { this._markerServiceSubscription.dispose(); } - if (this._sendModelEventsTimerId !== -1) { - clearTimeout(this._sendModelEventsTimerId); - this._sendModelEventsTimerId = -1; - } - } - - private _sendModelEvents(url:URL, events:any[]): void { - let modelId = url.toString(); - this._accumulatedModelEvents[modelId] = this._accumulatedModelEvents[modelId] || []; - this._accumulatedModelEvents[modelId] = this._accumulatedModelEvents[modelId].concat(events); - - this._sendModelEventsNow(); - // this._scheduleSendModelEvents(); - } - - // private _scheduleSendModelEvents(): void { - // if (this._sendModelEventsTimerId !== -1) { - // // sending model events already scheduled - // return; - // } - - // let elapsed = Date.now() - this._lastSentModelEventsTime; - // if (elapsed >= 100) { - // // more than 100ms have passed since last model events have been sent => send events now - // this._sendModelEventsNow(); - // } else { - // this._sendModelEventsTimerId = setTimeout(() => { - // this._sendModelEventsTimerId = -1; - // this._sendModelEventsNow(); - // }, 100 - elapsed); - // } - // } - - private _sendModelEventsNow(): void { - this._lastSentModelEventsTime = Date.now(); - - let sendingEvents = this._accumulatedModelEvents; - this._accumulatedModelEvents = {}; - this._workerHelper.$onModelsEvents(sendingEvents); } private _handleMarkerChange(changedResources: URI[]): void { - - changedResources.forEach(resource => { - var boundModel = this._models[resource.toString()]; - if (!boundModel) { + changedResources.forEach((resource) => { + let modelId = MODEL_ID(resource); + let modelData = this._models[modelId]; + if (!modelData) { return; } - boundModel.deltaMarkers(this._markerService.read({ resource: resource, take: 500 })); + ModelMarkerHandler.setMarkers(modelData, this._markerService.read({ resource: resource, take: 500 })); }); } // --- begin IModelService - public createModel(value:string, modeOrPromise:TPromise|Modes.IMode, resource: URL): EditorCommon.IModel { - var model = new Model(value, modeOrPromise, resource); - this.addModel(model); - return model; - } - - public addModel(model:EditorCommon.IModel): void { - var modelId = model.getAssociatedResource().toString(); + private _createModelData(value:string, modeOrPromise:TPromise|Modes.IMode, resource: URL): ModelData { + // create & save the model + let model = new Model(value, modeOrPromise, resource); + let modelId = MODEL_ID(model.getAssociatedResource()); if (this._models[modelId]) { // There already exists a model with this id => this is a programmer error - throw new Error('BoundModels: Cannot add model ' + anonymize(modelId) + ' because it already exists!'); + throw new Error('ModelService: Cannot add model ' + anonymize(modelId) + ' because it already exists!'); } - var boundModel = new BoundModel(model); + let modelData = new ModelData(model, (modelData, events) => this._onModelEvents(modelData, events)); + this._models[modelId] = modelData; - boundModel.toUnbind = model.addBulkListener((events) => this._onModelEvents(modelId, events)); - if(this._markerService) { - boundModel.deltaMarkers(this._markerService.read({ resource: model.getAssociatedResource() })); - } - this._models[modelId] = boundModel; - - // Create model in workers - this._workerHelper.$createModel(ModelServiceImpl._getBoundModelData(model)); - this._onModelAdded.fire(model); + return modelData; } - public removeModel(model:EditorCommon.IModel): void { - var modelId = model.getAssociatedResource().toString(); - - if (this._accumulatedModelEvents[modelId]) { - delete this._accumulatedModelEvents[modelId]; - } - - if (!this._models[modelId]) { - // There is no model with this id => this is a programmer error - throw new Error('BoundModels: Cannot remove model ' + anonymize(modelId) + ' because it doesn\'t exist!'); - } - - // Dispose model in workers - this._workerHelper.$disposeModel(model.getAssociatedResource()); - // this._modelDispose(model.getAssociatedResource()); - this._models[modelId].dispose(); - - delete this._models[modelId]; + public createModel(value:string, modeOrPromise:TPromise|Modes.IMode, resource: URL): EditorCommon.IModel { + let modelData = this._createModelData(value, modeOrPromise, resource); + let modelId = modelData.getModelId(); + // handle markers (marker service => model) if (this._markerService) { - var markers = this._markerService.read({ resource: model.getAssociatedResource() }), - owners: { [o: string]: any } = Object.create(null); - - markers.forEach(marker => owners[marker.owner] = this); - Object.keys(owners).forEach(owner => this._markerService.changeOne(owner, model.getAssociatedResource(), [])); + ModelMarkerHandler.setMarkers(modelData, this._markerService.read({ resource: modelData.model.getAssociatedResource() })); } - this._onModelRemoved.fire(model); + if (!modelData.model.isTooLargeForHavingARichMode()) { + // send this model to the workers + modelData.isSyncedToWorkers = true; + this._workerHelper.$_acceptNewModel(ModelServiceImpl._getBoundModelData(modelData.model)); + } + + this._onModelAdded.fire(modelData.model); + + return modelData.model; } public destroyModel(resource: URL): void { - let model = this.getModel(resource); - if (model) { - model.destroy(); + // We need to support that not all models get disposed through this service (i.e. model.dispose() should work!) + let modelData = this._models[MODEL_ID(resource)]; + if (!modelData) { + return; } + modelData.model.dispose(); } public getModels(): EditorCommon.IModel[] { - var ret: EditorCommon.IModel[] = []; - for (var modelId in this._models) { + let ret: EditorCommon.IModel[] = []; + for (let modelId in this._models) { if (this._models.hasOwnProperty(modelId)) { ret.push(this._models[modelId].model); } @@ -324,11 +275,12 @@ export class ModelServiceImpl implements IModelService { } public getModel(resource: URL): EditorCommon.IModel { - var boundModel = this._models[resource.toString()]; - if (boundModel) { - return boundModel.model; + let modelId = MODEL_ID(resource); + let modelData = this._models[modelId]; + if (!modelData) { + return null; } - return null; + return modelData.model; } public get onModelAdded(): EventProvider<(model:EditorCommon.IModel)=>void> { @@ -345,6 +297,30 @@ export class ModelServiceImpl implements IModelService { // --- end IModelService + private _onModelDisposing(model:EditorCommon.IModel): void { + let modelId = MODEL_ID(model.getAssociatedResource()); + let modelData = this._models[modelId]; + + // TODO@Joh why are we removing markers here? + if (this._markerService) { + var markers = this._markerService.read({ resource: model.getAssociatedResource() }), + owners: { [o: string]: any } = Object.create(null); + + markers.forEach(marker => owners[marker.owner] = this); + Object.keys(owners).forEach(owner => this._markerService.changeOne(owner, model.getAssociatedResource(), [])); + } + + if (modelData.isSyncedToWorkers) { + // Dispose model in workers + this._workerHelper.$_acceptDidDisposeModel(model.getAssociatedResource()); + } + + delete this._models[modelId]; + modelData.dispose(); + + this._onModelRemoved.fire(model); + } + private static _getBoundModelData(model:EditorCommon.IModel): IRawModelData { return { url: model.getAssociatedResource(), @@ -355,67 +331,47 @@ export class ModelServiceImpl implements IModelService { }; } - private _onModelEvents(modelId:string, events:IEmitterEvent[]): void { + private _onModelEvents(modelData:ModelData, events:IEmitterEvent[]): void { + let eventsForWorkers: IMirrorModelEvents = { contentChanged: [], propertiesChanged: null }; - var resultingEvents:any[] = [], - changed = false, - i:number, - len:number; + for (let i = 0, len = events.length; i < len; i++) { + let e = events[i]; + let data = e.getData(); - for (i = 0, len = events.length; i < len; i++) { - var e = events[i]; - var data = e.getData(); switch (e.getType()) { - case EditorCommon.EventType.ModelDispose: - this.removeModel(this._models[modelId].model); + this._onModelDisposing(modelData.model); + // no more event processing return; case EditorCommon.EventType.ModelContentChanged: - switch (data.changeType) { - case EditorCommon.EventType.ModelContentChangedFlush: - resultingEvents.push(this._mixinProperties({ type: e.getType() }, data, ['changeType', 'detail', 'versionId'])); - break; - - case EditorCommon.EventType.ModelContentChangedLinesDeleted: - resultingEvents.push(this._mixinProperties({ type: e.getType() }, data, ['changeType', 'fromLineNumber', 'toLineNumber', 'versionId'])); - break; - - case EditorCommon.EventType.ModelContentChangedLinesInserted: - resultingEvents.push(this._mixinProperties({ type: e.getType() }, data, ['changeType', 'fromLineNumber', 'toLineNumber', 'detail', 'versionId'])); - break; - - case EditorCommon.EventType.ModelContentChangedLineChanged: - resultingEvents.push(this._mixinProperties({ type: e.getType() }, data, ['changeType', 'lineNumber', 'detail', 'versionId'])); - break; + if (modelData.isSyncedToWorkers) { + eventsForWorkers.contentChanged.push(data); } - changed = true; break; case EditorCommon.EventType.ModelPropertiesChanged: - resultingEvents.push(this._mixinProperties({ type: e.getType() }, data, ['properties'])); + if (modelData.isSyncedToWorkers) { + eventsForWorkers.propertiesChanged = data; + } break; case EditorCommon.EventType.ModelModeChanged: let modeChangedEvent = data; - this._workerHelper.$onModelModeChanged(modelId, modeChangedEvent.oldMode.getId(), modeChangedEvent.newMode.getId()); - this._onModelModeChanged.fire(this._models[modelId].model, modeChangedEvent.oldMode.getId()); + if (modelData.isSyncedToWorkers) { + // Forward mode change to all the workers + this._workerHelper.$_acceptDidChangeModelMode(modelData.getModelId(), modeChangedEvent.oldMode.getId(), modeChangedEvent.newMode.getId()); + } + this._onModelModeChanged.fire(modelData.model, modeChangedEvent.oldMode.getId()); break; } } - if (resultingEvents.length > 0) { + if (eventsForWorkers.contentChanged.length > 0 || eventsForWorkers.propertiesChanged) { // Forward events to all the workers - this._sendModelEvents(this._models[modelId].model.getAssociatedResource(), resultingEvents); + this._workerHelper.$_acceptModelEvents(modelData.getModelId(), eventsForWorkers); } } - - private _mixinProperties(dst:any, src:any, properties:string[]): any { - for (var i = 0; i < properties.length; i++) { - dst[properties[i]] = src[properties[i]]; - } - return dst; - } } @Remotable.WorkerContext('ModelServiceWorkerHelper', ThreadAffinity.All) @@ -432,9 +388,9 @@ export class ModelServiceWorkerHelper { this._modeService = modeService; } - public $createModel(data:IRawModelData): TPromise { + public $_acceptNewModel(data:IRawModelData): TPromise { // Create & insert the mirror model eagerly in the resource service - var mirrorModel = new MirrorModel(this._resourceService, data.versionId, data.value, null, data.url, data.properties); + let mirrorModel = new MirrorModel(this._resourceService, data.versionId, data.value, null, data.url, data.properties); this._resourceService.insert(mirrorModel.getAssociatedResource(), mirrorModel); // Block worker execution until the mode is instantiated @@ -452,8 +408,8 @@ export class ModelServiceWorkerHelper { }); } - public $onModelModeChanged(modelId:string, oldModeId:string, newModeId:string): TPromise { - var mirrorModel = this._resourceService.get(URI.parse(modelId)); + public $_acceptDidChangeModelMode(modelId:string, oldModeId:string, newModeId:string): TPromise { + let mirrorModel = this._resourceService.get(URI.parse(modelId)); // Block worker execution until the mode is instantiated return this._modeService.getOrCreateMode(newModeId).then((mode) => { @@ -470,31 +426,23 @@ export class ModelServiceWorkerHelper { }); } - public $disposeModel(url:URL): void { - var model = this._resourceService.get(url); + public $_acceptDidDisposeModel(url:URL): void { + let model = this._resourceService.get(url); this._resourceService.remove(url); if (model) { model.dispose(); } } - public $onModelsEvents(events:IModelsEvents): void { - let missingModels: string[] = []; - Object.keys(events).forEach((strURL:string) => { - var model = this._resourceService.get(new URL(strURL)); - if (!model) { - missingModels.push(strURL); - return; - } - try { - model.onEvents(events[strURL]); - } catch (err) { - Errors.onUnexpectedError(err); - } - }); - - if (missingModels.length > 0) { - throw new Error('Received model events for missing models ' + missingModels.map(anonymize).join(' AND ')); + public $_acceptModelEvents(modelId: string, events:IMirrorModelEvents): void { + let model = this._resourceService.get(new URL(modelId)); + if (!model) { + throw new Error('Received model events for missing model ' + anonymize(modelId)); + } + try { + model.onEvents(events); + } catch (err) { + Errors.onUnexpectedError(err); } } } diff --git a/src/vs/editor/test/common/model/editableTextModel.test.ts b/src/vs/editor/test/common/model/editableTextModel.test.ts index 75c6088e86f..c1f09732675 100644 --- a/src/vs/editor/test/common/model/editableTextModel.test.ts +++ b/src/vs/editor/test/common/model/editableTextModel.test.ts @@ -13,7 +13,7 @@ import {TextModel} from 'vs/editor/common/model/textModel'; import {LineMarker, TextModelWithMarkers} from 'vs/editor/common/model/textModelWithMarkers'; import {ILineMarker} from 'vs/editor/common/model/modelLine'; import {PluginHostDocument} from 'vs/workbench/api/common/pluginHostDocuments'; -import {MirrorModel} from 'vs/editor/common/model/mirrorModel'; +import {MirrorModel, IMirrorModelEvents} from 'vs/editor/common/model/mirrorModel'; suite('EditorModel - EditableTextModel._getInverseEdits', () => { @@ -1194,8 +1194,11 @@ suite('EditorModel - EditableTextModel.applyEdits', () => { console.warn('Model version id did not advance between edits (1)'); } mirrorModel1PrevVersionId = versionId; - (e).type = EditorCommon.EventType.ModelContentChanged; - mirrorModel1.onEvents([e]); + let mirrorModelEvents:IMirrorModelEvents = { + propertiesChanged: null, + contentChanged: [e] + }; + mirrorModel1.onEvents(mirrorModelEvents); }); model.addListener(EditorCommon.EventType.ModelContentChanged2, (e:EditorCommon.IModelContentChangedEvent2) => { diff --git a/src/vs/editor/test/common/model/mirrorModel.test.ts b/src/vs/editor/test/common/model/mirrorModel.test.ts index 60b60229cd2..bbc608fa292 100644 --- a/src/vs/editor/test/common/model/mirrorModel.test.ts +++ b/src/vs/editor/test/common/model/mirrorModel.test.ts @@ -21,6 +21,57 @@ function equalRange(left, right) { assert.ok(true, 'ranges'); }; +function contentChangedFlushEvent(detail: EditorCommon.IRawText): EditorCommon.IModelContentChangedFlushEvent { + return { + changeType: EditorCommon.EventType.ModelContentChangedFlush, + isRedoing: false, + isUndoing: false, + versionId: 0, + detail: detail + }; +} + +function contentChangedLinesDeletedEvent(fromLineNumber: number, toLineNumber: number): EditorCommon.IModelContentChangedLinesDeletedEvent { + return { + changeType: EditorCommon.EventType.ModelContentChangedLinesDeleted, + isRedoing: false, + isUndoing: false, + versionId: 0, + fromLineNumber: fromLineNumber, + toLineNumber: toLineNumber + }; +} + +function contentChangedLinesInsertedEvent(fromLineNumber: number, toLineNumber: number, detail: string): EditorCommon.IModelContentChangedLinesInsertedEvent { + return { + changeType: EditorCommon.EventType.ModelContentChangedLinesInserted, + isRedoing: false, + isUndoing: false, + versionId: 0, + fromLineNumber: fromLineNumber, + toLineNumber: toLineNumber, + detail: detail + }; +} + +function contentChangedLineChanged(lineNumber: number, detail: string): EditorCommon.IModelContentChangedLineChangedEvent { + return { + changeType: EditorCommon.EventType.ModelContentChangedLineChanged, + isRedoing: false, + isUndoing: false, + versionId: 0, + lineNumber: lineNumber, + detail: detail + }; +} + +function mirrorModelEvents(contentChanged:EditorCommon.IModelContentChangedEvent[]): MirrorModel.IMirrorModelEvents { + return { + propertiesChanged: null, + contentChanged: contentChanged + }; +} + suite('Editor Model - MirrorModel', () => { var mirrorModel:MirrorModel.MirrorModel; @@ -46,19 +97,16 @@ suite('Editor Model - MirrorModel', () => { assert.equal(mirrorModel.getLineStart(2), 6); assert.equal(mirrorModel.getLineStart(3), 12); - var e = { - type: EditorCommon.EventType.ModelContentChanged, - changeType: EditorCommon.EventType.ModelContentChangedFlush, - detail: { - lines: [ - 'foo', - 'bar' - ], - BOM: '', - EOL: '\n' - } - }; - mirrorModel.onEvents([e]); + mirrorModel.onEvents(mirrorModelEvents([contentChangedFlushEvent({ + length: -1, + lines: [ + 'foo', + 'bar' + ], + BOM: '', + EOL: '\n' + })])); + assert.equal(mirrorModel.getLineStart(1), 0); assert.equal(mirrorModel.getLineStart(2), 4); }); @@ -170,14 +218,9 @@ suite('Editor Model - MirrorModel Eventing', () => { }); test('delete single line', () => { - var e = { - type: EditorCommon.EventType.ModelContentChanged, - changeType: EditorCommon.EventType.ModelContentChangedLinesDeleted, - fromLineNumber: 3, - toLineNumber: 3 - }; assert.equal(mirrorModel.getLineContent(3), 'line three'); - mirrorModel.onEvents([e]); + + mirrorModel.onEvents(mirrorModelEvents([contentChangedLinesDeletedEvent(3, 3)])); assert.equal(mirrorModel.getLineContent(3), 'line four'); var words = mirrorModel.getAllWords(); @@ -191,13 +234,8 @@ suite('Editor Model - MirrorModel Eventing', () => { }); test('delete multiple lines', () => { - var e = { - type: EditorCommon.EventType.ModelContentChanged, - changeType: EditorCommon.EventType.ModelContentChangedLinesDeleted, - fromLineNumber: 1, - toLineNumber: 2 - }; - mirrorModel.onEvents([e]); + mirrorModel.onEvents(mirrorModelEvents([contentChangedLinesDeletedEvent(1, 2)])); + assert.equal(mirrorModel.getLineContent(1), 'line three'); assert.equal(mirrorModel.getLineContent(2), 'line four'); var words = mirrorModel.getAllWords(); @@ -220,13 +258,8 @@ suite('Editor Model - MirrorModel Eventing', () => { }); test('delete all lines', () => { - var e = { - type: EditorCommon.EventType.ModelContentChanged, - changeType: EditorCommon.EventType.ModelContentChangedLinesDeleted, - fromLineNumber: 1, - toLineNumber: 4 - }; - mirrorModel.onEvents([e]); + mirrorModel.onEvents(mirrorModelEvents([contentChangedLinesDeletedEvent(1, 4)])); + var words = mirrorModel.getAllWords(); assert.equal(words.length, 0); var wordsWithRanges = mirrorModel.getAllWordsWithRange(); @@ -234,16 +267,10 @@ suite('Editor Model - MirrorModel Eventing', () => { }); test('add single lines', () => { - var e = { - type: EditorCommon.EventType.ModelContentChanged, - changeType: EditorCommon.EventType.ModelContentChangedLinesInserted, - fromLineNumber: 1, - toLineNumber: 1, - detail: 'foo bar\nbar foo' - }; - assert.equal(mirrorModel.getLineContent(1), 'line one'); - mirrorModel.onEvents([e]); + + mirrorModel.onEvents(mirrorModelEvents([contentChangedLinesInsertedEvent(1, 1, 'foo bar\nbar foo')])); + assert.equal(mirrorModel.getLineContent(1), 'foo bar'); assert.equal(mirrorModel.getLineContent(2), 'line one'); @@ -257,16 +284,10 @@ suite('Editor Model - MirrorModel Eventing', () => { test('add multiple lines', () => { - var e = { - type: EditorCommon.EventType.ModelContentChanged, - changeType: EditorCommon.EventType.ModelContentChangedLinesInserted, - fromLineNumber: 1, - toLineNumber: 2, - detail: 'foo bar\nbar foo' - }; - assert.equal(mirrorModel.getLineContent(1), 'line one'); - mirrorModel.onEvents([e]); + + mirrorModel.onEvents(mirrorModelEvents([contentChangedLinesInsertedEvent(1, 2, 'foo bar\nbar foo')])); + assert.equal(mirrorModel.getLineContent(1), 'foo bar'); assert.equal(mirrorModel.getLineContent(2), 'bar foo'); assert.equal(mirrorModel.getLineContent(3), 'line one'); @@ -284,16 +305,11 @@ suite('Editor Model - MirrorModel Eventing', () => { }); test('change line', () => { - var e = { - type: EditorCommon.EventType.ModelContentChanged, - changeType: EditorCommon.EventType.ModelContentChangedLineChanged, - lineNumber: 1, - detail: 'foobar' - }; assert.equal(mirrorModel.getLineContent(1), 'line one'); var wordsWithRanges = mirrorModel.getAllWordsWithRange(); assert.equal(wordsWithRanges.length, 8); - mirrorModel.onEvents([e]); + + mirrorModel.onEvents(mirrorModelEvents([contentChangedLineChanged(1, 'foobar')])); assert.equal(mirrorModel.getLineContent(1), 'foobar'); wordsWithRanges = mirrorModel.getAllWordsWithRange(); @@ -305,19 +321,17 @@ suite('Editor Model - MirrorModel Eventing', () => { test('flush model', () => { assert.equal(mirrorModel.getLineContent(1), 'line one'); assert.equal(mirrorModel.getLineContent(2), 'line two'); - var e = { - type: EditorCommon.EventType.ModelContentChanged, - changeType: EditorCommon.EventType.ModelContentChangedFlush, - detail: { - lines: [ - 'foo', - 'bar' - ], - BOM: '', - EOL: '\n' - } - }; - mirrorModel.onEvents([e]); + + mirrorModel.onEvents(mirrorModelEvents([contentChangedFlushEvent({ + length: -1, + lines: [ + 'foo', + 'bar' + ], + BOM: '', + EOL: '\n' + })])); + assert.equal(mirrorModel.getLineContent(1), 'foo'); assert.equal(mirrorModel.getLineContent(2), 'bar'); var wordsWithRanges = mirrorModel.getAllWordsWithRange(); diff --git a/src/vs/editor/test/common/modes/textToHtmlTokenizer.test.ts b/src/vs/editor/test/common/modes/textToHtmlTokenizer.test.ts index 525767021ac..7451b1737cc 100644 --- a/src/vs/editor/test/common/modes/textToHtmlTokenizer.test.ts +++ b/src/vs/editor/test/common/modes/textToHtmlTokenizer.test.ts @@ -84,4 +84,8 @@ class Mode implements modes.IMode { public getId(): string { return "testMode"; } + + public toSimplifiedMode(): modes.IMode { + return this; + } } diff --git a/src/vs/editor/test/common/modes/tokenization.test.ts b/src/vs/editor/test/common/modes/tokenization.test.ts index b1416d43323..3854a550cef 100644 --- a/src/vs/editor/test/common/modes/tokenization.test.ts +++ b/src/vs/editor/test/common/modes/tokenization.test.ts @@ -44,6 +44,10 @@ export class Mode implements modes.IMode { public getId(): string { return "testMode"; } + + public toSimplifiedMode(): modes.IMode { + return this; + } } @@ -114,6 +118,10 @@ export class SwitchingMode implements modes.IMode { return this._id; } + public toSimplifiedMode(): modes.IMode { + return this; + } + public addSupportChangedListener(callback: (e: EditorCommon.IModeSupportChangedEvent) => void): IDisposable { return EmptyDisposable; } diff --git a/src/vs/editor/test/common/modesTestUtils.ts b/src/vs/editor/test/common/modesTestUtils.ts index ef974978919..cdb3a85aa35 100644 --- a/src/vs/editor/test/common/modesTestUtils.ts +++ b/src/vs/editor/test/common/modesTestUtils.ts @@ -7,6 +7,25 @@ import modes = require('vs/editor/common/modes'); import {Arrays} from 'vs/editor/common/core/arrays'; +class SimpleTokenTypeClassificationMode implements modes.IMode { + + private _id:string; + public tokenTypeClassificationSupport: modes.ITokenTypeClassificationSupport; + + constructor(id:string, tokenTypeClassificationSupport: modes.ITokenTypeClassificationSupport) { + this._id = id; + this.tokenTypeClassificationSupport = tokenTypeClassificationSupport; + } + + public getId(): string { + return this._id; + } + + public toSimplifiedMode(): modes.IMode { + return this; + } +} + export function createMockMode(id:string, wordRegExp:RegExp = null):modes.IMode { var tokenTypeClassificationSupport: modes.ITokenTypeClassificationSupport; if (wordRegExp) { @@ -14,10 +33,7 @@ export function createMockMode(id:string, wordRegExp:RegExp = null):modes.IMode getWordDefinition: () => wordRegExp }; } - return { - getId: () => id, - tokenTypeClassificationSupport: tokenTypeClassificationSupport - }; + return new SimpleTokenTypeClassificationMode(id, tokenTypeClassificationSupport); } export interface TokenText { diff --git a/src/vs/editor/test/common/modesUtil.ts b/src/vs/editor/test/common/modesUtil.ts index 4726b0ae1b6..5ea5bb37704 100644 --- a/src/vs/editor/test/common/modesUtil.ts +++ b/src/vs/editor/test/common/modesUtil.ts @@ -87,11 +87,28 @@ export interface IOnEnterAsserter { indentsOutdents(oneLineAboveText:string, beforeText:string, afterText:string): void; } +class SimpleMode implements modes.IMode { + + private _id:string; + + constructor(id:string) { + this._id = id; + } + + public getId(): string { + return this._id; + } + + public toSimplifiedMode(): modes.IMode { + return this; + } +} + export function createOnEnterAsserter(modeId:string, onEnterSupport: modes.IOnEnterSupport): IOnEnterAsserter { var assertOne = (oneLineAboveText:string, beforeText:string, afterText:string, expected: modes.IndentAction) => { var model = new Model( [ oneLineAboveText, beforeText + afterText ].join('\n'), - { getId: () => modeId } + new SimpleMode(modeId) ); var actual = onEnterSupport.onEnter(model, { lineNumber: 2, column: beforeText.length + 1 }); if (expected === modes.IndentAction.None) { @@ -130,9 +147,7 @@ export function executeMonarchTokenizationTests(name:string, language:monarchTyp var modeService = servicesUtil.createMockModeService(); - var tokenizationSupport = monarchLexer.createTokenizationSupport(modeService, { - getId: () => 'mock.mode' - }, lexer); + var tokenizationSupport = monarchLexer.createTokenizationSupport(modeService, new SimpleMode('mock.mode'), lexer); executeTests(tokenizationSupport, tests); } diff --git a/src/vs/editor/test/common/testModes.ts b/src/vs/editor/test/common/testModes.ts index af9503e0d68..e9c097da553 100644 --- a/src/vs/editor/test/common/testModes.ts +++ b/src/vs/editor/test/common/testModes.ts @@ -76,6 +76,10 @@ export class TestingMode implements modes.IMode { public getId():string { return 'testing'; } + + public toSimplifiedMode(): modes.IMode { + return this; + } } export class AbstractIndentingMode extends TestingMode { diff --git a/src/vs/languages/typescript.workbench/test/common/projectResolver.test.ts b/src/vs/languages/typescript.workbench/test/common/projectResolver.test.ts index fc695e0f373..1d357b685a5 100644 --- a/src/vs/languages/typescript.workbench/test/common/projectResolver.test.ts +++ b/src/vs/languages/typescript.workbench/test/common/projectResolver.test.ts @@ -62,7 +62,6 @@ function createModelService(): IModelService { onModelAdded: undefined, onModelRemoved: undefined, onModelModeChanged: undefined, - removeModel: undefined, destroyModel: undefined } } From b255288e3bbfad07060d2be41700a442ee0761f4 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2015 13:54:16 +0100 Subject: [PATCH 073/588] fixes #139 - don't sync large models to extension host --- src/vs/workbench/api/common/mainThreadEditors.ts | 2 ++ .../workbench/api/common/pluginHostDocuments.ts | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/vs/workbench/api/common/mainThreadEditors.ts b/src/vs/workbench/api/common/mainThreadEditors.ts index 42c1af89f5d..26cb2666dc2 100644 --- a/src/vs/workbench/api/common/mainThreadEditors.ts +++ b/src/vs/workbench/api/common/mainThreadEditors.ts @@ -335,6 +335,8 @@ export class MainThreadEditorsTracker { private _doUpdateMapping(): void { let allModels = this._modelService.getModels(); + // Same filter as in pluginHostDocuments + allModels.filter((model) => !model.isTooLargeForHavingARichMode()); let allModelsMap: { [modelUri:string]: EditorCommon.IModel; } = Object.create(null); allModels.forEach((model) => { allModelsMap[model.getAssociatedResource().toString()] = model; diff --git a/src/vs/workbench/api/common/pluginHostDocuments.ts b/src/vs/workbench/api/common/pluginHostDocuments.ts index be475ce66ff..0936720cb98 100644 --- a/src/vs/workbench/api/common/pluginHostDocuments.ts +++ b/src/vs/workbench/api/common/pluginHostDocuments.ts @@ -532,6 +532,7 @@ export class MainThreadDocuments { private _toDispose: IDisposable[]; private _modelToDisposeMap: {[modelUrl:string]:IDisposable;}; private _proxy: PluginHostModelService; + private _modelIsSynced: {[modelId:string]:boolean;}; constructor( @IThreadService threadService: IThreadService, @@ -547,6 +548,7 @@ export class MainThreadDocuments { this._fileService = fileService; this._untitledEditorService = untitledEditorService; this._proxy = threadService.getRemotable(PluginHostModelService); + this._modelIsSynced = {}; this._toDispose = []; modelService.onModelAdded.add(this._onModelAdded, this, this._toDispose); @@ -575,7 +577,13 @@ export class MainThreadDocuments { } private _onModelAdded(model: EditorCommon.IModel): void { + // Same filter as in mainThreadEditors + if (model.isTooLargeForHavingARichMode()) { + // don't synchronize too large models + return null; + } let modelUrl = model.getAssociatedResource(); + this._modelIsSynced[modelUrl.toString()] = true; this._modelToDisposeMap[modelUrl.toString()] = model.addBulkListener2((events) => this._onModelEvents(modelUrl, events)); this._proxy._acceptModelAdd({ url: model.getAssociatedResource(), @@ -587,11 +595,19 @@ export class MainThreadDocuments { } private _onModelModeChanged(model: EditorCommon.IModel, oldModeId:string): void { + let modelUrl = model.getAssociatedResource(); + if (!this._modelIsSynced[modelUrl.toString()]) { + return; + } this._proxy._acceptModelModeChanged(model.getAssociatedResource(), oldModeId, model.getMode().getId()); } private _onModelRemoved(model: EditorCommon.IModel): void { let modelUrl = model.getAssociatedResource(); + if (!this._modelIsSynced[modelUrl.toString()]) { + return; + } + delete this._modelIsSynced[modelUrl.toString()]; this._modelToDisposeMap[modelUrl.toString()].dispose(); delete this._modelToDisposeMap[modelUrl.toString()]; this._proxy._acceptModelRemoved(modelUrl); From c3d18ddb044a21f580774565edfb32b6fab37114 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2015 15:48:22 +0100 Subject: [PATCH 074/588] add environment variable SKIP_INTEGRATION_TESTS --- test/run.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/run.sh b/test/run.sh index 93ac3073d55..80156c958a3 100755 --- a/test/run.sh +++ b/test/run.sh @@ -19,4 +19,6 @@ else fi # Integration Tests -./scripts/code.sh $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out \ No newline at end of file +if [[ "$SKIP_INTEGRATION_TESTS" == "" ]]; then + ./scripts/code.sh $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out +fi \ No newline at end of file From 31d872e081e0bd839e5fa3ea072711b619bc8eeb Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2015 16:08:40 +0100 Subject: [PATCH 075/588] definition provider as support --- src/vs/editor/common/modes.ts | 2 +- .../browser/goToDeclaration.ts | 40 +------ .../goToDeclaration/common/goToDeclaration.ts | 37 +++++- .../api/browser/pluginHost.api.impl.ts | 2 +- .../api/common/extHostLanguageFeatures.ts | 98 ++++++++++++---- .../workbench/api/common/languageFeatures.ts | 63 ---------- .../api/extHostLanguageFeatures.test.ts | 108 +++++++++++++++++- .../test/common/api/testThreadService.ts | 13 ++- 8 files changed, 233 insertions(+), 130 deletions(-) diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 45a94068f00..c395780a3e2 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -566,7 +566,7 @@ export interface IReferenceSupport { */ export interface IDeclarationSupport { canFindDeclaration(context:ILineContext, offset:number):boolean; - findDeclaration(resource:URL, position:EditorCommon.IPosition):TPromise; + findDeclaration(resource:URI, position:EditorCommon.IPosition):TPromise; } export interface ITypeDeclarationSupport { diff --git a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts index 8b6b9370b5f..e1665615a60 100644 --- a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts @@ -34,35 +34,7 @@ import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {IEditorService} from 'vs/platform/editor/common/editor'; import {FindReferencesController} from 'vs/editor/contrib/referenceSearch/browser/referenceSearch'; import {IKeybindingService, IKeybindingContextKey} from 'vs/platform/keybinding/common/keybindingService'; -import FeatureRegistry from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; - -function getDeclarationsAtPosition(editor: EditorCommon.ICommonCodeEditor, position = editor.getPosition()): TPromise { - - let references: Modes.IReference[] = []; - let promises: TPromise[] = []; - - let model = editor.getModel(); - - for (let provider of FeatureRegistry.all(model)) { - - let promise = provider.findDeclaration(model.getAssociatedResource(), - position); - - promises.push(promise.then(result => { - if (Array.isArray(result)) { - references.push(...result); - } else { - references.push(result); - } - }, err => { - Errors.onUnexpectedError(err); - })); - } - - return TPromise.join(promises).then(() => { - return coalesce(references); - }); -} +import {DeclarationRegistry, getDeclarationsAtPosition} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; export abstract class GoToTypeAction extends EditorAction { @@ -182,7 +154,7 @@ export class GoToDeclarationAction extends GoToTypeAction { } public isSupported(): boolean { - return FeatureRegistry.has(this.editor.getModel()) && super.isSupported(); + return DeclarationRegistry.has(this.editor.getModel()) && super.isSupported(); } public getEnablementState():boolean { @@ -193,7 +165,7 @@ export class GoToDeclarationAction extends GoToTypeAction { var model = this.editor.getModel(), position = this.editor.getSelection().getStartPosition(); - return FeatureRegistry.all(model).some(provider => { + return DeclarationRegistry.all(model).some(provider => { return provider.canFindDeclaration( model.getLineContext(position.lineNumber), position.column - 1); @@ -201,7 +173,7 @@ export class GoToDeclarationAction extends GoToTypeAction { } protected _resolve(resource: URI, position: EditorCommon.IPosition): TPromise { - return getDeclarationsAtPosition(this.editor); + return getDeclarationsAtPosition(this.editor.getModel().getAssociatedResource(), this.editor.getModel().getModeId(), this.editor.getPosition()); } } @@ -456,7 +428,7 @@ class GotoDefinitionWithMouseEditorContribution implements EditorCommon.IEditorC (Browser.isIE11orEarlier || mouseEvent.event.detail <= 1) && // IE does not support event.detail properly mouseEvent.target.type === EditorCommon.MouseTargetType.CONTENT_TEXT && (mouseEvent.event[GotoDefinitionWithMouseEditorContribution.TRIGGER_MODIFIER] || (withKey && withKey.keyCode === GotoDefinitionWithMouseEditorContribution.TRIGGER_KEY_VALUE)) && - FeatureRegistry.has(this.editor.getModel()); + DeclarationRegistry.has(this.editor.getModel()); } private findDefinition(target:EditorBrowser.IMouseTarget):TPromise { @@ -465,7 +437,7 @@ class GotoDefinitionWithMouseEditorContribution implements EditorCommon.IEditorC return TPromise.as(null); } - return getDeclarationsAtPosition(this.editor, target.position); + return getDeclarationsAtPosition(this.editor.getModel().getAssociatedResource(), this.editor.getModel().getModeId(), target.position); } private gotoDefinition(target:EditorBrowser.IMouseTarget, sideBySide:boolean):TPromise { diff --git a/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts index e3226572277..f704b82665b 100644 --- a/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts @@ -5,9 +5,42 @@ 'use strict'; +import URI from 'vs/base/common/uri'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {onUnexpectedError} from 'vs/base/common/errors'; +import {IPosition} from 'vs/editor/common/editorCommon'; import {IDeclarationSupport} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; +import {IReference} from 'vs/editor/common/modes'; -const FeatureRegistry = new LanguageFeatureRegistry('declarationSupport'); +export const DeclarationRegistry = new LanguageFeatureRegistry('declarationSupport'); -export default FeatureRegistry; \ No newline at end of file +export function getDeclarationsAtPosition(resource: URI, modeId:string, position: IPosition): TPromise { + + const promises: TPromise[] = []; + const provider = DeclarationRegistry.ordered({ uri: resource, language: modeId }); + const references: (IReference[]| IReference)[] = Array<(IReference[]| IReference)>(provider.length); + + // get results + provider.map((provider, idx) => { + let promise = provider.findDeclaration(resource, position); + promises.push(promise.then(result => { + references[idx] = result; + }, err => { + onUnexpectedError(err); + })); + }); + + return TPromise.join(promises).then(() => { + let result: IReference[] = []; + for (let item of references) { + if (Array.isArray(item)) { + result.push(...item) + } else if(item) { + result.push(item); + } + } + + return result; + }); +} \ No newline at end of file diff --git a/src/vs/workbench/api/browser/pluginHost.api.impl.ts b/src/vs/workbench/api/browser/pluginHost.api.impl.ts index 1d4ce1101ed..77db2dc301a 100644 --- a/src/vs/workbench/api/browser/pluginHost.api.impl.ts +++ b/src/vs/workbench/api/browser/pluginHost.api.impl.ts @@ -271,7 +271,7 @@ export class PluginHostAPIImplementation { return languageFeatures.registerCodeLensProvider(selector, provider); }, registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable { - return features.definition.register(selector, provider); + return languageFeatures.registerDefinitionProvider(selector, provider); }, registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable { return features.hover.register(selector, provider); diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 953592ba9c5..e33693d66f4 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -23,7 +23,7 @@ import {CancellationTokenSource} from 'vs/base/common/cancellation'; import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; import {IMarkerService, IMarker} from 'vs/platform/markers/common/markers'; import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; -import DeclarationRegistry from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; +import {DeclarationRegistry} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; import ExtraInfoRegistry from 'vs/editor/contrib/hover/common/hover'; import DocumentHighlighterRegistry from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; import ReferenceSearchRegistry from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; @@ -158,7 +158,44 @@ class CodeLensAdapter implements modes.ICodeLensSupport { } } -type Adapter = OutlineAdapter | CodeLensAdapter; +class DeclarationAdapter implements modes.IDeclarationSupport { + + private _documents: PluginHostModelService; + private _provider: vscode.DefinitionProvider; + + constructor(documents: PluginHostModelService, provider: vscode.DefinitionProvider) { + this._documents = documents; + this._provider = provider; + } + + canFindDeclaration() { + return true; + } + + findDeclaration(resource: URI, position: IPosition): TPromise { + let doc = this._documents.getDocument(resource); + let pos = TypeConverters.toPosition(position); + return asWinJsPromise(token => this._provider.provideDefinition(doc, pos, token)).then(value => { + if (Array.isArray(value)) { + return value.map(DeclarationAdapter._convertLocation); + } else if (value) { + return DeclarationAdapter._convertLocation(value); + } + }); + } + + private static _convertLocation(location: vscode.Location): modes.IReference { + if (!location) { + return; + } + return { + resource: location.uri, + range: TypeConverters.fromRange(location.range) + }; + } +} + +type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter; @Remotable.PluginHostContext('ExtHostLanguageFeatures') export class ExtHostLanguageFeatures { @@ -185,8 +222,12 @@ export class ExtHostLanguageFeatures { return ExtHostLanguageFeatures._handlePool++; } - private _noAdapter() { - return TPromise.wrapError(new Error('no adapter found')); + private _withAdapter(handle: number, ctor: { new (...args: any[]): A }, callback: (adapter: A) => TPromise): TPromise { + let adapter = this._adapter[handle]; + if (!(adapter instanceof ctor)) { + return TPromise.wrapError(new Error('no adapter found')); + } + return callback( adapter); } // --- outline @@ -199,12 +240,7 @@ export class ExtHostLanguageFeatures { } $getOutline(handle: number, resource: URI): TPromise{ - let adapter = this._adapter[handle]; - if (adapter instanceof OutlineAdapter) { - return adapter.getOutline(resource); - } else { - return this._noAdapter(); - } + return this._withAdapter(handle, OutlineAdapter, adapter => adapter.getOutline(resource)); } // --- code lens @@ -216,24 +252,26 @@ export class ExtHostLanguageFeatures { return this._createDisposable(handle); } - $findCodeLensSymbols(handle:number, resource: URI): TPromise { - let adapter = this._adapter[handle]; - if (adapter instanceof CodeLensAdapter) { - return adapter.findCodeLensSymbols(resource); - } else { - return this._noAdapter(); - } + $findCodeLensSymbols(handle: number, resource: URI): TPromise { + return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.findCodeLensSymbols(resource)); } $resolveCodeLensSymbol(handle:number, resource: URI, symbol: modes.ICodeLensSymbol): TPromise { - let adapter = this._adapter[handle]; - if (adapter instanceof CodeLensAdapter) { - return adapter.resolveCodeLensSymbol(resource, symbol); - } else { - return this._noAdapter(); - } + return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.resolveCodeLensSymbol(resource, symbol)); } + // --- declaration + + registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable { + const handle = this._nextHandle(); + this._adapter[handle] = new DeclarationAdapter(this._documents, provider); + this._proxy.$registerDeclaractionSupport(handle, selector); + return this._createDisposable(handle); + } + + $findDeclaration(handle: number, resource: URI, position: IPosition): TPromise { + return this._withAdapter(handle, DeclarationAdapter, adapter => adapter.findDeclaration(resource, position)); + } } @Remotable.MainContext('MainThreadLanguageFeatures') @@ -279,4 +317,18 @@ export class MainThreadLanguageFeatures { }); return undefined; } + + // --- declaration + + $registerDeclaractionSupport(handle: number, selector: vscode.DocumentSelector): TPromise { + this._registrations[handle] = DeclarationRegistry.register(selector, { + canFindDeclaration() { + return true; + }, + findDeclaration: (resource: URI, position: IPosition): TPromise => { + return this._proxy.$findDeclaration(handle, resource, position); + } + }); + return undefined; + } } \ No newline at end of file diff --git a/src/vs/workbench/api/common/languageFeatures.ts b/src/vs/workbench/api/common/languageFeatures.ts index 2d3a0fb57ea..a1c680db274 100644 --- a/src/vs/workbench/api/common/languageFeatures.ts +++ b/src/vs/workbench/api/common/languageFeatures.ts @@ -22,17 +22,14 @@ import {CancellationTokenSource} from 'vs/base/common/cancellation'; import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; import {IMarkerService, IMarker} from 'vs/platform/markers/common/markers'; import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; -import DeclarationRegistry from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; import ExtraInfoRegistry from 'vs/editor/contrib/hover/common/hover'; import DocumentHighlighterRegistry from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; import ReferenceSearchRegistry from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; import QuickFixRegistry from 'vs/editor/contrib/quickFix/common/quickFix'; -import {OutlineRegistry, IOutlineEntry, IOutlineSupport} from 'vs/editor/contrib/quickOpen/common/quickOpen'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import {NavigateTypesSupportRegistry, INavigateTypesSupport, ITypeBearing} from 'vs/workbench/parts/search/common/search' import {RenameRegistry} from 'vs/editor/contrib/rename/common/rename'; import {FormatRegistry, FormatOnTypeRegistry} from 'vs/editor/contrib/format/common/format'; -import {CodeLensRegistry} from 'vs/editor/contrib/codelens/common/codelens'; import {ParameterHintsRegistry} from 'vs/editor/contrib/parameterHints/common/parameterHints'; import {SuggestRegistry} from 'vs/editor/contrib/suggest/common/suggest'; @@ -137,64 +134,6 @@ export abstract class AbstractExtensionHostFeature { - - constructor(@IThreadService threadService: IThreadService) { - super(threadService.getRemotable(MainThreadDefinitionFeature), threadService); - } - - _runAsCommand(resource: URI, position: IPosition): TPromise { - - let document = this._models.getDocument(resource); - let pos = TypeConverters.toPosition(position); - let locations: vscode.Location[] = []; - - let promises = this._registry.all({ language: document.languageId, uri: document.uri }).map(provider => { - return asWinJsPromise(token => provider.provideDefinition(document, pos, token)).then(result => { - if (Array.isArray(result)) { - locations.push(...result); - } else { - locations.push( result); - } - }, err => { - console.error(err); - }); - }); - - return TPromise.join(promises).then(() => { - return locations.map(ExtensionHostDefinitionFeature._convertLocation); - }) - } - - private static _convertLocation(location: vscode.Location): modes.IReference { - if (!location) { - return; - } - return { - resource: location.uri, - range: TypeConverters.fromRange(location.range) - }; - } -} - -@Remotable.MainContext('MainThreadDefinitionProvider') -export class MainThreadDefinitionFeature extends AbstractMainThreadFeature implements modes.IDeclarationSupport { - - constructor(@IThreadService threadService: IThreadService) { - super('vscode.executeDefinitionProvider', DeclarationRegistry, threadService); - } - - canFindDeclaration() { - return true - } - - findDeclaration(resource: URI, position: IPosition): TPromise{ - return this._executeCommand(resource, position); - } -} - // ---- hover @@ -1076,7 +1015,6 @@ export class MainThreadWorkspaceSymbols implements INavigateTypesSupport { export namespace LanguageFeatures { export function createMainThreadInstances(threadService: IThreadService): void { - threadService.getRemotable(MainThreadDefinitionFeature); threadService.getRemotable(MainThreadHoverFeature); threadService.getRemotable(MainThreadOccurrencesFeature); threadService.getRemotable(MainThreadReferenceSearch); @@ -1092,7 +1030,6 @@ export namespace LanguageFeatures { export function createExtensionHostInstances(threadService: IThreadService) { return { - definition: new ExtensionHostDefinitionFeature(threadService), hover: new ExtensionHostHoverFeature(threadService), documentHighlight: new ExtensionHostOccurrencesFeature(threadService), referenceSearch: new ExtensionHostReferenceSearch(threadService), diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts index c4cd44d1a12..0abedfe4b66 100644 --- a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts @@ -19,10 +19,10 @@ import {ExtHostLanguageFeatures, MainThreadLanguageFeatures} from 'vs/workbench/ import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; import {SyncDescriptor0} from 'vs/platform/instantiation/common/descriptors'; +import {LanguageSelector, ModelLike} from 'vs/editor/common/modes/languageSelector'; import {OutlineRegistry, getOutlineEntries} from 'vs/editor/contrib/quickOpen/common/quickOpen'; import {CodeLensRegistry, getCodeLensData} from 'vs/editor/contrib/codelens/common/codelens'; -import {LanguageSelector, ModelLike} from 'vs/editor/common/modes/languageSelector'; - +import {DeclarationRegistry, getDeclarationsAtPosition} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; let model: ModelLike; let extHost: ExtHostLanguageFeatures; @@ -217,4 +217,108 @@ suite('ExtHostLanguageFeatures', function() { }); }); }); + + // --- definition + + test('Definition, data conversion', function(done) { + + disposables.push(extHost.registerDefinitionProvider('far', { + provideDefinition(): any { + return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))]; + } + })); + + threadService.sync().then(() => { + + getDeclarationsAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + assert.equal(value.length, 1); + let [entry] = value; + assert.deepEqual(entry.range, { startLineNumber: 2, startColumn: 3, endLineNumber: 4, endColumn: 5 }); + assert.equal(entry.resource.toString(), model.uri.toString()); + done(); + }, err => { + done(err); + }); + }); + }); + + test('Definition, one or many', function(done) { + + disposables.push(extHost.registerDefinitionProvider('far', { + provideDefinition(): any { + return [new types.Location(model.uri, new types.Range(1, 1, 1, 1))]; + } + })); + disposables.push(extHost.registerDefinitionProvider('far', { + provideDefinition(): any { + return new types.Location(model.uri, new types.Range(1, 1, 1, 1)); + } + })); + + threadService.sync().then(() => { + + getDeclarationsAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + assert.equal(value.length, 2); + done(); + }, err => { + done(err); + }); + }); + }); + + test('Definition, registration order', function(done) { + + disposables.push(extHost.registerDefinitionProvider('far', { + provideDefinition(): any { + return [new types.Location(URI.parse('far://first'), new types.Range(2, 3, 4, 5))]; + } + })); + + setTimeout(function() { // registration time matters + disposables.push(extHost.registerDefinitionProvider('far', { + provideDefinition(): any { + return new types.Location(URI.parse('far://second'), new types.Range(1, 2, 3, 4)); + } + })); + + threadService.sync().then(() => { + + getDeclarationsAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + assert.equal(value.length, 2); + // let [first, second] = value; + + assert.equal(value[0].resource.authority, 'second'); + assert.equal(value[1].resource.authority, 'first'); + done(); + + }, err => { + done(err); + }); + }); + }, 10); + }); + + test('Definition, evil provider', function(done) { + + disposables.push(extHost.registerDefinitionProvider('far', { + provideDefinition(): any { + throw new Error('evil provider') + } + })); + disposables.push(extHost.registerDefinitionProvider('far', { + provideDefinition(): any { + return new types.Location(model.uri, new types.Range(1, 1, 1, 1)); + } + })); + + threadService.sync().then(() => { + + getDeclarationsAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + assert.equal(value.length, 1); + done(); + }, err => { + done(err); + }); + }); + }); }); \ No newline at end of file diff --git a/src/vs/workbench/test/common/api/testThreadService.ts b/src/vs/workbench/test/common/api/testThreadService.ts index 5b408734768..1d83c6feab6 100644 --- a/src/vs/workbench/test/common/api/testThreadService.ts +++ b/src/vs/workbench/test/common/api/testThreadService.ts @@ -44,20 +44,25 @@ export class TestThreadService extends NullThreadService { protected _registerAndInstantiateMainProcessActor(id: string, descriptor: SyncDescriptor0): T { - let instance: any; + let _calls:{path: string; args: any[] }[] = []; + let _instance: any; return this._getOrCreateProxyInstance({ + + callOnRemote: (proxyId: string, path: string, args: any[]): TPromise => { this._callCount++; + _calls.push({path, args}); return TPromise.timeout(0).then(() => { - if (!instance) { - instance = create(descriptor.ctor, this); + if (!_instance) { + _instance = create(descriptor.ctor, this); } let p: TPromise; try { - let result = (instance[path]).apply(instance, args); + let {path, args} = _calls.shift(); + let result = (_instance[path]).apply(_instance, args); p = TPromise.is(result) ? result : TPromise.as(result); } catch (err) { p = TPromise.wrapError(err); From 386a1301009761ab55b2b0188a6c93678e47b6cc Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 25 Nov 2015 16:25:15 +0100 Subject: [PATCH 076/588] use semver to compare versions --- .../parts/extensions/electron-browser/extensionsQuickOpen.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen.ts index 5743ad36582..a48a982f1db 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen.ts @@ -26,6 +26,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions'; import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel'; import { Action } from 'vs/base/common/actions'; +import * as semver from 'semver'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import remote = require('remote'); const shell = remote.require('shell'); @@ -496,7 +497,7 @@ class ExtensionsUpdateModel implements IModel { .map(extension => ({ extension, highlights: getHighlights(input, extension) })) .filter(({ extension, highlights }) => { const local = this.localExtensions.filter(local => extensionEquals(local, extension))[0]; - return local && local.version < extension.version && !!highlights; + return local && semver.lt(local.version, extension.version) && !!highlights; }) .map(({ extension, highlights }: { extension: IExtension, highlights: IHighlights }) => { return { From 8572f720640182b1500b872ead8ffd85351d9b6b Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 25 Nov 2015 16:33:37 +0100 Subject: [PATCH 077/588] naming --- .../electron-browser/extensionsActions.ts | 6 +++--- .../electron-browser/extensionsQuickOpen.ts | 20 +++++++++---------- .../extensionsWorkbenchExtension.ts | 8 ++++---- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts index 8b039896ab8..5d71a8d24bb 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts @@ -55,10 +55,10 @@ export class InstallExtensionAction extends Action { } } -export class ListExtensionsUpdatesAction extends Action { +export class ListOutdatedExtensionsAction extends Action { - static ID = 'workbench.extensions.action.listExtensionsUpdates'; - static LABEL = nls.localize('showExtensionsUpdates', "Show Extensions Updates"); + static ID = 'workbench.extensions.action.listOutdatedExtensions'; + static LABEL = nls.localize('showOutdatedExtensions', "Show Outdated Extensions"); constructor( id: string, diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen.ts index a48a982f1db..b1ff72bfbf4 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen.ts @@ -475,7 +475,7 @@ export class GalleryExtensionsHandler extends QuickOpenHandler { } } -class ExtensionsUpdateModel implements IModel { +class OutdatedExtensionsModel implements IModel { public dataSource = new DataSource(); public renderer: IRenderer; @@ -499,20 +499,18 @@ class ExtensionsUpdateModel implements IModel { const local = this.localExtensions.filter(local => extensionEquals(local, extension))[0]; return local && semver.lt(local.version, extension.version) && !!highlights; }) - .map(({ extension, highlights }: { extension: IExtension, highlights: IHighlights }) => { - return { - extension, - highlights, - state: ExtensionState.Outdated - }; - }) + .map(({ extension, highlights }: { extension: IExtension, highlights: IHighlights }) => ({ + extension, + highlights, + state: ExtensionState.Outdated + })) .sort((a, b) => a.extension.name.localeCompare(b.extension.name)); } } -export class ExtensionsUpdateHandler extends QuickOpenHandler { +export class OutdatedExtensionsHandler extends QuickOpenHandler { - private modelPromise: TPromise; + private modelPromise: TPromise; constructor( @IInstantiationService private instantiationService: IInstantiationService, @@ -527,7 +525,7 @@ export class ExtensionsUpdateHandler extends QuickOpenHandler { if (!this.modelPromise) { this.telemetryService.publicLog('extensionGallery:open'); this.modelPromise = TPromise.join([this.galleryService.query(), this.extensionsService.getInstalled()]) - .then(result => this.instantiationService.createInstance(ExtensionsUpdateModel, result[0], result[1])); + .then(result => this.instantiationService.createInstance(OutdatedExtensionsModel, result[0], result[1])); } return this.modelPromise.then(model => { diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension.ts index 44326bc574b..fcb4272fc99 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension.ts @@ -16,7 +16,7 @@ import { IWorkspaceContextService } from 'vs/workbench/services/workspace/common import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions'; import wbaregistry = require('vs/workbench/browser/actionRegistry'); import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; -import { ListExtensionsAction, InstallExtensionAction, ListExtensionsUpdatesAction } from './extensionsActions'; +import { ListExtensionsAction, InstallExtensionAction, ListOutdatedExtensionsAction } from './extensionsActions'; import { IQuickOpenRegistry, Extensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen'; import ipc = require('ipc'); @@ -68,14 +68,14 @@ export class ExtensionsWorkbenchExtension implements IWorkbenchContribution { ) ); - actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ListExtensionsUpdatesAction, ListExtensionsUpdatesAction.ID, ListExtensionsUpdatesAction.LABEL), extensionsCategory); + actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ListOutdatedExtensionsAction, ListOutdatedExtensionsAction.ID, ListOutdatedExtensionsAction.LABEL), extensionsCategory); (platform.Registry.as(Extensions.Quickopen)).registerQuickOpenHandler( new QuickOpenHandlerDescriptor( 'vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen', - 'ExtensionsUpdateHandler', + 'OutdatedExtensionsHandler', 'ext update ', - nls.localize('extensionsUpdateCommands', "Extensions Update Commands"), + nls.localize('outdatedExtensionsCommands', "Outdated Extensions Commands"), true ) ); From 2b17de293a54874db5c4d4b42647e88147650294 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 25 Nov 2015 16:34:51 +0100 Subject: [PATCH 078/588] better labels for extension quick open contributions --- .../electron-browser/extensionsWorkbenchExtension.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension.ts index fcb4272fc99..f968b308e05 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension.ts @@ -51,7 +51,7 @@ export class ExtensionsWorkbenchExtension implements IWorkbenchContribution { 'vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen', 'LocalExtensionsHandler', 'ext ', - nls.localize('localExtensionsCommands', "Local Extensions Commands") + nls.localize('localExtensionsCommands', "Show Local Extensions") ) ); @@ -63,7 +63,7 @@ export class ExtensionsWorkbenchExtension implements IWorkbenchContribution { 'vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen', 'GalleryExtensionsHandler', 'ext install ', - nls.localize('galleryExtensionsCommands', "Gallery Extensions Commands"), + nls.localize('galleryExtensionsCommands', "Install Gallery Extensions"), true ) ); @@ -75,7 +75,7 @@ export class ExtensionsWorkbenchExtension implements IWorkbenchContribution { 'vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen', 'OutdatedExtensionsHandler', 'ext update ', - nls.localize('outdatedExtensionsCommands', "Outdated Extensions Commands"), + nls.localize('outdatedExtensionsCommands', "Update Outdated Extensions"), true ) ); From 782cb040c2cba9da8c02e010f9810eeb023ec773 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 25 Nov 2015 16:42:47 +0100 Subject: [PATCH 079/588] debug: make it to possible to cancel debug environment picker. fixes #626 --- src/vs/workbench/parts/debug/common/debug.ts | 2 +- .../debug/electron-browser/debugService.ts | 52 ++++++++++--------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index 5dcdeb96dc0..9a7161e546c 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -236,7 +236,7 @@ export interface IDebugService extends ee.IEventEmitter { getConfiguration(): IConfig; setConfiguration(name: string): Promise; - openConfigFile(sideBySide: boolean): Promise; + openConfigFile(sideBySide: boolean): TPromise; loadLaunchConfig(): TPromise; setFocusedStackFrameAndEvaluate(focusedStackFrame: IStackFrame): void; diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 509e35f76ac..e81bc0f76c9 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -334,28 +334,29 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService this.emit(debug.ServiceEvents.STATE_CHANGED, data); } - public openConfigFile(sideBySide: boolean): Promise { + public openConfigFile(sideBySide: boolean): TPromise { const resource = uri.file(paths.join(this.contextService.getWorkspace().resource.fsPath, '/.vscode/launch.json')); - return this.fileService.resolveContent(resource).then(content => { - let globalConfig = null; - try { - globalConfig = JSON.parse(content.value); - } catch (e) { } + return this.fileService.resolveContent(resource).then(content => true, err => + this.getInitialConfigFileContent().then(content => { + if (!content) { + return false; + } - if (!globalConfig || !globalConfig.configurations || globalConfig.configurations.length === 0) { - return this.createInitialConfigFile(resource, content.value); + return this.fileService.updateContent(resource, content).then(() => true); + } + )).then(configFileCreated => { + if (!configFileCreated) { + return false; } - }, err => this.createInitialConfigFile(resource, null)) - - .then(() => { this.telemetryService.publicLog('debugConfigure'); + return this.editorService.openEditor({ resource: resource, options: { forceOpen: true } - }, sideBySide); + }, sideBySide).then(() => true); }, (error) => { throw new Error(nls.localize('DebugConfig.failed', "Unable to create 'launch.json' file inside the '.vscode' folder ({0}).", error)); }); @@ -399,20 +400,20 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService }); } - private createInitialConfigFile(resource: uri, previousContent: string): Promise { + private getInitialConfigFileContent(): TPromise { return this.quickOpenService.pick(this.adapters, { placeHolder: nls.localize('selectDebug', "Select Debug Environment") }) - .then(adapter => - this.massageInitialConfigurations(adapter).then(() => { - if (previousContent && !adapter) { - return previousContent; - } + .then(adapter => { + if (!adapter) { + return null; + } - return JSON.stringify({ + return this.massageInitialConfigurations(adapter).then(() => + JSON.stringify({ version: '0.2.0', - configurations: adapter && adapter.initialConfigurations ? adapter.initialConfigurations : [] + configurations: adapter.initialConfigurations ? adapter.initialConfigurations : [] }, null, '\t') - }) - ).then(content => this.fileService.updateContent(resource, content)); + ) + }); } private massageInitialConfigurations(adapter: Adapter): Promise { @@ -531,8 +532,11 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService return this.pluginService.onReady().then(() => this.setConfiguration(this.configuration ? this.configuration.name : null, extensionHostData)).then(() => { if (!this.configuration) { - return this.openConfigFile(false).then(() => - this.messageService.show(severity.Info, nls.localize('NewLaunchConfig', "Please set up the launch configuration file to debug your application. Make sure that configurations have unique names."))); + return this.openConfigFile(false).then(openend => { + if (openend) { + this.messageService.show(severity.Info, nls.localize('NewLaunchConfig', "Please set up the launch configuration file to debug your application.")); + } + }); } var adapter = this.adapters.filter(adapter => adapter.type === this.configuration.type).pop(); From e91ddbe397779b696cc9c05f8440dc92bb78153e Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 25 Nov 2015 16:49:18 +0100 Subject: [PATCH 080/588] debug: fix margins in debug call stack fixes #627 --- src/vs/workbench/parts/debug/browser/media/debugViewlet.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/parts/debug/browser/media/debugViewlet.css b/src/vs/workbench/parts/debug/browser/media/debugViewlet.css index 783424b7385..1c0499ae22c 100644 --- a/src/vs/workbench/parts/debug/browser/media/debugViewlet.css +++ b/src/vs/workbench/parts/debug/browser/media/debugViewlet.css @@ -110,6 +110,7 @@ .debug-viewlet .debug-call-stack .stack-frame > .file:not(:first-child) { margin-left: 0.8em; + margin-right: 0.15em; } /* Variables & Expression view */ From 1b1e583a68a93ae70f506220f7d1003a1bec5a02 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2015 16:59:52 +0100 Subject: [PATCH 081/588] hover provider as support --- src/vs/editor/common/modes.ts | 2 +- .../hover/browser/modesContentHover.ts | 25 +---- src/vs/editor/contrib/hover/common/hover.ts | 32 +++++- .../api/browser/pluginHost.api.impl.ts | 2 +- .../api/common/extHostLanguageFeatures.ts | 65 +++++++++++- .../workbench/api/common/languageFeatures.ts | 76 -------------- .../api/extHostLanguageFeatures.test.ts | 98 ++++++++++++++++++- 7 files changed, 194 insertions(+), 106 deletions(-) diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index c395780a3e2..ed9672fb778 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -380,7 +380,7 @@ export interface IComputeExtraInfoResult { className?: string; } export interface IExtraInfoSupport { - computeInfo(resource:URL, position:EditorCommon.IPosition):TPromise; + computeInfo(resource:URI, position:EditorCommon.IPosition):TPromise; } diff --git a/src/vs/editor/contrib/hover/browser/modesContentHover.ts b/src/vs/editor/contrib/hover/browser/modesContentHover.ts index 4fbfae8608b..581eeb9287a 100644 --- a/src/vs/editor/contrib/hover/browser/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/browser/modesContentHover.ts @@ -15,8 +15,8 @@ import HoverWidget = require('./hoverWidgets'); import HtmlContent = require('vs/base/common/htmlContent'); import {renderHtml} from 'vs/base/browser/htmlContentRenderer'; import {tokenizeToHtmlContent} from 'vs/editor/common/modes/textToHtmlTokenizer'; -import ExtraInfoRegistry from '../common/hover'; import {Range} from 'vs/editor/common/core/range'; +import {ExtraInfoRegistry, getExtraInfoAtPosition} from '../common/hover'; class ModesContentComputer implements HoverOperation.IHoverComputer { @@ -46,27 +46,8 @@ class ModesContentComputer implements HoverOperation.IHoverComputer[] = []; - - for (let support of supports) { - promises.push(support.computeInfo(this._editor.getModel().getAssociatedResource(), { - lineNumber: this._range.startLineNumber, - column: this._range.startColumn, - }).then((result: Modes.IComputeExtraInfoResult) => { - if (result) { - let hasRange = (typeof result.range !== 'undefined'); - let hasValue = (typeof result.value !== 'undefined'); - let hasHtmlContent = (typeof result.htmlContent !== 'undefined' && result.htmlContent && result.htmlContent.length > 0); - if (hasRange && (hasValue || hasHtmlContent)) { - values.push(result); - } - } - })); - } - - return TPromise.join(promises).then(() => values); + return getExtraInfoAtPosition(model.getAssociatedResource(), model.getModeId(), + { lineNumber: this._range.startLineNumber, column: this._range.startColumn }); } public computeSync(): Modes.IComputeExtraInfoResult[] { diff --git a/src/vs/editor/contrib/hover/common/hover.ts b/src/vs/editor/contrib/hover/common/hover.ts index a811c6dac77..e0e2364712c 100644 --- a/src/vs/editor/contrib/hover/common/hover.ts +++ b/src/vs/editor/contrib/hover/common/hover.ts @@ -5,9 +5,35 @@ 'use strict'; -import {IExtraInfoSupport} from 'vs/editor/common/modes'; +import URI from 'vs/base/common/uri'; +import {IExtraInfoSupport, IComputeExtraInfoResult} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {coalesce} from 'vs/base/common/arrays'; +import {onUnexpectedError} from 'vs/base/common/errors'; +import {IPosition} from 'vs/editor/common/editorCommon'; -const ExtraInfoRegistry = new LanguageFeatureRegistry('extraInfoSupport'); +export const ExtraInfoRegistry = new LanguageFeatureRegistry('extraInfoSupport'); -export default ExtraInfoRegistry; \ No newline at end of file +export function getExtraInfoAtPosition(resource: URI, modeId: string, position: IPosition): TPromise { + + const supports = ExtraInfoRegistry.ordered({uri: resource, language: modeId }); + const values: IComputeExtraInfoResult[] = []; + + const promises = supports.map((support, idx) => { + return support.computeInfo(resource, position).then(result => { + if (result) { + let hasRange = (typeof result.range !== 'undefined'); + let hasValue = (typeof result.value !== 'undefined'); + let hasHtmlContent = (typeof result.htmlContent !== 'undefined' && result.htmlContent && result.htmlContent.length > 0); + if (hasRange && (hasValue || hasHtmlContent)) { + values[idx] = result; + } + } + }, err => { + onUnexpectedError(err); + }); + }); + + return TPromise.join(promises).then(() => coalesce(values)); +} \ No newline at end of file diff --git a/src/vs/workbench/api/browser/pluginHost.api.impl.ts b/src/vs/workbench/api/browser/pluginHost.api.impl.ts index 77db2dc301a..91b16d57765 100644 --- a/src/vs/workbench/api/browser/pluginHost.api.impl.ts +++ b/src/vs/workbench/api/browser/pluginHost.api.impl.ts @@ -274,7 +274,7 @@ export class PluginHostAPIImplementation { return languageFeatures.registerDefinitionProvider(selector, provider); }, registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable { - return features.hover.register(selector, provider); + return languageFeatures.registerHoverProvider(selector, provider); }, registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable { return features.documentHighlight.register(selector, provider); diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index e33693d66f4..bb762502983 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -24,7 +24,7 @@ import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocument import {IMarkerService, IMarker} from 'vs/platform/markers/common/markers'; import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; import {DeclarationRegistry} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; -import ExtraInfoRegistry from 'vs/editor/contrib/hover/common/hover'; +import {ExtraInfoRegistry} from 'vs/editor/contrib/hover/common/hover'; import DocumentHighlighterRegistry from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; import ReferenceSearchRegistry from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; import QuickFixRegistry from 'vs/editor/contrib/quickFix/common/quickFix'; @@ -195,7 +195,44 @@ class DeclarationAdapter implements modes.IDeclarationSupport { } } -type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter; +class ExtraInfoAdapter implements modes.IExtraInfoSupport { + + private _documents: PluginHostModelService; + private _provider: vscode.HoverProvider; + + constructor(documents: PluginHostModelService, provider: vscode.HoverProvider) { + this._documents = documents; + this._provider = provider; + } + + computeInfo(resource: URI, position: IPosition): TPromise { + + let doc = this._documents.getDocument(resource); + let pos = TypeConverters.toPosition(position); + + return asWinJsPromise(token => this._provider.provideHover(doc, pos, token)).then(value => { + if (!value) { + return; + } + + let {range, contents} = value; + + if (!range) { + range = doc.getWordRangeAtPosition(pos); + } + if (!range) { + range = new Range(pos, pos); + } + + return { + range: TypeConverters.fromRange(range), + htmlContent: contents && contents.map(TypeConverters.fromFormattedString) + } + }); + } +} + +type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | ExtraInfoAdapter; @Remotable.PluginHostContext('ExtHostLanguageFeatures') export class ExtHostLanguageFeatures { @@ -272,6 +309,19 @@ export class ExtHostLanguageFeatures { $findDeclaration(handle: number, resource: URI, position: IPosition): TPromise { return this._withAdapter(handle, DeclarationAdapter, adapter => adapter.findDeclaration(resource, position)); } + + // --- extra info + + registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable { + const handle = this._nextHandle(); + this._adapter[handle] = new ExtraInfoAdapter(this._documents, provider); + this._proxy.$registerExtraInfoSupport(handle, selector); + return this._createDisposable(handle); + } + + $computeInfo(handle:number, resource: URI, position: IPosition): TPromise { + return this._withAdapter(handle, ExtraInfoAdapter, adpater => adpater.computeInfo(resource, position)); + } } @Remotable.MainContext('MainThreadLanguageFeatures') @@ -331,4 +381,15 @@ export class MainThreadLanguageFeatures { }); return undefined; } + + // --- extra info + + $registerExtraInfoSupport(handle: number, selector: vscode.DocumentSelector): TPromise { + this._registrations[handle] = ExtraInfoRegistry.register(selector, { + computeInfo: (resource: URI, position: IPosition): TPromise => { + return this._proxy.$computeInfo(handle, resource, position); + } + }); + return undefined; + } } \ No newline at end of file diff --git a/src/vs/workbench/api/common/languageFeatures.ts b/src/vs/workbench/api/common/languageFeatures.ts index a1c680db274..188b0dc377c 100644 --- a/src/vs/workbench/api/common/languageFeatures.ts +++ b/src/vs/workbench/api/common/languageFeatures.ts @@ -22,7 +22,6 @@ import {CancellationTokenSource} from 'vs/base/common/cancellation'; import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; import {IMarkerService, IMarker} from 'vs/platform/markers/common/markers'; import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; -import ExtraInfoRegistry from 'vs/editor/contrib/hover/common/hover'; import DocumentHighlighterRegistry from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; import ReferenceSearchRegistry from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; import QuickFixRegistry from 'vs/editor/contrib/quickFix/common/quickFix'; @@ -134,79 +133,6 @@ export abstract class AbstractExtensionHostFeature { - - constructor( @IThreadService threadService: IThreadService) { - super(threadService.getRemotable(MainThreadHoverFeature), threadService); - } - - _runAsCommand(resource: URI, position: IPosition): TPromise { - - let document = this._models.getDocument(resource); - let pos = TypeConverters.toPosition(position); - - // incrementally building up the result - let contents: vscode.MarkedString[] = []; - let word = document.getWordRangeAtPosition(pos); - let start = word && word.start || pos; - let end = word && word.end || pos; - - let promises = this._registry.all({ language: document.languageId, uri: document.uri }).map(provider => { - - return asWinJsPromise(token => provider.provideHover(document, pos, token)).then(result => { - - if (!result) { - return; - } - - if (result.range) { - if (result.range.start.isBefore(start)) { - start = result.range.start; - } - if (end.isBefore(result.range.end)) { - end = result.range.end; - } - } - - for (let markedString of result.contents) { - if (markedString) { - contents.push(markedString); - } - } - contents.push('\n'); - - }, err => { - console.error(err); - }); - }); - - return TPromise.join(promises).then(() => { - - contents.pop(); // remove the last '\n' element we added - - return { - range: TypeConverters.fromRange(new Range(start, end)), - htmlContent: contents.map(TypeConverters.fromFormattedString) - }; - }); - } -} - -@Remotable.MainContext('MainThreadHoverFeature') -export class MainThreadHoverFeature extends AbstractMainThreadFeature implements modes.IExtraInfoSupport { - - constructor(@IThreadService threadService: IThreadService) { - super('vscode.executeHoverProvider', ExtraInfoRegistry, threadService); - } - - computeInfo(resource: URI, position: IPosition): TPromise { - return this._executeCommand(resource, position); - } -} - // --- occurrences @@ -1015,7 +941,6 @@ export class MainThreadWorkspaceSymbols implements INavigateTypesSupport { export namespace LanguageFeatures { export function createMainThreadInstances(threadService: IThreadService): void { - threadService.getRemotable(MainThreadHoverFeature); threadService.getRemotable(MainThreadOccurrencesFeature); threadService.getRemotable(MainThreadReferenceSearch); threadService.getRemotable(MainThreadCodeActions); @@ -1030,7 +955,6 @@ export namespace LanguageFeatures { export function createExtensionHostInstances(threadService: IThreadService) { return { - hover: new ExtensionHostHoverFeature(threadService), documentHighlight: new ExtensionHostOccurrencesFeature(threadService), referenceSearch: new ExtensionHostReferenceSearch(threadService), codeActions: new ExtensionHostCodeActions(threadService), diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts index 0abedfe4b66..ce090215b97 100644 --- a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts @@ -23,6 +23,7 @@ import {LanguageSelector, ModelLike} from 'vs/editor/common/modes/languageSelect import {OutlineRegistry, getOutlineEntries} from 'vs/editor/contrib/quickOpen/common/quickOpen'; import {CodeLensRegistry, getCodeLensData} from 'vs/editor/contrib/codelens/common/codelens'; import {DeclarationRegistry, getDeclarationsAtPosition} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; +import {ExtraInfoRegistry, getExtraInfoAtPosition} from 'vs/editor/contrib/hover/common/hover'; let model: ModelLike; let extHost: ExtHostLanguageFeatures; @@ -295,7 +296,7 @@ suite('ExtHostLanguageFeatures', function() { done(err); }); }); - }, 10); + }, 5); }); test('Definition, evil provider', function(done) { @@ -321,4 +322,99 @@ suite('ExtHostLanguageFeatures', function() { }); }); }); + + // --- extra info + + test('ExtraInfo, word range at pos', function(done) { + + disposables.push(extHost.registerHoverProvider('far', { + provideHover(): any { + return new types.Hover('Hello') + } + })); + + threadService.sync().then(() => { + + getExtraInfoAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + + assert.equal(value.length, 1); + let [entry] = value; + assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 5 }); + done(); + }); + }); + }); + + test('ExtraInfo, given range', function(done) { + + disposables.push(extHost.registerHoverProvider('far', { + provideHover(): any { + return new types.Hover('Hello', new types.Range(3, 0, 8, 7)); + } + })); + + threadService.sync().then(() => { + + getExtraInfoAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + assert.equal(value.length, 1); + let [entry] = value; + assert.deepEqual(entry.range, { startLineNumber: 4, startColumn: 1, endLineNumber: 9, endColumn: 8 }); + done(); + }); + }); + }); + + test('ExtraInfo, registration order', function(done) { + + disposables.push(extHost.registerHoverProvider('far', { + provideHover(): any { + return new types.Hover('registered first'); + } + })); + + setTimeout(function() { + disposables.push(extHost.registerHoverProvider('far', { + provideHover(): any { + return new types.Hover('registered second'); + } + })); + + threadService.sync().then(() => { + + getExtraInfoAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + assert.equal(value.length, 2); + let [first, second] = value; + assert.equal(first.htmlContent[0].formattedText, 'registered second'); + assert.equal(second.htmlContent[0].formattedText, 'registered first'); + done(); + }); + }); + + }, 5); + + }); + + test('ExtraInfo, evil provider', function(done) { + + disposables.push(extHost.registerHoverProvider('far', { + provideHover(): any { + throw new Error('evil') + } + })); + disposables.push(extHost.registerHoverProvider('far', { + provideHover(): any { + return new types.Hover('Hello') + } + })); + + threadService.sync().then(() => { + + getExtraInfoAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + + assert.equal(value.length, 1); + done(); + }); + }); + + }); }); \ No newline at end of file From 920ede826a20f078ecb976072fab2b5ef38f5c3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 25 Nov 2015 17:06:00 +0100 Subject: [PATCH 082/588] Update appveyor.yml --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index a88d64c6161..a1f9bacbdaa 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,6 +2,7 @@ environment: ATOM_SHELL_INTERNAL_RUN_AS_NODE: 1 install: + - ps: Install-Product node 4.1.1 x64 - npm install -g gulp mocha build_script: From 08ccecf3e00468874b775b2292e660c84091da3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 25 Nov 2015 17:06:08 +0100 Subject: [PATCH 083/588] Update appveyor.yml --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index a1f9bacbdaa..4092aa3f717 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,7 +2,7 @@ environment: ATOM_SHELL_INTERNAL_RUN_AS_NODE: 1 install: - - ps: Install-Product node 4.1.1 x64 + - ps: Install-Product node 4.1.1 x64 - npm install -g gulp mocha build_script: From c704df89985a21873fb0e7daf0f78411a0c50db3 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 25 Nov 2015 17:38:13 +0100 Subject: [PATCH 084/588] Update vscode-textmate to 1.0.7 --- npm-shrinkwrap.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index d6b0a970407..e94516a8b22 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -416,9 +416,9 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz" }, "vscode-textmate": { - "version": "1.0.6", - "from": "vscode-textmate@1.0.6", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-1.0.6.tgz", + "version": "1.0.7", + "from": "vscode-textmate@1.0.7", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-1.0.7.tgz", "dependencies": { "oniguruma": { "version": "5.1.1", diff --git a/package.json b/package.json index 006319d9dd1..7b54931f9fa 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "iconv-lite": "^0.4.13", "sax": "^1.1.1", "semver": "^4.2.0", - "vscode-textmate": "^1.0.6", + "vscode-textmate": "^1.0.7", "winreg": "0.0.12", "yauzl": "^2.3.1" }, From d3584c91a18810fb4e502e16aeb8e27f3687aaa3 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2015 17:51:58 +0100 Subject: [PATCH 085/588] doc highlight provider as support, also use IModel --- src/vs/editor/common/modes.ts | 2 +- .../contrib/codelens/browser/codelens.ts | 3 +- .../contrib/codelens/common/codelens.ts | 8 +- .../browser/goToDeclaration.ts | 4 +- .../goToDeclaration/common/goToDeclaration.ts | 7 +- .../hover/browser/modesContentHover.ts | 6 +- src/vs/editor/contrib/hover/common/hover.ts | 7 +- .../contrib/quickOpen/common/quickOpen.ts | 5 +- .../wordHighlighter/common/wordHighlighter.ts | 53 +++-- .../api/browser/pluginHost.api.impl.ts | 2 +- .../api/common/extHostLanguageFeatures.ts | 58 ++++- .../workbench/api/common/languageFeatures.ts | 59 ----- .../quickopen/browser/gotoSymbolHandler.ts | 5 +- .../api/extHostLanguageFeatures.test.ts | 208 +++++++++++++----- 14 files changed, 264 insertions(+), 163 deletions(-) diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index ed9672fb778..ff210dad06d 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -531,7 +531,7 @@ export interface IOccurence { * Interface used to find occurrences of a symbol */ export interface IOccurrencesSupport { - findOccurrences(resource:URL, position:EditorCommon.IPosition, strict?:boolean):TPromise; + findOccurrences(resource:URI, position:EditorCommon.IPosition, strict?:boolean):TPromise; } diff --git a/src/vs/editor/contrib/codelens/browser/codelens.ts b/src/vs/editor/contrib/codelens/browser/codelens.ts index 9ec540a9476..b65a862004e 100644 --- a/src/vs/editor/contrib/codelens/browser/codelens.ts +++ b/src/vs/editor/contrib/codelens/browser/codelens.ts @@ -424,8 +424,7 @@ export class CodeLensContribution implements EditorCommon.IEditorContribution { this._currentFindCodeLensSymbolsPromise.cancel(); } - this._currentFindCodeLensSymbolsPromise = getCodeLensData(model.getAssociatedResource(), - model.getModeId()); + this._currentFindCodeLensSymbolsPromise = getCodeLensData(model); var counterValue = ++this._modelChangeCounter; this._currentFindCodeLensSymbolsPromise.then((result) => { diff --git a/src/vs/editor/contrib/codelens/common/codelens.ts b/src/vs/editor/contrib/codelens/common/codelens.ts index 0392ab6a924..cd2da755419 100644 --- a/src/vs/editor/contrib/codelens/common/codelens.ts +++ b/src/vs/editor/contrib/codelens/common/codelens.ts @@ -9,7 +9,7 @@ import {onUnexpectedError} from 'vs/base/common/errors'; import URI from 'vs/base/common/uri'; import {IAction, Action} from 'vs/base/common/actions'; import {TPromise} from 'vs/base/common/winjs.base'; -import {IRange, IPosition} from 'vs/editor/common/editorCommon'; +import {IModel, IRange, IPosition} from 'vs/editor/common/editorCommon'; import {Range} from 'vs/editor/common/core/range'; import {ICodeLensSupport, ICodeLensSymbol, ICommand} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; @@ -21,11 +21,11 @@ export interface ICodeLensData { support: ICodeLensSupport; } -export function getCodeLensData(resource: URI, modeId: string) { +export function getCodeLensData(model: IModel) { const symbols: ICodeLensData[] = []; - const promises = CodeLensRegistry.all({ uri: resource, language: modeId }).map(support => { - return support.findCodeLensSymbols(resource).then(result => { + const promises = CodeLensRegistry.all(model).map(support => { + return support.findCodeLensSymbols(model.getAssociatedResource()).then(result => { if (!Array.isArray(result)) { return; } diff --git a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts index e1665615a60..d31e219e1ee 100644 --- a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts @@ -173,7 +173,7 @@ export class GoToDeclarationAction extends GoToTypeAction { } protected _resolve(resource: URI, position: EditorCommon.IPosition): TPromise { - return getDeclarationsAtPosition(this.editor.getModel().getAssociatedResource(), this.editor.getModel().getModeId(), this.editor.getPosition()); + return getDeclarationsAtPosition(this.editor.getModel(), this.editor.getPosition()); } } @@ -437,7 +437,7 @@ class GotoDefinitionWithMouseEditorContribution implements EditorCommon.IEditorC return TPromise.as(null); } - return getDeclarationsAtPosition(this.editor.getModel().getAssociatedResource(), this.editor.getModel().getModeId(), target.position); + return getDeclarationsAtPosition(this.editor.getModel(), target.position); } private gotoDefinition(target:EditorBrowser.IMouseTarget, sideBySide:boolean):TPromise { diff --git a/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts index f704b82665b..dea603b4c2c 100644 --- a/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts @@ -8,17 +8,18 @@ import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; import {onUnexpectedError} from 'vs/base/common/errors'; -import {IPosition} from 'vs/editor/common/editorCommon'; +import {IModel, IPosition} from 'vs/editor/common/editorCommon'; import {IDeclarationSupport} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import {IReference} from 'vs/editor/common/modes'; export const DeclarationRegistry = new LanguageFeatureRegistry('declarationSupport'); -export function getDeclarationsAtPosition(resource: URI, modeId:string, position: IPosition): TPromise { +export function getDeclarationsAtPosition(model: IModel, position: IPosition): TPromise { const promises: TPromise[] = []; - const provider = DeclarationRegistry.ordered({ uri: resource, language: modeId }); + const resource = model.getAssociatedResource(); + const provider = DeclarationRegistry.ordered(model); const references: (IReference[]| IReference)[] = Array<(IReference[]| IReference)>(provider.length); // get results diff --git a/src/vs/editor/contrib/hover/browser/modesContentHover.ts b/src/vs/editor/contrib/hover/browser/modesContentHover.ts index 581eeb9287a..e0e92c72331 100644 --- a/src/vs/editor/contrib/hover/browser/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/browser/modesContentHover.ts @@ -46,8 +46,10 @@ class ModesContentComputer implements HoverOperation.IHoverComputer('extraInfoSupport'); -export function getExtraInfoAtPosition(resource: URI, modeId: string, position: IPosition): TPromise { +export function getExtraInfoAtPosition(model: IModel, position: IPosition): TPromise { - const supports = ExtraInfoRegistry.ordered({uri: resource, language: modeId }); + const resource = model.getAssociatedResource(); + const supports = ExtraInfoRegistry.ordered(model); const values: IComputeExtraInfoResult[] = []; const promises = supports.map((support, idx) => { diff --git a/src/vs/editor/contrib/quickOpen/common/quickOpen.ts b/src/vs/editor/contrib/quickOpen/common/quickOpen.ts index 5894c18e632..4b135a963da 100644 --- a/src/vs/editor/contrib/quickOpen/common/quickOpen.ts +++ b/src/vs/editor/contrib/quickOpen/common/quickOpen.ts @@ -11,7 +11,6 @@ import {Range} from 'vs/editor/common/core/range'; import {IModel} from 'vs/editor/common/editorCommon'; import {IOutlineEntry, IOutlineSupport} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; -import {ModelLike} from 'vs/editor/common/modes/languageSelector'; const OutlineRegistry = new LanguageFeatureRegistry('outlineSupport'); @@ -21,7 +20,7 @@ export { IOutlineSupport } -export function getOutlineEntries(model: ModelLike): TPromise<{ entries: IOutlineEntry[], outlineGroupLabel: { [n: string]: string;} }> { +export function getOutlineEntries(model: IModel): TPromise<{ entries: IOutlineEntry[], outlineGroupLabel: { [n: string]: string;} }> { let groupLabels: { [n: string]: string } = Object.create(null); let entries: IOutlineEntry[] = []; @@ -36,7 +35,7 @@ export function getOutlineEntries(model: ModelLike): TPromise<{ entries: IOutlin } } - return support.getOutline( model.uri).then(result => { + return support.getOutline(model.getAssociatedResource()).then(result => { if (Array.isArray(result)) { entries.push(...result); } diff --git a/src/vs/editor/contrib/wordHighlighter/common/wordHighlighter.ts b/src/vs/editor/contrib/wordHighlighter/common/wordHighlighter.ts index 3b66e3ef597..5d817a7ad28 100644 --- a/src/vs/editor/contrib/wordHighlighter/common/wordHighlighter.ts +++ b/src/vs/editor/contrib/wordHighlighter/common/wordHighlighter.ts @@ -5,6 +5,7 @@ 'use strict'; import {TPromise} from 'vs/base/common/winjs.base'; +import URI from 'vs/base/common/uri'; import * as EditorCommon from 'vs/editor/common/editorCommon'; import {IOccurrencesSupport, IOccurence} from 'vs/editor/common/modes'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; @@ -14,8 +15,34 @@ import {INullService} from 'vs/platform/instantiation/common/instantiation'; import {sequence} from 'vs/base/common/async'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; -const DocumentHighlighterRegistry = new LanguageFeatureRegistry('occurrencesSupport'); -export default DocumentHighlighterRegistry; +export const OccurrencesRegistry = new LanguageFeatureRegistry('occurrencesSupport'); + +export function getOccurrencesAtPosition(model: EditorCommon.IModel, position: EditorCommon.IPosition):TPromise { + + const resource = model.getAssociatedResource(); + const orderedByScore = OccurrencesRegistry.ordered(model); + let foundResult = false; + + // in order of score ask the occurrences provider + // until someone response with a good result + // (good = none empty array) + return sequence(orderedByScore.map(provider => { + return () => { + if (!foundResult) { + return provider.findOccurrences(resource, position).then(data => { + if (Array.isArray(data) && data.length > 0) { + foundResult = true; + return data; + } + }, err => { + onUnexpectedError(err); + }); + } + } + })).then(values => { + return values[0] + }); +} class WordHighlighter { @@ -99,7 +126,7 @@ class WordHighlighter { } // no providers for this model - if(!DocumentHighlighterRegistry.has(this.model)) { + if(!OccurrencesRegistry.has(this.model)) { this._stopAll(); return; } @@ -175,25 +202,7 @@ class WordHighlighter { var myRequestId = ++this.workerRequestTokenId; this.workerRequestCompleted = false; - let foundResult = false; - let orderedByScore = DocumentHighlighterRegistry.ordered(this.model); - let resource = this.model.getAssociatedResource(); - let position = this.editor.getPosition(); - - // in order of score ask the occurrences provider - // until someone response with a good result - // (good = none empty array) - this.workerRequest = sequence(orderedByScore.map(provider => { - return () => { - if (!foundResult) { - return provider.findOccurrences(resource, position).then(data => { - if (Array.isArray(data) && data.length > 0) { - return data; - } - }); - } - } - })).then(values => values[0]); + this.workerRequest = getOccurrencesAtPosition(this.model, this.editor.getPosition()); this.workerRequest.then(data => { if (myRequestId === this.workerRequestTokenId) { diff --git a/src/vs/workbench/api/browser/pluginHost.api.impl.ts b/src/vs/workbench/api/browser/pluginHost.api.impl.ts index 91b16d57765..93c40d6acc9 100644 --- a/src/vs/workbench/api/browser/pluginHost.api.impl.ts +++ b/src/vs/workbench/api/browser/pluginHost.api.impl.ts @@ -277,7 +277,7 @@ export class PluginHostAPIImplementation { return languageFeatures.registerHoverProvider(selector, provider); }, registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable { - return features.documentHighlight.register(selector, provider); + return languageFeatures.registerDocumentHighlightProvider(selector, provider); }, registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable { return features.referenceSearch.register(selector, provider); diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index bb762502983..65943d85924 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -25,7 +25,7 @@ import {IMarkerService, IMarker} from 'vs/platform/markers/common/markers'; import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; import {DeclarationRegistry} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; import {ExtraInfoRegistry} from 'vs/editor/contrib/hover/common/hover'; -import DocumentHighlighterRegistry from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; +import {OccurrencesRegistry} from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; import ReferenceSearchRegistry from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; import QuickFixRegistry from 'vs/editor/contrib/quickFix/common/quickFix'; import {OutlineRegistry, IOutlineEntry, IOutlineSupport} from 'vs/editor/contrib/quickOpen/common/quickOpen'; @@ -232,7 +232,37 @@ class ExtraInfoAdapter implements modes.IExtraInfoSupport { } } -type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | ExtraInfoAdapter; +class OccurrencesAdapter implements modes.IOccurrencesSupport { + + private _documents: PluginHostModelService; + private _provider: vscode.DocumentHighlightProvider; + + constructor(documents: PluginHostModelService, provider: vscode.DocumentHighlightProvider) { + this._documents = documents; + this._provider = provider; + } + + findOccurrences(resource: URI, position: IPosition): TPromise { + + let doc = this._documents.getDocument(resource); + let pos = TypeConverters.toPosition(position); + + return asWinJsPromise(token => this._provider.provideDocumentHighlights(doc, pos, token)).then(value => { + if (Array.isArray(value)) { + return value.map(OccurrencesAdapter._convertDocumentHighlight); + } + }); + } + + private static _convertDocumentHighlight(documentHighlight: vscode.DocumentHighlight): modes.IOccurence { + return { + range: TypeConverters.fromRange(documentHighlight.range), + kind: DocumentHighlightKind[documentHighlight.kind].toString().toLowerCase() + } + } +} + +type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | ExtraInfoAdapter | OccurrencesAdapter; @Remotable.PluginHostContext('ExtHostLanguageFeatures') export class ExtHostLanguageFeatures { @@ -322,6 +352,19 @@ export class ExtHostLanguageFeatures { $computeInfo(handle:number, resource: URI, position: IPosition): TPromise { return this._withAdapter(handle, ExtraInfoAdapter, adpater => adpater.computeInfo(resource, position)); } + + // --- occurrences adapter + + registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable { + const handle = this._nextHandle(); + this._adapter[handle] = new OccurrencesAdapter(this._documents, provider); + this._proxy.$registerOccurrencesSupport(handle, selector); + return this._createDisposable(handle); + } + + $findOccurrences(handle:number, resource: URI, position: IPosition): TPromise { + return this._withAdapter(handle, OccurrencesAdapter, adapter => adapter.findOccurrences(resource, position)); + } } @Remotable.MainContext('MainThreadLanguageFeatures') @@ -392,4 +435,15 @@ export class MainThreadLanguageFeatures { }); return undefined; } + + // --- occurrences + + $registerOccurrencesSupport(handle: number, selector: vscode.DocumentSelector): TPromise { + this._registrations[handle] = OccurrencesRegistry.register(selector, { + findOccurrences: (resource: URI, position: IPosition): TPromise => { + return this._proxy.$findOccurrences(handle, resource, position); + } + }); + return undefined; + } } \ No newline at end of file diff --git a/src/vs/workbench/api/common/languageFeatures.ts b/src/vs/workbench/api/common/languageFeatures.ts index 188b0dc377c..d8cb2762569 100644 --- a/src/vs/workbench/api/common/languageFeatures.ts +++ b/src/vs/workbench/api/common/languageFeatures.ts @@ -22,7 +22,6 @@ import {CancellationTokenSource} from 'vs/base/common/cancellation'; import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; import {IMarkerService, IMarker} from 'vs/platform/markers/common/markers'; import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; -import DocumentHighlighterRegistry from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; import ReferenceSearchRegistry from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; import QuickFixRegistry from 'vs/editor/contrib/quickFix/common/quickFix'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; @@ -133,62 +132,6 @@ export abstract class AbstractExtensionHostFeature { - - constructor(@IThreadService threadService: IThreadService) { - super(threadService.getRemotable(MainThreadOccurrencesFeature), threadService); - } - - _runAsCommand(resource: URI, position: IPosition): TPromise { - - let document = this._models.getDocument(resource); - let pos = TypeConverters.toPosition(position); - let highlights: vscode.DocumentHighlight[]; - - let factory = this._getOrderedFor(document).map(provider => { - return () => { - if (!highlights) { - return asWinJsPromise(token => provider.provideDocumentHighlights(document, pos, token)).then(result => { - if (Array.isArray(result) && result.length > 0) { - highlights = result; - } - }, err => { - console.error(err); - }); - } - } - }); - - return sequence(factory).then(() => { - if (highlights) { - return highlights.map(ExtensionHostOccurrencesFeature._convertDocumentHighlight); - } - }); - } - - private static _convertDocumentHighlight(documentHighlight: vscode.DocumentHighlight): modes.IOccurence { - return { - range: TypeConverters.fromRange(documentHighlight.range), - kind: DocumentHighlightKind[documentHighlight.kind].toString().toLowerCase() - } - } -} - -@Remotable.MainContext('MainThreadOccurrencesFeature') -export class MainThreadOccurrencesFeature extends AbstractMainThreadFeature { - - constructor(@IThreadService threadService: IThreadService) { - super('vscode.executeDocumentHighlights', DocumentHighlighterRegistry, threadService); - } - - findOccurrences(resource: URI, position: IPosition): TPromise { - return this._executeCommand(resource, position); - } -} - // --- reference search export class ExtensionHostReferenceSearch extends AbstractExtensionHostFeature { @@ -941,7 +884,6 @@ export class MainThreadWorkspaceSymbols implements INavigateTypesSupport { export namespace LanguageFeatures { export function createMainThreadInstances(threadService: IThreadService): void { - threadService.getRemotable(MainThreadOccurrencesFeature); threadService.getRemotable(MainThreadReferenceSearch); threadService.getRemotable(MainThreadCodeActions); threadService.getRemotable(MainThreadWorkspaceSymbols); @@ -955,7 +897,6 @@ export namespace LanguageFeatures { export function createExtensionHostInstances(threadService: IThreadService) { return { - documentHighlight: new ExtensionHostOccurrencesFeature(threadService), referenceSearch: new ExtensionHostReferenceSearch(threadService), codeActions: new ExtensionHostCodeActions(threadService), workspaceSymbols: new ExtensionHostWorkspaceSymbols(threadService), diff --git a/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts b/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts index a4f86a7bc11..aa7743ebfdb 100644 --- a/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts +++ b/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts @@ -527,10 +527,7 @@ export class GotoSymbolHandler extends QuickOpenHandler { return TPromise.as(this.outlineToModelCache[modelId]); } - return getOutlineEntries({ - uri: ( model).getAssociatedResource(), - language: (model).getModeId() - }).then(outline => { + return getOutlineEntries( model).then(outline => { let model = new OutlineModel(outline, this.toQuickOpenEntries(outline)); diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts index ce090215b97..b93fbe0cccf 100644 --- a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts @@ -9,11 +9,13 @@ import * as assert from 'assert'; import {setUnexpectedErrorHandler, errorHandler} from 'vs/base/common/errors'; import {create} from 'vs/base/common/types'; import URI from 'vs/base/common/uri'; +import {URL} from 'vs/base/common/network'; import {TPromise} from 'vs/base/common/winjs.base'; import {PluginHostDocument} from 'vs/workbench/api/common/pluginHostDocuments'; import * as types from 'vs/workbench/api/common/pluginHostTypes'; import {Range as CodeEditorRange} from 'vs/editor/common/core/range'; import * as EditorCommon from 'vs/editor/common/editorCommon'; +import {Model as EditorModel} from 'vs/editor/common/model/model'; import threadService from './testThreadService' import {ExtHostLanguageFeatures, MainThreadLanguageFeatures} from 'vs/workbench/api/common/extHostLanguageFeatures'; import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; @@ -24,8 +26,19 @@ import {OutlineRegistry, getOutlineEntries} from 'vs/editor/contrib/quickOpen/co import {CodeLensRegistry, getCodeLensData} from 'vs/editor/contrib/codelens/common/codelens'; import {DeclarationRegistry, getDeclarationsAtPosition} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; import {ExtraInfoRegistry, getExtraInfoAtPosition} from 'vs/editor/contrib/hover/common/hover'; +import {OccurrencesRegistry, getOccurrencesAtPosition} from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; + + +const defaultSelector = { scheme: 'far' }; +const model: EditorCommon.IModel = new EditorModel( + [ + 'This is the first line', + 'This is the second line', + 'This is the third line', + ].join('\n'), + undefined, + URL.fromUri(URI.parse('far://testing/file.a'))); -let model: ModelLike; let extHost: ExtHostLanguageFeatures; let mainThread: MainThreadLanguageFeatures; let disposables: vscode.Disposable[] = []; @@ -38,27 +51,18 @@ suite('ExtHostLanguageFeatures', function() { originalErrorHandler = errorHandler.getUnexpectedErrorHandler(); setUnexpectedErrorHandler(() => { }); - model = { - language: 'far', - uri: URI.parse('far://testing/file.a') - }; - threadService.getRemotable(PluginHostModelService)._acceptModelAdd({ isDirty: false, - versionId: 1, - modeId: 'far', - url: model.uri, + versionId: model.getVersionId(), + modeId: model.getModeId(), + url: model.getAssociatedResource(), value: { - EOL: '\n', - lines: [ - 'This is the first line', - 'This is the second line', - 'This is the third line', - ], + EOL: model.getEOL(), + lines: model.getValue().split(model.getEOL()), BOM: '', length: -1 }, - }) + }); threadService.getRemotable(PluginHostCommands); threadService.getRemotable(MainThreadCommands); @@ -82,7 +86,7 @@ suite('ExtHostLanguageFeatures', function() { test('DocumentSymbols, register/deregister', function(done) { assert.equal(OutlineRegistry.all(model).length, 0); - let d1 = extHost.registerDocumentSymbolProvider('far', { + let d1 = extHost.registerDocumentSymbolProvider(defaultSelector, { provideDocumentSymbols() { return []; } @@ -99,12 +103,12 @@ suite('ExtHostLanguageFeatures', function() { }); test('DocumentSymbols, evil provider', function(done) { - disposables.push(extHost.registerDocumentSymbolProvider('far', { + disposables.push(extHost.registerDocumentSymbolProvider(defaultSelector, { provideDocumentSymbols(): any { throw new Error('evil document symbol provider'); } })); - disposables.push(extHost.registerDocumentSymbolProvider('far', { + disposables.push(extHost.registerDocumentSymbolProvider(defaultSelector, { provideDocumentSymbols(): any { return [new types.SymbolInformation('test', types.SymbolKind.Field, new types.Range(0, 0, 0, 0))]; } @@ -122,7 +126,7 @@ suite('ExtHostLanguageFeatures', function() { }); test('DocumentSymbols, data conversion', function(done) { - disposables.push(extHost.registerDocumentSymbolProvider('far', { + disposables.push(extHost.registerDocumentSymbolProvider(defaultSelector, { provideDocumentSymbols(): any { return [new types.SymbolInformation('test', types.SymbolKind.Field, new types.Range(0, 0, 0, 0))]; } @@ -148,19 +152,19 @@ suite('ExtHostLanguageFeatures', function() { test('CodeLens, evil provider', function(done) { - disposables.push(extHost.registerCodeLensProvider('far', { + disposables.push(extHost.registerCodeLensProvider(defaultSelector, { provideCodeLenses():any { throw new Error('evil') } })); - disposables.push(extHost.registerCodeLensProvider('far', { + disposables.push(extHost.registerCodeLensProvider(defaultSelector, { provideCodeLenses() { return [new types.CodeLens(new types.Range(0, 0, 0, 0))]; } })); threadService.sync().then(() => { - getCodeLensData(model.uri, model.language).then(value => { + getCodeLensData(model).then(value => { assert.equal(value.length, 1); done(); }); @@ -169,7 +173,7 @@ suite('ExtHostLanguageFeatures', function() { test('CodeLens, do not resolve a resolved lens', function(done) { - disposables.push(extHost.registerCodeLensProvider('far', { + disposables.push(extHost.registerCodeLensProvider(defaultSelector, { provideCodeLenses():any { return [new types.CodeLens( new types.Range(0, 0, 0, 0), @@ -182,11 +186,11 @@ suite('ExtHostLanguageFeatures', function() { threadService.sync().then(() => { - getCodeLensData(model.uri, model.language).then(value => { + getCodeLensData(model).then(value => { assert.equal(value.length, 1); let data = value[0]; - data.support.resolveCodeLensSymbol(model.uri, data.symbol).then(command => { + data.support.resolveCodeLensSymbol(model.getAssociatedResource(), data.symbol).then(command => { assert.equal(command.id, 'id'); assert.equal(command.title, 'Title'); done(); @@ -197,7 +201,7 @@ suite('ExtHostLanguageFeatures', function() { test('CodeLens, missing command', function(done) { - disposables.push(extHost.registerCodeLensProvider('far', { + disposables.push(extHost.registerCodeLensProvider(defaultSelector, { provideCodeLenses() { return [new types.CodeLens(new types.Range(0, 0, 0, 0))]; } @@ -205,11 +209,11 @@ suite('ExtHostLanguageFeatures', function() { threadService.sync().then(() => { - getCodeLensData(model.uri, model.language).then(value => { + getCodeLensData(model).then(value => { assert.equal(value.length, 1); let data = value[0]; - data.support.resolveCodeLensSymbol(model.uri, data.symbol).then(command => { + data.support.resolveCodeLensSymbol(model.getAssociatedResource(), data.symbol).then(command => { assert.equal(command.id, 'missing'); assert.equal(command.title, '<>'); @@ -223,19 +227,19 @@ suite('ExtHostLanguageFeatures', function() { test('Definition, data conversion', function(done) { - disposables.push(extHost.registerDefinitionProvider('far', { + disposables.push(extHost.registerDefinitionProvider(defaultSelector, { provideDefinition(): any { - return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))]; + return [new types.Location(model.getAssociatedResource(), new types.Range(1, 2, 3, 4))]; } })); threadService.sync().then(() => { - getDeclarationsAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + getDeclarationsAtPosition(model, { lineNumber: 1, column: 1 }).then(value => { assert.equal(value.length, 1); let [entry] = value; assert.deepEqual(entry.range, { startLineNumber: 2, startColumn: 3, endLineNumber: 4, endColumn: 5 }); - assert.equal(entry.resource.toString(), model.uri.toString()); + assert.equal(entry.resource.toString(), model.getAssociatedResource().toString()); done(); }, err => { done(err); @@ -245,20 +249,20 @@ suite('ExtHostLanguageFeatures', function() { test('Definition, one or many', function(done) { - disposables.push(extHost.registerDefinitionProvider('far', { + disposables.push(extHost.registerDefinitionProvider(defaultSelector, { provideDefinition(): any { - return [new types.Location(model.uri, new types.Range(1, 1, 1, 1))]; + return [new types.Location(model.getAssociatedResource(), new types.Range(1, 1, 1, 1))]; } })); - disposables.push(extHost.registerDefinitionProvider('far', { + disposables.push(extHost.registerDefinitionProvider(defaultSelector, { provideDefinition(): any { - return new types.Location(model.uri, new types.Range(1, 1, 1, 1)); + return new types.Location(model.getAssociatedResource(), new types.Range(1, 1, 1, 1)); } })); threadService.sync().then(() => { - getDeclarationsAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + getDeclarationsAtPosition(model, { lineNumber: 1, column: 1 }).then(value => { assert.equal(value.length, 2); done(); }, err => { @@ -269,14 +273,14 @@ suite('ExtHostLanguageFeatures', function() { test('Definition, registration order', function(done) { - disposables.push(extHost.registerDefinitionProvider('far', { + disposables.push(extHost.registerDefinitionProvider(defaultSelector, { provideDefinition(): any { return [new types.Location(URI.parse('far://first'), new types.Range(2, 3, 4, 5))]; } })); setTimeout(function() { // registration time matters - disposables.push(extHost.registerDefinitionProvider('far', { + disposables.push(extHost.registerDefinitionProvider(defaultSelector, { provideDefinition(): any { return new types.Location(URI.parse('far://second'), new types.Range(1, 2, 3, 4)); } @@ -284,7 +288,7 @@ suite('ExtHostLanguageFeatures', function() { threadService.sync().then(() => { - getDeclarationsAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + getDeclarationsAtPosition(model, { lineNumber: 1, column: 1 }).then(value => { assert.equal(value.length, 2); // let [first, second] = value; @@ -301,20 +305,20 @@ suite('ExtHostLanguageFeatures', function() { test('Definition, evil provider', function(done) { - disposables.push(extHost.registerDefinitionProvider('far', { + disposables.push(extHost.registerDefinitionProvider(defaultSelector, { provideDefinition(): any { throw new Error('evil provider') } })); - disposables.push(extHost.registerDefinitionProvider('far', { + disposables.push(extHost.registerDefinitionProvider(defaultSelector, { provideDefinition(): any { - return new types.Location(model.uri, new types.Range(1, 1, 1, 1)); + return new types.Location(model.getAssociatedResource(), new types.Range(1, 1, 1, 1)); } })); threadService.sync().then(() => { - getDeclarationsAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + getDeclarationsAtPosition(model, { lineNumber: 1, column: 1 }).then(value => { assert.equal(value.length, 1); done(); }, err => { @@ -327,7 +331,7 @@ suite('ExtHostLanguageFeatures', function() { test('ExtraInfo, word range at pos', function(done) { - disposables.push(extHost.registerHoverProvider('far', { + disposables.push(extHost.registerHoverProvider(defaultSelector, { provideHover(): any { return new types.Hover('Hello') } @@ -335,7 +339,7 @@ suite('ExtHostLanguageFeatures', function() { threadService.sync().then(() => { - getExtraInfoAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + getExtraInfoAtPosition(model, { lineNumber: 1, column: 1 }).then(value => { assert.equal(value.length, 1); let [entry] = value; @@ -347,7 +351,7 @@ suite('ExtHostLanguageFeatures', function() { test('ExtraInfo, given range', function(done) { - disposables.push(extHost.registerHoverProvider('far', { + disposables.push(extHost.registerHoverProvider(defaultSelector, { provideHover(): any { return new types.Hover('Hello', new types.Range(3, 0, 8, 7)); } @@ -355,7 +359,7 @@ suite('ExtHostLanguageFeatures', function() { threadService.sync().then(() => { - getExtraInfoAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + getExtraInfoAtPosition(model, { lineNumber: 1, column: 1 }).then(value => { assert.equal(value.length, 1); let [entry] = value; assert.deepEqual(entry.range, { startLineNumber: 4, startColumn: 1, endLineNumber: 9, endColumn: 8 }); @@ -366,14 +370,14 @@ suite('ExtHostLanguageFeatures', function() { test('ExtraInfo, registration order', function(done) { - disposables.push(extHost.registerHoverProvider('far', { + disposables.push(extHost.registerHoverProvider(defaultSelector, { provideHover(): any { return new types.Hover('registered first'); } })); setTimeout(function() { - disposables.push(extHost.registerHoverProvider('far', { + disposables.push(extHost.registerHoverProvider(defaultSelector, { provideHover(): any { return new types.Hover('registered second'); } @@ -381,7 +385,7 @@ suite('ExtHostLanguageFeatures', function() { threadService.sync().then(() => { - getExtraInfoAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + getExtraInfoAtPosition(model, { lineNumber: 1, column: 1 }).then(value => { assert.equal(value.length, 2); let [first, second] = value; assert.equal(first.htmlContent[0].formattedText, 'registered second'); @@ -396,12 +400,12 @@ suite('ExtHostLanguageFeatures', function() { test('ExtraInfo, evil provider', function(done) { - disposables.push(extHost.registerHoverProvider('far', { + disposables.push(extHost.registerHoverProvider(defaultSelector, { provideHover(): any { throw new Error('evil') } })); - disposables.push(extHost.registerHoverProvider('far', { + disposables.push(extHost.registerHoverProvider(defaultSelector, { provideHover(): any { return new types.Hover('Hello') } @@ -409,12 +413,106 @@ suite('ExtHostLanguageFeatures', function() { threadService.sync().then(() => { - getExtraInfoAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + getExtraInfoAtPosition(model, { lineNumber: 1, column: 1 }).then(value => { assert.equal(value.length, 1); done(); }); }); + }); + // --- occurrences + + test('Occurrences, data conversion', function(done) { + + disposables.push(extHost.registerDocumentHighlightProvider(defaultSelector, { + provideDocumentHighlights(): any { + return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))] + } + })); + + threadService.sync().then(() => { + + getOccurrencesAtPosition(model, { lineNumber: 1, column: 2 }).then(value => { + assert.equal(value.length, 1); + let [entry] = value; + assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 5 }); + assert.equal(entry.kind, 'text'); + done(); + }); + }); + }); + + test('Occurrences, order 1/2', function(done) { + + disposables.push(extHost.registerDocumentHighlightProvider(defaultSelector, { + provideDocumentHighlights(): any { + return [] + } + })); + disposables.push(extHost.registerDocumentHighlightProvider('*', { + provideDocumentHighlights(): any { + return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))] + } + })); + + threadService.sync().then(() => { + + getOccurrencesAtPosition(model, { lineNumber: 1, column: 2 }).then(value => { + assert.equal(value.length, 1); + let [entry] = value; + assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 5 }); + assert.equal(entry.kind, 'text'); + done(); + }); + }); + }); + + test('Occurrences, order 2/2', function(done) { + + disposables.push(extHost.registerDocumentHighlightProvider(defaultSelector, { + provideDocumentHighlights(): any { + return [new types.DocumentHighlight(new types.Range(0, 0, 0, 2))] + } + })); + disposables.push(extHost.registerDocumentHighlightProvider('*', { + provideDocumentHighlights(): any { + return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))] + } + })); + + threadService.sync().then(() => { + + getOccurrencesAtPosition(model, { lineNumber: 1, column: 2 }).then(value => { + assert.equal(value.length, 1); + let [entry] = value; + assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 3 }); + assert.equal(entry.kind, 'text'); + done(); + }); + }); + }); + + test('Occurrences, evil provider', function(done) { + + disposables.push(extHost.registerDocumentHighlightProvider(defaultSelector, { + provideDocumentHighlights(): any { + throw new Error('evil'); + } + })); + + disposables.push(extHost.registerDocumentHighlightProvider(defaultSelector, { + provideDocumentHighlights(): any { + return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))] + } + })); + + threadService.sync().then(() => { + + getOccurrencesAtPosition(model, { lineNumber: 1, column: 2 }).then(value => { + assert.equal(value.length, 1); + done(); + }); + }); }); }); \ No newline at end of file From c27c691d354429affdf98a3444afaa6bcc0eac5e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2015 18:03:04 +0100 Subject: [PATCH 086/588] Running `code .` in a terminal does not get env vars from the terminal if there is any Code window already open (fixes #560) --- src/vs/workbench/electron-main/env.ts | 4 ++++ src/vs/workbench/electron-main/main.ts | 18 ++++++++++-------- src/vs/workbench/electron-main/window.ts | 3 +-- src/vs/workbench/electron-main/windows.ts | 18 +++++++++--------- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/electron-main/env.ts b/src/vs/workbench/electron-main/env.ts index 25fe30ea7f3..a84deb92cf3 100644 --- a/src/vs/workbench/electron-main/env.ts +++ b/src/vs/workbench/electron-main/env.ts @@ -115,6 +115,10 @@ export function log(...a: any[]): void { } } +export interface IProcessEnvironment { + [key: string]: string; +} + export interface ICommandLineArguments { verboseLogging: boolean; debugPluginHostPort: number; diff --git a/src/vs/workbench/electron-main/main.ts b/src/vs/workbench/electron-main/main.ts index cbea266a3ed..7c48beb2981 100644 --- a/src/vs/workbench/electron-main/main.ts +++ b/src/vs/workbench/electron-main/main.ts @@ -20,24 +20,24 @@ import menu = require('vs/workbench/electron-main/menus'); import settings = require('vs/workbench/electron-main/settings'); import {Instance as UpdateManager} from 'vs/workbench/electron-main/update-manager'; import {Server, serve, connect} from 'vs/base/node/service.net'; -import {getUserEnvironment, IEnv} from 'vs/base/node/env'; +import {getUserEnvironment} from 'vs/base/node/env'; import {Promise, TPromise} from 'vs/base/common/winjs.base'; import {GitAskpassService} from 'vs/workbench/parts/git/electron-main/askpassService'; -import { spawnSharedProcess } from 'vs/workbench/electron-main/sharedProcess'; +import {spawnSharedProcess} from 'vs/workbench/electron-main/sharedProcess'; export class LaunchService { - public start(args: env.ICommandLineArguments): Promise { + public start(args: env.ICommandLineArguments, userEnv: env.IProcessEnvironment): Promise { env.log('Received data from other instance', args); // Otherwise handle in windows manager if (!!args.pluginDevelopmentPath) { - windows.manager.openPluginDevelopmentHostWindow({ cli: args }); + windows.manager.openPluginDevelopmentHostWindow({ cli: args, userEnv: userEnv }); } else if (args.pathArguments.length === 0 && args.openNewWindow) { - windows.manager.open({ cli: args, forceNewWindow: true, forceEmpty: true }); + windows.manager.open({ cli: args, userEnv: userEnv, forceNewWindow: true, forceEmpty: true }); } else if (args.pathArguments.length === 0) { windows.manager.focusLastActive(args); } else { - windows.manager.open({ cli: args, forceNewWindow: !args.openInSameWindow }); + windows.manager.open({ cli: args, userEnv: userEnv, forceNewWindow: !args.openInSameWindow }); } return Promise.as(null); @@ -80,7 +80,7 @@ function quit(arg?: any) { process.exit(); } -function main(ipcServer: Server, userEnv: IEnv): void { +function main(ipcServer: Server, userEnv: env.IProcessEnvironment): void { env.log('### VSCode main.js ###'); env.log(env.appRoot, env.cliArgs); @@ -203,7 +203,7 @@ function setupIPC(): TPromise { const service = client.getService('LaunchService', LaunchService); - return service.start(env.cliArgs) + return service.start(env.cliArgs, process.env) .then(() => client.dispose()) .then(() => Promise.wrapError('Sent env to running instance. Terminating...')); }, @@ -231,6 +231,8 @@ function setupIPC(): TPromise { return setup(true); } +// On some platforms we need to manually read from the global environment variables +// and assign them to the process environment (e.g. when doubleclick app on Mac) getUserEnvironment() .then(userEnv => { assign(process.env, userEnv); diff --git a/src/vs/workbench/electron-main/window.ts b/src/vs/workbench/electron-main/window.ts index c924a897af2..066fba4d282 100644 --- a/src/vs/workbench/electron-main/window.ts +++ b/src/vs/workbench/electron-main/window.ts @@ -16,7 +16,6 @@ import platform = require('vs/base/common/platform'); import objects = require('vs/base/common/objects'); import env = require('vs/workbench/electron-main/env'); import storage = require('vs/workbench/electron-main/storage'); -import {IEnv} from 'vs/base/node/env'; export interface IWindowState { width?: number; @@ -113,7 +112,7 @@ export interface IWindowConfiguration extends env.ICommandLineArguments { releaseNotesUrl: string; productDownloadUrl: string; enableTelemetry: boolean; - userEnv: IEnv, + userEnv: env.IProcessEnvironment, aiConfig: { key: string; asimovKey: string; diff --git a/src/vs/workbench/electron-main/windows.ts b/src/vs/workbench/electron-main/windows.ts index 936dda2ab76..f928b91863f 100644 --- a/src/vs/workbench/electron-main/windows.ts +++ b/src/vs/workbench/electron-main/windows.ts @@ -28,7 +28,6 @@ import objects = require('vs/base/common/objects'); import storage = require('vs/workbench/electron-main/storage'); import settings = require('vs/workbench/electron-main/settings'); import {Instance as UpdateManager, IUpdate} from 'vs/workbench/electron-main/update-manager'; -import {IEnv} from 'vs/base/node/env'; const eventEmitter = new events.EventEmitter(); @@ -63,6 +62,7 @@ enum WindowError { export interface IOpenConfiguration { cli: env.ICommandLineArguments; + userEnv?: env.IProcessEnvironment; pathsToOpen?: string[]; forceNewWindow?: boolean; forceEmpty?: boolean; @@ -102,13 +102,13 @@ export class WindowsManager { private static WINDOWS: window.VSCodeWindow[] = []; - private userEnv: IEnv; + private initialUserEnv: env.IProcessEnvironment; private windowsState: IWindowsState; - public ready(userEnv: IEnv): void { + public ready(initialUserEnv: env.IProcessEnvironment): void { this.registerListeners(); - this.userEnv = userEnv; + this.initialUserEnv = initialUserEnv; this.windowsState = storage.getItem(WindowsManager.windowsStateStorageKey) || { openedFolders: [] }; } @@ -403,7 +403,7 @@ export class WindowsManager { // Otherwise open instance with files else { - configuration = this.toConfiguration(openConfig.cli, null, filesToOpen, filesToCreate, extensionsToInstall); + configuration = this.toConfiguration(openConfig.userEnv || this.initialUserEnv, openConfig.cli, null, filesToOpen, filesToCreate, extensionsToInstall); this.openInBrowserWindow(configuration, true /* new window */); openConfig.forceNewWindow = true; // any other folders to open must open in new window then @@ -442,7 +442,7 @@ export class WindowsManager { return; // ignore folders that are already open } - configuration = this.toConfiguration(openConfig.cli, folderToOpen.workspacePath, filesToOpen, filesToCreate, extensionsToInstall); + configuration = this.toConfiguration(openConfig.userEnv || this.initialUserEnv, openConfig.cli, folderToOpen.workspacePath, filesToOpen, filesToCreate, extensionsToInstall); this.openInBrowserWindow(configuration, openConfig.forceNewWindow, openConfig.forceNewWindow ? void 0 : openConfig.windowToUse); // Reset these because we handled them @@ -457,7 +457,7 @@ export class WindowsManager { // Handle empty if (emptyToOpen.length > 0) { emptyToOpen.forEach(() => { - let configuration = this.toConfiguration(openConfig.cli); + let configuration = this.toConfiguration(openConfig.userEnv || this.initialUserEnv, openConfig.cli); this.openInBrowserWindow(configuration, openConfig.forceNewWindow, openConfig.forceNewWindow ? void 0 : openConfig.windowToUse); openConfig.forceNewWindow = true; // any other folders to open must open in new window then @@ -510,7 +510,7 @@ export class WindowsManager { this.open({ cli: openConfig.cli, forceNewWindow: true, forceEmpty: openConfig.cli.pathArguments.length === 0 }); } - private toConfiguration(cli: env.ICommandLineArguments, workspacePath?: string, filesToOpen?: window.IPath[], filesToCreate?: window.IPath[], extensionsToInstall?: string[]): window.IWindowConfiguration { + private toConfiguration(userEnv: env.IProcessEnvironment, cli: env.ICommandLineArguments, workspacePath?: string, filesToOpen?: window.IPath[], filesToCreate?: window.IPath[], extensionsToInstall?: string[]): window.IWindowConfiguration { let configuration: window.IWindowConfiguration = objects.mixin({}, cli); // inherit all properties from CLI configuration.execPath = process.execPath; configuration.workspacePath = workspacePath; @@ -539,7 +539,7 @@ export class WindowsManager { configuration.aiConfig = env.product.aiConfig; configuration.sendASmile = env.product.sendASmile; configuration.enableTelemetry = env.product.enableTelemetry; - configuration.userEnv = this.userEnv; + configuration.userEnv = userEnv; return configuration; } From 2ede316636d63458b71bd32633513d8e840556b1 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2015 18:37:11 +0100 Subject: [PATCH 087/588] reference provider as support --- .../browser/referenceSearch.ts | 22 +----- .../referenceSearch/common/referenceSearch.ts | 31 +++++++- .../api/browser/pluginHost.api.impl.ts | 2 +- .../api/common/extHostLanguageFeatures.ts | 67 +++++++++++++++- .../workbench/api/common/languageFeatures.ts | 60 -------------- .../api/extHostLanguageFeatures.test.ts | 78 ++++++++++++++++++- 6 files changed, 174 insertions(+), 86 deletions(-) diff --git a/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts b/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts index eff53f50596..4f0846b52f8 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts @@ -30,7 +30,7 @@ import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {IKeybindingService, IKeybindingContextKey, ICommandHandler} from 'vs/platform/keybinding/common/keybindingService'; import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry'; import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; -import ReferenceSearchRegistry from '../common/referenceSearch'; +import {ReferenceRegistry, findReferences} from '../common/referenceSearch'; import IPeekViewService = peekView.IPeekViewService; export class FindReferencesController implements EditorCommon.IEditorContribution { @@ -265,7 +265,7 @@ export class ReferenceAction extends EditorAction { } public isSupported():boolean { - return ReferenceSearchRegistry.has(this.editor.getModel()) && super.isSupported(); + return ReferenceRegistry.has(this.editor.getModel()) && super.isSupported(); } public getEnablementState():boolean { @@ -278,7 +278,7 @@ export class ReferenceAction extends EditorAction { let context = model.getLineContext(position.lineNumber); let offset = position.column - 1; - return ReferenceSearchRegistry.all(model).some(support => { + return ReferenceRegistry.all(model).some(support => { return support.canFindReferences(context, offset); }); } @@ -292,22 +292,6 @@ export class ReferenceAction extends EditorAction { } } -function findReferences(model: EditorCommon.IModel, position: EditorCommon.IPosition): TPromise { - let references: Modes.IReference[] = []; - - // collect references from all providers - let promises = ReferenceSearchRegistry.all(model).map(provider => { - return provider.findReferences(model.getAssociatedResource(), position, true).then(result => { - if (Array.isArray(result)) { - references.push(...result); - } - }, err => { - errors.onUnexpectedError(err); - }); - }); - - return TPromise.join(promises).then(() => references); -} let findReferencesCommand: ICommandHandler = (accessor, args) => { diff --git a/src/vs/editor/contrib/referenceSearch/common/referenceSearch.ts b/src/vs/editor/contrib/referenceSearch/common/referenceSearch.ts index d578fcbe0cc..333047e044e 100644 --- a/src/vs/editor/contrib/referenceSearch/common/referenceSearch.ts +++ b/src/vs/editor/contrib/referenceSearch/common/referenceSearch.ts @@ -6,8 +6,35 @@ 'use strict'; import {IReferenceSupport} from 'vs/editor/common/modes'; +import {IReference} from 'vs/editor/common/modes'; +import {IModel, IPosition} from 'vs/editor/common/editorCommon'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {onUnexpectedError} from 'vs/base/common/errors'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; -const ReferenceSearchRegistry = new LanguageFeatureRegistry('referenceSupport'); +export const ReferenceRegistry = new LanguageFeatureRegistry('referenceSupport'); -export default ReferenceSearchRegistry; \ No newline at end of file +export function findReferences(model: IModel, position: IPosition): TPromise { + + + // collect references from all providers + const promises = ReferenceRegistry.ordered(model).map(provider => { + return provider.findReferences(model.getAssociatedResource(), position, true).then(result => { + if (Array.isArray(result)) { + return result; + } + }, err => { + onUnexpectedError(err); + }); + }); + + return TPromise.join(promises).then(references => { + let result: IReference[] = []; + for (let ref of references) { + if (ref) { + result.push(...ref); + } + } + return result; + }); +} diff --git a/src/vs/workbench/api/browser/pluginHost.api.impl.ts b/src/vs/workbench/api/browser/pluginHost.api.impl.ts index 93c40d6acc9..d36f3f7a2de 100644 --- a/src/vs/workbench/api/browser/pluginHost.api.impl.ts +++ b/src/vs/workbench/api/browser/pluginHost.api.impl.ts @@ -280,7 +280,7 @@ export class PluginHostAPIImplementation { return languageFeatures.registerDocumentHighlightProvider(selector, provider); }, registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable { - return features.referenceSearch.register(selector, provider); + return languageFeatures.registerReferenceProvider(selector, provider); }, registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable { return features.rename.register(selector, provider); diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 65943d85924..61df0119d4c 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -26,7 +26,7 @@ import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pl import {DeclarationRegistry} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; import {ExtraInfoRegistry} from 'vs/editor/contrib/hover/common/hover'; import {OccurrencesRegistry} from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; -import ReferenceSearchRegistry from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; +import {ReferenceRegistry} from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; import QuickFixRegistry from 'vs/editor/contrib/quickFix/common/quickFix'; import {OutlineRegistry, IOutlineEntry, IOutlineSupport} from 'vs/editor/contrib/quickOpen/common/quickOpen'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; @@ -262,7 +262,40 @@ class OccurrencesAdapter implements modes.IOccurrencesSupport { } } -type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | ExtraInfoAdapter | OccurrencesAdapter; +class ReferenceAdapter implements modes.IReferenceSupport { + + private _documents: PluginHostModelService; + private _provider: vscode.ReferenceProvider; + + constructor(documents: PluginHostModelService, provider: vscode.ReferenceProvider) { + this._documents = documents; + this._provider = provider; + } + + canFindReferences():boolean { + return true + } + + findReferences(resource: URI, position: IPosition, includeDeclaration: boolean): TPromise { + let doc = this._documents.getDocument(resource); + let pos = TypeConverters.toPosition(position); + + return asWinJsPromise(token => this._provider.provideReferences(doc, pos, { includeDeclaration }, token)).then(value => { + if (Array.isArray(value)) { + return value.map(ReferenceAdapter._convertLocation); + } + }); + } + + private static _convertLocation(location: vscode.Location): modes.IReference { + return { + resource: location.uri, + range: TypeConverters.fromRange(location.range) + }; + } +} + +type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | ExtraInfoAdapter | OccurrencesAdapter | ReferenceAdapter; @Remotable.PluginHostContext('ExtHostLanguageFeatures') export class ExtHostLanguageFeatures { @@ -353,7 +386,7 @@ export class ExtHostLanguageFeatures { return this._withAdapter(handle, ExtraInfoAdapter, adpater => adpater.computeInfo(resource, position)); } - // --- occurrences adapter + // --- occurrences registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable { const handle = this._nextHandle(); @@ -365,6 +398,20 @@ export class ExtHostLanguageFeatures { $findOccurrences(handle:number, resource: URI, position: IPosition): TPromise { return this._withAdapter(handle, OccurrencesAdapter, adapter => adapter.findOccurrences(resource, position)); } + + // --- references + + registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable { + const handle = this._nextHandle(); + this._adapter[handle] = new ReferenceAdapter(this._documents, provider); + this._proxy.$registerReferenceSupport(handle, selector); + return this._createDisposable(handle); + } + + $findReferences(handle: number, resource: URI, position: IPosition, includeDeclaration: boolean): TPromise { + return this._withAdapter(handle, ReferenceAdapter, adapter => adapter.findReferences(resource, position, includeDeclaration)); + } + } @Remotable.MainContext('MainThreadLanguageFeatures') @@ -446,4 +493,18 @@ export class MainThreadLanguageFeatures { }); return undefined; } + + // --- references + + $registerReferenceSupport(handle: number, selector: vscode.DocumentSelector): TPromise { + this._registrations[handle] = ReferenceRegistry.register(selector, { + canFindReferences() { + return true; + }, + findReferences: (resource: URI, position: IPosition, includeDeclaration: boolean): TPromise => { + return this._proxy.$findReferences(handle, resource, position, includeDeclaration); + } + }); + return undefined; + } } \ No newline at end of file diff --git a/src/vs/workbench/api/common/languageFeatures.ts b/src/vs/workbench/api/common/languageFeatures.ts index d8cb2762569..4b82cf172d9 100644 --- a/src/vs/workbench/api/common/languageFeatures.ts +++ b/src/vs/workbench/api/common/languageFeatures.ts @@ -22,7 +22,6 @@ import {CancellationTokenSource} from 'vs/base/common/cancellation'; import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; import {IMarkerService, IMarker} from 'vs/platform/markers/common/markers'; import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; -import ReferenceSearchRegistry from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; import QuickFixRegistry from 'vs/editor/contrib/quickFix/common/quickFix'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import {NavigateTypesSupportRegistry, INavigateTypesSupport, ITypeBearing} from 'vs/workbench/parts/search/common/search' @@ -132,63 +131,6 @@ export abstract class AbstractExtensionHostFeature { - - constructor(@IThreadService threadService: IThreadService) { - super(threadService.getRemotable(MainThreadReferenceSearch), threadService); - } - - protected _runAsCommand(resource: URI, position: IPosition, includeDeclaration: boolean): TPromise { - - if (!(resource instanceof URI)) { - return TPromise.wrapError('resource expected'); - } - - let document = this._models.getDocument(resource); - let pos = TypeConverters.toPosition(position); - let locations: vscode.Location[] = []; - - let promises = this._registry.all({ language: document.languageId, uri: document.uri }).map(provider => { - return asWinJsPromise(token => provider.provideReferences(document, pos, { includeDeclaration }, token)).then(result => { - if (Array.isArray(result)) { - locations.push(...result); - } - }, err => { - console.error(err); - }); - }); - - return TPromise.join(promises).then(() => { - return locations.map(ExtensionHostReferenceSearch._convertLocation); - }); - } - - private static _convertLocation(location: vscode.Location): modes.IReference { - return { - resource: location.uri, - range: TypeConverters.fromRange(location.range) - }; - } -} - -@Remotable.MainContext('MainThreadReferenceSearch') -export class MainThreadReferenceSearch extends AbstractMainThreadFeature implements modes.IReferenceSupport { - - constructor(@IThreadService threadService: IThreadService) { - super('vscode.executeReferenceProvider', ReferenceSearchRegistry, threadService); - } - - canFindReferences():boolean { - return true - } - - findReferences(resource: URI, position: IPosition, includeDeclaration: boolean): TPromise { - return this._executeCommand(resource, position, includeDeclaration); - } -} - // --- quick fix aka code actions export class ExtensionHostCodeActions extends AbstractExtensionHostFeature { @@ -884,7 +826,6 @@ export class MainThreadWorkspaceSymbols implements INavigateTypesSupport { export namespace LanguageFeatures { export function createMainThreadInstances(threadService: IThreadService): void { - threadService.getRemotable(MainThreadReferenceSearch); threadService.getRemotable(MainThreadCodeActions); threadService.getRemotable(MainThreadWorkspaceSymbols); threadService.getRemotable(MainThreadRename); @@ -897,7 +838,6 @@ export namespace LanguageFeatures { export function createExtensionHostInstances(threadService: IThreadService) { return { - referenceSearch: new ExtensionHostReferenceSearch(threadService), codeActions: new ExtensionHostCodeActions(threadService), workspaceSymbols: new ExtensionHostWorkspaceSymbols(threadService), rename: new ExtensionHostRename(threadService), diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts index b93fbe0cccf..b7b89a03c96 100644 --- a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts @@ -27,7 +27,7 @@ import {CodeLensRegistry, getCodeLensData} from 'vs/editor/contrib/codelens/comm import {DeclarationRegistry, getDeclarationsAtPosition} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; import {ExtraInfoRegistry, getExtraInfoAtPosition} from 'vs/editor/contrib/hover/common/hover'; import {OccurrencesRegistry, getOccurrencesAtPosition} from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; - +import {ReferenceRegistry, findReferences} from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; const defaultSelector = { scheme: 'far' }; const model: EditorCommon.IModel = new EditorModel( @@ -515,4 +515,80 @@ suite('ExtHostLanguageFeatures', function() { }); }); }); + + // --- references + + test('References, registration order', function(done) { + + disposables.push(extHost.registerReferenceProvider(defaultSelector, { + provideReferences(): any { + return [new types.Location(URI.parse('far://register/first'), new types.Range(0, 0, 0, 0))]; + } + })); + + setTimeout(function() { + disposables.push(extHost.registerReferenceProvider(defaultSelector, { + provideReferences(): any { + return [new types.Location(URI.parse('far://register/second'), new types.Range(0, 0, 0, 0))]; + } + })); + + threadService.sync().then(() => { + + findReferences(model, { lineNumber: 1, column: 2 }).then(value => { + assert.equal(value.length, 2); + + let [first, second] = value; + assert.equal(first.resource.path, '/second'); + assert.equal(second.resource.path, '/first'); + done(); + }); + }); + }, 5); + }); + + test('References, data conversion', function(done) { + + disposables.push(extHost.registerReferenceProvider(defaultSelector, { + provideReferences(): any { + return [new types.Location(model.getAssociatedResource(), new types.Position(0, 0))]; + } + })); + + threadService.sync().then(() => { + + findReferences(model, { lineNumber: 1, column: 2 }).then(value => { + assert.equal(value.length, 1); + + let [item] = value; + assert.deepEqual(item.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }); + assert.equal(item.resource.toString(), model.getAssociatedResource().toString()); + done(); + }); + + }); + }); + + test('References, evil provider', function(done) { + + disposables.push(extHost.registerReferenceProvider(defaultSelector, { + provideReferences(): any { + throw new Error('evil'); + } + })); + disposables.push(extHost.registerReferenceProvider(defaultSelector, { + provideReferences(): any { + return [new types.Location(model.getAssociatedResource(), new types.Range(0, 0, 0, 0))]; + } + })); + + threadService.sync().then(() => { + + findReferences(model, { lineNumber: 1, column: 2 }).then(value => { + assert.equal(value.length, 1); + done(); + }); + + }); + }); }); \ No newline at end of file From fc95d2a7eb022006a6e3b4b657ee9b4f3d1eef8b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 25 Nov 2015 18:40:08 +0100 Subject: [PATCH 088/588] simply code --- .../goToDeclaration/common/goToDeclaration.ts | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts index dea603b4c2c..2af92d98124 100644 --- a/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts @@ -17,31 +17,27 @@ export const DeclarationRegistry = new LanguageFeatureRegistry { - const promises: TPromise[] = []; const resource = model.getAssociatedResource(); const provider = DeclarationRegistry.ordered(model); - const references: (IReference[]| IReference)[] = Array<(IReference[]| IReference)>(provider.length); // get results - provider.map((provider, idx) => { - let promise = provider.findDeclaration(resource, position); - promises.push(promise.then(result => { - references[idx] = result; + const promises = provider.map((provider, idx) => { + return provider.findDeclaration(resource, position).then(result => { + return result; }, err => { onUnexpectedError(err); - })); + }); }); - return TPromise.join(promises).then(() => { + return TPromise.join(promises).then(allReferences => { let result: IReference[] = []; - for (let item of references) { - if (Array.isArray(item)) { - result.push(...item) - } else if(item) { - result.push(item); + for (let references of allReferences) { + if (Array.isArray(references)) { + result.push(...references); + } else if (references) { + result.push(references); } } - return result; }); } \ No newline at end of file From 6a14d07be22504f041ca66eca1d37bd09210860f Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 25 Nov 2015 18:49:13 +0100 Subject: [PATCH 089/588] debug: move replHistory to common. --- src/vs/workbench/parts/debug/browser/replEditor.ts | 2 +- src/vs/workbench/parts/debug/{browser => common}/replHistory.ts | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/vs/workbench/parts/debug/{browser => common}/replHistory.ts (100%) diff --git a/src/vs/workbench/parts/debug/browser/replEditor.ts b/src/vs/workbench/parts/debug/browser/replEditor.ts index 14c266334b6..0c7bd7975da 100644 --- a/src/vs/workbench/parts/debug/browser/replEditor.ts +++ b/src/vs/workbench/parts/debug/browser/replEditor.ts @@ -20,7 +20,7 @@ import viewer = require('vs/workbench/parts/debug/browser/replViewer'); import debug = require('vs/workbench/parts/debug/common/debug'); import model = require('vs/workbench/parts/debug/common/debugModel'); import debugactions = require('vs/workbench/parts/debug/browser/debugActions'); -import replhistory = require('vs/workbench/parts/debug/browser/replHistory'); +import replhistory = require('vs/workbench/parts/debug/common/replHistory'); import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService, INullService } from 'vs/platform/instantiation/common/instantiation'; diff --git a/src/vs/workbench/parts/debug/browser/replHistory.ts b/src/vs/workbench/parts/debug/common/replHistory.ts similarity index 100% rename from src/vs/workbench/parts/debug/browser/replHistory.ts rename to src/vs/workbench/parts/debug/common/replHistory.ts From 259decb3781c176674a3ada0b109a753f84389ee Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 25 Nov 2015 19:02:20 +0100 Subject: [PATCH 090/588] debug: simple view model tests. --- .../debug/test/common/debugViewModel.test.ts | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/vs/workbench/parts/debug/test/common/debugViewModel.test.ts diff --git a/src/vs/workbench/parts/debug/test/common/debugViewModel.test.ts b/src/vs/workbench/parts/debug/test/common/debugViewModel.test.ts new file mode 100644 index 00000000000..a60ac72fd44 --- /dev/null +++ b/src/vs/workbench/parts/debug/test/common/debugViewModel.test.ts @@ -0,0 +1,38 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import assert = require('assert'); +import { ViewModel } from 'vs/workbench/parts/debug/common/debugViewModel'; +import { StackFrame, Expression } from 'vs/workbench/parts/debug/common/debugModel'; + +suite('Debug - View Model', () => { + var model: ViewModel; + + setup(() => { + model = new ViewModel(); + }); + + teardown(() => { + model = null; + }); + + test('focused stack frame', () => { + assert.equal(model.getFocusedStackFrame(), null); + assert.equal(model.getFocusedThreadId(), 0); + const frame = new StackFrame(1, 1, null, 'app.js', 1, 1); + model.setFocusedStackFrame(frame); + + assert.equal(model.getFocusedStackFrame(), frame); + assert.equal(model.getFocusedThreadId(), 1); + }); + + test('selected expression', () => { + assert.equal(model.getSelectedExpression(), null); + const expression = new Expression('my expression', false); + model.setSelectedExpression(expression); + + assert.equal(model.getSelectedExpression(), expression); + }); +}); From 07614ff96e60d9f62cfe48f5d98a7f419fc8bbef Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2015 19:48:42 +0100 Subject: [PATCH 091/588] set exit code properly from main side --- src/vs/workbench/electron-main/main.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/electron-main/main.ts b/src/vs/workbench/electron-main/main.ts index 7c48beb2981..1a26f9a059a 100644 --- a/src/vs/workbench/electron-main/main.ts +++ b/src/vs/workbench/electron-main/main.ts @@ -67,9 +67,11 @@ process.on('uncaughtException', (err: any) => { function quit(error?: Error); function quit(message?: string); function quit(arg?: any) { + let exitCode = 0; if (typeof arg === 'string') { env.log(arg) } else { + exitCode = 1; // signal error to the outside if (arg.stack) { console.error(arg.stack); } else { @@ -77,7 +79,7 @@ function quit(arg?: any) { } } - process.exit(); + process.exit(exitCode); } function main(ipcServer: Server, userEnv: env.IProcessEnvironment): void { From 948a320932676d7ee121cd51990b4437cac28f44 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 25 Nov 2015 19:51:39 +0100 Subject: [PATCH 092/588] debug: adapter attributes are optional. --- src/vs/workbench/parts/debug/common/debug.ts | 24 ++++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index 9a7161e546c..ce5c819f3f3 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -195,21 +195,21 @@ export interface IConfig { } export interface IRawEnvAdapter { - type: string; - label: string; - program: string; - args: string[]; - runtime: string; - runtimeArgs: string[]; + type?: string; + label?: string; + program?: string; + args?: string[]; + runtime?: string; + runtimeArgs?: string[]; } export interface IRawAdapter extends IRawEnvAdapter { - enableBreakpointsFor: { languageIds: string[] }; - configurationAttributes: any; - initialConfigurations: any[]; - win: IRawEnvAdapter; - osx: IRawEnvAdapter; - linux: IRawEnvAdapter; + enableBreakpointsFor?: { languageIds: string[] }; + configurationAttributes?: any; + initialConfigurations?: any[]; + win?: IRawEnvAdapter; + osx?: IRawEnvAdapter; + linux?: IRawEnvAdapter; } export interface IRawDebugSession extends ee.EventEmitter { From b87999149ccf22f8ccc6c32256cc3b962abf69b6 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 25 Nov 2015 19:52:05 +0100 Subject: [PATCH 093/588] debug: adapter tests. --- .../debug/test/node/debugAdapter.test.ts | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/vs/workbench/parts/debug/test/node/debugAdapter.test.ts diff --git a/src/vs/workbench/parts/debug/test/node/debugAdapter.test.ts b/src/vs/workbench/parts/debug/test/node/debugAdapter.test.ts new file mode 100644 index 00000000000..ef80386e627 --- /dev/null +++ b/src/vs/workbench/parts/debug/test/node/debugAdapter.test.ts @@ -0,0 +1,80 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import assert = require('assert'); +import paths = require('vs/base/common/paths'); +import platform = require('vs/base/common/platform'); +import { Adapter } from 'vs/workbench/parts/debug/node/debugAdapter'; + +suite('Debug - Adapter', () => { + var adapter: Adapter; + var extensionFolderPath = 'a/b/c/'; + var rawAdapter = { + type: 'mock', + label: 'Mock Debug', + enableBreakpointsFor: { 'languageIds': [ 'markdown' ] }, + program: './out/mock/mockDebug.js', + win: { + runtime: 'winRuntime' + }, + linux: { + runtime: 'linuxRuntime' + }, + osx: { + runtime: 'osxRuntime' + }, + configurationAttributes: { + launch: { + required: [ 'program' ], + properties: { + program: { + 'type': 'string', + 'description': 'Workspace relative path to a text file.', + 'default': 'readme.md' + } + } + } + }, + + initialConfigurations: [ + { + name: 'Mock-Debug', + type: 'mock', + request: 'launch', + program: 'readme.md' + } + ] + } + + setup(() => { + adapter = new Adapter(rawAdapter, null, extensionFolderPath); + }); + + teardown(() => { + adapter = null; + }); + + test('adapter attributes', () => { + assert.equal(adapter.type, rawAdapter.type); + assert.equal(adapter.label, rawAdapter.label); + assert.equal(adapter.program, paths.join(extensionFolderPath, rawAdapter.program)); + assert.equal(adapter.runtime, platform.isLinux ? rawAdapter.linux.runtime : platform.isMacintosh ? rawAdapter.osx.runtime : rawAdapter.win.runtime); + assert.deepEqual(adapter.initialConfigurations, rawAdapter.initialConfigurations); + }); + + test('schema attributes', () => { + const schemaAttribute = adapter.getSchemaAttributes()[0]; + assert.notDeepEqual(schemaAttribute, rawAdapter.configurationAttributes); + Object.keys(rawAdapter.configurationAttributes.launch).forEach(key => { + assert.deepEqual(schemaAttribute[key], rawAdapter.configurationAttributes.launch[key]); + }); + + assert.equal(schemaAttribute['additionalProperties'], false); + assert.equal(!!schemaAttribute['properties']['request'], true); + assert.equal(!!schemaAttribute['properties']['name'], true); + assert.equal(!!schemaAttribute['properties']['type'], true); + assert.equal(!!schemaAttribute['properties']['preLaunchTask'], true); + }); +}); \ No newline at end of file From b2a6b8d8656d290bbdfce9c1ca1e6127717bf862 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 25 Nov 2015 20:28:15 +0100 Subject: [PATCH 094/588] Cannot read property 'word' of null (fixes #648) --- .../editor/contrib/goToDeclaration/browser/goToDeclaration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts index 8b6b9370b5f..a9e8d95ffb0 100644 --- a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts @@ -313,7 +313,7 @@ class GotoDefinitionWithMouseEditorContribution implements EditorCommon.IEditorC startColumn: word.startColumn, endLineNumber: position.lineNumber, endColumn: word.endColumn - }, nls.localize('multipleResults', "Click to show the {0} definitions for '{1}'.", results.length, this.currentWordUnderMouse.word), false); + }, nls.localize('multipleResults', "Click to show the {0} definitions found.", results.length), false); } // Single result From a14d8e2131637010ee034fa60b391cd176a524e3 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 25 Nov 2015 22:01:45 +0100 Subject: [PATCH 095/588] refactor gulp.hygiene for a pre-commit hook related to #636 --- build/gulpfile.hygiene.js | 43 ++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js index 3427f3240d2..f617b0458ce 100644 --- a/build/gulpfile.hygiene.js +++ b/build/gulpfile.hygiene.js @@ -8,12 +8,16 @@ var filter = require('gulp-filter'); var es = require('event-stream'); var path = require('path'); -var eolFilter = [ +var all = [ 'build/**/*', 'extensions/**/*', 'scripts/**/*', 'src/**/*', - 'test/**/*', + 'test/**/*' +]; + +var eolFilter = [ + '**', '!extensions/csharp-o/bin/**', '!extensions/**/out/**', '!**/node_modules/**', @@ -64,12 +68,12 @@ var copyrightHeader = [ ' *--------------------------------------------------------------------------------------------*/' ].join('\n'); -gulp.task('hygiene', function() { +var hygiene = exports.hygiene = function (some) { var errorCount = 0; var eol = es.through(function (file) { if (/\r\n?/g.test(file.contents.toString('utf8'))) { - console.error(file.path + ': Bad EOL found'); + console.error(file.relative + ': Bad EOL found'); errorCount++; } @@ -88,7 +92,7 @@ gulp.task('hygiene', function() { } else if (/^[\t]* \*/.test(line)) { // block comment using an extra space } else { - console.error(file.path + '(' + (i + 1) + ',1): Bad whitespace indentation'); + console.error(file.relative + '(' + (i + 1) + ',1): Bad whitespace indentation'); errorCount++; } }); @@ -98,15 +102,16 @@ gulp.task('hygiene', function() { var copyrights = es.through(function (file) { if (file.contents.toString('utf8').indexOf(copyrightHeader) !== 0) { - console.error(file.path + ': Missing or bad copyright statement'); + console.error(file.relative + ': Missing or bad copyright statement'); errorCount++; } this.emit('data', file); }); - return gulp.src(eolFilter, { base: '.' }) + return gulp.src(some || all, { base: '.' }) .pipe(filter(function (f) { return !f.stat.isDirectory(); })) + .pipe(filter(eolFilter)) .pipe(eol) .pipe(filter(indentationFilter)) .pipe(indentation) @@ -119,4 +124,28 @@ gulp.task('hygiene', function() { this.emit('end'); } })); +}; + +gulp.task('hygiene', function () { + return hygiene(); }); + +// this allows us to run this as a git pre-commit hook +if (require.main === module) { + var cp = require('child_process'); + cp.exec('git diff --cached --name-only', function (err, out) { + if (err) { + console.log(err); + process.exit(1); + } + + var some = out + .split(/\r?\n/) + .filter(function (l) { return !!l; }); + + hygiene(some).on('error', function (err) { + console.log(err); + process.exit(1); + }); + }); +} From 0dfc06e0f9de5925de792cdf9f0e6597bb25908f Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 25 Nov 2015 22:08:23 +0100 Subject: [PATCH 096/588] add ghooks dev dependency related to #636 --- package.json | 174 ++++++++++++++++++++++++++------------------------- 1 file changed, 90 insertions(+), 84 deletions(-) diff --git a/package.json b/package.json index 7b54931f9fa..5badd18213f 100644 --- a/package.json +++ b/package.json @@ -1,86 +1,92 @@ { - "name": "Code", - "version": "0.10.1", - "electronVersion": "0.34.1", - "author": { - "name": "Microsoft Corporation" - }, - "main": "./out/vs/workbench/electron-main/bootstrap", - "private": true, - "engines": { - "node": ">= 0.10.0 < 0.11.0" - }, - "scripts": { - "test": "node node_modules/mocha/bin/_mocha", - "postinstall": "npm --prefix extensions/csharp-o/ install extensions/csharp-o/ && npm --prefix extensions/vscode-api-tests/ install extensions/vscode-api-tests/" - }, - "dependencies": { - "applicationinsights": "0.15.6", - "chokidar": "1.0.5", - "emmet": "^1.3.0", - "getmac": "1.0.7", - "graceful-fs": "4.1.2", - "http-proxy-agent": "^0.2.6", - "https-proxy-agent": "^0.3.5", - "iconv-lite": "^0.4.13", - "sax": "^1.1.1", - "semver": "^4.2.0", - "vscode-textmate": "^1.0.7", - "winreg": "0.0.12", - "yauzl": "^2.3.1" - }, - "devDependencies": { - "async": "^1.4.0", - "azure-storage": "^0.3.1", - "clone": "^1.0.2", - "debounce": "^1.0.0", - "event-stream": "^3.1.7", - "express": "^4.13.1", - "glob": "^5.0.13", - "gulp": "^3.8.9", - "gulp-atom-electron": "^0.17.2", - "gulp-azure-storage": "^0.3.0", - "gulp-bom": "^1.0.0", - "gulp-concat": "^2.6.0", - "gulp-filter": "^3.0.0", - "gulp-insert": "^0.5.0", - "gulp-json-editor": "^2.2.1", - "gulp-minify-css": "^1.2.1", - "clean-css": "3.4.6", - "gulp-mocha": "^2.1.3", - "gulp-remote-src": "^0.4.0", - "gulp-rename": "^1.2.0", - "gulp-sourcemaps": "^1.6.0", - "gulp-tsb": "^1.7.3", - "gulp-uglify": "^1.4.1", - "gulp-util": "^3.0.6", - "gulp-symdest": "^1.0.0", - "gulp-vinyl-zip": "^1.1.0", - "gulp-watch": "^4.2.4", - "innosetup-compiler": "^5.5.60", - "istanbul": "^0.3.17", - "jsdom-no-contextify": "^3.1.0", - "json-comments": "^0.2.1", - "lazy.js": "^0.4.2", - "mime": "1.2.11", - "minimatch": "^2.0.10", - "mkdirp": "^0.5.0", - "mocha": "^2.2.5", - "object-assign": "^4.0.1", - "optimist": "0.3.5", - "queue": "3.0.6", - "rimraf": "^2.2.8", - "sinon": "^1.17.2", - "source-map": "^0.4.4", - "uglify-js": "2.4.8", - "underscore": "^1.8.2", - "vinyl": "^0.4.5" - }, - "repository": { - "type": "git", - "url": "https://github.com/Microsoft/vscode.git" - }, - "bugs": { - "url": "https://github.com/Microsoft/vscode/issues" - } + "name": "Code", + "version": "0.10.1", + "electronVersion": "0.34.1", + "author": { + "name": "Microsoft Corporation" + }, + "main": "./out/vs/workbench/electron-main/bootstrap", + "private": true, + "engines": { + "node": ">= 0.10.0 < 0.11.0" + }, + "scripts": { + "test": "node node_modules/mocha/bin/_mocha", + "postinstall": "npm --prefix extensions/csharp-o/ install extensions/csharp-o/ && npm --prefix extensions/vscode-api-tests/ install extensions/vscode-api-tests/" + }, + "dependencies": { + "applicationinsights": "0.15.6", + "chokidar": "1.0.5", + "emmet": "^1.3.0", + "getmac": "1.0.7", + "graceful-fs": "4.1.2", + "http-proxy-agent": "^0.2.6", + "https-proxy-agent": "^0.3.5", + "iconv-lite": "^0.4.13", + "sax": "^1.1.1", + "semver": "^4.2.0", + "vscode-textmate": "^1.0.7", + "winreg": "0.0.12", + "yauzl": "^2.3.1" + }, + "devDependencies": { + "async": "^1.4.0", + "azure-storage": "^0.3.1", + "clean-css": "3.4.6", + "clone": "^1.0.2", + "debounce": "^1.0.0", + "event-stream": "^3.1.7", + "express": "^4.13.1", + "ghooks": "^1.0.1", + "glob": "^5.0.13", + "gulp": "^3.8.9", + "gulp-atom-electron": "^0.17.2", + "gulp-azure-storage": "^0.3.0", + "gulp-bom": "^1.0.0", + "gulp-concat": "^2.6.0", + "gulp-filter": "^3.0.0", + "gulp-insert": "^0.5.0", + "gulp-json-editor": "^2.2.1", + "gulp-minify-css": "^1.2.1", + "gulp-mocha": "^2.1.3", + "gulp-remote-src": "^0.4.0", + "gulp-rename": "^1.2.0", + "gulp-sourcemaps": "^1.6.0", + "gulp-symdest": "^1.0.0", + "gulp-tsb": "^1.7.3", + "gulp-uglify": "^1.4.1", + "gulp-util": "^3.0.6", + "gulp-vinyl-zip": "^1.1.0", + "gulp-watch": "^4.2.4", + "innosetup-compiler": "^5.5.60", + "istanbul": "^0.3.17", + "jsdom-no-contextify": "^3.1.0", + "json-comments": "^0.2.1", + "lazy.js": "^0.4.2", + "mime": "1.2.11", + "minimatch": "^2.0.10", + "mkdirp": "^0.5.0", + "mocha": "^2.2.5", + "object-assign": "^4.0.1", + "optimist": "0.3.5", + "queue": "3.0.6", + "rimraf": "^2.2.8", + "sinon": "^1.17.2", + "source-map": "^0.4.4", + "uglify-js": "2.4.8", + "underscore": "^1.8.2", + "vinyl": "^0.4.5" + }, + "repository": { + "type": "git", + "url": "https://github.com/Microsoft/vscode.git" + }, + "bugs": { + "url": "https://github.com/Microsoft/vscode/issues" + }, + "config": { + "ghooks": { + "pre-commit": "node build/gulpfile.hygiene.js" + } + } } From 2a74a926822dc2617c129f896b010e39b40c1051 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2015 07:48:58 +0100 Subject: [PATCH 097/588] File watcher fails with chinese characters in path (#481) --- .../files/node/watcher/win32/CodeHelper.exe | Bin 83456 -> 83968 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/vs/workbench/services/files/node/watcher/win32/CodeHelper.exe b/src/vs/workbench/services/files/node/watcher/win32/CodeHelper.exe index 289ca5513a3c80cd0448966285425bf61a9b35db..4d4b673782552467a10c962b2006c0a229878153 100644 GIT binary patch delta 9230 zcma)B3v^TGk)Hq8)xDBzE0%2h0NcpefUu1Nm=Z_`vGIdP%p>3cX=rU>U2K7@YjkCT z;~0r-N|TnuLX=HTv!^F;l5R=TcF7@anr@qhHr-9%k96Cl4@#S}ePsJcw{4p3reweQ z@0G2bWFObZGylv#GynWE^Ur-Kcfy-Hbm4AR2;7ZwO=^^jq?u z5{pG&{*qV_8HaJcHsW8BmnxSK{c#?V2UI1I4tvY8pOAKlC@}3I(xe^cp_hkI=1R}B z&V)8?0JStY+?ILEJoIlciuFQOrE;nclT&P9VOdy4D_GIt`B~W+`Y`OsIE2gMb+Q&b z2}Gf+2Xt!=#uZv?ZAi1KFf4He*$2a_1_u*0Kua%ODh+9E2FO~FKPob4%>~1uE2lLm zwytt0SBCwVp7kqx6r0eZhzgVdH4B>wD8)+wUz_fa*7E`_yj#pj+ChtssFYwV>BS#V z08=z?nMQ8_OE)5K2}ZO5CMvYB7M+g)*5Qp?5sa6XXJyqi3PY3nGz@92o8=UfOV`UO zrjNp)c3_Ww^$J<-$W3u3(r|jb$j*rcaL;35TY9t+b}i8EIv%Tu$NDsHTuyOBmTs{T zB)!Ct({)+UM&&f`+%T@_z`ETG1;vqaYBpT6finKLK#6jWf~4R5-ib`1X7+n5c&^v9 z2jvt(syTjDWm~FSR!HT!g|ZIJ)YxG;g$QX=2pQbQrZgqwiDCyjr=tQzxB(cU4%v`G z{m5xn(LK{FE~gN7O~0apr`wBRJBp~aw#lj%cZ#iM9kUjWMxeSy8NC`}SR`a4-+F}} zf?0OL#-f3MIw2*V3ZtsRxB6ZzA2LF|2TOIIvxQd3w8aZl8>lkB+INNKbFeq0Rd>{d zyfq!wy5I66{<^gka*GVV)y}x}+K^V$5e#{&JN*7C3klF$7qgNU^0qbjLtckf=`P~4 zu7;N3Q)v$Qs`pg*LcWl3GI7K3n{U1u(w!sC5yyBLM5j3{MhJlcQ_tGV!Hc5IT92a9 zXiGztS9H{;Zg+s6W0vCc32kL1XzQ~&AzdYtlhWGqUXM0^?+HXwL{~xCx(1-?ifGw9 ze+AkYX%XuCVpEPQ8d;tyW4s`X7NbVs1QiDiH7FEL0WXqTRTQFn3r5v5qZ((lKx$E_ z=`A?zD0oe?R%7)-oqP_7!lpttGLE|UPO}Kge*tAtD4uEbAPvRNNL69=o@ulq?t5rM zn!N_5P+iXawIK9r>pDjBE3CDQq?%t5S=AyN7n^fRYH6t}WX%CBampzXT!Hy~2$&SEEeb$fN8r5I^V(0FTUx`vTA z-3H`#!_6?!vRT=8lx38ys;FqRm)GY|9>vW?vu?x;00C_UerUTS04@GYRogRQ|)((uSTV&OP0X@1C3F&OjGumzp-*yr~EHJm{YM^(FO-7j_W#j;+#4{KEucr|KU^ zlxvso64abORx&^9btyQbG~g`Rlmxt8!RP4X82^@D0DMDn4vH5byIXFN0ZJ&CRWPsM z7vv*Sr}dtwN2f8*t$=qacvit@6?{p-|6rJSMaOar?nCK z3B1-R=>08Z+7rc3to2aPu`zl9MIYIwF<@*98oZ8Fn^cvTP;ZU8Fw2xJ#4%{ zLCStd5wBr7KzI9iPajqAX9`OH7VKtCfR(o^ct>D7pwrm^^FO8F3jucGCx8g08$+RR zIo0C9*^4p%l_MMLK$W4L2_$DbDBMM_!ZR69M%84cdO|CwTNPD}r(F-8OLoJwm*&x2 zMNQ(|d#Rr46m>#T5t^^40FIuQ7Eq(2-h)!|QZqGC2>l`e_(7HCb8te?m$7PA(4Vk~ zATJ&g1%*U2V2x-6T%=%!f_V2PaG6z#RzX0q?gFV$1sy;6r*P;1l|UC~#iU@5H## zb6jzbK)%+)TI2q9NM`*n(e?-j|9H(Fu^fxt*Qh9Zujs^6)*f^sqGL2E`cU|JbPA^K z5jzl@>^JyG&}j-Ae=7`nTuq*?@%S>*N6#qgxbI%E2QBTNUFxjZ3+kILbza2CPv3W` zr-cdXvO~d{0|epnuZ(U$LT)*0aQ94!GD+hDE|jQL4Q^7Pl|7NnC}M^s3wNl3WXf_CQhYP${rM0 zK}gac!7nJZ;DAY2`TsL+Qg$B0K`dBs7Is!_%+4%>9$>IgvC&3PjP{_U5(*wta8kiz z3f`mOX$3!|;8_J91^hfcp~g=ucu~PG13pJD0q&)r0v^EGQK(eGU(rXrFQWlH?tKM4 z;iC7?$n7`1271B|y%pj=N$9mgh${U6WEuc#sadZVwbY_FiC@t*db{w8UcC=+i{39v zX}7+IYDG%lF4~lZQku{!#7e9c7fS>$Uz-(&j6Jkgv6hR6jE{;QCDgAR>ZkL@cSJvZ z)_4){OBk0b*bkYXK$1-ixVm36Ud681^m6eFqe?CpzcW_JTEGP0e;JmHD<{?{tuO9SAPi+c*NG*RBaDnHn_<7*-bXNR1aDd`!b`AX%oI_$x z$r4Xe?b1h`G>vA}Lw5phr1t~%(+O&)DXP`l@o13k^R!b1odUF}9IRIQ2aNxQ7GT_= z`19xtI86$6D|jot1kQDI5%3^+Ac?0D&lzeJchY4AUsjL=b36)06zo*6Tft$5S%iXx z&MJ6OL6XdgDA=jskb=)Dcv(U6u#8Z!QNb<+JH!F;oamRIm0y(4%cUL*I ziU}ND19t?0IPkY5KjHaDpeuXnEA%Q(U#ZwF-Xk6o&xkLJUx+gKA^Cf$<@i_@U;SR^ z397&oG^~bNfdMS=ti;z_d3WH5^XrU+1H8PC@5)}}L8qJOGdSr!nV@CzATZ?CZn5GM zNpl@_TXA!vnH)FM?dB1adJmha%=WZ3Y}&S!roKed+#SmdkDAU{P1CNOtkuqwJ16ao zIY!;1vDAn;Fgb1#lt8}DtX$qvNqgA_NDu}L*@^xC_vWD<%AD`mHDFjHnaF--jlJ2SMLO!n5ME;S1p zUc{58<7Cnr8G+Zyn4M9Kfy9{U7~h$Rr88!n?D5!G_oz91P%#D)TOq)_-LZ5EPsROg zAWrSW83e)&iDP;b@4-yR_9aa$y46aL#gd8Jopo*6WN(k9;aC2Zn)#s-Gc!0I%Z!rk z4)Uw;kz;r^Tx#-gEIDBg4(7L3*Jk^-ZJ^sY~ZOwy7*R!7AjcH=VZ9%Gs_o9`C!;W-MbC$<0pfFjKKHGd{z}|6{}a{7}`L?0#fd zac`P1CrsKBOQgt3DGo3P2Qi`4RMvyp>e#n}DH$j=A40f&5*yk$mOcIr-nzF3!JiZYaNL?%Mn# zwG}m8wr!5>OHOuABr_9fQ`uk>`E~V?{Gr;)stpr~_zaf{;`txd*5+TVozvm2)RTyf zq%1p=7`Ca$+&3{Y!dafxb9itX=O=$_eN%qP+(`cZxeeLbb3|*`4G#|XB%V`)SI z+d!K@)>0GZ?gZ+v_edf`JxH`VQ@rZdtaY1OejqV?&~_ZLkZ8D(>A>dHYbN#aNy$)G zJpT3=#oo>urdT{~#+}}x3eV;PY~t+l*+3X)k6u=F0uJT7irF*VYp8o?^V)T*2M3eZ za4c!>dq=6&xZM>QozY%JeMsQY3dhKr!NKkrT4KB_Wu+#^tOPk%_AF98_(v$1~5`m*=-)K&% zFmK}ayTc5OA(ONlecH@-RaIrTrQ>FLy~^7#LXH@wk&C!_WZQmpG}Y4HR;GxY(S#J3~i8OB6R(g_qg^gRZH9pvTXacv%%p^HI zPG!a&E5n=Y^|-B#q|rCx=oq+1D|T;+o6?S0!bVqgyTA_gNPgPM{nKuWQJPYCjY-i6 zT}u(l4@Dl$mo?s>Pt1QgOU-khJ@v@muFgj~Uwe3T%{@<&@2T7O?y6mR`5vkJq+aLI z!)1m(Cma&tQpR(Db%ldc$1g-O7?HwZGYono0um(=@MCS3`7j9b zfH~qSsRun#^5H+|(L?3=i%pf;P{b3i56;>QHyT(Yyf9R*j4xp~mclk3AAR-8mgI?0 z;;n9$!F8X~DAVy%YF#;`sJ?hG$%YM6g>%Ai{M$DHq*MCAzv>*^qZc(6t2A_$_cCSZ62;W}9dL5^Wa zg-eD@;b{c_@IlBRKNkDKrG5zHPGiz%s6kMM%Y~G@Yy&*UR0By*049_n%@E;cANU`Z zLFK>1ZX%)r+u-O`P=(-GHYlrMs9>kqnik-=WL+^|Z8Q8#Ng^`XrZ31Z-`I1dTU3oYM<@)GWxUWKmpI`A7x~RS$|#)s zxPzW>&?j|6hU>#o4gg|>Uu1Ye&QcJ8REYs>L{bEnHb`Ss2fM0-A{5Sj4yg<0F6u0u zyXeJFHR0TsU_hdnC8Xgr3fNig>u}pwV;I43?%OJ}r3yBNE8#<1{_w)h`PZ6rexJZA z24DFvHAkHn6r#e9`#i(Hx;OXYAKy=Q?Cjau{rXpb+EM=N&G&tzao`WX*>DQW(D1c; zHzYDW=3z5wjgR4(W$$6UF~rTK{7k8yfX(#M+Y+g`b(@_JEsEy95I-Lt?c-&g>nM*S zryHx}cwc^GQS*h9i%yE{d9(%ocKtjsKA_{Rk#ayqS5P_sI{55Hxu6`sN#Tdk93n-X zz&h|AV1A_<2gZjPx*HguTIdWgKA+R4f%*IQw}9~-o_-08U*hl;T~ZFex={@ZR^6|P_2j(y{Me&H%VO>~ZZcdt)B1e!PLUPF(A=3uy& z?@7d&gXLb|`V4+Y;2^r!>Su{|JNDJrKsxn3EV#ZfjUeL3sdEcw>7jLkM)5mG;d&lf zILFy^uknPSyEzN)^*Vm^ALZ=1*U)VOuiLZN85CzJXPNK|24BmL2zsUHmAmu-|Mhq& zPd@PI^`c2^eBkTXi|YH=iGI=fz?OBw0{YxK@qSDkxp!2JvwI)Lm;Yyx8(a z#f8i3+Nv(p-Fz;1;k(19P?sI`=FhaOzVNlXB2^dOcrd#D!pa|? zTlmzkr5K(2RJ>lCD}So4UEJ+|>d9-wsD|JO{9?cte?Q<9N$Tu$C{B=vmMwEAPLD>> zs7oO^UW!Cq3aQbl235~iI57s5BYI46TAa)Y+$1?Ees_fkMK>cQ0e6XrN=S*jL`0>d z)LjB|FjwX-5mBiKx=TP3iMZ+kvr}|G^;oC)n2=?G3m4NBn9$>f7-FDp5=b~9=^+nDleD-52yGs?Y0@;WCP2UY&#Wy& zPESW??)$(0{qKM8zq7N--{H&O>bv9S#@CMh*ADWoSE!MSL>Eyj1a(46Zy&nzb30e9 z86w)u{9d9x)viXW3m`A381z>LiE5oYS9Unphuhz^<`GM z)V-y{P-nM63qE1}mR@vDQt3&M49}*@la#Oos|s2*EYaW6FA_#UgEp;4a$M5#5 zUuab+t#X*2y)Bu(RnaQqet2jD6+K5)x>Td0#gSwkQF4$W?1jqPfduJ6<@OF;xjk9g z9ga7_X$Hz!s~J?ZO{uu2$RBS3y(;P|?}gHzi=!rko(+$Ub}v(+_hepxGQJY3c2Thi z-l&=+B?VK-o*+lV%3x3fXi z>HxA<0UX61<(9g^9=ZNo@=$5TN8xv=9{Z%*o$Mvgni3loru&V6r2|K;i=m05%Yv;H zZJl;Eh&&2NYdfjfT)>N{c}=lbGYMXkWt|J6b`dTYDr!_ipfyMQpziXuHC z;yoA{?*%A{sPXpz7b^?w$hrjds#2w55yh)1#v%$@Yu~6WFuQ6%Sz!Js>Qpfl%r@QEq*!WC>Yijc!br*hV1m^pua=c<9`AE zOq;+86$;SV-%t<@fud8X7ui7zg>6(W&H!Z*ShLr{zDTCGSS_h2)82a@%mZQVo-&_5 z?2{|9u7FKP>Kwa{=P%R4x&@DV8OtSMg#FQ;y0B5%Q{{(}lVSB^XsZEkfQj}i!v4yh zWnm-Q6AbGWvX|Q1d6*V9IvT@z*l=ah!esD0h>->`r!lNWcOz{%EpU7CirsI&{kHB_ z2GXhN_7E%<8$cSUV6>8M4?_}1aP3FYFm6$znNa&Ed);0SZA+dtaRoLQ)O^7peS!VP zv5@w*ovM~OF3?^ZF(_wU1z7QxXxmu7I?tODqbtAKl;>(`yF^*w(^a!ZVbdo2J&Bz1 zm3asrRGF=JR!sbASSt(Mv>od*kHfCYGvVAuJEQKf%1(dg4UwbS_TtRjFlzT@$`tm= z*^Y0559tUEAtz1%qs_ucxuvYlP-70+;uh*y_vU*w(*z&xeD0=VK9_Lkd*^gHcX!Xv z*M5H|pWS+%PnNd#$#r`1%YJZ!S}ns+tu36GyVQ=@Qafuaq}DcG0e6tMj2aZ~%UA?X zR)sG*&wb3H%!lrEBCar;@R+l60l;B7}id} zRj<4pG&*#{+6Cs!Qb)Pnkhp^7Zu8;1;NU!?^BpUtg|_7}|3}l}2tf`NJX$o{Zrk!F z{g_BV=I)73>Z0^;JfK!Ky!b^97b zAJ8KbdJn`=+kbcO-mN!hRo1N+fKRaIciVM^iDjOv1aR zWI;RY(`kF)N!b5hWzS#HLFcGOJc$RSQvX&ZNOu?vZkR`eA2A)A&#}$S@^)q}Q z9EE7B`Uapb-hk5|aisLL{|tiI0~eg7Aac%0=D$+9FK|-tcR3{SLG`3Qf~OZ<>NG#= z3_fIF`DvZGB7RN4THqLwA&T4*Kw{ZVO91Vzq_ z-VC@`=K&wq+m$dK@$~>+hhbrAmySl2%b|7jwSbof1_190v;)4WZv>oIw*vk`Vfax= z|BW(+lppi&0({ZO^y!>`T)70N?1WN5_s~Yb6QUjP$AXPMsZ0SrYK#NEX$$~9h)=(Q zD1L3-fo(g;#Q%;`a9#V`8#s%m{o^F61Q3CWckNX+8BKoz* zO^Qd95_*%l9Grehd_h@81~(_&Nzdv}BEd_8iBKa>9_T7x^?zB3P^aWRf!s40A;)fXl-R3M`9b=F__bDh>)5Oxi{>RCR3O0S_mc-*7n1*MksmC{R&&Wc|t zD=rvVM;)$`K1#n+>MqdLQ!frxp8gQMsnpXJk2@;fRALucHqZl}?s;)7HPF+Na|3NW zXPM*GH`4Q-=~JYtybq{Y-+8!2=kxLlIIvYzFUy~RR-tFq0xf7QXhq8ZfAswZkNrXp zP8E7hPIdw`Hxk32$tiy#Cs^v5Cl<5}S~rLSbi;MEF6{Gy3(!k`f%AnIS_K%SivUZh zTf*ELiTWiRk#MVo*GQNEET^QT4@o#L;VpnV3X7o-JM?-wF6rY`hF&^OTa9wSIe!y{ z#Y_G+&|gxz0KYHcYk*a*JV)PDE~N&~=vMz)7(L(<^eDBWM~i8rx&;&5pkGT*QV%2- ziBI?sQMb59Eu}SLZQ%XTjs|W7tP6es_B`2g3Hznb5y0DNM66QF0e^tcl3J-fPW6Fu zc+1_Z+)K?e_6`ZRijVl8pns-+4}2N$?~Jce2Yo$&qXg4D2iF`>2c1y1P_K0K4f<{1 z`}7T((a+FUac$ry)F=J);oDWI=%a`93c%ZZrJ_T^K8#%`=z+oW(Zv}kHcNd;|c;bt&?oUE88n{<9)3Ew5AcyiWozYK{2EAR%uaj_sJ`Tx2 zdK}QEXL9N~>AGLSy%Odn{IP_p;OUzrTqoh6gnK2NkT5Ud2PHfv;R6y@(@q+vlXR9I z6pxA5go2(SG;IK#u|+RYna`;J3i_IFA7~A5gl?w4q+|41`ZgJ&MYM~};_KoE;wM7O zbK@<&#&I6F&rhyYQ~2xIJ7w-O!-aM)A`G1WehfD-X#jT+4+%xMi*c9WzKu4DJ84!p zz>o7mfyctN6XWAUNqaVxm>*0fY`c5B>(2;R|5<4dO9wM%B5SVQH$DzF_U^IL=;}l= z%_d#Wq1y6ZjM|d1CQRENK5VA5Qh|YM#>czIyQ!~WEEy^78SmzSmv)1A_YAIdX&l`& zGMt{9F*AvMDRXbP)4ig?=%2_Ytu&a1%8H?aI%{S2cGGCm&H@c?Z|+9zdF$?RFiS)1;o;p7y36ie zY6|AODVViuptUCFQs!FcV6@74qrAR*J&kT2yo$EZ+gWp_b7V6O?;PGVHa;{w+J6ll zPNe3{@o}25C#*~=xsP+^^w*T7I@goBi<(%fLCX3b2e zdBk)U>nd|2=}Gg*=KY05xZ8%EqQhoppJki8W6WCV0_D}lwz+f`>FeBSW^8l-+l*Q6 zw?h=j6!8{qNo1$#{fX?vw4|mWx^ga+I>&5I%<=#pDG9b8HPcg&&1TH~$s-wYWfC*Q{zg#Ov~xRWqVvjRDrvgQ zk<~)ngoR9OGxw)V*?hF#%nl!!FlV{bX|`a1ia11rDKn9w6qj{|;LqH}tMzEtwI^}< z>&h$G!j;M`+JGuSO*o0VvfTN-p)vDFRu)}G=3VsMT$Mg`C;15^DAncUq{0m-m$#?3|Sad|?+V~6Bya(i8Bf1$_F7OrIJ z2aoFz$5Pfi1!ajMt%uD`*jcIGWWAp@XC}?ez&zoUOU$Er`ZF2e!B$i^>d?N*oTvUY z)X5BDwlec%&5jQrn!|dt^F+?K8ve~$jQxYA?g4XI!zXfd&wYPbyzON1z%5VFhJWn( z(|1XW31O%)5&FtZ^Bisl!QS||*i75NYQVv4A(WG0fo#YMNd=uTLL^zz8nB4V(Y zGE)5*9}`L_?AIc(kgEdBiO3E-_eb)7tr4_7QbM6xKp-C*gw1( zB0|r`s4P`rlYjgIqg)++T=WIu!zh235B4WB!udBs9B~NGRJ^KM-V8&F;epi`L;9X9 z_G`6pKMyJAoK_%Wjs=cm2x=ZdgJ(5zBe${({9>aLQo@+{T=X(-H7G*H=^OU!tm=K` z7N@^yc}~#{MGvWZxY+L|)L_i}py;)#9x<8a{m`X4q~M1wUGZ#pz@QR$v&WlkgzQ0N z;O@ZP%lpZxG{P}8vh{p{pgxdtl*u*WVr+znT(5K4MXqtt_1ITqMF@2vLXe-UD-n{$ zMo|nh&H}a-^@_4`$L)}67n-0kGayo@#)N2i=a1Js{;@zQsj)a=AB^c zMt-M7g&&Psbv^DggScCWwrwBUK6=~0Skc{AjXqlP%o`=UA2`6z*MpbsS)a@f;lN2* zvokn8_V58%IPa%d#zToAn0eR2kh3XXt-C)9I|t&;r#>FP6Tbi`l;=06UBLL!fc64= zBRmw65A&ZV%5z}P0rNBYE5I7??}5>FR4OQsFWiJ*N%DBwr**)*?A^flvX19-%JYlY zn}P8o0v!X!4<2~^0)k(^eg~M}_x%*uDQ#cw;Jv!?y$UDPUZE7PlIUxfOLXIUiF&uV zx?K`|Xpcl^GZHmFF438Pk!b8UjMQRXILq40Yad*8;kOg{Z3XYRDzS8)S*u-+eR`#B zxwfGo`MoRYDA`jf=-57@ZoGV^QxA7tzC7^yVXT^8HJ*BP=;Dgf+S`au@It)nROxjm zLZR<{3Q}ITyiR>F`MIK!TR#h#TN)UA{oEr)=@8QV9H-H{P8mm^)0fqrCYt6XyVt32 ze<>T=(GUWT>Q~hZPIcSHdB Date: Thu, 26 Nov 2015 09:03:29 +0100 Subject: [PATCH 098/588] place electron in .build/electron related to #22 --- .gitignore | 1 + .vscode/settings.json | 1 + build/gulpfile.vscode.js | 3 ++- scripts/code.bat | 2 +- scripts/code.sh | 4 ++-- test/run.bat | 2 +- test/run.sh | 4 ++-- 7 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 7fcf2c97b8b..736b3124ec5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ npm-debug.log Thumbs.db node_modules/ +.build/ out/ out-build/ out-editor/ diff --git a/.vscode/settings.json b/.vscode/settings.json index 43712cc1ac4..7acd2c0fbe4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,6 +9,7 @@ "search.exclude": { "**/node_modules/**": true, "**/bower_components": true, + ".build/**": true, "out*/**": true, "extensions/**/out/**": true } diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 50eb15484d3..0274aa68427 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -25,6 +25,7 @@ var util = require('./lib/util'); var buildfile = require('../src/buildfile'); var common = require('./gulpfile.common'); var root = path.dirname(__dirname); +var build = path.join(root, '.build'); var commit = util.getVersion(root); var baseModules = [ @@ -112,7 +113,7 @@ var config = { gulp.task('electron', function () { // Force windows to use ia32 var arch = (process.platform === 'win32' ? 'ia32' : process.arch); - return electron.dest(path.join(path.dirname(root), 'Electron-Build'), _.extend({}, config, { arch: arch })); + return electron.dest(path.join(build, 'electron'), _.extend({}, config, { arch: arch })); }); function mixinProduct() { diff --git a/scripts/code.bat b/scripts/code.bat index 82a0e57162d..735bf031555 100644 --- a/scripts/code.bat +++ b/scripts/code.bat @@ -8,5 +8,5 @@ set ELECTRON_ENABLE_STACK_DUMPING=1 pushd %~dp0\.. node .\node_modules\gulp\bin\gulp.js electron -..\Electron-Build\CodeOSS.exe . %* +.\.build\electron\CodeOSS.exe . %* popd diff --git a/scripts/code.sh b/scripts/code.sh index 44e2ff3ffb8..66cbb1290e3 100755 --- a/scripts/code.sh +++ b/scripts/code.sh @@ -17,7 +17,7 @@ export ELECTRON_ENABLE_STACK_DUMPING=1 cd $ROOT ; node node_modules/gulp/bin/gulp.js electron if [[ "$OSTYPE" == "darwin"* ]]; then - cd $ROOT; ../Electron-Build/Electron.app/Contents/MacOS/Electron . $* + cd $ROOT; ./.build/electron/Electron.app/Contents/MacOS/Electron . $* else - cd $ROOT; ../Electron-Build/electron . $* + cd $ROOT; ./.build/electron/electron . $* fi diff --git a/test/run.bat b/test/run.bat index 570fa74c4ab..9d23d422fa4 100644 --- a/test/run.bat +++ b/test/run.bat @@ -3,5 +3,5 @@ set ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 pushd %~dp0\.. -..\Electron-Build\Code.exe .\node_modules\mocha\bin\_mocha %* +.\.build\electron\Code.exe .\node_modules\mocha\bin\_mocha %* popd diff --git a/test/run.sh b/test/run.sh index 80156c958a3..256febee48a 100755 --- a/test/run.sh +++ b/test/run.sh @@ -10,11 +10,11 @@ fi # Unit Tests if [[ "$OSTYPE" == "darwin"* ]]; then cd $ROOT ; ulimit -n 4096 ; ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 \ - ../Electron-Build/Electron.app/Contents/MacOS/Electron \ + ./.build/electron/Electron.app/Contents/MacOS/Electron \ node_modules/mocha/bin/_mocha $* else cd $ROOT ; ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 \ - ../Electron-Build/electron \ + ./.build/electron/electron \ node_modules/mocha/bin/_mocha $* fi From b845a937e6f92f77abf5ac779169e401bf607a0d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2015 09:26:21 +0100 Subject: [PATCH 099/588] close picker when promise input errors --- .../browser/parts/quickopen/quickOpenController.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts index 0b040799230..9bd45cc26e6 100644 --- a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts +++ b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts @@ -363,7 +363,11 @@ export class QuickOpenController extends WorkbenchComponent implements IQuickOpe } else { this.pickOpenWidget.setInput(model, autoFocus); } - }, error); + }, (err) => { + this.pickOpenWidget.hide(); + + error(err); + }); // Progress if task takes a long time Promise.timeout(800).then(() => { From 4a85ac575c694c91cce6329ff9f5094df2938efe Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 26 Nov 2015 09:29:43 +0100 Subject: [PATCH 100/588] run npm install on scripts/code #22 --- scripts/code.bat | 12 ++++++++++-- scripts/code.sh | 34 ++++++++++++++++++++++------------ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/scripts/code.bat b/scripts/code.bat index 735bf031555..ee66e316c04 100644 --- a/scripts/code.bat +++ b/scripts/code.bat @@ -1,12 +1,20 @@ @echo off title VSCode Dev +pushd %~dp0\.. + +:: Node modules +if not exist node_modules call .\scripts\npm.bat install + +:: Get electron +node .\node_modules\gulp\bin\gulp.js electron + +:: Configuration set NODE_ENV=development set VSCODE_DEV=1 set ELECTRON_ENABLE_LOGGING=1 set ELECTRON_ENABLE_STACK_DUMPING=1 -pushd %~dp0\.. -node .\node_modules\gulp\bin\gulp.js electron +:: Launch Code .\.build\electron\CodeOSS.exe . %* popd diff --git a/scripts/code.sh b/scripts/code.sh index 66cbb1290e3..cad06c7ccaa 100755 --- a/scripts/code.sh +++ b/scripts/code.sh @@ -7,17 +7,27 @@ else ROOT=$(dirname $(dirname $(readlink -f $0))) fi -# Configuration -export NODE_ENV=development -export VSCODE_DEV=1 -export ELECTRON_ENABLE_LOGGING=1 -export ELECTRON_ENABLE_STACK_DUMPING=1 +function code() { + cd $ROOT -# Prepare -cd $ROOT ; node node_modules/gulp/bin/gulp.js electron + # Node modules + test -d node_modules || ./scripts/npm.sh install -if [[ "$OSTYPE" == "darwin"* ]]; then - cd $ROOT; ./.build/electron/Electron.app/Contents/MacOS/Electron . $* -else - cd $ROOT; ./.build/electron/electron . $* -fi + # Get electron + node node_modules/gulp/bin/gulp.js electron + + # Configuration + export NODE_ENV=development + export VSCODE_DEV=1 + export ELECTRON_ENABLE_LOGGING=1 + export ELECTRON_ENABLE_STACK_DUMPING=1 + + # Launch Code + if [[ "$OSTYPE" == "darwin"* ]]; then + ./.build/electron/Electron.app/Contents/MacOS/Electron . $* + else + ./.build/electron/electron . $* + fi +} + +code From c9fd775ddd516cfd529e7d7f25353db9ac689713 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2015 09:33:04 +0100 Subject: [PATCH 101/588] code action provider as support --- .../contrib/quickFix/browser/quickFix.ts | 2 +- .../contrib/quickFix/browser/quickFixModel.ts | 24 +--- .../contrib/quickFix/common/quickFix.ts | 32 +++++- .../referenceSearch/common/referenceSearch.ts | 3 +- .../thread/common/abstractThreadService.ts | 3 +- .../api/browser/pluginHost.api.impl.ts | 2 +- .../api/common/extHostLanguageFeatures.ts | 107 +++++++++++++++++- .../workbench/api/common/languageFeatures.ts | 101 ----------------- .../api/extHostLanguageFeatures.test.ts | 90 +++++++++++++++ .../test/common/api/testThreadService.ts | 3 +- 10 files changed, 232 insertions(+), 135 deletions(-) diff --git a/src/vs/editor/contrib/quickFix/browser/quickFix.ts b/src/vs/editor/contrib/quickFix/browser/quickFix.ts index 3f708ee8392..160d467807f 100644 --- a/src/vs/editor/contrib/quickFix/browser/quickFix.ts +++ b/src/vs/editor/contrib/quickFix/browser/quickFix.ts @@ -24,7 +24,7 @@ import {IEventService} from 'vs/platform/event/common/event'; import {IEditorService} from 'vs/platform/editor/common/editor'; import {IMessageService} from 'vs/platform/message/common/message'; import {bulkEdit} from 'vs/editor/common/services/bulkEdit'; -import QuickFixRegistry, {IQuickFix2} from '../common/quickFix'; +import {QuickFixRegistry, IQuickFix2} from '../common/quickFix'; import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; export class QuickFixController implements EditorCommon.IEditorContribution { diff --git a/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts b/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts index f7fdff0c7eb..29677542a14 100644 --- a/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts +++ b/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts @@ -16,7 +16,7 @@ import schedulers = require('vs/base/common/async'); import errors = require('vs/base/common/errors'); import {Range} from 'vs/editor/common/core/range'; import {IMarkerService, IMarker} from 'vs/platform/markers/common/markers'; -import QuickFixRegistry, {IQuickFix2} from '../common/quickFix'; +import {QuickFixRegistry, IQuickFix2, getQuickFixes} from '../common/quickFix'; import LightBulpWidget = require('./lightBulpWidget'); enum QuickFixSuggestState { @@ -212,27 +212,7 @@ export class QuickFixModel extends events.EventEmitter { } this.quickFixRequestPromiseRange = range; - let quickFixes: IQuickFix2[] = []; - let promises = QuickFixRegistry.all(model).map(support => { - return support.getQuickFixes(model.getAssociatedResource(), range).then(result => { - if (!Array.isArray(result)) { - return - } - for (let fix of result) { - quickFixes.push({ - id: fix.id, - label: fix.label, - documentation: fix.documentation, - score: fix.score, - support - }); - } - }, err => { - errors.onUnexpectedError(err); - }); - }); - - this.quickFixRequestPromise = TPromise.join(promises).then(() => quickFixes); + this.quickFixRequestPromise = getQuickFixes(model, range); return this.quickFixRequestPromise; } diff --git a/src/vs/editor/contrib/quickFix/common/quickFix.ts b/src/vs/editor/contrib/quickFix/common/quickFix.ts index 3b17a46819b..4e7e841c8ae 100644 --- a/src/vs/editor/contrib/quickFix/common/quickFix.ts +++ b/src/vs/editor/contrib/quickFix/common/quickFix.ts @@ -5,13 +5,39 @@ 'use strict'; +import {IModel, IRange} from 'vs/editor/common/editorCommon'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {onUnexpectedError} from 'vs/base/common/errors'; import {IQuickFixSupport, IQuickFix} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; -const QuickFixRegistry = new LanguageFeatureRegistry('quickFixSupport'); - -export default QuickFixRegistry; +export const QuickFixRegistry = new LanguageFeatureRegistry('quickFixSupport'); export interface IQuickFix2 extends IQuickFix { support: IQuickFixSupport; +} + +export function getQuickFixes(model: IModel, range: IRange): TPromise { + + const quickFixes: IQuickFix2[] = []; + const promises = QuickFixRegistry.all(model).map(support => { + return support.getQuickFixes(model.getAssociatedResource(), range).then(result => { + if (!Array.isArray(result)) { + return + } + for (let fix of result) { + quickFixes.push({ + id: fix.id, + label: fix.label, + documentation: fix.documentation, + score: fix.score, + support + }); + } + }, err => { + onUnexpectedError(err); + }); + }); + + return TPromise.join(promises).then(() => quickFixes); } \ No newline at end of file diff --git a/src/vs/editor/contrib/referenceSearch/common/referenceSearch.ts b/src/vs/editor/contrib/referenceSearch/common/referenceSearch.ts index 333047e044e..df94dd6e558 100644 --- a/src/vs/editor/contrib/referenceSearch/common/referenceSearch.ts +++ b/src/vs/editor/contrib/referenceSearch/common/referenceSearch.ts @@ -5,8 +5,7 @@ 'use strict'; -import {IReferenceSupport} from 'vs/editor/common/modes'; -import {IReference} from 'vs/editor/common/modes'; +import {IReferenceSupport, IReference} from 'vs/editor/common/modes'; import {IModel, IPosition} from 'vs/editor/common/editorCommon'; import {TPromise} from 'vs/base/common/winjs.base'; import {onUnexpectedError} from 'vs/base/common/errors'; diff --git a/src/vs/platform/thread/common/abstractThreadService.ts b/src/vs/platform/thread/common/abstractThreadService.ts index 8cbd86d9965..251646149c5 100644 --- a/src/vs/platform/thread/common/abstractThreadService.ts +++ b/src/vs/platform/thread/common/abstractThreadService.ts @@ -45,7 +45,8 @@ export abstract class AbstractThreadService implements remote.IManyHandler { public isInMainThread:boolean; - private _instantiationService:instantiation.IInstantiationService; + protected _instantiationService: instantiation.IInstantiationService; + _boundObjects:{[id:string]:IThreadSynchronizableObject;}; _pendingObjects:winjs.Promise[]; private _localObjMap: { [id:string]: any; }; diff --git a/src/vs/workbench/api/browser/pluginHost.api.impl.ts b/src/vs/workbench/api/browser/pluginHost.api.impl.ts index d36f3f7a2de..a958e68f6a8 100644 --- a/src/vs/workbench/api/browser/pluginHost.api.impl.ts +++ b/src/vs/workbench/api/browser/pluginHost.api.impl.ts @@ -265,7 +265,7 @@ export class PluginHostAPIImplementation { return score(selector, { uri: document.uri, language: document.languageId }); }, registerCodeActionsProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable { - return features.codeActions.register(selector, provider); + return languageFeatures.registerCodeActionProvider(selector, provider); }, registerCodeLensProvider(selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable { return languageFeatures.registerCodeLensProvider(selector, provider); diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 61df0119d4c..497e9cade19 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -27,7 +27,7 @@ import {DeclarationRegistry} from 'vs/editor/contrib/goToDeclaration/common/goTo import {ExtraInfoRegistry} from 'vs/editor/contrib/hover/common/hover'; import {OccurrencesRegistry} from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; import {ReferenceRegistry} from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; -import QuickFixRegistry from 'vs/editor/contrib/quickFix/common/quickFix'; +import {QuickFixRegistry} from 'vs/editor/contrib/quickFix/common/quickFix'; import {OutlineRegistry, IOutlineEntry, IOutlineSupport} from 'vs/editor/contrib/quickOpen/common/quickOpen'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import {NavigateTypesSupportRegistry, INavigateTypesSupport, ITypeBearing} from 'vs/workbench/parts/search/common/search' @@ -295,7 +295,68 @@ class ReferenceAdapter implements modes.IReferenceSupport { } } -type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | ExtraInfoAdapter | OccurrencesAdapter | ReferenceAdapter; +class QuickFixAdapter implements modes.IQuickFixSupport { + + private _documents: PluginHostModelService; + private _commands: PluginHostCommands; + private _provider: vscode.CodeActionProvider; + private _cache: { [key: string]: vscode.Command[] } = Object.create(null); + + constructor(documents: PluginHostModelService, commands: PluginHostCommands, provider: vscode.CodeActionProvider) { + this._documents = documents; + this._commands = commands; + this._provider = provider; + } + + getQuickFixes(resource: URI, range: IRange, marker?: IMarker[]): TPromise { + + // return this._executeCommand(resource, range, markers); + const key = resource.toString(); + delete this._cache[key]; + + const doc = this._documents.getDocument(resource); + const ran = TypeConverters.toRange(range); + const diagnostics = marker.map(marker => { + const diag = new Diagnostic(TypeConverters.toRange(marker), marker.message); + diag.code = marker.code; + diag.severity = TypeConverters.toDiagnosticSeverty(marker.severity); + return diag; + }); + + return asWinJsPromise(token => this._provider.provideCodeActions(doc, ran, { diagnostics: diagnostics }, token)).then(commands => { + if (!Array.isArray(commands)) { + return; + } + + this._cache[key] = commands; + + return commands.map((command, i) => { + return { + id: String(i), + label: command.title, + score: 1 + }; + }); + }); + } + + runQuickFixAction(resource: URI, range: IRange, id: string): any { + + let commands = this._cache[resource.toString()]; + if (!commands) { + return TPromise.wrapError('no command for ' + resource.toString()); + } + + let command = commands[Number(id)]; + if (!command) { + return TPromise.wrapError('no command for ' + resource.toString()); + } + + return this._commands.executeCommand(command.command, ...command.arguments); + } +} + +type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | ExtraInfoAdapter | OccurrencesAdapter | ReferenceAdapter | QuickFixAdapter; @Remotable.PluginHostContext('ExtHostLanguageFeatures') export class ExtHostLanguageFeatures { @@ -304,11 +365,13 @@ export class ExtHostLanguageFeatures { private _proxy: MainThreadLanguageFeatures; private _documents: PluginHostModelService; + private _commands: PluginHostCommands; private _adapter: { [handle: number]: Adapter } = Object.create(null); constructor( @IThreadService threadService: IThreadService) { this._proxy = threadService.getRemotable(MainThreadLanguageFeatures); this._documents = threadService.getRemotable(PluginHostModelService); + this._commands = threadService.getRemotable(PluginHostCommands); } private _createDisposable(handle: number): Disposable { @@ -412,16 +475,34 @@ export class ExtHostLanguageFeatures { return this._withAdapter(handle, ReferenceAdapter, adapter => adapter.findReferences(resource, position, includeDeclaration)); } + // --- quick fix + + registerCodeActionProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable { + const handle = this._nextHandle(); + this._adapter[handle] = new QuickFixAdapter(this._documents, this._commands, provider); + this._proxy.$registerQuickFixSupport(handle, selector); + return this._createDisposable(handle); + } + + $getQuickFixes(handle:number, resource: URI, range: IRange, marker: IMarker[]): TPromise { + return this._withAdapter(handle, QuickFixAdapter, adapter => adapter.getQuickFixes(resource, range, marker)); + } + + $runQuickFixAction(handle: number, resource: URI, range: IRange, id: string): any { + return this._withAdapter(handle, QuickFixAdapter, adapter => adapter.runQuickFixAction(resource, range, id)); + } } @Remotable.MainContext('MainThreadLanguageFeatures') export class MainThreadLanguageFeatures { private _proxy: ExtHostLanguageFeatures; + private _markerService: IMarkerService; private _registrations: { [handle: number]: IDisposable; } = Object.create(null); - constructor( @IThreadService threadService: IThreadService) { + constructor( @IThreadService threadService: IThreadService, @IMarkerService markerService: IMarkerService) { this._proxy = threadService.getRemotable(ExtHostLanguageFeatures); + this._markerService = markerService; } $unregister(handle: number): TPromise { @@ -507,4 +588,24 @@ export class MainThreadLanguageFeatures { }); return undefined; } + + // --- quick fix + + $registerQuickFixSupport(handle: number, selector: vscode.DocumentSelector): TPromise { + this._registrations[handle] = QuickFixRegistry.register(selector, { + getQuickFixes: (resource: URI, range: IRange): TPromise => { + let markers: IMarker[] = []; + this._markerService.read({ resource }).forEach(marker => { + if (EditorRange.lift(marker).intersectRanges(range)) { + markers.push(marker); + } + }); + return this._proxy.$getQuickFixes(handle, resource, range, markers); + }, + runQuickFixAction: (resource: URI, range: IRange, id: string) => { + return this._proxy.$runQuickFixAction(handle, resource, range, id); + } + }); + return undefined; + } } \ No newline at end of file diff --git a/src/vs/workbench/api/common/languageFeatures.ts b/src/vs/workbench/api/common/languageFeatures.ts index 4b82cf172d9..bd81407d0ec 100644 --- a/src/vs/workbench/api/common/languageFeatures.ts +++ b/src/vs/workbench/api/common/languageFeatures.ts @@ -22,7 +22,6 @@ import {CancellationTokenSource} from 'vs/base/common/cancellation'; import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; import {IMarkerService, IMarker} from 'vs/platform/markers/common/markers'; import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; -import QuickFixRegistry from 'vs/editor/contrib/quickFix/common/quickFix'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import {NavigateTypesSupportRegistry, INavigateTypesSupport, ITypeBearing} from 'vs/workbench/parts/search/common/search' import {RenameRegistry} from 'vs/editor/contrib/rename/common/rename'; @@ -131,104 +130,6 @@ export abstract class AbstractExtensionHostFeature { - - private _disposable: Disposable; - - constructor(@IThreadService threadService: IThreadService) { - super(threadService.getRemotable(MainThreadCodeActions), threadService); - } - - _runAsCommand(resource: URI, range: IRange, marker:IMarker[]): TPromise { - - let document = this._models.getDocument(resource); - let _range = TypeConverters.toRange(range); - let commands: vscode.Command[] = []; - - let diagnostics = marker.map(marker => { - let diag = new Diagnostic(TypeConverters.toRange(marker), marker.message); - diag.code = marker.code; - diag.severity = TypeConverters.toDiagnosticSeverty(marker.severity); - return diag; - }); - - let promises = this._getAllFor(document).map(provider => { - return asWinJsPromise(token => provider.provideCodeActions(document, _range, { diagnostics }, token)).then(result => { - if (Array.isArray(result)) { - commands.push(...result); - } - }, err => { - console.error(err); - }); - }); - - return TPromise.join(promises).then(() => { - if (this._disposable) { - this._disposable.dispose(); - } - - let disposables: IDisposable[] = []; - let quickFixes: modes.IQuickFix[] = []; - - commands.forEach((command, i) => { - - let id = '_code_action_action_wrapper_#' + i; - - // create fake action such that the aruments don't - // have to be send between ext-host - disposables.push(this._commands.registerCommand(id, () => { - return this._commands.executeCommand(command.command, ...command.arguments); - })); - - // create quick fix - quickFixes.push({ - id, - label: command.title, - score: 1 - }); - }); - - // not very nice... we need - // some sort of event to tell us when - // quick fix is bored of our commands - this._disposable = Disposable.from(...disposables); - return quickFixes; - }); - } -} - -@Remotable.MainContext('MainThreadCodeAction') -export class MainThreadCodeActions extends AbstractMainThreadFeature implements modes.IQuickFixSupport { - - private _keybindingService: IKeybindingService; - private _markerService: IMarkerService; - - constructor( @IThreadService threadService: IThreadService, @IKeybindingService keybindingService: IKeybindingService, - @IMarkerService markerService: IMarkerService) { - - super('vscode.executeCodeActionProvider', QuickFixRegistry, threadService); - this._keybindingService = keybindingService; - this._markerService = markerService; - } - - getQuickFixes(resource: URI, range: IRange): TPromise { - - let markers: IMarker[] = []; - this._markerService.read({ resource }).forEach(marker => { - if (EditorRange.lift(marker).intersectRanges(range)) { - markers.push(marker); - } - }); - - return this._executeCommand(resource, range, markers); - } - - runQuickFixAction (resource:URI, range:IRange, id:string) { - return TPromise.as(this._keybindingService.executeCommand(id)); - } -} // -- Rename provider @@ -826,7 +727,6 @@ export class MainThreadWorkspaceSymbols implements INavigateTypesSupport { export namespace LanguageFeatures { export function createMainThreadInstances(threadService: IThreadService): void { - threadService.getRemotable(MainThreadCodeActions); threadService.getRemotable(MainThreadWorkspaceSymbols); threadService.getRemotable(MainThreadRename); threadService.getRemotable(MainThreadFormatDocument); @@ -838,7 +738,6 @@ export namespace LanguageFeatures { export function createExtensionHostInstances(threadService: IThreadService) { return { - codeActions: new ExtensionHostCodeActions(threadService), workspaceSymbols: new ExtensionHostWorkspaceSymbols(threadService), rename: new ExtensionHostRename(threadService), formatDocument: new ExtHostFormatDocument(threadService), diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts index b7b89a03c96..997e30d7bfa 100644 --- a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts @@ -17,6 +17,10 @@ import {Range as CodeEditorRange} from 'vs/editor/common/core/range'; import * as EditorCommon from 'vs/editor/common/editorCommon'; import {Model as EditorModel} from 'vs/editor/common/model/model'; import threadService from './testThreadService' +import {create as createInstantiationService} from 'vs/platform/instantiation/common/instantiationService'; +import {MarkerService} from 'vs/platform/markers/common/markerService'; +import {IMarkerService} from 'vs/platform/markers/common/markers'; +import {IThreadService} from 'vs/platform/thread/common/thread'; import {ExtHostLanguageFeatures, MainThreadLanguageFeatures} from 'vs/workbench/api/common/extHostLanguageFeatures'; import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; @@ -28,6 +32,7 @@ import {DeclarationRegistry, getDeclarationsAtPosition} from 'vs/editor/contrib/ import {ExtraInfoRegistry, getExtraInfoAtPosition} from 'vs/editor/contrib/hover/common/hover'; import {OccurrencesRegistry, getOccurrencesAtPosition} from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; import {ReferenceRegistry, findReferences} from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; +import {getQuickFixes} from 'vs/editor/contrib/quickFix/common/quickFix'; const defaultSelector = { scheme: 'far' }; const model: EditorCommon.IModel = new EditorModel( @@ -48,6 +53,11 @@ suite('ExtHostLanguageFeatures', function() { suiteSetup(() => { + let instantiationService = createInstantiationService(); + threadService.setInstantiationService(instantiationService); + instantiationService.addSingleton(IMarkerService, new MarkerService(threadService)); + instantiationService.addSingleton(IThreadService, threadService); + originalErrorHandler = errorHandler.getUnexpectedErrorHandler(); setUnexpectedErrorHandler(() => { }); @@ -591,4 +601,84 @@ suite('ExtHostLanguageFeatures', function() { }); }); + + // --- quick fix + + test('Quick Fix, data conversion', function(done) { + + disposables.push(extHost.registerCodeActionProvider(defaultSelector, { + provideCodeActions(): any { + return [ + { command: 'test', title: 'Testing1' }, + { command: 'test', title: 'Testing2' } + ]; + } + })); + + threadService.sync().then(() => { + getQuickFixes(model, model.getFullModelRange()).then(value => { + assert.equal(value.length, 2); + + let [first, second] = value; + assert.equal(first.label, 'Testing1'); + assert.equal(first.id, String(0)); + assert.equal(second.label, 'Testing2'); + assert.equal(second.id, String(1)); + done(); + }); + }); + }); + + test('Quick Fix, invoke command+args', function(done) { + let actualArgs: any; + let commands = threadService.getRemotable(PluginHostCommands); + disposables.push(commands.registerCommand('test1', function(...args: any[]) { + actualArgs = args; + })); + + disposables.push(extHost.registerCodeActionProvider(defaultSelector, { + provideCodeActions(): any { + return [{ command: 'test1', title: 'Testing', arguments: [true, 1, { bar: 'boo', foo: 'far' }, null] }]; + } + })); + + threadService.sync().then(() => { + getQuickFixes(model, model.getFullModelRange()).then(value => { + assert.equal(value.length, 1); + + let [entry] = value; + entry.support.runQuickFixAction(model.getAssociatedResource(), model.getFullModelRange(), entry.id).then(value => { + assert.equal(value, undefined); + + assert.equal(actualArgs.length, 4); + assert.equal(actualArgs[0], true) + assert.equal(actualArgs[1], 1) + assert.deepEqual(actualArgs[2], { bar: 'boo', foo: 'far' }); + assert.equal(actualArgs[3], null) + done(); + }); + }); + }); + }); + + test('Quick Fix, evil provider', function(done) { + + disposables.push(extHost.registerCodeActionProvider(defaultSelector, { + provideCodeActions(): any { + throw new Error('evil'); + } + })); + disposables.push(extHost.registerCodeActionProvider(defaultSelector, { + provideCodeActions(): any { + return [{ command: 'test', title: 'Testing' }]; + } + })); + + threadService.sync().then(() => { + getQuickFixes(model, model.getFullModelRange()).then(value => { + assert.equal(value.length, 1); + done(); + }); + }); + }); }); \ No newline at end of file diff --git a/src/vs/workbench/test/common/api/testThreadService.ts b/src/vs/workbench/test/common/api/testThreadService.ts index 1d83c6feab6..6bf5118e96a 100644 --- a/src/vs/workbench/test/common/api/testThreadService.ts +++ b/src/vs/workbench/test/common/api/testThreadService.ts @@ -9,6 +9,7 @@ import {NullThreadService} from 'vs/platform/test/common/nullThreadService'; import {create} from 'vs/base/common/types'; import {SyncDescriptor0} from 'vs/platform/instantiation/common/descriptors'; import {TPromise} from 'vs/base/common/winjs.base'; +import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; export class TestThreadService extends NullThreadService { @@ -57,7 +58,7 @@ export class TestThreadService extends NullThreadService { return TPromise.timeout(0).then(() => { if (!_instance) { - _instance = create(descriptor.ctor, this); + _instance = this._instantiationService.createInstance(descriptor.ctor); } let p: TPromise; try { From 5dbc95b077a22d6d8def1bd3dbb057765d7b2b26 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2015 09:37:16 +0100 Subject: [PATCH 102/588] window.showQuickPick is not closed when promise is rejected --- .../api/browser/pluginHostQuickOpen.ts | 18 ++++++++++++++++++ .../parts/quickopen/quickOpenController.ts | 6 +++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/api/browser/pluginHostQuickOpen.ts b/src/vs/workbench/api/browser/pluginHostQuickOpen.ts index 173753869fe..1e7c19a0385 100644 --- a/src/vs/workbench/api/browser/pluginHostQuickOpen.ts +++ b/src/vs/workbench/api/browser/pluginHostQuickOpen.ts @@ -67,6 +67,10 @@ export class PluginHostQuickOpen { return items[handle]; } }); + }, (err) => { + this._proxy._setError(err); + + return TPromise.wrapError(err); }); } @@ -80,6 +84,7 @@ export class MainThreadQuickOpen { private _quickOpenService: IQuickOpenService; private _doSetItems: (items: MyQuickPickItems[]) => any; + private _doSetError: (error: Error) => any; private _contents: TPromise; private _token = 0; @@ -97,6 +102,12 @@ export class MainThreadQuickOpen { c(items); } }; + + this._doSetError = (error) => { + if (myToken === this._token) { + e(error); + } + }; }); return this._quickOpenService.pick(this._contents, options).then(item => { @@ -113,6 +124,13 @@ export class MainThreadQuickOpen { } } + _setError(error: Error): Thenable { + if (this._doSetError) { + this._doSetError(error); + return; + } + } + _input(options?: InputBoxOptions): Thenable { return this._quickOpenService.input(options); } diff --git a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts index 9bd45cc26e6..6a43116abe3 100644 --- a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts +++ b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts @@ -209,7 +209,11 @@ export class QuickOpenController extends WorkbenchComponent implements IQuickOpe onOk: () => { /* ignore, handle later */ }, onCancel: () => { /* ignore, handle later */ }, onType: (value: string) => { /* ignore, handle later */ }, - onShow: () => this.emitQuickOpenVisibilityChange(true) + onShow: () => this.emitQuickOpenVisibilityChange(true), + onHide: () => { + this.restoreFocus(); // focus back to editor or viewlet + this.emitQuickOpenVisibilityChange(false); // event + } }, { inputPlaceHolder: options.placeHolder || '' }, From 4727065eb9b9fdbfbb90384f3be9cd159f23ff60 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 26 Nov 2015 09:57:22 +0100 Subject: [PATCH 103/588] prevent plain npm #22 --- build/npm/preinstall.js | 13 +++++++++++++ package.json | 1 + 2 files changed, 14 insertions(+) create mode 100644 build/npm/preinstall.js diff --git a/build/npm/preinstall.js b/build/npm/preinstall.js new file mode 100644 index 00000000000..d70393040fd --- /dev/null +++ b/build/npm/preinstall.js @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +var win = "Please run '.\\scripts\\npm.bat install' instead." +var nix = "Please run './scripts/npm.sh install' instead." + +if (process.env['npm_config_disturl'] !== 'https://atom.io/download/atom-shell') { + console.error("You can't use plain npm to install Code's dependencies."); + console.error(/^win/.test(process.platform) ? win : nix); + process.exit(1); +} \ No newline at end of file diff --git a/package.json b/package.json index 5badd18213f..2500de069f0 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ }, "scripts": { "test": "node node_modules/mocha/bin/_mocha", + "preinstall": "node build/npm/preinstall.js", "postinstall": "npm --prefix extensions/csharp-o/ install extensions/csharp-o/ && npm --prefix extensions/vscode-api-tests/ install extensions/vscode-api-tests/" }, "dependencies": { From 072c7887897247fb29dd75b5a187c24ab23b14af Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 26 Nov 2015 09:57:29 +0100 Subject: [PATCH 104/588] improve hygiene messages --- build/gulpfile.hygiene.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js index f617b0458ce..4a97747e272 100644 --- a/build/gulpfile.hygiene.js +++ b/build/gulpfile.hygiene.js @@ -119,7 +119,7 @@ var hygiene = exports.hygiene = function (some) { .pipe(copyrights) .pipe(es.through(null, function () { if (errorCount > 0) { - this.emit('error', 'Hygiene failed with ' + errorCount + ' errors.\nCheck build/gulpfile.hygiene.js for the hygiene rules.'); + this.emit('error', 'Hygiene failed with ' + errorCount + ' errors. Check \'build/gulpfile.hygiene.js\'.'); } else { this.emit('end'); } @@ -135,7 +135,8 @@ if (require.main === module) { var cp = require('child_process'); cp.exec('git diff --cached --name-only', function (err, out) { if (err) { - console.log(err); + console.error(); + console.error(err); process.exit(1); } @@ -144,7 +145,8 @@ if (require.main === module) { .filter(function (l) { return !!l; }); hygiene(some).on('error', function (err) { - console.log(err); + console.error(); + console.error(err); process.exit(1); }); }); From 70988681faadfa26dccfee61bbfd80cfc77ca58b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2015 10:00:46 +0100 Subject: [PATCH 105/588] formatting edit provider as support --- .../api/browser/pluginHost.api.impl.ts | 6 +- .../api/common/extHostLanguageFeatures.ts | 141 +++++++++++++++++- .../api/common/pluginHostTypeConverters.ts | 9 +- 3 files changed, 151 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/api/browser/pluginHost.api.impl.ts b/src/vs/workbench/api/browser/pluginHost.api.impl.ts index a958e68f6a8..a87e5e38be4 100644 --- a/src/vs/workbench/api/browser/pluginHost.api.impl.ts +++ b/src/vs/workbench/api/browser/pluginHost.api.impl.ts @@ -292,13 +292,13 @@ export class PluginHostAPIImplementation { return features.workspaceSymbols.register(provider); }, registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable { - return features.formatDocument.register(selector, provider); + return languageFeatures.registerDocumentFormattingEditProvider(selector, provider); }, registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable { - return features.formatRange.register(selector, provider); + return languageFeatures.registerDocumentRangeFormattingEditProvider(selector, provider); }, registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, firstTriggerCharacter: string, ...moreTriggerCharacters: string[]): vscode.Disposable { - return features.formatOnType.register(selector, { triggerCharacters: [firstTriggerCharacter].concat(moreTriggerCharacters), provider }); + return languageFeatures.registerOnTypeFormattingEditProvider(selector, provider, [firstTriggerCharacter].concat(moreTriggerCharacters)); }, registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, ...triggerCharacters: string[]): vscode.Disposable { return features.signatureHelp.register(selector, { triggerCharacters, provider }); diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 497e9cade19..046d93e0a3c 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -356,7 +356,78 @@ class QuickFixAdapter implements modes.IQuickFixSupport { } } -type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | ExtraInfoAdapter | OccurrencesAdapter | ReferenceAdapter | QuickFixAdapter; +class DocumentFormattingAdapter implements modes.IFormattingSupport { + + private _documents: PluginHostModelService; + private _provider: vscode.DocumentFormattingEditProvider; + + constructor(documents: PluginHostModelService, provider: vscode.DocumentFormattingEditProvider) { + this._documents = documents; + this._provider = provider; + } + + formatDocument(resource: URI, options: modes.IFormattingOptions): TPromise { + + let doc = this._documents.getDocument(resource); + + return asWinJsPromise(token => this._provider.provideDocumentFormattingEdits(doc, options, token)).then(value => { + if (Array.isArray(value)) { + return value.map(TypeConverters.fromTextEdit); + } + }); + } +} + +class RangeFormattingAdapter implements modes.IFormattingSupport { + + private _documents: PluginHostModelService; + private _provider: vscode.DocumentRangeFormattingEditProvider; + + constructor(documents: PluginHostModelService, provider: vscode.DocumentRangeFormattingEditProvider) { + this._documents = documents; + this._provider = provider; + } + + formatRange(resource: URI, range: IRange, options: modes.IFormattingOptions): TPromise { + + let doc = this._documents.getDocument(resource); + let ran = TypeConverters.toRange(range); + + return asWinJsPromise(token => this._provider.provideDocumentRangeFormattingEdits(doc, ran, options, token)).then(value => { + if (Array.isArray(value)) { + return value.map(TypeConverters.fromTextEdit); + } + }); + } +} + +class OnTypeFormattingAdapter implements modes.IFormattingSupport { + + private _documents: PluginHostModelService; + private _provider: vscode.OnTypeFormattingEditProvider; + + constructor(documents: PluginHostModelService, provider: vscode.OnTypeFormattingEditProvider) { + this._documents = documents; + this._provider = provider; + } + + autoFormatTriggerCharacters = []; // not here + + formatAfterKeystroke(resource: URI, position: IPosition, ch: string, options: modes.IFormattingOptions): TPromise { + + let doc = this._documents.getDocument(resource); + let pos = TypeConverters.toPosition(position); + + return asWinJsPromise(token => this._provider.provideOnTypeFormattingEdits(doc, pos, ch, options, token)).then(value => { + if (Array.isArray(value)) { + return value.map(TypeConverters.fromTextEdit); + } + }); + } +} + +type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | ExtraInfoAdapter | OccurrencesAdapter | ReferenceAdapter | QuickFixAdapter + | DocumentFormattingAdapter | RangeFormattingAdapter | OnTypeFormattingAdapter; @Remotable.PluginHostContext('ExtHostLanguageFeatures') export class ExtHostLanguageFeatures { @@ -491,6 +562,42 @@ export class ExtHostLanguageFeatures { $runQuickFixAction(handle: number, resource: URI, range: IRange, id: string): any { return this._withAdapter(handle, QuickFixAdapter, adapter => adapter.runQuickFixAction(resource, range, id)); } + + // --- formatting + + registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable { + const handle = this._nextHandle(); + this._adapter[handle] = new DocumentFormattingAdapter(this._documents, provider); + this._proxy.$registerDocumentFormattingSupport(handle, selector); + return this._createDisposable(handle); + } + + $formatDocument(handle: number, resource: URI, options: modes.IFormattingOptions): TPromise{ + return this._withAdapter(handle, DocumentFormattingAdapter, adapter => adapter.formatDocument(resource, options)); + } + + registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable { + const handle = this._nextHandle(); + this._adapter[handle] = new RangeFormattingAdapter(this._documents, provider); + this._proxy.$registerRangeFormattingSupport(handle, selector); + return this._createDisposable(handle); + } + + $formatRange(handle: number, resource: URI, range: IRange, options: modes.IFormattingOptions): TPromise{ + return this._withAdapter(handle, RangeFormattingAdapter, adapter => adapter.formatRange(resource, range, options)); + } + + registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, triggerCharacters: string[]): vscode.Disposable { + const handle = this._nextHandle(); + this._adapter[handle] = new OnTypeFormattingAdapter(this._documents, provider); + this._proxy.$registerOnTypeFormattingSupport(handle, selector, triggerCharacters); + return this._createDisposable(handle); + } + + $formatAfterKeystroke(handle: number, resource: URI, position: IPosition, ch: string, options: modes.IFormattingOptions): TPromise{ + return this._withAdapter(handle, OnTypeFormattingAdapter, adapter => adapter.formatAfterKeystroke(resource, position, ch, options)); + } + } @Remotable.MainContext('MainThreadLanguageFeatures') @@ -608,4 +715,36 @@ export class MainThreadLanguageFeatures { }); return undefined; } + + // --- formatting + + $registerDocumentFormattingSupport(handle: number, selector: vscode.DocumentSelector): TPromise { + this._registrations[handle] = FormatRegistry.register(selector, { + formatDocument: (resource: URI, options: modes.IFormattingOptions): TPromise => { + return this._proxy.$formatDocument(handle, resource, options); + } + }); + return undefined; + } + + $registerRangeFormattingSupport(handle: number, selector: vscode.DocumentSelector): TPromise { + this._registrations[handle] = FormatRegistry.register(selector, { + formatRange: (resource: URI, range: IRange, options: modes.IFormattingOptions): TPromise => { + return this._proxy.$formatRange(handle, resource, range, options); + } + }); + return undefined; + } + + $registerOnTypeFormattingSupport(handle: number, selector: vscode.DocumentSelector, autoFormatTriggerCharacters: string[]): TPromise { + this._registrations[handle] = FormatOnTypeRegistry.register(selector, { + + autoFormatTriggerCharacters, + + formatAfterKeystroke: (resource: URI, position: IPosition, ch: string, options: modes.IFormattingOptions): TPromise => { + return this._proxy.$formatAfterKeystroke(handle, resource, position, ch, options); + } + }); + return undefined; + } } \ No newline at end of file diff --git a/src/vs/workbench/api/common/pluginHostTypeConverters.ts b/src/vs/workbench/api/common/pluginHostTypeConverters.ts index 74f3d9c5d9c..f87fa4d2617 100644 --- a/src/vs/workbench/api/common/pluginHostTypeConverters.ts +++ b/src/vs/workbench/api/common/pluginHostTypeConverters.ts @@ -8,7 +8,7 @@ import Severity from 'vs/base/common/severity'; import * as objects from 'vs/base/common/objects'; import {Position as EditorPosition} from 'vs/platform/editor/common/editor'; import {Selection, Range, Position, SymbolKind, DiagnosticSeverity, ViewColumn} from './pluginHostTypes'; -import {IPosition, ISelection, IRange, IRangeWithMessage} from 'vs/editor/common/editorCommon'; +import {IPosition, ISelection, IRange, IRangeWithMessage, ISingleEditOperation} from 'vs/editor/common/editorCommon'; import {IHTMLContentElement} from 'vs/base/common/htmlContent'; export interface PositionLike { @@ -189,3 +189,10 @@ export function fromRangeOrRangeWithMessage(ranges:vscode.Range[]|vscode.Decorat }); } } + +export function fromTextEdit(edit: vscode.TextEdit) { + return { + text: edit.newText, + range: fromRange(edit.range) + } +} \ No newline at end of file From 0b6f18f6231e0a39b426eb3f10f5c9d0f014c266 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 26 Nov 2015 10:07:11 +0100 Subject: [PATCH 106/588] compile before code #22 --- scripts/code.bat | 3 +++ scripts/code.sh | 3 +++ 2 files changed, 6 insertions(+) diff --git a/scripts/code.bat b/scripts/code.bat index ee66e316c04..16ef475d615 100644 --- a/scripts/code.bat +++ b/scripts/code.bat @@ -9,6 +9,9 @@ if not exist node_modules call .\scripts\npm.bat install :: Get electron node .\node_modules\gulp\bin\gulp.js electron +:: Build +if not exist out node .\node_modules\gulp\bin\gulp.js compile + :: Configuration set NODE_ENV=development set VSCODE_DEV=1 diff --git a/scripts/code.sh b/scripts/code.sh index cad06c7ccaa..ba92a3fe5e6 100755 --- a/scripts/code.sh +++ b/scripts/code.sh @@ -16,6 +16,9 @@ function code() { # Get electron node node_modules/gulp/bin/gulp.js electron + # Build + test -d out || gulp compile + # Configuration export NODE_ENV=development export VSCODE_DEV=1 From 36b86128fe99cbbc1dfe46534a64933ebaf64820 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2015 10:08:57 +0100 Subject: [PATCH 107/588] extract method to send data to a window --- src/vs/workbench/electron-main/lifecycle.ts | 2 +- src/vs/workbench/electron-main/menus.ts | 2 +- src/vs/workbench/electron-main/window.ts | 14 ++++++++++++-- src/vs/workbench/electron-main/windows.ts | 16 ++++++---------- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/electron-main/lifecycle.ts b/src/vs/workbench/electron-main/lifecycle.ts index 4d0cbc3f5f6..b1963df8953 100644 --- a/src/vs/workbench/electron-main/lifecycle.ts +++ b/src/vs/workbench/electron-main/lifecycle.ts @@ -133,7 +133,7 @@ export class Lifecycle { c(true); // veto }); - vscodeWindow.win.webContents.send('vscode:beforeUnload', { okChannel: oneTimeOkEvent, cancelChannel: oneTimeCancelEvent }); + vscodeWindow.send('vscode:beforeUnload', { okChannel: oneTimeOkEvent, cancelChannel: oneTimeCancelEvent }); }); } diff --git a/src/vs/workbench/electron-main/menus.ts b/src/vs/workbench/electron-main/menus.ts index 0187db6b3ac..3a233e4eb2a 100644 --- a/src/vs/workbench/electron-main/menus.ts +++ b/src/vs/workbench/electron-main/menus.ts @@ -119,7 +119,7 @@ export class VSCodeMenu { // Resolve keybindings when workbench window is up if (this.actionIdKeybindingRequests.length) { - win.win.webContents.send('vscode:resolveKeybindings', JSON.stringify(this.actionIdKeybindingRequests)); + win.send('vscode:resolveKeybindings', JSON.stringify(this.actionIdKeybindingRequests)); } } diff --git a/src/vs/workbench/electron-main/window.ts b/src/vs/workbench/electron-main/window.ts index 066fba4d282..7bd14c3c996 100644 --- a/src/vs/workbench/electron-main/window.ts +++ b/src/vs/workbench/electron-main/window.ts @@ -294,9 +294,9 @@ export class VSCodeWindow { // Support navigation via mouse buttons 4/5 if (cmd === 'browser-backward') { - this._win.webContents.send('vscode:runAction', 'workbench.action.navigateBack'); + this.send('vscode:runAction', 'workbench.action.navigateBack'); } else if (cmd === 'browser-forward') { - this._win.webContents.send('vscode:runAction', 'workbench.action.navigateForward'); + this.send('vscode:runAction', 'workbench.action.navigateForward'); } }); @@ -532,6 +532,16 @@ export class VSCodeWindow { this.win.setMenuBarVisibility(isFullScreen); } + public sendWhenReady(channel: string, ...args: any[]): void { + this.ready().then(() => { + this.send(channel, ...args); + }); + } + + public send(channel: string, ...args: any[]): void { + this._win.webContents.send(channel, ...args); + } + public dispose(): void { if (this.showTimeoutHandle) { clearTimeout(this.showTimeoutHandle); diff --git a/src/vs/workbench/electron-main/windows.ts b/src/vs/workbench/electron-main/windows.ts index f928b91863f..308f5603a4c 100644 --- a/src/vs/workbench/electron-main/windows.ts +++ b/src/vs/workbench/electron-main/windows.ts @@ -390,13 +390,13 @@ export class WindowsManager { if (!openFilesInNewWindow && lastActiveWindow) { lastActiveWindow.restore(); lastActiveWindow.ready().then((readyWindow) => { - readyWindow.win.webContents.send('vscode:openFiles', { + readyWindow.send('vscode:openFiles', { filesToOpen: filesToOpen, filesToCreate: filesToCreate }); if (extensionsToInstall.length) { - readyWindow.win.webContents.send('vscode:installExtensions', { extensionsToInstall }); + readyWindow.send('vscode:installExtensions', { extensionsToInstall }); } }); } @@ -418,13 +418,13 @@ export class WindowsManager { if (windowsOnWorkspacePath.length > 0) { windowsOnWorkspacePath[0].restore(); // just focus one of them windowsOnWorkspacePath[0].ready().then((readyWindow) => { - readyWindow.win.webContents.send('vscode:openFiles', { + readyWindow.send('vscode:openFiles', { filesToOpen: filesToOpen, filesToCreate: filesToCreate }); if (extensionsToInstall.length) { - readyWindow.win.webContents.send('vscode:installExtensions', { extensionsToInstall }); + readyWindow.send('vscode:installExtensions', { extensionsToInstall }); } }); @@ -889,9 +889,7 @@ export class WindowsManager { const focusedWindow = this.getFocusedWindow() || this.getLastActiveWindow(); if (focusedWindow) { - focusedWindow.ready().then((readyWindow) => { - readyWindow.win.webContents.send(channel, ...args); - }); + focusedWindow.sendWhenReady(channel, ...args); } } @@ -901,9 +899,7 @@ export class WindowsManager { return; // do not send if we are instructed to ignore it } - w.ready().then((readyWindow) => { - readyWindow.win.webContents.send(channel, payload); - }); + w.sendWhenReady(channel, payload); }); } From 316bcc0f14a968a0c025a5c256a1a1836477589f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2015 10:34:03 +0100 Subject: [PATCH 108/588] debug: inline extension handler into debug service --- .../electron-browser/debug.contribution.ts | 8 +- .../debug/electron-browser/debugService.ts | 87 ++++++++++++- .../debug/electron-browser/extensionOutput.ts | 115 ------------------ 3 files changed, 87 insertions(+), 123 deletions(-) delete mode 100644 src/vs/workbench/parts/debug/electron-browser/extensionOutput.ts diff --git a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts index 6a2e98b4778..c7d4e3ed74a 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts @@ -8,12 +8,6 @@ import platform = require('vs/platform/platform'); import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IDebugService } from 'vs/workbench/parts/debug/common/debug'; import service = require('vs/workbench/parts/debug/electron-browser/debugService'); -import { ExtensionOutputHandler } from 'vs/workbench/parts/debug/electron-browser/extensionOutput'; // Register Service -registerSingleton(IDebugService, service.DebugService); - -// Register Extension Output Handler -(platform.Registry.as(Extensions.Workbench)).registerWorkbenchContribution( - ExtensionOutputHandler -); \ No newline at end of file +registerSingleton(IDebugService, service.DebugService); \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index e81bc0f76c9..7267882fea7 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -13,6 +13,7 @@ import uri from 'vs/base/common/uri'; import arrays = require('vs/base/common/arrays'); import actions = require('vs/base/common/actions'); import json = require('vs/base/common/json'); +import types = require('vs/base/common/types'); import errors = require('vs/base/common/errors'); import severity from 'vs/base/common/severity'; import { Promise, TPromise } from 'vs/base/common/winjs.base'; @@ -49,7 +50,8 @@ import { IPluginService, IPluginDescription } from 'vs/platform/plugins/common/p import { IOutputService } from 'vs/workbench/parts/output/common/output'; import { IKeybindingService, IKeybindingContextKey } from 'vs/platform/keybinding/common/keybindingService'; import { IQuickOpenService } from 'vs/workbench/services/quickopen/browser/quickOpenService'; -import { IWindowService } from 'vs/workbench/services/window/electron-browser/windowService'; +import { IWindowService, IBroadcast } from 'vs/workbench/services/window/electron-browser/windowService'; +import { ILogEntry, PLUGIN_LOG_BROADCAST_CHANNEL } from 'vs/workbench/services/thread/electron-browser/threadService'; var DEBUG_BREAKPOINTS_KEY = 'debug.breakpoint'; var DEBUG_BREAKPOINTS_ACTIVATED_KEY = 'debug.breakpointactivated'; @@ -184,6 +186,89 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService lifecycleService.onShutdown.add(this.store, this); lifecycleService.onShutdown.add(this.dispose, this); + + this.windowService.onBroadcast.add(this.onBroadcast, this); + } + + private onBroadcast(broadcast: IBroadcast): void { + let session = this.getActiveSession(); + if (!session || session.getType() !== 'extensionHost') { + return; // we are only intersted if we have an active debug session for extensionHost + } + + // A plugin logged output, show it inside the REPL + if (broadcast.channel === PLUGIN_LOG_BROADCAST_CHANNEL) { + let extensionOutput: ILogEntry = broadcast.payload; + let sev = extensionOutput.severity === 'warn' ? severity.Warning : extensionOutput.severity === 'error' ? severity.Error : severity.Info; + + let args: any[] = []; + try { + let parsed = JSON.parse(extensionOutput.arguments); + args.push(...Object.getOwnPropertyNames(parsed).map(o => parsed[o])); + } catch (error) { + args.push(extensionOutput.arguments); + } + + // Add output for each argument logged + let simpleVals: any[] = []; + for (let i = 0; i < args.length; i++) { + let a = args[i]; + + // Undefined gets printed as 'undefined' + if (typeof a === 'undefined') { + simpleVals.push('undefined'); + } + + // Null gets printed as 'null' + else if (a === null) { + simpleVals.push('null'); + } + + // Objects & Arrays are special because we want to inspect them in the REPL + else if (types.isObject(a) || Array.isArray(a)) { + + // Flush any existing simple values logged + if (simpleVals.length) { + this.logToRepl(simpleVals.join(' '), sev); + simpleVals = []; + } + + // Show object + this.logToRepl(a, sev); + } + + // String: watch out for % replacement directive + // String substitution and formatting @ https://developer.chrome.com/devtools/docs/console + else if (typeof a === 'string') { + let buf = ''; + + for (let j = 0, len = a.length; j < len; j++) { + if (a[j] === '%' && (a[j + 1] === 's' || a[j + 1] === 'i' || a[j + 1] === 'd')) { + i++; // read over substitution + buf += !types.isUndefinedOrNull(args[i]) ? args[i] : ''; // replace + j++; // read over directive + } else { + buf += a[j]; + } + } + + simpleVals.push(buf); + } + + // number or boolean is joined together + else { + simpleVals.push(a); + } + } + + // Flush simple values + if (simpleVals.length) { + this.logToRepl(simpleVals.join(' '), sev); + } + + // Show repl + this.revealRepl(true /* in background */).done(null, errors.onUnexpectedError); + } } private registerSessionListeners(): void { diff --git a/src/vs/workbench/parts/debug/electron-browser/extensionOutput.ts b/src/vs/workbench/parts/debug/electron-browser/extensionOutput.ts deleted file mode 100644 index 83eb9d1e7d9..00000000000 --- a/src/vs/workbench/parts/debug/electron-browser/extensionOutput.ts +++ /dev/null @@ -1,115 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { IDebugService } from 'vs/workbench/parts/debug/common/debug'; -import errors = require('vs/base/common/errors'); -import types = require('vs/base/common/types'); -import severity from 'vs/base/common/severity'; -import { ILogEntry, PLUGIN_LOG_BROADCAST_CHANNEL } from 'vs/workbench/services/thread/electron-browser/threadService'; -import { IWindowService, IBroadcast } from 'vs/workbench/services/window/electron-browser/windowService'; - -import ipc = require('ipc'); - -export class ExtensionOutputHandler implements IWorkbenchContribution { - - static ID = 'debug.extensionOutputHandler'; - - constructor( - @IDebugService private debugService: IDebugService, - @IWindowService private windowService: IWindowService - ) { - this.registerListeners(); - } - - private registerListeners(): void { - this.windowService.onBroadcast.add(this.onBroadcast, this); - } - - private onBroadcast(broadcast: IBroadcast): void { - let session = this.debugService.getActiveSession(); - if (!session || session.getType() !== 'extensionHost') { - return; // we are only intersted if we have an active debug session for extensionHost - } - - // A plugin logged output, show it inside the REPL - if (broadcast.channel === PLUGIN_LOG_BROADCAST_CHANNEL) { - let extensionOutput: ILogEntry = broadcast.payload; - let sev = extensionOutput.severity === 'warn' ? severity.Warning : extensionOutput.severity === 'error' ? severity.Error : severity.Info; - - let args: any[] = []; - try { - let parsed = JSON.parse(extensionOutput.arguments); - args.push(...Object.getOwnPropertyNames(parsed).map(o => parsed[o])); - } catch (error) { - args.push(extensionOutput.arguments); - } - - // Add output for each argument logged - let simpleVals: any[] = []; - for (let i = 0; i < args.length; i++) { - let a = args[i]; - - // Undefined gets printed as 'undefined' - if (typeof a === 'undefined') { - simpleVals.push('undefined'); - } - - // Null gets printed as 'null' - else if (a === null) { - simpleVals.push('null'); - } - - // Objects & Arrays are special because we want to inspect them in the REPL - else if (types.isObject(a) || Array.isArray(a)) { - - // Flush any existing simple values logged - if (simpleVals.length) { - this.debugService.logToRepl(simpleVals.join(' '), sev); - simpleVals = []; - } - - // Show object - this.debugService.logToRepl(a, sev); - } - - // String: watch out for % replacement directive - // String substitution and formatting @ https://developer.chrome.com/devtools/docs/console - else if (typeof a === 'string') { - let buf = ''; - - for (let j = 0, len = a.length; j < len; j++) { - if (a[j] === '%' && (a[j + 1] === 's' || a[j + 1] === 'i' || a[j + 1] === 'd')) { - i++; // read over substitution - buf += !types.isUndefinedOrNull(args[i]) ? args[i] : ''; // replace - j++; // read over directive - } else { - buf += a[j]; - } - } - - simpleVals.push(buf); - } - - // number or boolean is joined together - else { - simpleVals.push(a); - } - } - - // Flush simple values - if (simpleVals.length) { - this.debugService.logToRepl(simpleVals.join(' '), sev); - } - - // Show repl - this.debugService.revealRepl(true /* in background */).done(null, errors.onUnexpectedError); - } - } - - public getId(): string { - return ExtensionOutputHandler.ID; - } -} \ No newline at end of file From a7ff9cdb4843b2ecc13295e650573a70a701a966 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2015 10:51:44 +0100 Subject: [PATCH 109/588] workspace symbol provider as support --- .../api/browser/pluginHost.api.impl.ts | 2 +- .../api/common/extHostLanguageFeatures.ts | 53 ++++++++- .../workbench/api/common/languageFeatures.ts | 107 ------------------ .../parts/search/browser/openSymbolHandler.ts | 18 +-- .../workbench/parts/search/common/search.ts | 24 +++- .../api/extHostLanguageFeatures.test.ts | 26 +++++ 6 files changed, 100 insertions(+), 130 deletions(-) diff --git a/src/vs/workbench/api/browser/pluginHost.api.impl.ts b/src/vs/workbench/api/browser/pluginHost.api.impl.ts index a87e5e38be4..e466e1dd0fa 100644 --- a/src/vs/workbench/api/browser/pluginHost.api.impl.ts +++ b/src/vs/workbench/api/browser/pluginHost.api.impl.ts @@ -289,7 +289,7 @@ export class PluginHostAPIImplementation { return languageFeatures.registerDocumentSymbolProvider(selector, provider); }, registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable { - return features.workspaceSymbols.register(provider); + return languageFeatures.registerWorkspaceSymbolProvider(provider); }, registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable { return languageFeatures.registerDocumentFormattingEditProvider(selector, provider); diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 046d93e0a3c..72618bb2842 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -426,8 +426,36 @@ class OnTypeFormattingAdapter implements modes.IFormattingSupport { } } +class NavigateTypeAdapter implements INavigateTypesSupport { + + private _provider: vscode.WorkspaceSymbolProvider; + + constructor(provider: vscode.WorkspaceSymbolProvider) { + this._provider = provider; + } + + getNavigateToItems(search: string): TPromise { + return asWinJsPromise(token => this._provider.provideWorkspaceSymbols(search, token)).then(value => { + if (Array.isArray(value)) { + return value.map(NavigateTypeAdapter._fromSymbolInformation); + } + }); + } + + private static _fromSymbolInformation(info: vscode.SymbolInformation): ITypeBearing { + return { + name: info.name, + type: SymbolKind[info.kind || SymbolKind.Property].toLowerCase(), + range: TypeConverters.fromRange(info.location.range), + resourceUri: info.location.uri, + containerName: info.containerName, + parameters: '', + }; + } +} + type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | ExtraInfoAdapter | OccurrencesAdapter | ReferenceAdapter | QuickFixAdapter - | DocumentFormattingAdapter | RangeFormattingAdapter | OnTypeFormattingAdapter; + | DocumentFormattingAdapter | RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter; @Remotable.PluginHostContext('ExtHostLanguageFeatures') export class ExtHostLanguageFeatures { @@ -598,6 +626,18 @@ export class ExtHostLanguageFeatures { return this._withAdapter(handle, OnTypeFormattingAdapter, adapter => adapter.formatAfterKeystroke(resource, position, ch, options)); } + // --- navigate types + + registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable { + const handle = this._nextHandle(); + this._adapter[handle] = new NavigateTypeAdapter(provider); + this._proxy.$registerNavigateTypeSupport(handle); + return this._createDisposable(handle); + } + + $getNavigateToItems(handle: number, search: string): TPromise { + return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.getNavigateToItems(search)); + } } @Remotable.MainContext('MainThreadLanguageFeatures') @@ -747,4 +787,15 @@ export class MainThreadLanguageFeatures { }); return undefined; } + + // --- navigate type + + $registerNavigateTypeSupport(handle: number): TPromise { + this._registrations[handle] = NavigateTypesSupportRegistry.register({ + getNavigateToItems: (search: string): TPromise => { + return this._proxy.$getNavigateToItems(handle, search); + } + }); + return undefined; + } } \ No newline at end of file diff --git a/src/vs/workbench/api/common/languageFeatures.ts b/src/vs/workbench/api/common/languageFeatures.ts index bd81407d0ec..0d4b5744de0 100644 --- a/src/vs/workbench/api/common/languageFeatures.ts +++ b/src/vs/workbench/api/common/languageFeatures.ts @@ -625,124 +625,17 @@ export class MainThreadCompletions extends AbstractMainThreadFeature { - let idx = this._provider.indexOf(provider); - if (idx >= 0) { - this._provider.splice(idx, 1); - if (this._provider.length === 0) { - this._proxy._enable(false); - } - } - }); - } - - private _runAsCommand(query: string): TPromise { - - if (typeof query !== 'string') { - return TPromise.wrapError('query is not string'); - } - - let symbols: vscode.SymbolInformation[] = []; - let promises = this._provider.map(provider => { - return asWinJsPromise(token => { - return provider.provideWorkspaceSymbols(query, token) - }).then(value => { - if (Array.isArray(value)) { - symbols.push(...value); - } - }, err => { - console.error(err); - }); - }); - - return TPromise.join(promises).then(() => { - return symbols.map(ExtensionHostWorkspaceSymbols._fromSymbolInformation); - }); - } - - private static _fromSymbolInformation(info: vscode.SymbolInformation): ITypeBearing { - return { - name: info.name, - type: SymbolKind[info.kind || SymbolKind.Property].toLowerCase(), - range: TypeConverters.fromRange(info.location.range), - resourceUri: info.location.uri, - containerName: info.containerName, - parameters: '', - }; - } -} - -@Remotable.MainContext('MainThreadWorkspaceSymbols') -export class MainThreadWorkspaceSymbols implements INavigateTypesSupport { - - static CommandId = 'vscode.executeWorkspaceSymbolProvider'; - - private _commands: PluginHostCommands; - private _disposable: IDisposable; - - constructor(@IThreadService threadService: IThreadService) { - this._commands = threadService.getRemotable(PluginHostCommands); - } - - _enable(value: boolean): void { - if (value) { - this._disposable = NavigateTypesSupportRegistry.register(this); - } else if (this._disposable) { - this._disposable.dispose(); - this._disposable = undefined; - } - } - - getNavigateToItems(search: string): TPromise { - let value = this._commands.executeCommand(MainThreadWorkspaceSymbols.CommandId, search); - return TPromise.as(value); - } -} - export namespace LanguageFeatures { export function createMainThreadInstances(threadService: IThreadService): void { - threadService.getRemotable(MainThreadWorkspaceSymbols); threadService.getRemotable(MainThreadRename); - threadService.getRemotable(MainThreadFormatDocument); - threadService.getRemotable(MainThreadFormatRange); - threadService.getRemotable(MainThreadFormatOnType); threadService.getRemotable(MainThreadSignatureHelp); threadService.getRemotable(MainThreadCompletions); } export function createExtensionHostInstances(threadService: IThreadService) { return { - workspaceSymbols: new ExtensionHostWorkspaceSymbols(threadService), rename: new ExtensionHostRename(threadService), - formatDocument: new ExtHostFormatDocument(threadService), - formatRange: new ExtHostFormatRange(threadService), - formatOnType: new ExtHostFormatOnType(threadService), signatureHelp: new ExtHostSignatureHelp(threadService), completions: threadService.getRemotable(ExtHostCompletions) }; diff --git a/src/vs/workbench/parts/search/browser/openSymbolHandler.ts b/src/vs/workbench/parts/search/browser/openSymbolHandler.ts index 9ba6d686ae4..ce269924a21 100644 --- a/src/vs/workbench/parts/search/browser/openSymbolHandler.ts +++ b/src/vs/workbench/parts/search/browser/openSymbolHandler.ts @@ -23,7 +23,7 @@ import {IWorkbenchEditorService, IFileInput} from 'vs/workbench/services/editor/ import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {IModeService} from 'vs/editor/common/services/modeService'; -import {NavigateTypesSupportRegistry, ITypeBearing} from '../common/search'; +import {NavigateTypesSupportRegistry, ITypeBearing, getNavigateToItems} from '../common/search'; class SymbolEntry extends EditorQuickOpenEntry { private name: string; @@ -135,21 +135,7 @@ export class OpenSymbolHandler extends QuickOpenHandler { private doGetResults(searchValue: string): TPromise { - let registry = Registry.as(Extensions.EditorModes); - - // Find Types (and ignore error) - let bearings: ITypeBearing[] = []; - let promises = NavigateTypesSupportRegistry.getAll().map(support => { - return support.getNavigateToItems(searchValue).then(result => { - if (Array.isArray(result)) { - bearings.push(...result); - } - }, err => { - errors.onUnexpectedError(err); - }); - }); - - return TPromise.join(promises).then(() => { + return getNavigateToItems(searchValue).then(bearings => { return this.toQuickOpenEntries(bearings, searchValue); }); } diff --git a/src/vs/workbench/parts/search/common/search.ts b/src/vs/workbench/parts/search/common/search.ts index 92013490687..b62874ccf73 100644 --- a/src/vs/workbench/parts/search/common/search.ts +++ b/src/vs/workbench/parts/search/common/search.ts @@ -6,6 +6,7 @@ 'use strict'; import {TPromise} from 'vs/base/common/winjs.base'; +import {onUnexpectedError} from 'vs/base/common/errors'; import {IDisposable} from 'vs/base/common/lifecycle'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import {IRange} from 'vs/editor/common/editorCommon'; @@ -51,11 +52,24 @@ export namespace NavigateTypesSupportRegistry { } } - // export function has(): boolean { - // return _supports.length > 0; - // } - - export function getAll(): INavigateTypesSupport[] { + export function all(): INavigateTypesSupport[] { return _supports.slice(0); } } + +export function getNavigateToItems(query: string): TPromise { + + const promises = NavigateTypesSupportRegistry.all().map(support => { + return support.getNavigateToItems(query).then(value => value, onUnexpectedError); + }); + + return TPromise.join(promises).then(all => { + const result: ITypeBearing[] = []; + for (let bearings of all) { + if (Array.isArray(bearings)) { + result.push(...bearings); + } + } + return result; + }); +} \ No newline at end of file diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts index 997e30d7bfa..079bae46d01 100644 --- a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts @@ -33,6 +33,7 @@ import {ExtraInfoRegistry, getExtraInfoAtPosition} from 'vs/editor/contrib/hover import {OccurrencesRegistry, getOccurrencesAtPosition} from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; import {ReferenceRegistry, findReferences} from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; import {getQuickFixes} from 'vs/editor/contrib/quickFix/common/quickFix'; +import {getNavigateToItems} from 'vs/workbench/parts/search/common/search'; const defaultSelector = { scheme: 'far' }; const model: EditorCommon.IModel = new EditorModel( @@ -681,4 +682,29 @@ suite('ExtHostLanguageFeatures', function() { }); }); }); + + // --- navigate types + + test('Navigate types, evil provider', function(done) { + + disposables.push(extHost.registerWorkspaceSymbolProvider({ + provideWorkspaceSymbols(): any { + throw new Error('evil'); + } + })); + + disposables.push(extHost.registerWorkspaceSymbolProvider({ + provideWorkspaceSymbols(): any { + return [new types.SymbolInformation('testing', types.SymbolKind.Array, new types.Range(0, 0, 1, 1))] + } + })); + + threadService.sync().then(() => { + + getNavigateToItems('').then(value => { + assert.equal(value.length, 1); + done(); + }); + }); + }) }); \ No newline at end of file From 6dfbf6a34c51b675e74d6f3a8180745728294549 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2015 11:09:34 +0100 Subject: [PATCH 110/588] Slow startup / crashes - unusable (fixes #335) --- src/vs/base/browser/browser.ts | 1 - src/vs/nls.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/base/browser/browser.ts b/src/vs/base/browser/browser.ts index 31038fa56dc..513203741e1 100644 --- a/src/vs/base/browser/browser.ts +++ b/src/vs/base/browser/browser.ts @@ -55,7 +55,6 @@ var globals = (typeof self === 'object' ? self : global); var userAgent = globals.navigator ? globals.navigator.userAgent : ''; var isTest = !!globals.isTest; -var isPseudo = globals.document && globals.document.URL.match(/[^\?]*\?[^\#]*pseudo=true/); // DOCUMENTED FOR FUTURE REFERENCE: // When running IE11 in IE10 document mode, the code below will identify the browser as being IE10, diff --git a/src/vs/nls.js b/src/vs/nls.js index 90214658a15..3687ff29b8a 100644 --- a/src/vs/nls.js +++ b/src/vs/nls.js @@ -22,7 +22,7 @@ var NLSLoaderPlugin; var global = _nlsPluginGlobal; var Resources = global.Plugin && global.Plugin.Resources ? global.Plugin.Resources : undefined; var DEFAULT_TAG = 'i-default'; - var IS_PSEUDO = (global && global.document && global.document.URL.match(/[^\?]*\?[^\#]*pseudo=true/)); + var IS_PSEUDO = (global && global.document && global.document.location && global.document.location.hash.indexOf('pseudo=true') >= 0); var slice = Array.prototype.slice; function _format(message, args) { var result; From 9ce3f2cfda36b0fa7d6d101e8ce3981f610456cb Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2015 11:32:52 +0100 Subject: [PATCH 111/588] rename provider as support --- .../editor/contrib/rename/browser/rename2.ts | 40 ++-------- src/vs/editor/contrib/rename/common/rename.ts | 51 ++++++++++++- .../api/browser/pluginHost.api.impl.ts | 2 +- .../api/common/extHostLanguageFeatures.ts | 76 ++++++++++++++++++- .../workbench/api/common/languageFeatures.ts | 75 ------------------ .../api/extHostLanguageFeatures.test.ts | 74 +++++++++++++++++- 6 files changed, 204 insertions(+), 114 deletions(-) diff --git a/src/vs/editor/contrib/rename/browser/rename2.ts b/src/vs/editor/contrib/rename/browser/rename2.ts index 95be4ac6cb4..e6a3abc2e6e 100644 --- a/src/vs/editor/contrib/rename/browser/rename2.ts +++ b/src/vs/editor/contrib/rename/browser/rename2.ts @@ -25,7 +25,7 @@ import {IKeybindingService, IKeybindingContextKey} from 'vs/platform/keybinding/ import {IEventService} from 'vs/platform/event/common/event'; import {IEditorService} from 'vs/platform/editor/common/editor'; import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; -import {RenameRegistry} from '../common/rename'; +import {RenameRegistry, rename} from '../common/rename'; export class RenameAction extends EditorAction { @@ -145,42 +145,12 @@ export class RenameAction extends EditorAction { // start recording of file changes so that we can figure out if a file that // is to be renamed conflicts with another (concurrent) modification - let sourceModel = this.editor.getModel().getAssociatedResource(); - let sourceSelections = this.editor.getSelections(); + let edit = createBulkEdit(this._eventService, this._editorService, this.editor); - let supports = RenameRegistry.ordered(this.editor.getModel()); - let hasResult = false; - let rejects: string[] = []; - - let factory = supports.map(support => { - return () => { - if (!hasResult) { - return support.rename(sourceModel, this.editor.getPosition(), newName).then(result => { - if (!result) { - // ignore - } else if (!result.rejectReason) { - hasResult = true; - return result; - } else { - rejects.push(result.rejectReason); - } - }); - } - }; - }); - - let edit = createBulkEdit(this._eventService, this._editorService, - this.editor); - - return sequence(factory).then(values => { - - let result = values[0]; - if (rejects.length > 0) { - return TPromise.wrapError(rejects.join('\n')); - } else if (!result) { - return TPromise.wrapError(nls.localize('no result', "No result.")); + return rename(this.editor.getModel(), this.editor.getPosition(), newName).then(result => { + if (result.rejectReason) { + return TPromise.wrapError(result.rejectReason); } - edit.add(result.edits); return edit; }); diff --git a/src/vs/editor/contrib/rename/common/rename.ts b/src/vs/editor/contrib/rename/common/rename.ts index a511e319128..a7e122a87a9 100644 --- a/src/vs/editor/contrib/rename/common/rename.ts +++ b/src/vs/editor/contrib/rename/common/rename.ts @@ -5,7 +5,56 @@ 'use strict'; -import {IRenameSupport} from 'vs/editor/common/modes'; +import {IRenameSupport, IRenameResult} from 'vs/editor/common/modes'; +import {IModel, IPosition} from 'vs/editor/common/editorCommon'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {localize} from 'vs/nls'; +import {sequence} from 'vs/base/common/async'; +import {onUnexpectedError} from 'vs/base/common/errors'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; export const RenameRegistry = new LanguageFeatureRegistry('renameSupport'); + +export function rename(model: IModel, position: IPosition, newName: string): TPromise { + + const supports = RenameRegistry.ordered(model); + const resource = model.getAssociatedResource(); + const rejects: string[] = []; + let hasResult = false; + + const factory = supports.map(support => { + return () => { + if (!hasResult) { + return support.rename(resource, position, newName).then(result => { + if (!result) { + // ignore + } else if (!result.rejectReason) { + hasResult = true; + return result; + } else { + rejects.push(result.rejectReason); + } + }); + } + }; + }); + + return sequence(factory).then(values => { + let result = values[0]; + if (rejects.length > 0) { + return { + currentName: undefined, + edits: undefined, + rejectReason: rejects.join('\n') + }; + } else if (!result) { + return { + currentName: undefined, + edits: undefined, + rejectReason: localize('no result', "No result.") + }; + } else { + return result; + } + }); +} \ No newline at end of file diff --git a/src/vs/workbench/api/browser/pluginHost.api.impl.ts b/src/vs/workbench/api/browser/pluginHost.api.impl.ts index e466e1dd0fa..8de01d9e74a 100644 --- a/src/vs/workbench/api/browser/pluginHost.api.impl.ts +++ b/src/vs/workbench/api/browser/pluginHost.api.impl.ts @@ -283,7 +283,7 @@ export class PluginHostAPIImplementation { return languageFeatures.registerReferenceProvider(selector, provider); }, registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable { - return features.rename.register(selector, provider); + return languageFeatures.registerRenameProvider(selector, provider); }, registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable { return languageFeatures.registerDocumentSymbolProvider(selector, provider); diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 72618bb2842..e49617773f1 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -454,8 +454,58 @@ class NavigateTypeAdapter implements INavigateTypesSupport { } } +class RenameAdapter implements modes.IRenameSupport { + + private _documents: PluginHostModelService; + private _provider: vscode.RenameProvider; + + constructor(documents: PluginHostModelService, provider: vscode.RenameProvider) { + this._documents = documents; + this._provider = provider; + } + + rename(resource: URI, position: IPosition, newName: string): TPromise { + + let doc = this._documents.getDocument(resource); + let pos = TypeConverters.toPosition(position); + + return asWinJsPromise(token => this._provider.provideRenameEdits(doc, pos, newName, token)).then(value => { + + if (!value) { + return; + } + + let result = { + currentName: undefined, + edits: [] + }; + + for (let entry of value.entries()) { + let [uri, textEdits] = entry; + for (let textEdit of textEdits) { + result.edits.push({ + resource: uri, + newText: textEdit.newText, + range: TypeConverters.fromRange(textEdit.range) + }); + } + } + return result; + }, err => { + if (typeof err === 'string') { + return { + currentName: undefined, + edits: undefined, + rejectReason: err + }; + } + return TPromise.wrapError(err); + }); + } +} + type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | ExtraInfoAdapter | OccurrencesAdapter | ReferenceAdapter | QuickFixAdapter - | DocumentFormattingAdapter | RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter; + | DocumentFormattingAdapter | RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter; @Remotable.PluginHostContext('ExtHostLanguageFeatures') export class ExtHostLanguageFeatures { @@ -638,6 +688,19 @@ export class ExtHostLanguageFeatures { $getNavigateToItems(handle: number, search: string): TPromise { return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.getNavigateToItems(search)); } + + // --- rename + + registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable { + const handle = this._nextHandle(); + this._adapter[handle] = new RenameAdapter(this._documents, provider); + this._proxy.$registerRenameSupport(handle, selector); + return this._createDisposable(handle); + } + + $rename(handle: number, resource: URI, position: IPosition, newName: string): TPromise { + return this._withAdapter(handle, RenameAdapter, adapter => adapter.rename(resource, position, newName)); + } } @Remotable.MainContext('MainThreadLanguageFeatures') @@ -798,4 +861,15 @@ export class MainThreadLanguageFeatures { }); return undefined; } + + // --- rename + + $registerRenameSupport(handle: number, selector: vscode.DocumentSelector): TPromise { + this._registrations[handle] = RenameRegistry.register(selector, { + rename: (resource: URI, position: IPosition, newName: string): TPromise => { + return this._proxy.$rename(handle, resource, position, newName); + } + }); + return undefined; + } } \ No newline at end of file diff --git a/src/vs/workbench/api/common/languageFeatures.ts b/src/vs/workbench/api/common/languageFeatures.ts index 0d4b5744de0..9a9a94c05f4 100644 --- a/src/vs/workbench/api/common/languageFeatures.ts +++ b/src/vs/workbench/api/common/languageFeatures.ts @@ -131,79 +131,6 @@ export abstract class AbstractExtensionHostFeature { - - constructor( @IThreadService threadService: IThreadService) { - super(threadService.getRemotable(MainThreadRename), threadService); - } - - _runAsCommand(resource: URI, position: IPosition, newName: string): TPromise { - - let document = this._models.getDocument(resource); - let pos = TypeConverters.toPosition(position); - - let hasResult = false; - let rejects: string[] = []; - let factory = this._getOrderedFor(document).map(provider => { - return () => { - if (!hasResult) { - return asWinJsPromise(token => provider.provideRenameEdits(document, pos, newName, token)).then(result => { - if (result && result.size > 0) { - hasResult = true; - return result; - } - }, err => { - if (typeof err === 'string') { - rejects.push(err); - } - }); - } - }; - }); - - return sequence(factory).then(results => { - let rename = results[0]; - if (!rename) { - return { - rejectReason: rejects.join('\n'), - edits: undefined, - currentName: undefined - }; - } - - let result = { - currentName: undefined, - edits: [] - }; - for (let entry of rename.entries()) { - let [uri, textEdits] = entry; - for (let textEdit of textEdits) { - result.edits.push({ - resource: uri, - newText: textEdit.newText, - range: TypeConverters.fromRange(textEdit.range) - }); - } - } - return result; - }); - } -} - -@Remotable.MainContext('MainThreadRename') -export class MainThreadRename extends AbstractMainThreadFeature implements modes.IRenameSupport { - - constructor( @IThreadService threadService: IThreadService) { - super('vscode.executeDocumentRenameProvider', RenameRegistry, threadService); - } - - rename(resource: URI, position: IPosition, newName: string): TPromise { - return this._executeCommand(resource, position, newName); - } -} - // --- format export class ExtHostFormatDocument extends AbstractExtensionHostFeature { @@ -628,14 +555,12 @@ export class MainThreadCompletions extends AbstractMainThreadFeature{ + provideRenameEdits(): any { + throw Error('evil'); + } + })); + + threadService.sync().then(() => { + + rename(model, { lineNumber: 1, column: 1 }, 'newName').then(value => { + done(new Error('')); + }, err => { + done(); // expected + }); + }); + }); + + test('Rename, evil provider 2/2', function(done) { + + disposables.push(extHost.registerRenameProvider('*', { + provideRenameEdits(): any { + throw Error('evil'); + } + })); + + disposables.push(extHost.registerRenameProvider(defaultSelector, { + provideRenameEdits(): any { + let edit = new types.WorkspaceEdit(); + edit.replace(model.getAssociatedResource(), new types.Range(0, 0, 0, 0), 'testing'); + return edit; + } + })); + + threadService.sync().then(() => { + + rename(model, { lineNumber: 1, column: 1 }, 'newName').then(value => { + assert.equal(value.edits.length, 1); + done(); + }); + }); + }); + + test('Rename, ordering', function(done) { + + disposables.push(extHost.registerRenameProvider('*', { + provideRenameEdits(): any { + let edit = new types.WorkspaceEdit(); + edit.replace(model.getAssociatedResource(), new types.Range(0, 0, 0, 0), 'testing'); + edit.replace(model.getAssociatedResource(), new types.Range(1, 0, 1, 0), 'testing'); + return edit; + } + })); + + disposables.push(extHost.registerRenameProvider(defaultSelector, { + provideRenameEdits(): any { + return; + } + })); + + threadService.sync().then(() => { + + rename(model, { lineNumber: 1, column: 1 }, 'newName').then(value => { + assert.equal(value.edits.length, 2); // least relevant renamer + done(); + }); + }); + }); }); \ No newline at end of file From d836c48813af63c820c71de0f577c01d332d1e74 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2015 11:56:46 +0100 Subject: [PATCH 112/588] more changes for "Slow startup / crashes - unusable" --- src/vs/base/browser/dom.ts | 19 ------------------- src/vs/base/common/flags.ts | 11 +---------- 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index 29fd964ea8a..88ac5bee779 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -1046,25 +1046,6 @@ export function removeScriptTags(html:string):string { return div.innerHTML; }; -export function parseSearch():{[key:string]:string} { - var result:{[key:string]:string} = {}; - var search = window.location.search; - if (search) { - var params = search.split(/[?&]/); - for (var i = 0; i < params.length; i++) { - var param = params[i]; - if (param) { - var keyValue = param.split('='); - if (keyValue.length === 2) { - result[keyValue[0]] = decodeURIComponent(keyValue[1]); - } - } - } - } - - return result; -} - export function append(parent: HTMLElement, child: T): T { parent.appendChild(child); return child; diff --git a/src/vs/base/common/flags.ts b/src/vs/base/common/flags.ts index 779cd213d0f..a442271d045 100644 --- a/src/vs/base/common/flags.ts +++ b/src/vs/base/common/flags.ts @@ -6,16 +6,7 @@ import { globals } from 'vs/base/common/platform'; -function getWorkersCount(): number { - var defaultValue = 2; - var url_matches = (globals.location ? globals.location.search : '').match(/monaco-workers=(\d+)/i); - if (url_matches) { - defaultValue = parseInt(url_matches[1], 10); - } - return environment('workersCount', defaultValue); -} - -export const workersCount = getWorkersCount(); +export const workersCount = environment('workersCount', 2); export const enableTasks = environment('enableTasks'); export const enableSendASmile = environment('enableSendASmile'); export const enableJavaScriptRewriting = environment('enableJavaScriptRewriting'); From 253b92ed0b671021334e2026f4a0a06ca694d6e5 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2015 12:09:57 +0100 Subject: [PATCH 113/588] completion item provider as support --- src/vs/editor/common/modes.ts | 1 + .../api/browser/pluginHost.api.impl.ts | 2 +- .../api/common/extHostLanguageFeatures.ts | 162 +++++++++++++++++- .../workbench/api/common/languageFeatures.ts | 155 ----------------- 4 files changed, 162 insertions(+), 158 deletions(-) diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index ff210dad06d..2f52a0d07f0 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -402,6 +402,7 @@ export interface ISuggestion { filterText?: string; sortText?: string; noAutoAccept?: boolean; + id?: string; } /** diff --git a/src/vs/workbench/api/browser/pluginHost.api.impl.ts b/src/vs/workbench/api/browser/pluginHost.api.impl.ts index 8de01d9e74a..bb5de6b7174 100644 --- a/src/vs/workbench/api/browser/pluginHost.api.impl.ts +++ b/src/vs/workbench/api/browser/pluginHost.api.impl.ts @@ -304,7 +304,7 @@ export class PluginHostAPIImplementation { return features.signatureHelp.register(selector, { triggerCharacters, provider }); }, registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, ...triggerCharacters: string[]): vscode.Disposable { - return features.completions.register(selector, { triggerCharacters, provider }); + return languageFeatures.registerCompletionItemProvider(selector, provider, triggerCharacters); }, setLanguageConfiguration: (language: string, configuration: vscode.LanguageConfiguration):vscode.Disposable => { return this._setLanguageConfiguration(language, configuration); diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index e49617773f1..bcca2a482da 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -7,6 +7,7 @@ import URI from 'vs/base/common/uri'; import Event, {Emitter} from 'vs/base/common/event'; import Severity from 'vs/base/common/severity'; +import {DefaultFilter} from 'vs/editor/common/modes/modesFilters'; import {TPromise} from 'vs/base/common/winjs.base'; import {onUnexpectedError} from 'vs/base/common/errors'; import {sequence} from 'vs/base/common/async'; @@ -504,8 +505,122 @@ class RenameAdapter implements modes.IRenameSupport { } } -type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | ExtraInfoAdapter | OccurrencesAdapter | ReferenceAdapter | QuickFixAdapter - | DocumentFormattingAdapter | RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter; +class SuggestAdapter implements modes.ISuggestSupport { + + private _documents: PluginHostModelService; + private _provider: vscode.CompletionItemProvider; + private _cache: { [key: string]: vscode.CompletionItem[] } = Object.create(null); + + constructor(documents: PluginHostModelService, provider: vscode.CompletionItemProvider) { + this._documents = documents; + this._provider = provider; + } + + suggest(resource: URI, position: IPosition): TPromise { + + const doc = this._documents.getDocument(resource); + const pos = TypeConverters.toPosition(position); + const ran = doc.getWordRangeAtPosition(pos); + + const key = resource.toString(); + delete this._cache[key]; + + return asWinJsPromise(token => this._provider.provideCompletionItems(doc, pos, token)).then(value => { + + let defaultSuggestions: modes.ISuggestions = { + suggestions: [], + currentWord: ran ? doc.getText(new Range(ran.start, pos)) : '', + }; + let allSuggestions: modes.ISuggestions[] = [defaultSuggestions]; + + + for (let i = 0; i < value.length; i++) { + const item = value[i]; + const suggestion = SuggestAdapter._convertCompletionItem(item); + + if (item.textEdit) { + + let editRange = item.textEdit.range; + + // invalid text edit + if (!editRange.isSingleLine || editRange.start.line !== pos.line) { + console.warn('INVALID text edit, must be single line and on the same line'); + continue; + } + + // insert the text of the edit and create a dedicated + // suggestion-container with overwrite[Before|After] + suggestion.codeSnippet = item.textEdit.newText; + + allSuggestions.push({ + currentWord: doc.getText(editRange), + suggestions: [suggestion], + overwriteBefore: pos.character - editRange.start.character, + overwriteAfter: editRange.end.character - pos.character + }); + + } else { + defaultSuggestions.suggestions.push(suggestion); + } + + // assign identifier to suggestion + suggestion.id = String(i); + } + + // cache for details call + this._cache[key] = value; + + return allSuggestions; + }); + } + + getSuggestionDetails(resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise { + if (typeof this._provider.resolveCompletionItem !== 'function') { + return TPromise.as(suggestion); + } + let items = this._cache[resource.toString()]; + if (!items) { + return TPromise.as(suggestion); + } + let item = items[Number(suggestion.id)]; + if (!item) { + return TPromise.as(suggestion); + } + return asWinJsPromise(token => this._provider.resolveCompletionItem(item, token)).then(resolvedItem => { + return SuggestAdapter._convertCompletionItem(resolvedItem || item); + }); + } + + private static _convertCompletionItem(item: vscode.CompletionItem): modes.ISuggestion { + return { + label: item.label, + codeSnippet: item.insertText || item.label, + type: CompletionItemKind[item.kind || CompletionItemKind.Text].toString().toLowerCase(), + typeLabel: item.detail, + documentationLabel: item.documentation, + sortText: item.sortText, + filterText: item.filterText + }; + } + + getFilter(): any{ + throw new Error('illegal state'); + } + getTriggerCharacters(): string[] { + throw new Error('illegal state'); + } + shouldShowEmptySuggestionList(): boolean { + throw new Error('illegal state'); + } + shouldAutotriggerSuggest(context: modes.ILineContext, offset: number, triggeredByCharacter: string): boolean { + throw new Error('illegal state'); + } +} + +type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | ExtraInfoAdapter + | OccurrencesAdapter | ReferenceAdapter | QuickFixAdapter | DocumentFormattingAdapter + | RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter + | SuggestAdapter; @Remotable.PluginHostContext('ExtHostLanguageFeatures') export class ExtHostLanguageFeatures { @@ -701,6 +816,23 @@ export class ExtHostLanguageFeatures { $rename(handle: number, resource: URI, position: IPosition, newName: string): TPromise { return this._withAdapter(handle, RenameAdapter, adapter => adapter.rename(resource, position, newName)); } + + // --- suggestion + + registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable { + const handle = this._nextHandle(); + this._adapter[handle] = new SuggestAdapter(this._documents, provider); + this._proxy.$registerSuggestSupport(handle, selector, triggerCharacters); + return this._createDisposable(handle); + } + + $suggest(handle: number, resource: URI, position: IPosition): TPromise { + return this._withAdapter(handle, SuggestAdapter, adapter => adapter.suggest(resource, position)); + } + + $getSuggestionDetails(handle: number, resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise { + return this._withAdapter(handle, SuggestAdapter, adapter => adapter.getSuggestionDetails(resource, position, suggestion)); + } } @Remotable.MainContext('MainThreadLanguageFeatures') @@ -872,4 +1004,30 @@ export class MainThreadLanguageFeatures { }); return undefined; } + + // --- suggest + + $registerSuggestSupport(handle: number, selector: vscode.DocumentSelector, triggerCharacters: string[]): TPromise { + this._registrations[handle] = SuggestRegistry.register(selector, { + suggest: (resource: URI, position: IPosition, triggerCharacter?: string): TPromise => { + return this._proxy.$suggest(handle, resource, position); + }, + getSuggestionDetails: (resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise => { + return this._proxy.$getSuggestionDetails(handle, resource, position, suggestion); + }, + getFilter() { + return DefaultFilter; + }, + getTriggerCharacters(): string[] { + return triggerCharacters; + }, + shouldShowEmptySuggestionList(): boolean { + return true; + }, + shouldAutotriggerSuggest(): boolean { + return true; + } + }); + return undefined; + } } \ No newline at end of file diff --git a/src/vs/workbench/api/common/languageFeatures.ts b/src/vs/workbench/api/common/languageFeatures.ts index 9a9a94c05f4..82b14ecbf4b 100644 --- a/src/vs/workbench/api/common/languageFeatures.ts +++ b/src/vs/workbench/api/common/languageFeatures.ts @@ -398,171 +398,16 @@ export class MainThreadSignatureHelp extends AbstractMainThreadFeature { - - private _detailsStorage: {[n:number]:[vscode.CompletionItemProvider, vscode.CompletionItem]} = Object.create(null); - - constructor( @IThreadService threadService: IThreadService) { - super(threadService.getRemotable(MainThreadCompletions), threadService); - } - - register(selector: vscode.DocumentSelector, entry: CompletionItemEnty): vscode.Disposable { - let disposable = this._registry.register(selector, entry); - let registered = this._proxy._register(selector, entry.triggerCharacters); - return new Disposable(() => { - disposable.dispose(); - registered.then(() => this._proxy._unregister()); - }); - } - - _runAsCommand(resource: URI, position: IPosition, character?: string): TPromise { - - this._detailsStorage = Object.create(null); - - let document = this._models.getDocument(resource); - let pos = TypeConverters.toPosition(position); - let ran = document.getWordRangeAtPosition(pos); - let entries = this._getOrderedFor(document); - - // filter - if (character) { - entries = entries.filter(provider => provider.triggerCharacters.indexOf(character) >= 0); - } - - let defaultSuggestions: modes.ISuggestions = { - suggestions: [], - currentWord: ran ? document.getText(new Range(ran.start, pos)) : '', - }; - let allSuggestions: modes.ISuggestions[] = [defaultSuggestions]; - - let promises = entries.map(entry => { - return asWinJsPromise(token => entry.provider.provideCompletionItems(document, pos, token)).then(result => { - if (!Array.isArray(result)) { - return; - } - - let canResolveDetails = typeof entry.provider.resolveCompletionItem === 'function'; - let detailsIdPool = 1; - - for (let item of result) { - - let suggestion = ExtHostCompletions._convertCompletionItem(item); - if (item.textEdit) { - - let editRange = item.textEdit.range; - - // invalid text edit - if (!editRange.isSingleLine || editRange.start.line !== pos.line) { - console.warn('INVALID text edit, must be single line and on the same line'); - continue; - } - - // insert the text of the edit and create a dedicated - // suggestion-container with overwrite[Before|After] - suggestion.codeSnippet = item.textEdit.newText; - - allSuggestions.push({ - currentWord: document.getText(editRange), - suggestions: [suggestion], - overwriteBefore: pos.character - editRange.start.character, - overwriteAfter: editRange.end.character - pos.character - }); - - } else { - defaultSuggestions.suggestions.push(suggestion); - } - - if (canResolveDetails) { - let id = detailsIdPool++; - (suggestion)._detailsId = id; - this._detailsStorage[id] = [entry.provider, item]; - } - } - }); - }); - - return TPromise.join(promises).then(() => allSuggestions); - } - - _resolveDetails(suggestion: modes.ISuggestion): TPromise { - let id = (suggestion)._detailsId; - if (this._detailsStorage[id]) { - let [provider, item] = this._detailsStorage[id]; - return asWinJsPromise(token => provider.resolveCompletionItem(item, token)).then(resolvedItem => { - return ExtHostCompletions._convertCompletionItem(resolvedItem || item); - }); - } - } - - private static _convertCompletionItem(item: vscode.CompletionItem): modes.ISuggestion { - return { - label: item.label, - codeSnippet: item.insertText || item.label, - type: CompletionItemKind[item.kind || CompletionItemKind.Text].toString().toLowerCase(), - typeLabel: item.detail, - documentationLabel: item.documentation, - sortText: item.sortText, - filterText: item.filterText - }; - } -} - -@Remotable.MainContext('MainThreadCompletions') -export class MainThreadCompletions extends AbstractMainThreadFeature { - - private _triggerCharacters: string[] = []; - private _proxy: ExtHostCompletions; - - constructor( @IThreadService threadService: IThreadService) { - super('vscode.executeCompletionItemProvider', SuggestRegistry, threadService); - this._proxy = threadService.getRemotable(ExtHostCompletions); - } - - _register(selector: vscode.DocumentSelector, triggerCharacters: string[] = []): TPromise { - this._triggerCharacters.push(...triggerCharacters); - return super._register(selector); - } - - suggest(resource: URI, position: IPosition, triggerCharacter?: string): TPromise { - return this._executeCommand(resource, position, triggerCharacter); - } - - getSuggestionDetails(resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise { - return this._proxy._resolveDetails(suggestion).then(value => { - return value || suggestion - }); - } - - getTriggerCharacters(): string[] { - return this._triggerCharacters; - } - - shouldShowEmptySuggestionList(): boolean { - return false; - } - - shouldAutotriggerSuggest(context: modes.ILineContext, offset: number, triggeredByCharacter: string): boolean { - return true; - } -} export namespace LanguageFeatures { export function createMainThreadInstances(threadService: IThreadService): void { threadService.getRemotable(MainThreadSignatureHelp); - threadService.getRemotable(MainThreadCompletions); } export function createExtensionHostInstances(threadService: IThreadService) { return { signatureHelp: new ExtHostSignatureHelp(threadService), - completions: threadService.getRemotable(ExtHostCompletions) }; } } \ No newline at end of file From bbd9cbd3482a4f25b9b6c741c3c667cbe04f14ab Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 26 Nov 2015 12:18:28 +0100 Subject: [PATCH 114/588] uri: improve error message when can not convert to file uri. Fixes #667 --- src/vs/base/common/uri.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/common/uri.ts b/src/vs/base/common/uri.ts index 7706c3a752b..0a6328c8920 100644 --- a/src/vs/base/common/uri.ts +++ b/src/vs/base/common/uri.ts @@ -174,7 +174,7 @@ export default class URI { var ret = URI._parse(path); if (ret.scheme || ret.fragment || ret.query) { - throw new Error(); + throw new Error(`Path ${ path } contains a scheme, fragment or a query. Can not convert it to a file uri.`); } ret = ret.with('file', undefined, From f8d9b7d0c0c218c1826c4360c8a6340ddb9fc28c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2015 12:26:57 +0100 Subject: [PATCH 115/588] make sure recent list of paths is bounded --- src/vs/workbench/electron-main/menus.ts | 5 ++--- src/vs/workbench/electron-main/windows.ts | 6 ++++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/electron-main/menus.ts b/src/vs/workbench/electron-main/menus.ts index 3a233e4eb2a..c8b51c2b871 100644 --- a/src/vs/workbench/electron-main/menus.ts +++ b/src/vs/workbench/electron-main/menus.ts @@ -37,7 +37,6 @@ export class VSCodeMenu { private static lastKnownKeybindingsMapStorageKey = 'lastKnownKeybindings'; - private static MAX_RECENT_ENTRIES = 10; private static AUTO_SAVE_DELAY_DEFAULT = 1000; // in ms private static AUTO_SAVE_DISABLED = -1; @@ -423,7 +422,7 @@ export class VSCodeMenu { // Folders recentList.folders.forEach((folder, index) => { - if (index < VSCodeMenu.MAX_RECENT_ENTRIES) { + if (index < windows.WindowsManager.MAX_RECENT_ENTRIES) { openRecentMenu.append(this.createOpenRecentMenuItem(folder)); } }); @@ -435,7 +434,7 @@ export class VSCodeMenu { } recentList.files.forEach((file, index) => { - if (index < VSCodeMenu.MAX_RECENT_ENTRIES) { + if (index < windows.WindowsManager.MAX_RECENT_ENTRIES) { openRecentMenu.append(this.createOpenRecentMenuItem(file)); } }); diff --git a/src/vs/workbench/electron-main/windows.ts b/src/vs/workbench/electron-main/windows.ts index 308f5603a4c..f7e8ebdb77b 100644 --- a/src/vs/workbench/electron-main/windows.ts +++ b/src/vs/workbench/electron-main/windows.ts @@ -95,8 +95,9 @@ export class WindowsManager { public static autoSaveDelayStorageKey = 'autoSaveDelay'; public static openedPathsListStorageKey = 'openedPathsList'; - private static workingDirPickerStorageKey = 'pickerWorkingDir'; + public static MAX_RECENT_ENTRIES = 10; + private static workingDirPickerStorageKey = 'pickerWorkingDir'; private static windowsStateStorageKey = 'windowsState'; private static themeStorageKey = 'theme'; // TODO@Ben this key is only used to find out if a window can be shown instantly because of light theme, remove once we have support for bg color @@ -567,7 +568,8 @@ export class WindowsManager { // Clear those dupes recentPaths = arrays.distinct(recentPaths); - return recentPaths; + // Make sure it is bounded + return recentPaths.slice(0, WindowsManager.MAX_RECENT_ENTRIES); } private toIPath(anyPath: string, ignoreFileNotFound?: boolean, gotoLineMode?: boolean): window.IPath { From 7d1de2c673065a63dca778aba33a7e04543056c3 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2015 12:34:48 +0100 Subject: [PATCH 116/588] signature help provider as support --- .../browser/parameterHintsModel.ts | 11 +- .../parameterHints/common/parameterHints.ts | 15 ++- .../api/browser/pluginHost.api.impl.ts | 2 +- .../api/common/extHostLanguageFeatures.ts | 103 ++++++++++++++- .../workbench/api/common/languageFeatures.ts | 118 ------------------ .../api/extHostLanguageFeatures.test.ts | 22 ++++ 6 files changed, 141 insertions(+), 130 deletions(-) diff --git a/src/vs/editor/contrib/parameterHints/browser/parameterHintsModel.ts b/src/vs/editor/contrib/parameterHints/browser/parameterHintsModel.ts index 9dee0382288..d5a645759eb 100644 --- a/src/vs/editor/contrib/parameterHints/browser/parameterHintsModel.ts +++ b/src/vs/editor/contrib/parameterHints/browser/parameterHintsModel.ts @@ -11,7 +11,7 @@ import async = require('vs/base/common/async'); import events = require('vs/base/common/eventEmitter'); import EditorCommon = require('vs/editor/common/editorCommon'); import Modes = require('vs/editor/common/modes'); -import {ParameterHintsRegistry} from '../common/parameterHints'; +import {ParameterHintsRegistry, getParameterHints} from '../common/parameterHints'; import {sequence} from 'vs/base/common/async'; function hashParameterHints(hints: Modes.IParameterHints): string { @@ -96,15 +96,8 @@ export class ParameterHintsModel extends events.EventEmitter { } public doTrigger(triggerCharacter: string): TPromise { - let model = this.editor.getModel(); - let support = ParameterHintsRegistry.ordered(model)[0]; - if (!support) { - return TPromise.as(false); - } - - return support.getParameterHints(model.getAssociatedResource(), this.editor.getPosition(), triggerCharacter).then((result: Modes.IParameterHints) => { + return getParameterHints(this.editor.getModel(), this.editor.getPosition(), triggerCharacter).then(result => { var hash = hashParameterHints(result); - if (!result || result.signatures.length === 0 || (this.hash && hash !== this.hash)) { this.cancel(); this.emit('cancel'); diff --git a/src/vs/editor/contrib/parameterHints/common/parameterHints.ts b/src/vs/editor/contrib/parameterHints/common/parameterHints.ts index 47b974a63f3..58b4bd073bc 100644 --- a/src/vs/editor/contrib/parameterHints/common/parameterHints.ts +++ b/src/vs/editor/contrib/parameterHints/common/parameterHints.ts @@ -5,7 +5,20 @@ 'use strict'; -import {IParameterHintsSupport} from 'vs/editor/common/modes'; +import {IParameterHintsSupport, IParameterHints} from 'vs/editor/common/modes'; +import {IModel, IPosition} from 'vs/editor/common/editorCommon'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {onUnexpectedError} from 'vs/base/common/errors'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; export const ParameterHintsRegistry = new LanguageFeatureRegistry('parameterHintsSupport'); + +export function getParameterHints(model:IModel, position:IPosition, triggerCharacter: string): TPromise { + + let support = ParameterHintsRegistry.ordered(model)[0]; + if (!support) { + return TPromise.as(undefined); + } + + return support.getParameterHints(model.getAssociatedResource(), position, triggerCharacter); +} \ No newline at end of file diff --git a/src/vs/workbench/api/browser/pluginHost.api.impl.ts b/src/vs/workbench/api/browser/pluginHost.api.impl.ts index bb5de6b7174..606d5ccfb5c 100644 --- a/src/vs/workbench/api/browser/pluginHost.api.impl.ts +++ b/src/vs/workbench/api/browser/pluginHost.api.impl.ts @@ -301,7 +301,7 @@ export class PluginHostAPIImplementation { return languageFeatures.registerOnTypeFormattingEditProvider(selector, provider, [firstTriggerCharacter].concat(moreTriggerCharacters)); }, registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, ...triggerCharacters: string[]): vscode.Disposable { - return features.signatureHelp.register(selector, { triggerCharacters, provider }); + return languageFeatures.registerSignatureHelpProvider(selector, provider, triggerCharacters); }, registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, ...triggerCharacters: string[]): vscode.Disposable { return languageFeatures.registerCompletionItemProvider(selector, provider, triggerCharacters); diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index bcca2a482da..e638636c307 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -617,10 +617,81 @@ class SuggestAdapter implements modes.ISuggestSupport { } } +class ParameterHintsAdapter implements modes.IParameterHintsSupport { + + private _documents: PluginHostModelService; + private _provider: vscode.SignatureHelpProvider; + + constructor(documents: PluginHostModelService, provider: vscode.SignatureHelpProvider) { + this._documents = documents; + this._provider = provider; + } + + getParameterHints(resource: URI, position: IPosition, triggerCharacter?: string): TPromise { + + const doc = this._documents.getDocument(resource); + const pos = TypeConverters.toPosition(position); + + return asWinJsPromise(token => this._provider.provideSignatureHelp(doc, pos, token)).then(value => { + if (value instanceof SignatureHelp) { + return ParameterHintsAdapter._convertSignatureHelp(value); + } + }); + } + + private static _convertSignatureHelp(signatureHelp: SignatureHelp): modes.IParameterHints { + + let result: modes.IParameterHints = { + currentSignature: signatureHelp.activeSignature, + currentParameter: signatureHelp.activeParameter, + signatures: [] + } + + for (let signature of signatureHelp.signatures) { + + let signatureItem: modes.ISignature = { + label: signature.label, + documentation: signature.documentation, + parameters: [] + }; + + let idx = 0; + for (let parameter of signature.parameters) { + + let parameterItem: modes.IParameter = { + label: parameter.label, + documentation: parameter.documentation, + }; + + signatureItem.parameters.push(parameterItem); + idx = signature.label.indexOf(parameter.label, idx); + + if (idx >= 0) { + parameterItem.signatureLabelOffset = idx; + idx += parameter.label.length; + parameterItem.signatureLabelEnd = idx; + } + } + + result.signatures.push(signatureItem); + } + + return result; + } + + getParameterHintsTriggerCharacters(): string[] { + throw new Error('illegal state'); + } + + shouldTriggerParameterHints(context: modes.ILineContext, offset: number): boolean { + throw new Error('illegal state'); + } +} + type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | ExtraInfoAdapter | OccurrencesAdapter | ReferenceAdapter | QuickFixAdapter | DocumentFormattingAdapter | RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter - | SuggestAdapter; + | SuggestAdapter | ParameterHintsAdapter; @Remotable.PluginHostContext('ExtHostLanguageFeatures') export class ExtHostLanguageFeatures { @@ -833,6 +904,19 @@ export class ExtHostLanguageFeatures { $getSuggestionDetails(handle: number, resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise { return this._withAdapter(handle, SuggestAdapter, adapter => adapter.getSuggestionDetails(resource, position, suggestion)); } + + // --- parameter hints + + registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, triggerCharacters: string[]): vscode.Disposable { + const handle = this._nextHandle(); + this._adapter[handle] = new ParameterHintsAdapter(this._documents, provider); + this._proxy.$registerParameterHintsSupport(handle, selector, triggerCharacters); + return this._createDisposable(handle); + } + + $getParameterHints(handle: number, resource: URI, position: IPosition, triggerCharacter?: string): TPromise { + return this._withAdapter(handle, ParameterHintsAdapter, adapter => adapter.getParameterHints(resource, position, triggerCharacter)); + } } @Remotable.MainContext('MainThreadLanguageFeatures') @@ -1030,4 +1114,21 @@ export class MainThreadLanguageFeatures { }); return undefined; } + + // --- parameter hints + + $registerParameterHintsSupport(handle: number, selector: vscode.DocumentSelector, triggerCharacter: string[]): TPromise { + this._registrations[handle] = ParameterHintsRegistry.register(selector, { + getParameterHints: (resource: URI, position: IPosition, triggerCharacter?: string): TPromise => { + return this._proxy.$getParameterHints(handle, resource, position, triggerCharacter); + }, + getParameterHintsTriggerCharacters(): string[] { + return triggerCharacter; + }, + shouldTriggerParameterHints(context: modes.ILineContext, offset: number): boolean { + return true; + } + }); + return undefined; + } } \ No newline at end of file diff --git a/src/vs/workbench/api/common/languageFeatures.ts b/src/vs/workbench/api/common/languageFeatures.ts index 82b14ecbf4b..fa22152bcc6 100644 --- a/src/vs/workbench/api/common/languageFeatures.ts +++ b/src/vs/workbench/api/common/languageFeatures.ts @@ -282,132 +282,14 @@ export class MainThreadFormatOnType extends AbstractMainThreadFeature { - - constructor( @IThreadService threadService: IThreadService) { - super(threadService.getRemotable(MainThreadSignatureHelp), threadService); - } - - register(selector: vscode.DocumentSelector, entry: SignatureHelpEntry): vscode.Disposable { - - let disposable = this._registry.register(selector, entry); - let registered = this._proxy._register(selector, entry.triggerCharacters); - - return new Disposable(() => { - disposable.dispose(); - registered.then(() => this._proxy._unregister()); - }); - } - - _runAsCommand(resource: URI, position: IPosition, triggerCharacter?: string): TPromise { - - let document = this._models.getDocument(resource); - let pos = TypeConverters.toPosition(position); - - let entry = this._getOrderedFor(document)[0]; - if (entry) { - - if (triggerCharacter) { - if (entry.triggerCharacters.indexOf(triggerCharacter) < 0) { - return; - } - } - - return asWinJsPromise(token => entry.provider.provideSignatureHelp(document, pos, token)).then(result => { - if (result instanceof SignatureHelp) { - return ExtHostSignatureHelp._convertSignatureHelp(result); - } - }); - } - } - - private static _convertSignatureHelp(signatureHelp: SignatureHelp): modes.IParameterHints { - - let result: modes.IParameterHints = { - currentSignature: signatureHelp.activeSignature, - currentParameter: signatureHelp.activeParameter, - signatures: [] - } - - for (let signature of signatureHelp.signatures) { - - let signatureItem: modes.ISignature = { - label: signature.label, - documentation: signature.documentation, - parameters: [] - }; - - let idx = 0; - for (let parameter of signature.parameters) { - - let parameterItem: modes.IParameter = { - label: parameter.label, - documentation: parameter.documentation, - }; - - signatureItem.parameters.push(parameterItem); - idx = signature.label.indexOf(parameter.label, idx); - - if (idx >= 0) { - parameterItem.signatureLabelOffset = idx; - idx += parameter.label.length; - parameterItem.signatureLabelEnd = idx; - } - } - - result.signatures.push(signatureItem); - } - - return result; - } -} - -@Remotable.MainContext('MainThreadSignatureHelp') -export class MainThreadSignatureHelp extends AbstractMainThreadFeature implements modes.IParameterHintsSupport { - - private _triggerCharacters: string[] = []; - - constructor( @IThreadService threadService: IThreadService) { - super('vscode.executeSignatureHelpProvider', ParameterHintsRegistry, threadService); - } - - _register(selector: vscode.DocumentSelector, triggerCharacters: string[] = []): TPromise { - this._triggerCharacters.push(...triggerCharacters); - return super._register(selector); - } - - getParameterHintsTriggerCharacters(): string[] { - return this._triggerCharacters; - } - - shouldTriggerParameterHints(context: modes.ILineContext, offset: number): boolean { - return true; - } - - getParameterHints(resource: URI, position: IPosition, triggerCharacter?: string): TPromise { - return this._executeCommand(resource, position, triggerCharacter); - } -} - -// ---- Completions - export namespace LanguageFeatures { export function createMainThreadInstances(threadService: IThreadService): void { - threadService.getRemotable(MainThreadSignatureHelp); } export function createExtensionHostInstances(threadService: IThreadService) { return { - signatureHelp: new ExtHostSignatureHelp(threadService), }; } } \ No newline at end of file diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts index 2de690442a2..6c5073e6325 100644 --- a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts @@ -35,6 +35,7 @@ import {ReferenceRegistry, findReferences} from 'vs/editor/contrib/referenceSear import {getQuickFixes} from 'vs/editor/contrib/quickFix/common/quickFix'; import {getNavigateToItems} from 'vs/workbench/parts/search/common/search'; import {rename} from 'vs/editor/contrib/rename/common/rename'; +import {getParameterHints} from 'vs/editor/contrib/parameterHints/common/parameterHints'; const defaultSelector = { scheme: 'far' }; const model: EditorCommon.IModel = new EditorModel( @@ -779,4 +780,25 @@ suite('ExtHostLanguageFeatures', function() { }); }); }); + + // --- parameter hints + + test('Parameter Hints, evil provider', function(done) { + + disposables.push(extHost.registerSignatureHelpProvider(defaultSelector, { + provideSignatureHelp(): any { + throw new Error('evil'); + } + }, [])); + + threadService.sync().then(() => { + + getParameterHints(model, { lineNumber: 1, column: 1 }, '(').then(value => { + done(new Error('error expeted')); + }, err => { + assert.equal(err.message, 'evil'); + done(); + }) + }); + }) }); \ No newline at end of file From f192e04e7ebf1d9b3ec647397e051684b3fd171d Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2015 12:38:58 +0100 Subject: [PATCH 117/588] remove old stuff --- .../api/browser/pluginHost.api.impl.ts | 2 - .../workbench/api/common/languageFeatures.ts | 295 ------------------ src/vs/workbench/electron-browser/shell.ts | 2 - 3 files changed, 299 deletions(-) delete mode 100644 src/vs/workbench/api/common/languageFeatures.ts diff --git a/src/vs/workbench/api/browser/pluginHost.api.impl.ts b/src/vs/workbench/api/browser/pluginHost.api.impl.ts index 606d5ccfb5c..eacd47d1fa8 100644 --- a/src/vs/workbench/api/browser/pluginHost.api.impl.ts +++ b/src/vs/workbench/api/browser/pluginHost.api.impl.ts @@ -17,7 +17,6 @@ import {PluginHostQuickOpen} from 'vs/workbench/api/browser/pluginHostQuickOpen' import {PluginHostStatusBar} from 'vs/workbench/api/browser/pluginHostStatusBar'; import {PluginHostCommands} from 'vs/workbench/api/common/pluginHostCommands'; import {ExtHostOutputService} from 'vs/workbench/api/browser/extHostOutputService'; -import {LanguageFeatures} from 'vs/workbench/api/common/languageFeatures'; import {PluginHostMessageService} from 'vs/workbench/api/common/pluginHostMessageService'; import {PluginHostTelemetryService} from 'vs/workbench/api/common/pluginHostTelemetry'; import {PluginHostEditors} from 'vs/workbench/api/common/pluginHostEditors'; @@ -251,7 +250,6 @@ export class PluginHostAPIImplementation { // const languages = new ExtHostLanguages(this._threadService); const pluginHostDiagnostics = new PluginHostDiagnostics(this._threadService); - const features = LanguageFeatures.createExtensionHostInstances(this._threadService); const languageFeatures = threadService.getRemotable(ExtHostLanguageFeatures); this.languages = { diff --git a/src/vs/workbench/api/common/languageFeatures.ts b/src/vs/workbench/api/common/languageFeatures.ts deleted file mode 100644 index fa22152bcc6..00000000000 --- a/src/vs/workbench/api/common/languageFeatures.ts +++ /dev/null @@ -1,295 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import URI from 'vs/base/common/uri'; -import Event, {Emitter} from 'vs/base/common/event'; -import Severity from 'vs/base/common/severity'; -import {TPromise} from 'vs/base/common/winjs.base'; -import {sequence} from 'vs/base/common/async'; -import {Range as EditorRange} from 'vs/editor/common/core/range'; -import {IDisposable} from 'vs/base/common/lifecycle'; -import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; -import {Remotable, IThreadService} from 'vs/platform/thread/common/thread'; -import * as vscode from 'vscode'; -import * as TypeConverters from 'vs/workbench/api/common/pluginHostTypeConverters'; -import {Position, Range, SymbolKind, DocumentHighlightKind, Disposable, Diagnostic, DiagnosticSeverity, Location, SignatureHelp, CompletionItemKind} from 'vs/workbench/api/common/pluginHostTypes'; -import {IPosition, IRange, ISingleEditOperation} from 'vs/editor/common/editorCommon'; -import * as modes from 'vs/editor/common/modes'; -import {CancellationTokenSource} from 'vs/base/common/cancellation'; -import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; -import {IMarkerService, IMarker} from 'vs/platform/markers/common/markers'; -import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; -import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; -import {NavigateTypesSupportRegistry, INavigateTypesSupport, ITypeBearing} from 'vs/workbench/parts/search/common/search' -import {RenameRegistry} from 'vs/editor/contrib/rename/common/rename'; -import {FormatRegistry, FormatOnTypeRegistry} from 'vs/editor/contrib/format/common/format'; -import {ParameterHintsRegistry} from 'vs/editor/contrib/parameterHints/common/parameterHints'; -import {SuggestRegistry} from 'vs/editor/contrib/suggest/common/suggest'; - -function isThenable(obj: any): obj is Thenable { - return obj && typeof obj['then'] === 'function'; -} - -function asWinJsPromise(callback: (token: vscode.CancellationToken) => T | Thenable): TPromise { - let source = new CancellationTokenSource(); - return new TPromise((resolve, reject) => { - let item = callback(source.token); - if (isThenable(item)) { - item.then(resolve, reject); - } else { - resolve(item); - } - }, () => { - source.cancel(); - }); -} - -export abstract class AbstractMainThreadFeature { - - private _id: string; - protected _commands: PluginHostCommands; - protected _refCount = 0; - protected _disposable: IDisposable; - protected _registry: LanguageFeatureRegistry; - - constructor(id: string, registry: LanguageFeatureRegistry, @IThreadService threadService: IThreadService) { - this._id = id; - this._registry = registry; - this._commands = threadService.getRemotable(PluginHostCommands); - } - - _getId(): TPromise { - return TPromise.as(this._id); - } - - _register(selector: vscode.DocumentSelector): TPromise { - if (this._refCount++ === 0) { - this._disposable = this._registry.register(selector, this); - } - return undefined; - } - - _unregister(): TPromise { - if (--this._refCount === 0) { - this._disposable.dispose(); - } - return undefined; - } - - _executeCommand(...args:any[]):TPromise { - let result = this._commands.executeCommand(this._id, ...args); - return new TPromise((c, e) => { - result.then(c, e); - }); - } -} - -export abstract class AbstractExtensionHostFeature> { - - protected _commands: PluginHostCommands; - protected _proxy: P; - protected _registry = new LanguageFeatureRegistry(); - protected _models: PluginHostModelService; - - constructor(proxy: P, @IThreadService threadService: IThreadService) { - this._proxy = proxy; - this._models = threadService.getRemotable(PluginHostModelService); - this._commands = threadService.getRemotable(PluginHostCommands); - - proxy._getId().then(value => this._commands.registerCommand(value, this._runAsCommand, this)); - } - - register(selector: vscode.DocumentSelector, provider: T): vscode.Disposable { - - let disposable = this._registry.register(selector, provider); - let registered = this._proxy._register(selector); - - return new Disposable(() => { - disposable.dispose(); // remove locally - registered.then(() => this._proxy._unregister()); - }); - } - - protected abstract _runAsCommand(...args: any[]): any; - - protected _getAllFor(document: vscode.TextDocument): T[] { - return this._registry.all({ - language: document.languageId, - uri: document.uri - }); - } - - protected _getOrderedFor(document: vscode.TextDocument): T[] { - return this._registry.ordered({ - language: document.languageId, - uri: document.uri - }); - } -} - - -// --- format - -export class ExtHostFormatDocument extends AbstractExtensionHostFeature { - - constructor( @IThreadService threadService: IThreadService) { - super(threadService.getRemotable(MainThreadFormatDocument), threadService); - } - - _runAsCommand(resource: URI, options: modes.IFormattingOptions): TPromise { - - let document = this._models.getDocument(resource); - let provider = this._getOrderedFor(document)[0]; - - return asWinJsPromise(token => provider.provideDocumentFormattingEdits(document, options, token)).then(result => { - if (Array.isArray(result)) { - return result.map(ExtHostFormatDocument.convertTextEdit); - } - }); - } - - static convertTextEdit(edit: vscode.TextEdit): ISingleEditOperation { - return { - text: edit.newText, - range: TypeConverters.fromRange(edit.range) - } - } -} - -@Remotable.MainContext('MainThreadFormatDocument') -export class MainThreadFormatDocument extends AbstractMainThreadFeature implements modes.IFormattingSupport { - - constructor( @IThreadService threadService: IThreadService) { - super('vscode.executeFormatDocumentProvider', FormatRegistry, threadService); - } - - formatDocument(resource: URI, options: modes.IFormattingOptions):TPromise { - return this._executeCommand(resource, options); - } -} - -export class ExtHostFormatRange extends AbstractExtensionHostFeature { - - constructor( @IThreadService threadService: IThreadService) { - super(threadService.getRemotable(MainThreadFormatRange), threadService); - } - - _runAsCommand(resource: URI, range: IRange, options: modes.IFormattingOptions): TPromise { - - let document = this._models.getDocument(resource); - let provider = this._getOrderedFor(document)[0]; - let ran: Range; - - if (range) { - ran = TypeConverters.toRange(range); - } else { - let lastLine = document.lineAt(document.lineCount - 1); - let {line, character} = lastLine.range.end; - ran = new Range(0, 0, line, character); - } - - return asWinJsPromise(token => provider.provideDocumentRangeFormattingEdits(document, ran, options, token)).then(result => { - if (Array.isArray(result)) { - return result.map(ExtHostFormatDocument.convertTextEdit); - } - }); - } -} - -@Remotable.MainContext('MainThreadFormatRange') -export class MainThreadFormatRange extends AbstractMainThreadFeature implements modes.IFormattingSupport { - - constructor( @IThreadService threadService: IThreadService) { - super('vscode.executeFormatRangeProvider', FormatRegistry, threadService); - } - - formatRange(resource: URI, range:IRange, options: modes.IFormattingOptions):TPromise { - return this._executeCommand(resource, range, options); - } -} - -// --- format on type - -export interface FormatOnTypeEntry { - triggerCharacters: string[]; - provider: vscode.OnTypeFormattingEditProvider; -} - -export class ExtHostFormatOnType extends AbstractExtensionHostFeature { - - constructor( @IThreadService threadService: IThreadService) { - super(threadService.getRemotable(MainThreadFormatOnType), threadService); - } - - register(selector: vscode.DocumentSelector, provider: FormatOnTypeEntry): vscode.Disposable { - - let disposable = this._registry.register(selector, provider); - let registered = this._proxy._register(selector, provider.triggerCharacters); - - return new Disposable(() => { - disposable.dispose(); - registered.then(() => this._proxy._unregister()); - }); - } - - _runAsCommand(resource: URI, position: IPosition, ch: string, options: modes.IFormattingOptions): TPromise { - - let document = this._models.getDocument(resource); - let pos = TypeConverters.toPosition(position); - - let ordered = this._getOrderedFor(document); - let provider: vscode.OnTypeFormattingEditProvider; - for (let entry of ordered) { - if (entry.triggerCharacters.indexOf(ch) >= 0) { - provider = entry.provider; - break; - } - } - - if (provider) { - return asWinJsPromise(token => provider.provideOnTypeFormattingEdits(document, pos, ch, options, token)).then(result => { - if (Array.isArray(result)) { - return result.map(ExtHostFormatDocument.convertTextEdit); - } - }); - } - } -} - -@Remotable.MainContext('MainThreadFormatOnType') -export class MainThreadFormatOnType extends AbstractMainThreadFeature implements modes.IFormattingSupport { - - autoFormatTriggerCharacters: string[] = []; - - constructor( @IThreadService threadService: IThreadService) { - super('vscode.executeFormatOnTypeProvider', FormatOnTypeRegistry, threadService); - } - - _register(selector: vscode.DocumentSelector, triggerCharacters: string[] = []): TPromise { - this.autoFormatTriggerCharacters.push(...triggerCharacters); - return super._register(selector); - } - - formatDocument(resource: URI, options: modes.IFormattingOptions):TPromise { - throw new Error('format on type only'); - } - - formatAfterKeystroke(resource: URI, position: IPosition, ch: string, options: modes.IFormattingOptions): TPromise { - return this._executeCommand(resource, position, ch, options); - } -} - - -export namespace LanguageFeatures { - - export function createMainThreadInstances(threadService: IThreadService): void { - } - - export function createExtensionHostInstances(threadService: IThreadService) { - return { - }; - } -} \ No newline at end of file diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index d463ad5bb6f..6046a64f19c 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -67,7 +67,6 @@ import {MainThreadLanguages} from 'vs/workbench/api/common/extHostLanguages'; import {MainThreadEditors} from 'vs/workbench/api/common/pluginHostEditors'; import {MainThreadWorkspace} from 'vs/workbench/api/browser/pluginHostWorkspace'; import {MainThreadConfiguration} from 'vs/workbench/api/common/pluginHostConfiguration'; -import {LanguageFeatures} from 'vs/workbench/api/common/languageFeatures'; import {MainThreadLanguageFeatures} from 'vs/workbench/api/common/extHostLanguageFeatures'; import {EventService} from 'vs/platform/event/common/eventService'; import {IOptions} from 'vs/workbench/common/options'; @@ -338,7 +337,6 @@ export class WorkbenchShell { this.threadServiceInstance.getRemotable(MainThreadEditors); this.threadServiceInstance.getRemotable(MainThreadStorage); this.threadServiceInstance.getRemotable(MainThreadLanguageFeatures); - LanguageFeatures.createMainThreadInstances(this.threadServiceInstance); } public open(): void { From 8cb9b202e6e290c43e5a714b0ac3bd0c631b0e47 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2015 12:58:13 +0100 Subject: [PATCH 118/588] some refactorings --- src/vs/workbench/browser/workbench.ts | 25 +-- src/vs/workbench/electron-browser/shell.ts | 193 ++++++++++++--------- 2 files changed, 116 insertions(+), 102 deletions(-) diff --git a/src/vs/workbench/browser/workbench.ts b/src/vs/workbench/browser/workbench.ts index 9cd4bd4071e..c809ce7d63f 100644 --- a/src/vs/workbench/browser/workbench.ts +++ b/src/vs/workbench/browser/workbench.ts @@ -34,7 +34,6 @@ import {WorkbenchLayout, LayoutOptions} from 'vs/workbench/browser/layout'; import {IActionBarRegistry, Extensions as ActionBarExtensions} from 'vs/workbench/browser/actionBarRegistry'; import {IViewletRegistry, Extensions as ViewletExtensions} from 'vs/workbench/browser/viewlet'; import {QuickOpenController} from 'vs/workbench/browser/parts/quickopen/quickOpenController'; -import {WorkspaceStats} from 'vs/platform/telemetry/common/workspaceStats'; import {getServices} from 'vs/platform/instantiation/common/extensions'; import {AbstractKeybindingService} from 'vs/platform/keybinding/browser/keybindingServiceImpl'; import {UntitledEditorService, IUntitledEditorService} from 'vs/workbench/services/untitled/browser/untitledEditorService'; @@ -71,6 +70,7 @@ interface WorkbenchParams { export interface IWorkbenchCallbacks { onServicesCreated?: () => void; + onWorkbenchStarted?: () => void; } /** @@ -247,26 +247,9 @@ export class Workbench implements IPartService { this.eventService.emit(EventType.WORKBENCH_CREATED); this.creationPromiseComplete(true); - // Log to telemetry service - let windowSize = { - innerHeight: window.innerHeight, - innerWidth: window.innerWidth, - outerHeight: window.outerHeight, - outerWidth: window.outerWidth - }; - - this.telemetryService.publicLog('workspaceLoad', - { - userAgent: navigator.userAgent, - windowSize: windowSize, - autoSaveEnabled: this.contextService.isAutoSaveEnabled && this.contextService.isAutoSaveEnabled(), - emptyWorkbench: !this.contextService.getWorkspace(), - customKeybindingsCount: this.keybindingService.customKeybindingsCount(), - theme: this.currentTheme - }); - - let workspaceStats: WorkspaceStats = this.instantiationService.createInstance(WorkspaceStats); - workspaceStats.reportWorkspaceTags(); + if (this.callbacks && this.callbacks.onWorkbenchStarted) { + this.callbacks.onWorkbenchStarted(); + } }, errors.onUnexpectedError); } catch (error) { diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index c157c54a422..6ba3ab87394 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -14,7 +14,7 @@ import 'vs/css!vs/workbench/browser/media/vs-theme'; import 'vs/css!vs/workbench/browser/media/vs-dark-theme'; import 'vs/css!vs/workbench/browser/media/hc-black-theme'; -import {Promise,TPromise} from 'vs/base/common/winjs.base'; +import {Promise, TPromise} from 'vs/base/common/winjs.base'; import {Dimension, Builder, $} from 'vs/base/browser/builder'; import objects = require('vs/base/common/objects'); import env = require('vs/base/common/flags'); @@ -32,6 +32,7 @@ import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {ElectronTelemetryService} from 'vs/platform/telemetry/electron-browser/electronTelemetryService'; import {ElectronIntegration} from 'vs/workbench/electron-browser/integration'; import {Update} from 'vs/workbench/electron-browser/update'; +import {WorkspaceStats} from 'vs/platform/telemetry/common/workspaceStats'; import {IWindowService, WindowService} from 'vs/workbench/services/window/electron-browser/windowService'; import {MessageService} from 'vs/workbench/services/message/electron-browser/messageService'; import {RequestService} from 'vs/workbench/services/request/node/requestService'; @@ -146,7 +147,7 @@ export function getDelayedService(clientPromise: TPromise, ser return servicePromise().then(service => service[key](...args)); } }); - }, {}); + }, {}); } /** @@ -154,12 +155,15 @@ export function getDelayedService(clientPromise: TPromise, ser * With the Shell being the top level element in the page, it is also responsible for driving the layouting. */ export class WorkbenchShell { - private storageServiceInstance: IStorageService; - private messageServiceInstance: IMessageService; - private contextViewServiceInstance: ContextViewService; - private windowServiceInstance: IWindowService; - private threadServiceInstance: MainThreadService; + private storageService: IStorageService; + private messageService: IMessageService; + private contextViewService: ContextViewService; + private windowService: IWindowService; + private threadService: MainThreadService; private themeService: IThemeService; + private contextService: WorkspaceContextService; + private telemetryService: ElectronTelemetryService; + private keybindingService: PluginWorkbenchKeybindingService; private container: HTMLElement; private toUnbind: { (): void; }[]; @@ -208,6 +212,9 @@ export class WorkbenchShell { this.workbench.startup({ onServicesCreated: () => { this.initPluginSystem(); + }, + onWorkbenchStarted: () => { + this.onWorkbenchStarted(); } }); @@ -229,88 +236,112 @@ export class WorkbenchShell { return workbenchContainer; } - private initInstantiationService(): IInstantiationService { - let eventServiceInstance = new EventService(); + private onWorkbenchStarted(): void { - let contextServiceInstance = new WorkspaceContextService(eventServiceInstance, this.workspace, this.configuration, this.options); - contextServiceInstance.getConfiguration().additionalWorkerServices = [ + // Log to telemetry service + let windowSize = { + innerHeight: window.innerHeight, + innerWidth: window.innerWidth, + outerHeight: window.outerHeight, + outerWidth: window.outerWidth + }; + + this.telemetryService.publicLog('workspaceLoad', + { + userAgent: navigator.userAgent, + windowSize: windowSize, + autoSaveEnabled: this.contextService.isAutoSaveEnabled && this.contextService.isAutoSaveEnabled(), + emptyWorkbench: !this.contextService.getWorkspace(), + customKeybindingsCount: this.keybindingService.customKeybindingsCount(), + theme: this.currentTheme + }); + + let workspaceStats: WorkspaceStats = this.workbench.getInstantiationService().createInstance(WorkspaceStats); + workspaceStats.reportWorkspaceTags(); + } + + private initInstantiationService(): IInstantiationService { + let eventService = new EventService(); + + this.contextService = new WorkspaceContextService(eventService, this.workspace, this.configuration, this.options); + this.contextService.getConfiguration().additionalWorkerServices = [ { serviceId: 'requestService', moduleName: 'vs/workbench/services/request/common/requestService', ctorName: 'WorkerRequestService' } ]; - this.windowServiceInstance = new WindowService(); - this.storageServiceInstance = new Storage(contextServiceInstance); + this.windowService = new WindowService(); + this.storageService = new Storage(this.contextService); // no telemetry in a window for plugin development! let enableTelemetry = this.configuration.env.isBuilt && !this.configuration.env.pluginDevelopmentPath ? !!this.configuration.env.enableTelemetry : false; - let telemetryServiceInstance = new ElectronTelemetryService(this.storageServiceInstance, { enableTelemetry: enableTelemetry, version: this.configuration.env.version, commitHash: this.configuration.env.commitHash }); + this.telemetryService = new ElectronTelemetryService(this.storageService, { enableTelemetry: enableTelemetry, version: this.configuration.env.version, commitHash: this.configuration.env.commitHash }); - let keybindingServiceInstance = new PluginWorkbenchKeybindingService(contextServiceInstance, eventServiceInstance, telemetryServiceInstance, window); + this.keybindingService = new PluginWorkbenchKeybindingService(this.contextService, eventService, this.telemetryService, window); - this.messageServiceInstance = new MessageService(contextServiceInstance, this.windowServiceInstance, telemetryServiceInstance, keybindingServiceInstance); - keybindingServiceInstance.setMessageService(this.messageServiceInstance); + this.messageService = new MessageService(this.contextService, this.windowService, this.telemetryService, this.keybindingService); + this.keybindingService.setMessageService(this.messageService); - let configServiceInstance = new ConfigurationService( - contextServiceInstance, - eventServiceInstance + let configService = new ConfigurationService( + this.contextService, + eventService ); - let fileServiceInstance = new FileService( - configServiceInstance, - eventServiceInstance, - contextServiceInstance + let fileService = new FileService( + configService, + eventService, + this.contextService ); - this.contextViewServiceInstance = new ContextViewService(this.container, telemetryServiceInstance, this.messageServiceInstance); + this.contextViewService = new ContextViewService(this.container, this.telemetryService, this.messageService); - let lifecycleServiceInstance = new LifecycleService(this.messageServiceInstance, this.windowServiceInstance); - lifecycleServiceInstance.onShutdown.add(() => fileServiceInstance.dispose()); + let lifecycleService = new LifecycleService(this.messageService, this.windowService); + lifecycleService.onShutdown.add(() => fileService.dispose()); - this.threadServiceInstance = new MainThreadService(contextServiceInstance, this.messageServiceInstance, this.windowServiceInstance); - lifecycleServiceInstance.onShutdown.add(() => this.threadServiceInstance.dispose()); + this.threadService = new MainThreadService(this.contextService, this.messageService, this.windowService); + lifecycleService.onShutdown.add(() => this.threadService.dispose()); - let requestServiceInstance = new RequestService( - contextServiceInstance, - configServiceInstance, - telemetryServiceInstance + let requestService = new RequestService( + this.contextService, + configService, + this.telemetryService ); - this.threadServiceInstance.registerInstance(requestServiceInstance); - lifecycleServiceInstance.onShutdown.add(() => requestServiceInstance.dispose()); + this.threadService.registerInstance(requestService); + lifecycleService.onShutdown.add(() => requestService.dispose()); - let markerServiceInstance = new MarkerService(this.threadServiceInstance); + let markerService = new MarkerService(this.threadService); - let pluginService = new MainProcessPluginService(contextServiceInstance, this.threadServiceInstance, this.messageServiceInstance, telemetryServiceInstance); - keybindingServiceInstance.setPluginService(pluginService); + let pluginService = new MainProcessPluginService(this.contextService, this.threadService, this.messageService, this.telemetryService); + this.keybindingService.setPluginService(pluginService); - let modelServiceInstance = new ModelServiceImpl(this.threadServiceInstance, markerServiceInstance); - let modeService = new MainThreadModeServiceImpl(this.threadServiceInstance, pluginService, modelServiceInstance); + let modelService = new ModelServiceImpl(this.threadService, markerService); + let modeService = new MainThreadModeServiceImpl(this.threadService, pluginService, modelService); let untitledEditorService = new UntitledEditorService(); this.themeService = new ThemeService(pluginService); let result = createInstantiationService(); - result.addSingleton(ITelemetryService, telemetryServiceInstance); - result.addSingleton(IEventService, eventServiceInstance); - result.addSingleton(IRequestService, requestServiceInstance); - result.addSingleton(IWorkspaceContextService, contextServiceInstance); - result.addSingleton(IContextViewService, this.contextViewServiceInstance); - result.addSingleton(IContextMenuService, new ContextMenuService(this.messageServiceInstance, telemetryServiceInstance)); - result.addSingleton(IMessageService, this.messageServiceInstance); - result.addSingleton(IStorageService, this.storageServiceInstance); - result.addSingleton(ILifecycleService, lifecycleServiceInstance); - result.addSingleton(IThreadService, this.threadServiceInstance); + result.addSingleton(ITelemetryService, this.telemetryService); + result.addSingleton(IEventService, eventService); + result.addSingleton(IRequestService, requestService); + result.addSingleton(IWorkspaceContextService, this.contextService); + result.addSingleton(IContextViewService, this.contextViewService); + result.addSingleton(IContextMenuService, new ContextMenuService(this.messageService, this.telemetryService)); + result.addSingleton(IMessageService, this.messageService); + result.addSingleton(IStorageService, this.storageService); + result.addSingleton(ILifecycleService, lifecycleService); + result.addSingleton(IThreadService, this.threadService); result.addSingleton(IPluginService, pluginService); result.addSingleton(IModeService, modeService); - result.addSingleton(IFileService, fileServiceInstance); + result.addSingleton(IFileService, fileService); result.addSingleton(IUntitledEditorService, untitledEditorService); - result.addSingleton(ISearchService, new SearchService(modelServiceInstance, untitledEditorService, contextServiceInstance, configServiceInstance)); - result.addSingleton(IWindowService, this.windowServiceInstance); - result.addSingleton(IConfigurationService, configServiceInstance); - result.addSingleton(IKeybindingService, keybindingServiceInstance); - result.addSingleton(IMarkerService, markerServiceInstance); - result.addSingleton(IModelService, modelServiceInstance); + result.addSingleton(ISearchService, new SearchService(modelService, untitledEditorService, this.contextService, configService)); + result.addSingleton(IWindowService, this.windowService); + result.addSingleton(IConfigurationService, configService); + result.addSingleton(IKeybindingService, this.keybindingService); + result.addSingleton(IMarkerService, markerService); + result.addSingleton(IModelService, modelService); result.addSingleton(ICodeEditorService, new CodeEditorServiceImpl()); result.addSingleton(IThemeService, this.themeService); - result.addSingleton(IActionsService, new ActionsService(pluginService, keybindingServiceInstance)); + result.addSingleton(IActionsService, new ActionsService(pluginService, this.keybindingService)); return result; @@ -318,25 +349,25 @@ export class WorkbenchShell { // TODO@Alex, TODO@Joh move this out of here? private initPluginSystem(): void { - this.threadServiceInstance.getRemotable(MainProcessVSCodeAPIHelper); - this.threadServiceInstance.getRemotable(MainThreadDocuments); - this.threadServiceInstance.getRemotable(RemoteTelemetryServiceHelper); + this.threadService.getRemotable(MainProcessVSCodeAPIHelper); + this.threadService.getRemotable(MainThreadDocuments); + this.threadService.getRemotable(RemoteTelemetryServiceHelper); this.workbench.getInstantiationService().createInstance(MainProcessTextMateSyntax); this.workbench.getInstantiationService().createInstance(MainProcessTextMateSnippet); this.workbench.getInstantiationService().createInstance(LanguageConfigurationFileHandler); - this.threadServiceInstance.getRemotable(MainThreadConfiguration); - this.threadServiceInstance.getRemotable(MainThreadQuickOpen); - this.threadServiceInstance.getRemotable(MainThreadStatusBar); + this.threadService.getRemotable(MainThreadConfiguration); + this.threadService.getRemotable(MainThreadQuickOpen); + this.threadService.getRemotable(MainThreadStatusBar); this.workbench.getInstantiationService().createInstance(MainThreadFileSystemEventService); - this.threadServiceInstance.getRemotable(MainThreadCommands); - this.threadServiceInstance.getRemotable(MainThreadOutputService); - this.threadServiceInstance.getRemotable(MainThreadDiagnostics); - this.threadServiceInstance.getRemotable(MainThreadMessageService); - this.threadServiceInstance.getRemotable(MainThreadLanguages); - this.threadServiceInstance.getRemotable(MainThreadWorkspace); - this.threadServiceInstance.getRemotable(MainThreadEditors); - this.threadServiceInstance.getRemotable(MainThreadStorage); - LanguageFeatures.createMainThreadInstances(this.threadServiceInstance); + this.threadService.getRemotable(MainThreadCommands); + this.threadService.getRemotable(MainThreadOutputService); + this.threadService.getRemotable(MainThreadDiagnostics); + this.threadService.getRemotable(MainThreadMessageService); + this.threadService.getRemotable(MainThreadLanguages); + this.threadService.getRemotable(MainThreadWorkspace); + this.threadService.getRemotable(MainThreadEditors); + this.threadService.getRemotable(MainThreadStorage); + LanguageFeatures.createMainThreadInstances(this.threadService); } public open(): void { @@ -365,15 +396,15 @@ export class WorkbenchShell { this.registerListeners(); // Enable theme support - let themeId = this.storageServiceInstance.get(Preferences.THEME, StorageScope.GLOBAL, null); + let themeId = this.storageService.get(Preferences.THEME, StorageScope.GLOBAL, null); if (!themeId) { themeId = themes.toId(themes.BaseTheme.VS_DARK); - this.storageServiceInstance.store(Preferences.THEME, themeId, StorageScope.GLOBAL); + this.storageService.store(Preferences.THEME, themeId, StorageScope.GLOBAL); } this.setTheme(themeId, false); - this.toUnbind.push(this.storageServiceInstance.addListener(StorageEventType.STORAGE, (e: StorageEvent) => { + this.toUnbind.push(this.storageService.addListener(StorageEventType.STORAGE, (e: StorageEvent) => { if (e.key === Preferences.THEME) { this.setTheme(e.newValue); } @@ -487,8 +518,8 @@ export class WorkbenchShell { console.error(errorMsg); // Show to user if friendly message provided - if (error.friendlyMessage && this.messageServiceInstance) { - this.messageServiceInstance.show(Severity.Error, error.friendlyMessage); + if (error.friendlyMessage && this.messageService) { + this.messageService.show(Severity.Error, error.friendlyMessage); } } @@ -498,7 +529,7 @@ export class WorkbenchShell { let contentsSize = new Dimension(clArea.width, clArea.height); this.contentsContainer.size(contentsSize.width, contentsSize.height); - this.contextViewServiceInstance.layout(); + this.contextViewService.layout(); this.workbench.layout(); } @@ -518,8 +549,8 @@ export class WorkbenchShell { } } - this.contextViewServiceInstance.dispose(); - this.storageServiceInstance.dispose(); + this.contextViewService.dispose(); + this.storageService.dispose(); // Listeners while (this.toUnbind.length) { From f38e086bfdfd1f7632fc588b9bb0dc55e7ac3806 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 26 Nov 2015 13:02:05 +0100 Subject: [PATCH 119/588] debug: replHistory.test --- .../debug/test/common/replHistory.test.ts | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/vs/workbench/parts/debug/test/common/replHistory.test.ts diff --git a/src/vs/workbench/parts/debug/test/common/replHistory.test.ts b/src/vs/workbench/parts/debug/test/common/replHistory.test.ts new file mode 100644 index 00000000000..1da7fe5b94e --- /dev/null +++ b/src/vs/workbench/parts/debug/test/common/replHistory.test.ts @@ -0,0 +1,47 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import assert = require('assert'); +import { ReplHistory } from 'vs/workbench/parts/debug/common/replHistory'; + +suite('Debug - Repl History', () => { + var history: ReplHistory; + + setup(() => { + history = new ReplHistory(['one', 'two', 'three', 'four', 'five']); + }); + + teardown(() => { + history = null; + }); + + test('previous and next', () => { + assert.equal(history.previous(), 'five'); + assert.equal(history.previous(), 'four'); + assert.equal(history.previous(), 'three'); + assert.equal(history.previous(), 'two'); + assert.equal(history.previous(), 'one'); + assert.equal(history.previous(), null); + assert.equal(history.next(), 'two'); + assert.equal(history.next(), 'three'); + assert.equal(history.next(), 'four'); + assert.equal(history.next(), 'five'); + }); + + test('evaluated and remember', () => { + history.evaluated('six'); + assert.equal(history.previous(), 'six'); + assert.equal(history.previous(), 'five'); + assert.equal(history.next(), 'six'); + + history.remember('six++', true); + assert.equal(history.next(), 'six++'); + assert.equal(history.previous(), 'six'); + + history.evaluated('seven'); + assert.equal(history.previous(), 'seven'); + assert.equal(history.previous(), 'six'); + }); +}); From b1d9a055b91d39df1e1010cc1f6ef7807de0612d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2015 14:00:32 +0100 Subject: [PATCH 120/588] Quick open widget doesn't acknowledge tree.reveal(...) as a promise --- src/vs/base/parts/quickopen/browser/quickOpenWidget.ts | 8 ++++---- src/vs/workbench/browser/viewlet.ts | 3 ++- .../parts/files/browser/views/workingFilesView.ts | 3 ++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts index 2d60a6612aa..dd7fb2bf7c2 100644 --- a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts +++ b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts @@ -343,7 +343,7 @@ export class QuickOpenWidget implements IModelProvider { // Reveal focus = this.tree.getFocus(); if (focus) { - revealToTop ? this.tree.reveal(focus, 0) : this.tree.reveal(focus); + revealToTop ? this.tree.reveal(focus, 0).done(null, errors.onUnexpectedError) : this.tree.reveal(focus).done(null, errors.onUnexpectedError); } } @@ -543,7 +543,7 @@ export class QuickOpenWidget implements IModelProvider { let entryToFocus = caseSensitiveMatch || caseInsensitiveMatch; if (entryToFocus) { this.tree.setFocus(entryToFocus); - this.tree.reveal(entryToFocus, 0); + this.tree.reveal(entryToFocus, 0).done(null, errors.onUnexpectedError); return; } @@ -552,14 +552,14 @@ export class QuickOpenWidget implements IModelProvider { // Second check for auto focus of first entry if (autoFocus.autoFocusFirstEntry) { this.tree.focusFirst(); - this.tree.reveal(this.tree.getFocus(), 0); + this.tree.reveal(this.tree.getFocus(), 0).done(null, errors.onUnexpectedError); } // Third check for specific index option else if (typeof autoFocus.autoFocusIndex === 'number') { if (entries.length > autoFocus.autoFocusIndex) { this.tree.focusNth(autoFocus.autoFocusIndex); - this.tree.reveal(this.tree.getFocus()); + this.tree.reveal(this.tree.getFocus()).done(null, errors.onUnexpectedError); } } diff --git a/src/vs/workbench/browser/viewlet.ts b/src/vs/workbench/browser/viewlet.ts index 0f57f43ecad..51df182e679 100644 --- a/src/vs/workbench/browser/viewlet.ts +++ b/src/vs/workbench/browser/viewlet.ts @@ -7,6 +7,7 @@ import nls = require('vs/nls'); import {Promise, TPromise} from 'vs/base/common/winjs.base'; import DOM = require('vs/base/browser/dom'); +import errors = require('vs/base/common/errors'); import {IEventEmitter} from 'vs/base/common/eventEmitter'; import {Registry} from 'vs/platform/platform'; import {Dimension, Builder, $} from 'vs/base/browser/builder'; @@ -283,7 +284,7 @@ export abstract class ViewerViewlet extends Viewlet { // Make sure the current selected element is revealed let selection = this.viewer.getSelection(); if (selection.length > 0) { - this.reveal(selection[0], 0.5); + this.reveal(selection[0], 0.5).done(null, errors.onUnexpectedError); } // Pass Focus to Viewer diff --git a/src/vs/workbench/parts/files/browser/views/workingFilesView.ts b/src/vs/workbench/parts/files/browser/views/workingFilesView.ts index 2945647ab47..57ee8ab4767 100644 --- a/src/vs/workbench/parts/files/browser/views/workingFilesView.ts +++ b/src/vs/workbench/parts/files/browser/views/workingFilesView.ts @@ -14,6 +14,7 @@ import workbenchEditorCommon = require('vs/workbench/common/editor'); import {CollapsibleState} from 'vs/base/browser/ui/splitview/splitview'; import {IWorkingFileEntry, IWorkingFilesModel, IWorkingFileModelChangeEvent, LocalFileChangeEvent, EventType as FileEventType, IFilesConfiguration, ITextFileService} from 'vs/workbench/parts/files/common/files'; import dom = require('vs/base/browser/dom'); +import errors = require('vs/base/common/errors'); import {EditorEvent, EventType as WorkbenchEventType, UntitledEditorEvent} from 'vs/workbench/browser/events'; import {AdaptiveCollapsibleViewletView} from 'vs/workbench/browser/viewlet'; import {CloseWorkingFileAction, SaveAllAction} from 'vs/workbench/parts/files/browser/fileActions'; @@ -275,7 +276,7 @@ export class WorkingFilesView extends AdaptiveCollapsibleViewletView { if (entry) { this.tree.setFocus(entry); this.tree.setSelection([entry]); - this.tree.reveal(entry); + this.tree.reveal(entry).done(null, errors.onUnexpectedError); } } From ca49e38ea4b3a382abad1f3fc352641bef5c9192 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 26 Nov 2015 14:36:17 +0100 Subject: [PATCH 121/588] fix the build --- scripts/code.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/code.sh b/scripts/code.sh index ba92a3fe5e6..6f080650a64 100755 --- a/scripts/code.sh +++ b/scripts/code.sh @@ -33,4 +33,4 @@ function code() { fi } -code +code $* From b8ef6df7420f2edbb3c8509cd690616149558c40 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2015 14:47:44 +0100 Subject: [PATCH 122/588] fix merge issue --- src/vs/workbench/electron-browser/shell.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index c446bc8c553..c3aee8b3eed 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -367,7 +367,7 @@ export class WorkbenchShell { this.threadService.getRemotable(MainThreadWorkspace); this.threadService.getRemotable(MainThreadEditors); this.threadService.getRemotable(MainThreadStorage); - this.threadServiceInstance.getRemotable(MainThreadLanguageFeatures); + this.threadService.getRemotable(MainThreadLanguageFeatures); } public open(): void { From 5f4102f4e789cf517514724a9d909bfd701bc261 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 26 Nov 2015 14:49:16 +0100 Subject: [PATCH 123/588] uri: can not throw an error with a path due to privacy issues. --- src/vs/base/common/uri.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/common/uri.ts b/src/vs/base/common/uri.ts index 0a6328c8920..8fd945fdcfd 100644 --- a/src/vs/base/common/uri.ts +++ b/src/vs/base/common/uri.ts @@ -174,7 +174,7 @@ export default class URI { var ret = URI._parse(path); if (ret.scheme || ret.fragment || ret.query) { - throw new Error(`Path ${ path } contains a scheme, fragment or a query. Can not convert it to a file uri.`); + throw new Error('Path contains a scheme, fragment or a query. Can not convert it to a file uri.'); } ret = ret.with('file', undefined, From b086ce41a0df2ce984fa6dbe4ed607416736c29b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2015 14:55:19 +0100 Subject: [PATCH 124/588] bump 0.10.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2500de069f0..50b241f37a9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Code", - "version": "0.10.1", + "version": "0.10.3", "electronVersion": "0.34.1", "author": { "name": "Microsoft Corporation" From d147ddd44424e1b244da4cea4083a5b320e9caf5 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2015 15:13:52 +0100 Subject: [PATCH 125/588] Actually set the maxResults-value when finding files, fixs #697 --- src/vs/workbench/api/browser/pluginHostWorkspace.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/api/browser/pluginHostWorkspace.ts b/src/vs/workbench/api/browser/pluginHostWorkspace.ts index f68254d2e3d..55b94c717f0 100644 --- a/src/vs/workbench/api/browser/pluginHostWorkspace.ts +++ b/src/vs/workbench/api/browser/pluginHostWorkspace.ts @@ -101,7 +101,7 @@ export class MainThreadWorkspace { this._eventService = eventService; } - findFiles(include: string, exclude: string, maxResults?: number): Thenable { + findFiles(include: string, exclude: string, maxResults: number): Thenable { if (!this._workspace) { return; @@ -110,7 +110,7 @@ export class MainThreadWorkspace { return this._searchService.search({ rootResources: [this._workspace.resource], type: QueryType.File, - maxResults: 100, + maxResults, includePattern: { [include]: true }, excludePattern: { [exclude]: true }, }).then(result => { From fa3494b109840fd90ce02d001c9e6f31a03bdfc9 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 26 Nov 2015 15:15:00 +0100 Subject: [PATCH 126/588] debug: move debugSource to its own file. --- src/vs/workbench/parts/debug/common/debug.ts | 32 +--------------- .../parts/debug/common/debugModel.ts | 15 ++++---- .../parts/debug/common/debugSource.ts | 37 +++++++++++++++++++ .../debug/electron-browser/debugService.ts | 11 +++--- 4 files changed, 52 insertions(+), 43 deletions(-) create mode 100644 src/vs/workbench/parts/debug/common/debugSource.ts diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index ce5c819f3f3..232f4a64e96 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -7,12 +7,12 @@ import nls = require('vs/nls'); import uri from 'vs/base/common/uri'; import { TPromise, Promise } from 'vs/base/common/winjs.base'; import ee = require('vs/base/common/eventEmitter'); -import paths = require('vs/base/common/paths'); import severity from 'vs/base/common/severity'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; import pluginsRegistry = require('vs/platform/plugins/common/pluginsRegistry'); import editor = require('vs/editor/common/editorCommon'); +import { Source } from 'vs/workbench/parts/debug/common/debugSource'; export var VIEWLET_ID = 'workbench.view.debug'; export var DEBUG_SERVICE_ID = 'debugService'; @@ -79,36 +79,6 @@ export interface IExceptionBreakpoint extends IEnablement { name: string; } -export class Source { - - public uri: uri; - public inMemory: boolean; - public available: boolean; - - private static INTERNAL_URI_PREFIX = 'debug://internal/'; - - constructor(public name: string, uriStr: string, public reference = 0) { - this.uri = uri.parse(uriStr); - this.inMemory = uriStr.indexOf(Source.INTERNAL_URI_PREFIX) === 0; - this.available = true; - } - - public toRawSource(): DebugProtocol.Source { - return this.inMemory ? { name: this.name } : - { path: paths.normalize(this.uri.fsPath, true) }; - } - - public static fromRawSource(rawSource: DebugProtocol.Source): Source { - var uriStr = rawSource.path ? uri.file(rawSource.path).toString() : Source.INTERNAL_URI_PREFIX + rawSource.name; - return new Source(rawSource.name, uriStr, rawSource.sourceReference); - } - - public static fromUri(uri: uri): Source { - var uriStr = uri.toString(); - return new Source(uriStr.substr(uriStr.lastIndexOf('/') + 1), uriStr); - } -} - // Events export var ModelEvents = { diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index 61f57fc6b2c..792a26ade46 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -13,6 +13,7 @@ import severity from 'vs/base/common/severity'; import types = require('vs/base/common/types'); import arrays = require('vs/base/common/arrays'); import debug = require('vs/workbench/parts/debug/common/debug'); +import { Source } from 'vs/workbench/parts/debug/common/debugSource'; function resolveChildren(debugService: debug.IDebugService, parent: debug.IExpressionContainer): TPromise { var session = debugService.getActiveSession(); @@ -204,7 +205,7 @@ export class StackFrame implements debug.IStackFrame { private internalId: string; private scopes: TPromise; - constructor(public threadId: number, public frameId: number, public source: debug.Source, public name: string, public lineNumber: number, public column: number) { + constructor(public threadId: number, public frameId: number, public source: Source, public name: string, public lineNumber: number, public column: number) { this.internalId = uuid.generateUuid(); this.scopes = null; } @@ -229,7 +230,7 @@ export class Breakpoint implements debug.IBreakpoint { public lineNumber: number; private id: string; - constructor(public source: debug.Source, public desiredLineNumber: number, public enabled: boolean) { + constructor(public source: Source, public desiredLineNumber: number, public enabled: boolean) { this.lineNumber = this.desiredLineNumber; this.id = uuid.generateUuid(); } @@ -326,7 +327,7 @@ export class Model extends ee.EventEmitter implements debug.IModel { } if (!found) { - this.breakpoints.push(new Breakpoint(debug.Source.fromUri(modelUri), lineNumber, true)); + this.breakpoints.push(new Breakpoint(Source.fromUri(modelUri), lineNumber, true)); this.breakpointsActivated = true; } @@ -370,7 +371,7 @@ export class Model extends ee.EventEmitter implements debug.IModel { public setBreakpointsForModel(modelUri: uri, data: { lineNumber: number; enabled: boolean; }[]): void { this.clearBreakpoints(modelUri); for (var i = 0, len = data.length; i < len; i++) { - this.breakpoints.push(new Breakpoint(debug.Source.fromUri(modelUri), data[i].lineNumber, data[i].enabled)); + this.breakpoints.push(new Breakpoint(Source.fromUri(modelUri), data[i].lineNumber, data[i].enabled)); } this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); } @@ -533,7 +534,7 @@ export class Model extends ee.EventEmitter implements debug.IModel { this.emit(debug.ModelEvents.WATCH_EXPRESSIONS_UPDATED); } - public sourceIsUnavailable(source: debug.Source): void { + public sourceIsUnavailable(source: Source): void { Object.keys(this.threads).forEach(key => { this.threads[key].callStack.forEach(stackFrame => { if (stackFrame.source.uri.toString() === source.uri.toString()) { @@ -555,10 +556,10 @@ export class Model extends ee.EventEmitter implements debug.IModel { this.threads[data.threadId].callStack = data.callStack.map( (rsf, level) => { if (!rsf) { - return new StackFrame(data.threadId, 0, debug.Source.fromUri(uri.parse('unknown')), nls.localize('unknownStack', "Unknown stack location"), undefined, undefined); + return new StackFrame(data.threadId, 0, Source.fromUri(uri.parse('unknown')), nls.localize('unknownStack', "Unknown stack location"), undefined, undefined); } - return new StackFrame(data.threadId, rsf.id, rsf.source ? debug.Source.fromRawSource(rsf.source) : debug.Source.fromUri(uri.parse('unknown')), rsf.name, rsf.line, rsf.column); + return new StackFrame(data.threadId, rsf.id, rsf.source ? Source.fromRawSource(rsf.source) : Source.fromUri(uri.parse('unknown')), rsf.name, rsf.line, rsf.column); }); this.threads[data.threadId].exception = data.exception; diff --git a/src/vs/workbench/parts/debug/common/debugSource.ts b/src/vs/workbench/parts/debug/common/debugSource.ts new file mode 100644 index 00000000000..c2aa0f731c5 --- /dev/null +++ b/src/vs/workbench/parts/debug/common/debugSource.ts @@ -0,0 +1,37 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import uri from 'vs/base/common/uri'; +import paths = require('vs/base/common/paths'); + +export class Source { + + public uri: uri; + public inMemory: boolean; + public available: boolean; + + private static INTERNAL_URI_PREFIX = 'debug://internal/'; + + constructor(public name: string, uriStr: string, public reference = 0) { + this.uri = uri.parse(uriStr); + this.inMemory = uriStr.indexOf(Source.INTERNAL_URI_PREFIX) === 0; + this.available = true; + } + + public toRawSource(): DebugProtocol.Source { + return this.inMemory ? { name: this.name } : + { path: paths.normalize(this.uri.fsPath, true) }; + } + + public static fromRawSource(rawSource: DebugProtocol.Source): Source { + var uriStr = rawSource.path ? uri.file(rawSource.path).toString() : Source.INTERNAL_URI_PREFIX + rawSource.name; + return new Source(rawSource.name, uriStr, rawSource.sourceReference); + } + + public static fromUri(uri: uri): Source { + var uriStr = uri.toString(); + return new Source(uriStr.substr(uriStr.lastIndexOf('/') + 1), uriStr); + } +} diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 7267882fea7..cc8f53dd6ac 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -31,6 +31,7 @@ import viewmodel = require('vs/workbench/parts/debug/common/debugViewModel'); import debugactions = require('vs/workbench/parts/debug/browser/debugActions'); import { Adapter } from 'vs/workbench/parts/debug/node/debugAdapter'; import { Repl } from 'vs/workbench/parts/debug/browser/replEditor'; +import { Source } from 'vs/workbench/parts/debug/common/debugSource'; import { Position } from 'vs/platform/editor/common/editor'; import { ITaskService , TaskEvent, TaskType, TaskServiceEvents} from 'vs/workbench/parts/tasks/common/taskService'; import { IViewletService } from 'vs/workbench/services/viewlet/common/viewletService'; @@ -366,7 +367,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService private loadBreakpoints(): debug.IBreakpoint[] { try { return JSON.parse(this.storageService.get(DEBUG_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((breakpoint: any) => { - return new model.Breakpoint(new debug.Source(breakpoint.source.name, breakpoint.source.uri, breakpoint.source.reference), breakpoint.desiredLineNumber || breakpoint.lineNumber, breakpoint.enabled); + return new model.Breakpoint(new Source(breakpoint.source.name, breakpoint.source.uri, breakpoint.source.reference), breakpoint.desiredLineNumber || breakpoint.lineNumber, breakpoint.enabled); }); } catch (e) { return []; @@ -746,7 +747,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService return this.viewModel; } - public openOrRevealEditor(source: debug.Source, lineNumber: number, preserveFocus: boolean, sideBySide: boolean): Promise { + public openOrRevealEditor(source: Source, lineNumber: number, preserveFocus: boolean, sideBySide: boolean): Promise { const visibleEditors = this.editorService.getVisibleEditors(); for (var i = 0; i < visibleEditors.length; i++) { const fileInput = wbeditorcommon.asFileEditorInput(visibleEditors[i].input); @@ -798,7 +799,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService ); } - private sourceIsUnavailable(source: debug.Source, sideBySide: boolean): Promise { + private sourceIsUnavailable(source: Source, sideBySide: boolean): Promise { this.model.sourceIsUnavailable(source); const editorInput = this.getDebugStringEditorInput(source, 'Source is not available.', 'text/plain'); @@ -844,7 +845,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService }); } - private getDebugStringEditorInput(source: debug.Source, value: string, mtype: string): debuginputs.DebugStringEditorInput { + private getDebugStringEditorInput(source: Source, value: string, mtype: string): debuginputs.DebugStringEditorInput { var filtered = this.debugStringEditorInputs.filter(input => input.getResource().toString() === source.uri.toString()); if (filtered.length === 0) { @@ -880,7 +881,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService this.model.getBreakpoints().filter(bp => this.model.areBreakpointsActivated() && bp.enabled && bp.source.uri.toString() === modelUri.toString()), bp => `${ bp.desiredLineNumber }` ); - return this.session.setBreakpoints({ source: debug.Source.fromUri(modelUri).toRawSource(), lines: breakpointsToSend.map(bp => bp.desiredLineNumber) }).then(response => { + return this.session.setBreakpoints({ source: Source.fromUri(modelUri).toRawSource(), lines: breakpointsToSend.map(bp => bp.desiredLineNumber) }).then(response => { let index = 0; breakpointsToSend.forEach(bp => { const lineNumber = response.body.breakpoints[index++].line; From 61f6ee8bf4cb27925c6ce8281e0cf008b139ecab Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 26 Nov 2015 15:23:26 +0100 Subject: [PATCH 127/588] debug: debugSource.test.ts --- .../debug/test/common/debugSource.test.ts | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/vs/workbench/parts/debug/test/common/debugSource.test.ts diff --git a/src/vs/workbench/parts/debug/test/common/debugSource.test.ts b/src/vs/workbench/parts/debug/test/common/debugSource.test.ts new file mode 100644 index 00000000000..60bf576fccf --- /dev/null +++ b/src/vs/workbench/parts/debug/test/common/debugSource.test.ts @@ -0,0 +1,50 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import assert = require('assert'); +import uri from 'vs/base/common/uri'; +import { Source } from 'vs/workbench/parts/debug/common/debugSource'; + +suite('Debug - Source', () => { + + test('from uri', () => { + const u = uri.file('/a/b/c/d'); + const source = Source.fromUri(u); + + assert.equal(source.available, true); + assert.equal(source.inMemory, false); + assert.equal(source.reference, 0); + assert.equal(source.uri.toString(), u.toString()); + assert.equal(source.name, 'd'); + }); + + test('from raw source', () => { + const rawSource = { + name: 'zz', + path: '/xx/yy/zz', + sourceReference: 0 + }; + const source = Source.fromRawSource(rawSource); + + assert.equal(source.available, true); + assert.equal(source.name, rawSource.name); + assert.equal(source.inMemory, false); + assert.equal(source.reference, rawSource.sourceReference); + assert.equal(source.uri.fsPath, rawSource.path); + }); + + test('from raw internal source', () => { + const rawSource = { + name: 'internalModule.js', + sourceReference: 11 + }; + const source = Source.fromRawSource(rawSource); + + assert.equal(source.available, true); + assert.equal(source.name, rawSource.name); + assert.equal(source.inMemory, true); + assert.equal(source.reference, rawSource.sourceReference); + }); +}); From 3e1cbe1209cd5e83d7bcbff1e558bb9fdafc87f8 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2015 15:38:29 +0100 Subject: [PATCH 128/588] workspace.rootPath should be undefined when no folder is open, not null. fixes #690 --- src/vs/workbench/api/browser/pluginHost.api.impl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/api/browser/pluginHost.api.impl.ts b/src/vs/workbench/api/browser/pluginHost.api.impl.ts index eacd47d1fa8..bdc5061e270 100644 --- a/src/vs/workbench/api/browser/pluginHost.api.impl.ts +++ b/src/vs/workbench/api/browser/pluginHost.api.impl.ts @@ -189,7 +189,7 @@ export class PluginHostAPIImplementation { }; // - const workspacePath = contextService.getWorkspace() && contextService.getWorkspace().resource.fsPath; + const workspacePath = contextService.getWorkspace() ? contextService.getWorkspace().resource.fsPath : undefined; const pluginHostFileSystemEvent = threadService.getRemotable(PluginHostFileSystemEventService); const pluginHostWorkspace = new PluginHostWorkspace(this._threadService, workspacePath); const pluginHostDocuments = this._threadService.getRemotable(PluginHostModelService); From 9d1054fb707ea08544c5c3b4428dda08dab4a08c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2015 15:39:36 +0100 Subject: [PATCH 129/588] don't search for project when no folder has been opened, fixes #649 --- extensions/csharp-o/src/launchTargetFinder.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/extensions/csharp-o/src/launchTargetFinder.ts b/extensions/csharp-o/src/launchTargetFinder.ts index e3630c850a4..1459af222f9 100644 --- a/extensions/csharp-o/src/launchTargetFinder.ts +++ b/extensions/csharp-o/src/launchTargetFinder.ts @@ -18,6 +18,11 @@ export interface LaunchTarget { export default function getLaunchTargets(): Thenable { + + if (!workspace.rootPath) { + return Promise.resolve([]); + } + return workspace.findFiles('{**/*.sln,**/*.csproj,**/project.json}', '{**/node_modules/**,**/.git/**,**/bower_components/**}', 100).then(resources => { return select(resources, Uri.file(workspace.rootPath)); }); From 62727a35d91cecb80fec77b1c4b3c1025ea21011 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Nov 2015 15:57:57 +0100 Subject: [PATCH 130/588] fixes #672 --- extensions/csharp-o/src/features/omnisharpStatus.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/extensions/csharp-o/src/features/omnisharpStatus.ts b/extensions/csharp-o/src/features/omnisharpStatus.ts index bf7609ff0e2..9cc121ce6a2 100644 --- a/extensions/csharp-o/src/features/omnisharpStatus.ts +++ b/extensions/csharp-o/src/features/omnisharpStatus.ts @@ -122,8 +122,10 @@ export function reportDocumentStatus(server: OmnisharpServer): vscode.Disposable for (let project of info.MSBuild.Projects) { fileNames.push({ pattern: project.Path }); - for (let sourceFile of project.SourceFiles) { - fileNames.push({ pattern: sourceFile }); + if (project.SourceFiles) { + for (let sourceFile of project.SourceFiles) { + fileNames.push({ pattern: sourceFile }); + } } } } @@ -134,8 +136,10 @@ export function reportDocumentStatus(server: OmnisharpServer): vscode.Disposable count += 1; fileNames.push({ pattern: project.Path }); - for (let sourceFile of project.SourceFiles) { - fileNames.push({ pattern: sourceFile }); + if (project.SourceFiles) { + for (let sourceFile of project.SourceFiles) { + fileNames.push({ pattern: sourceFile }); + } } } if (label) { From cc17718c73d21a30ea1f8c2c9f254f454ad82798 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2015 16:06:08 +0100 Subject: [PATCH 131/588] handle case where process.send fails --- src/bootstrap.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/bootstrap.js b/src/bootstrap.js index d3e6e707d23..43458652f50 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -63,16 +63,24 @@ if (!!process.send && process.env.PIPE_LOGGING === 'true') { return res; } + function safeSend(arg) { + try { + process.send(arg); + } catch (error) { + // Can happen if the parent channel is closed meanwhile + } + } + // Pass console logging to the outside so that we have it in the main side if told so if (process.env.VERBOSE_LOGGING === 'true') { - console.log = function () { process.send({ type: '__$console', severity: 'log', arguments: safeStringify(arguments) }); }; - console.warn = function () { process.send({ type: '__$console', severity: 'warn', arguments: safeStringify(arguments) }); }; + console.log = function () { safeSend({ type: '__$console', severity: 'log', arguments: safeStringify(arguments) }); }; + console.warn = function () { safeSend({ type: '__$console', severity: 'warn', arguments: safeStringify(arguments) }); }; } else { console.log = function () { /* ignore */ }; console.warn = function () { /* ignore */ }; } - console.error = function () { process.send({ type: '__$console', severity: 'error', arguments: safeStringify(arguments) }); }; + console.error = function () { safeSend({ type: '__$console', severity: 'error', arguments: safeStringify(arguments) }); }; // Let stdout, stderr and stdin be no-op streams. This prevents an issue where we would get an EBADF // error when we are inside a forked process and this process tries to access those channels. From aced9f6660a18115de1e5031810258aa6015f244 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 26 Nov 2015 17:33:25 +0100 Subject: [PATCH 132/588] Add a helper widget active in keybinding.json to help with defining keybindings --- src/vs/base/common/keyCodes.ts | 11 +- src/vs/editor/browser/editor.all.js | 1 + .../browser/defineKeybinding.css | 43 +++ .../browser/defineKeybinding.ts | 296 ++++++++++++++++++ .../common/commonKeybindingResolver.ts | 10 +- 5 files changed, 351 insertions(+), 10 deletions(-) create mode 100644 src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.css create mode 100644 src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts diff --git a/src/vs/base/common/keyCodes.ts b/src/vs/base/common/keyCodes.ts index 9a2729a8251..d2ad8bbc617 100644 --- a/src/vs/base/common/keyCodes.ts +++ b/src/vs/base/common/keyCodes.ts @@ -385,7 +385,16 @@ export class Keybinding { * Format the binding to a format appropiate for the user settings file. */ public static toUserSettingsLabel(value:number): string { - return _asString(value, UserSettingsKeyLabelProvider.INSTANCE); + let result = _asString(value, UserSettingsKeyLabelProvider.INSTANCE); + result = result.toLowerCase().replace(/arrow/g, ''); + + if (Platform.isMacintosh) { + result = result.replace(/meta/g, 'cmd'); + } else if (Platform.isWindows) { + result = result.replace(/meta/g, 'win'); + } + + return result; } public value:number; diff --git a/src/vs/editor/browser/editor.all.js b/src/vs/editor/browser/editor.all.js index f3ed8cb8ef5..71f01907ab0 100644 --- a/src/vs/editor/browser/editor.all.js +++ b/src/vs/editor/browser/editor.all.js @@ -36,6 +36,7 @@ define([ 'vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode', 'vs/editor/contrib/wordHighlighter/common/wordHighlighter', 'vs/editor/contrib/workerStatusReporter/browser/workerStatusReporter', + 'vs/editor/contrib/defineKeybinding/browser/defineKeybinding', // include these in the editor bundle because they are widely used by many languages 'vs/editor/common/languages.common' diff --git a/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.css b/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.css new file mode 100644 index 00000000000..bf06fd067b0 --- /dev/null +++ b/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.css @@ -0,0 +1,43 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +.monaco-editor .defineKeybindingLauncher { + background: rgba(0,255,0,0.3); + padding: 10px; + border-radius: 5px; + cursor: pointer; +} + +.monaco-editor .defineKeybindingWidget { + width: 340px; + height: 60px; + padding: 10px; +} + +.monaco-editor .defineKeybindingWidget .message { + width: 320px; + text-align: center; +} + +.monaco-editor .defineKeybindingWidget .input { + width: 320px; + display: block; +} + +.monaco-editor .defineKeybindingWidget .output { + width: 320px; + text-align: center; +} + +/* Theming */ +.monaco-editor .defineKeybindingWidget { + background-color: #EFEFF2; + box-shadow: 0 2px 8px #A8A8A8; +} + +.monaco-editor.vs-dark .defineKeybindingWidget { + background-color: #2D2D30; + box-shadow: 0 2px 8px #000; +} \ No newline at end of file diff --git a/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts b/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts new file mode 100644 index 00000000000..d2c49f89160 --- /dev/null +++ b/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts @@ -0,0 +1,296 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import 'vs/css!./defineKeybinding'; +import nls = require('vs/nls'); +import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; +import DomUtils = require('vs/base/browser/dom'); +import EditorBrowser = require('vs/editor/browser/editorBrowser'); +import EditorCommon = require('vs/editor/common/editorCommon'); +import {disposeAll, IDisposable} from 'vs/base/common/lifecycle'; +import {INullService} from 'vs/platform/instantiation/common/instantiation'; +import {StandardKeyboardEvent} from 'vs/base/browser/keyboardEvent'; +import {KeyMod, KeyCode, CommonKeybindings, Keybinding} from 'vs/base/common/keyCodes'; +import Snippet = require('vs/editor/contrib/snippet/common/snippet'); +import {EditorAction, Behaviour} from 'vs/editor/common/editorAction'; +import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; + +export class DefineKeybindingController implements EditorCommon.IEditorContribution { + + static ID = 'editor.contrib.defineKeybinding'; + + static get(editor:EditorCommon.ICommonCodeEditor): DefineKeybindingController { + return editor.getContribution(DefineKeybindingController.ID); + } + + private _editor: EditorBrowser.ICodeEditor; + private _launchWidget: DefineKeybindingLauncherWidget; + private _defineWidget: DefineKeybindingWidget; + private _toDispose: IDisposable[]; + + constructor( + editor:EditorBrowser.ICodeEditor, + @IKeybindingService keybindingService:IKeybindingService + ) { + this._editor = editor; + this._toDispose = []; + this._launchWidget = new DefineKeybindingLauncherWidget(this._editor, keybindingService, () => this.launch()); + this._defineWidget = new DefineKeybindingWidget(this._editor, (keybinding) => this._onAccepted(keybinding)); + + this._toDispose.push(this._editor.addListener2(EditorCommon.EventType.ModelChanged, (e) => { + if (isInterestingEditorModel(this._editor)) { + this._launchWidget.show(); + } else { + this._launchWidget.hide(); + } + })); + } + + public getId(): string { + return DefineKeybindingController.ID; + } + + public dispose(): void { + this._toDispose = disposeAll(this._toDispose); + this._launchWidget.dispose(); + this._launchWidget = null; + this._defineWidget.dispose(); + this._defineWidget = null; + } + + public launch(): void { + if (isInterestingEditorModel(this._editor)) { + this._defineWidget.start(); + } + } + + private _onAccepted(keybinding:string): void { + let snippetText = [ + '{', + '\t"key": "' + keybinding + '",', + '\t"command": "{{commandId}}",', + '\t"when": "{{editorTextFocus}}"', + '}{{}}' + ].join('\n'); + + Snippet.get(this._editor).run(new Snippet.CodeSnippet(snippetText), 0, 0); + } +} + +class DefineKeybindingLauncherWidget implements EditorBrowser.IOverlayWidget { + + private static ID = 'editor.contrib.defineKeybindingLauncherWidget'; + + private _editor: EditorBrowser.ICodeEditor; + + private _domNode: HTMLElement; + private _toDispose: IDisposable[]; + + constructor(editor:EditorBrowser.ICodeEditor, keybindingService:IKeybindingService, onLaunch:()=>void) { + this._editor = editor; + this._domNode = document.createElement('div'); + this._domNode.className = 'defineKeybindingLauncher'; + this._domNode.style.display = 'none'; + let keybinding = keybindingService.lookupKeybindings(DefineKeybindingAction.ID); + let extra = ''; + if (keybinding.length > 0) { + extra += ' ('+keybinding[0].toLabel()+')'; + } + this._domNode.appendChild(document.createTextNode(nls.localize('defineKeybinding.start', "Define Keybinding" + extra))); + + this._toDispose = []; + this._toDispose.push(DomUtils.addDisposableListener(this._domNode, 'click', (e) => { + onLaunch(); + })) + + this._editor.addOverlayWidget(this); + } + + public dispose(): void { + this._editor.removeOverlayWidget(this); + this._toDispose = disposeAll(this._toDispose); + } + + public show(): void { + this._domNode.style.display = 'block'; + } + + public hide(): void { + this._domNode.style.display = 'none'; + } + + // ----- IOverlayWidget API + + public getId(): string { + return DefineKeybindingLauncherWidget.ID; + } + + public getDomNode(): HTMLElement { + return this._domNode; + } + + public getPosition(): EditorBrowser.IOverlayWidgetPosition { + return { + preference: EditorBrowser.OverlayWidgetPositionPreference.BOTTOM_RIGHT_CORNER + }; + } +} + +class DefineKeybindingWidget implements EditorBrowser.IContentWidget { + + private static ID = 'editor.contrib.defineKeybindingWidget'; + + private _editor: EditorBrowser.ICodeEditor; + + private _domNode: HTMLElement; + private _toDispose: IDisposable[]; + private _position: EditorCommon.IPosition; + + private _messageNode: HTMLElement; + private _inputNode: HTMLInputElement; + private _outputNode: HTMLElement; + + private _lastKeybinding: Keybinding; + private _onAccepted: (keybinding:string) => void; + + constructor(editor:EditorBrowser.ICodeEditor, onAccepted:(keybinding:string) => void) { + this._editor = editor; + this._onAccepted = onAccepted; + this._toDispose = []; + this._position = null; + this._lastKeybinding = null; + + this._domNode = document.createElement('div'); + this._domNode.className = 'defineKeybindingWidget'; + + this._messageNode = document.createElement('div'); + this._messageNode.className = 'message'; + this._messageNode.innerText = nls.localize('defineKeybinding.initial', "Press desired key combination and ENTER"); + this._domNode.appendChild(this._messageNode); + + this._inputNode = document.createElement('input'); + this._inputNode.className = 'input'; + this._domNode.appendChild(this._inputNode); + + this._outputNode = document.createElement('div'); + this._outputNode.className = 'output'; + this._domNode.appendChild(this._outputNode); + + this._toDispose.push(DomUtils.addDisposableListener(this._inputNode, 'keydown', (e) => { + let keyEvent = new StandardKeyboardEvent(e); + keyEvent.preventDefault(); + keyEvent.stopPropagation(); + + let kb = new Keybinding(keyEvent.asKeybinding()); + switch (kb.value) { + case CommonKeybindings.ENTER: + if (this._lastKeybinding) { + this._onAccepted(this._lastKeybinding.toUserSettingsLabel()); + } + this._stop(); + return; + + case CommonKeybindings.ESCAPE: + this._stop(); + return; + } + + this._lastKeybinding = kb; + + this._outputNode.innerText = this._lastKeybinding.toUserSettingsLabel().toLowerCase(); + this._outputNode.title = 'keyCode: ' + keyEvent.browserEvent.keyCode; + })); + + this._toDispose.push(DomUtils.addDisposableListener(this._inputNode, 'blur', (e) => this._stop())); + + this._editor.addContentWidget(this); + } + + public dispose(): void { + this._editor.removeContentWidget(this); + this._toDispose = disposeAll(this._toDispose); + } + + public getId(): string { + return DefineKeybindingWidget.ID; + } + + public getDomNode(): HTMLElement { + return this._domNode; + } + + public getPosition(): EditorBrowser.IContentWidgetPosition { + if (!this._position) { + return null; + } + return { + position: this._position, + preference: [EditorBrowser.ContentWidgetPositionPreference.BELOW] + }; + } + + public start(): void { + this._position = this._editor.getPosition(); + this._editor.revealPositionInCenterIfOutsideViewport(this._position); + this._editor.layoutContentWidget(this); + + // Force a view render + this._editor.getOffsetForColumn(this._position.lineNumber, this._position.column); + + this._lastKeybinding = null; + this._outputNode.innerText = ''; + this._outputNode.title = ''; + this._inputNode.focus(); + } + + private _stop(): void { + this._editor.focus(); + this._position = null; + this._editor.layoutContentWidget(this); + } +} + +export class DefineKeybindingAction extends EditorAction { + + static ID = 'editor.action.defineKeybinding'; + + constructor(descriptor:EditorCommon.IEditorActionDescriptorData, editor:EditorCommon.ICommonCodeEditor, @INullService ns) { + super(descriptor, editor, Behaviour.WidgetFocus | Behaviour.UpdateOnModelChange | Behaviour.Writeable); + } + + public isSupported(): boolean { + if (!super.isSupported()) { + return false; + } + return isInterestingEditorModel(this.editor); + } + + public run(): TPromise { + var controller = DefineKeybindingController.get(this.editor); + controller.launch(); + return TPromise.as(true); + } + +} + +const INTERESTING_FILE = /keybindings\.json$/; +function isInterestingEditorModel(editor:EditorCommon.ICommonCodeEditor): boolean { + let model = editor.getModel(); + if (!model) { + return false; + } + let url = model.getAssociatedResource().toString(); + return INTERESTING_FILE.test(url); +} + +EditorBrowserRegistry.registerEditorContribution(DefineKeybindingController); +CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(DefineKeybindingAction, DefineKeybindingAction.ID, nls.localize('DefineKeybindingAction',"Define Keybinding"), { + context: ContextKey.EditorFocus, + primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_K) +})); \ No newline at end of file diff --git a/src/vs/platform/keybinding/common/commonKeybindingResolver.ts b/src/vs/platform/keybinding/common/commonKeybindingResolver.ts index c61aa57a480..e0ffc6af39d 100644 --- a/src/vs/platform/keybinding/common/commonKeybindingResolver.ts +++ b/src/vs/platform/keybinding/common/commonKeybindingResolver.ts @@ -404,15 +404,7 @@ export class IOSupport { } private static writeKeybinding(input: number): string { - var r = Keybinding.toUserSettingsLabel(input).toLowerCase().replace(/arrow/g, ''); - - if (Platform.isMacintosh) { - r = r.replace(/meta/g, 'cmd'); - } else if (Platform.isWindows) { - r = r.replace(/meta/g, 'win'); - } - - return r; + return Keybinding.toUserSettingsLabel(input); } public static readKeybinding(input: string): number { From bac062f890be7eb4387a940a527afa8230f0b16f Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 26 Nov 2015 16:33:33 +0100 Subject: [PATCH 133/588] debug: move getFullExpressionName to debugModel. --- .../parts/debug/browser/debugActions.ts | 31 ++----------------- .../parts/debug/common/debugModel.ts | 27 ++++++++++++++++ 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugActions.ts b/src/vs/workbench/parts/debug/browser/debugActions.ts index e22b376cc26..538c4d86b4e 100644 --- a/src/vs/workbench/parts/debug/browser/debugActions.ts +++ b/src/vs/workbench/parts/debug/browser/debugActions.ts @@ -411,7 +411,7 @@ export class CopyValueAction extends AbstractDebugAction { if (this.value instanceof model.Variable) { const frameId = this.debugService.getViewModel().getFocusedStackFrame().frameId; const session = this.debugService.getActiveSession(); - return session.evaluate({ expression: getFullName(this.value, session.getType()), frameId }).then(result => { + return session.evaluate({ expression: model.getFullExpressionName(this.value, session.getType()), frameId }).then(result => { clipboard.writeText(result.body.result); }, err => clipboard.writeText(this.value.value)); } @@ -539,7 +539,7 @@ export class AddToWatchExpressionsAction extends AbstractDebugAction { } public run(): Promise { - return this.debugService.addWatchExpression(getFullName(this.expression, this.debugService.getActiveSession().getType())); + return this.debugService.addWatchExpression(model.getFullExpressionName(this.expression, this.debugService.getActiveSession().getType())); } } @@ -617,30 +617,3 @@ export class ClearReplAction extends baseeditor.EditorInputAction { return Promise.as(null); } } - -function getFullName(expression: debug.IExpression, sessionType: string): string { - let names = [expression.name]; - if (expression instanceof model.Variable) { - var v = ( expression).parent; - while (v instanceof model.Variable || v instanceof model.Expression) { - names.push(( v).name); - v = ( v).parent; - } - } - names = names.reverse(); - - let result = null; - const propertySyntax = /^[a-zA-Z_][a-zA-Z0-9_]*$/; - names.forEach(name => { - if (!result) { - result = name; - } else if (sessionType === 'node' && !propertySyntax.test(name)) { - // Use safe way to access node properties a['property_name']. Also handles array elements. - result = name && name.indexOf('[') === 0 ? `${ result }${ name }` : `${ result }['${ name }']`; - } else { - result = `${ result }.${ name }`; - } - }); - - return result; -} diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index 792a26ade46..3f608850c6e 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -33,6 +33,33 @@ function massageValue(value: string): string { return value ? value.replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\t/g, '\\t') : value; } +export function getFullExpressionName(expression: debug.IExpression, sessionType: string): string { + let names = [expression.name]; + if (expression instanceof Variable) { + var v = ( expression).parent; + while (v instanceof Variable || v instanceof Expression) { + names.push(( v).name); + v = ( v).parent; + } + } + names = names.reverse(); + + let result = null; + const propertySyntax = /^[a-zA-Z_][a-zA-Z0-9_]*$/; + names.forEach(name => { + if (!result) { + result = name; + } else if (sessionType === 'node' && !propertySyntax.test(name)) { + // Use safe way to access node properties a['property_name']. Also handles array elements. + result = name && name.indexOf('[') === 0 ? `${ result }${ name }` : `${ result }['${ name }']`; + } else { + result = `${ result }.${ name }`; + } + }); + + return result; +} + export class Thread implements debug.IThread { public exception: boolean; From 0838482b15ab856321e6633587528d1083a7d9b7 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 26 Nov 2015 17:35:27 +0100 Subject: [PATCH 134/588] debug: more model tests. --- .../parts/debug/common/debugModel.ts | 2 +- .../debug/test/common/debugModel.test.ts | 90 +++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index 3f608850c6e..d9f1828420c 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -100,7 +100,7 @@ export class KeyValueOutputElement extends OutputElement { private children: debug.ITreeElement[]; private _valueName: string; - constructor(public key: string, public valueObj: any, public annotation?: string, grouped?) { + constructor(public key: string, public valueObj: any, public annotation?: string, grouped?: boolean) { super(grouped); this._valueName = null; diff --git a/src/vs/workbench/parts/debug/test/common/debugModel.test.ts b/src/vs/workbench/parts/debug/test/common/debugModel.test.ts index 6d9e3fa1e60..fd96ea09fe8 100644 --- a/src/vs/workbench/parts/debug/test/common/debugModel.test.ts +++ b/src/vs/workbench/parts/debug/test/common/debugModel.test.ts @@ -5,6 +5,7 @@ import assert = require('assert'); import uri from 'vs/base/common/uri'; +import severity from 'vs/base/common/severity'; import debug = require('vs/workbench/parts/debug/common/debug'); import debugmodel = require('vs/workbench/parts/debug/common/debugModel'); @@ -88,4 +89,93 @@ suite('Debug - Model', () => { model.clearThreads(true); assert.equal(model.getThreads[threadId], null); }); + + // Expressions + + function assertWatchExpressions(watchExpressions: debugmodel.Expression[], expectedName: string) { + assert.equal(watchExpressions.length, 2); + watchExpressions.forEach(we => { + assert.equal(we.available, false); + assert.equal(we.reference, 0); + assert.equal(we.name, expectedName); + }); + } + + test('watch expressions', () => { + const stackFrame = new debugmodel.StackFrame(1, 1, null, 'app.js', 1, 1); + model.addWatchExpression(null, stackFrame, 'console').done(); + model.addWatchExpression(null, stackFrame, 'console').done(); + const watchExpressions = model.getWatchExpressions(); + assertWatchExpressions(watchExpressions, 'console'); + + model.renameWatchExpression(null, stackFrame, watchExpressions[0].getId(), 'new_name').done(); + model.renameWatchExpression(null, stackFrame, watchExpressions[1].getId(), 'new_name').done(); + assertWatchExpressions(model.getWatchExpressions(), 'new_name'); + + model.clearWatchExpressionValues(); + assertWatchExpressions(model.getWatchExpressions(), 'new_name'); + + model.clearWatchExpressions(); + assert.equal(model.getWatchExpressions().length, 0); + }); + + test('repl expressions', () => { + const stackFrame = new debugmodel.StackFrame(1, 1, null, 'app.js', 1, 1); + model.addReplExpression(null, stackFrame, 'myVariable').done(); + model.addReplExpression(null, stackFrame, 'myVariable').done(); + model.addReplExpression(null, stackFrame, 'myVariable').done(); + + assert.equal(model.getReplElements().length, 3); + model.getReplElements().forEach(re => { + assert.equal(( re).available, false); + assert.equal(( re).name, 'myVariable'); + assert.equal(( re).reference, 0); + }); + + model.clearReplExpressions(); + assert.equal(model.getReplElements().length, 0); + }); + + // Repl output + + test('repl output', () => { + model.logToRepl('first line', severity.Error); + model.logToRepl('second line', severity.Warning); + model.logToRepl('second line', severity.Warning); + model.logToRepl('second line', severity.Error); + + let elements = model.getReplElements(); + assert.equal(elements.length, 3); + assert.equal(elements[0].value, 'first line'); + assert.equal(elements[0].counter, 1); + assert.equal(elements[0].severity, severity.Error); + assert.equal(elements[0].grouped, false); + assert.equal(elements[1].value, 'second line'); + assert.equal(elements[1].counter, 2); + assert.equal(elements[1].severity, severity.Warning); + assert.equal(elements[1].grouped, false); + + model.appendReplOutput('1', severity.Error); + model.appendReplOutput('2', severity.Error); + model.appendReplOutput('3', severity.Error); + elements = model.getReplElements(); + assert.equal(elements.length, 4); + assert.equal(elements[3].value, '123'); + assert.equal(elements[3].severity, severity.Error); + + const keyValueObject = { 'key1' : 2, 'key2': 'value' }; + model.logToRepl(keyValueObject); + const element = model.getReplElements()[4]; + assert.equal(element.value, 'Object'); + assert.deepEqual(element.valueObj, keyValueObject); + + model.clearReplExpressions(); + assert.equal(model.getReplElements().length, 0); + }); + + // Utils + + test('full expression name', () => { + assert.equal(true, true); + }); }); From b33692968642af56e189b6eb8249ac3a7e27fa01 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 26 Nov 2015 18:28:01 +0100 Subject: [PATCH 135/588] Dispose inputBox properly (fixes #656) --- src/vs/base/browser/ui/inputbox/inputBox.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/base/browser/ui/inputbox/inputBox.ts b/src/vs/base/browser/ui/inputbox/inputBox.ts index 77c198e4600..70051e5d296 100644 --- a/src/vs/base/browser/ui/inputbox/inputBox.ts +++ b/src/vs/base/browser/ui/inputbox/inputBox.ts @@ -343,6 +343,9 @@ export class InputBox extends ee.EventEmitter { } public dispose(): void { + + this.toDispose = lifecycle.disposeAll(this.toDispose); + this._hideMessage(); this.element = null; From 9ea057a6cca51c50255e7beef927ce9b9ae086bc Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 26 Nov 2015 18:27:38 +0100 Subject: [PATCH 136/588] debug: full expression name test. --- .../parts/debug/test/common/debugModel.test.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/test/common/debugModel.test.ts b/src/vs/workbench/parts/debug/test/common/debugModel.test.ts index fd96ea09fe8..afcdd5a5b1b 100644 --- a/src/vs/workbench/parts/debug/test/common/debugModel.test.ts +++ b/src/vs/workbench/parts/debug/test/common/debugModel.test.ts @@ -102,6 +102,7 @@ suite('Debug - Model', () => { } test('watch expressions', () => { + assert.equal(model.getWatchExpressions().length, 0); const stackFrame = new debugmodel.StackFrame(1, 1, null, 'app.js', 1, 1); model.addWatchExpression(null, stackFrame, 'console').done(); model.addWatchExpression(null, stackFrame, 'console').done(); @@ -120,6 +121,7 @@ suite('Debug - Model', () => { }); test('repl expressions', () => { + assert.equal(model.getReplElements().length, 0); const stackFrame = new debugmodel.StackFrame(1, 1, null, 'app.js', 1, 1); model.addReplExpression(null, stackFrame, 'myVariable').done(); model.addReplExpression(null, stackFrame, 'myVariable').done(); @@ -176,6 +178,14 @@ suite('Debug - Model', () => { // Utils test('full expression name', () => { - assert.equal(true, true); + const type = 'node'; + assert.equal(debugmodel.getFullExpressionName(new debugmodel.Expression(null, false), type), null); + assert.equal(debugmodel.getFullExpressionName(new debugmodel.Expression('son', false), type), 'son'); + + const son = new debugmodel.Variable(new debugmodel.Variable(new debugmodel.Variable(null, 0, 'grandfather', '75'), 0, 'father', '45'), 0, 'son', '20'); + assert.equal(debugmodel.getFullExpressionName(son, type), 'grandfather.father.son'); + + const grandson = new debugmodel.Variable(son, 0, '/weird_name', '1'); + assert.equal(debugmodel.getFullExpressionName(grandson, type), 'grandfather.father.son[\'/weird_name\']'); }); }); From 0f5afc9ee578bf79d8dbaf0ca0c09e7936bb7e5e Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 26 Nov 2015 14:41:50 +0100 Subject: [PATCH 137/588] cleanup gitApp --- .../parts/git/electron-browser/gitApp.ts | 59 +++++++------------ 1 file changed, 21 insertions(+), 38 deletions(-) diff --git a/src/vs/workbench/parts/git/electron-browser/gitApp.ts b/src/vs/workbench/parts/git/electron-browser/gitApp.ts index 0b81bf5eb6d..6de5d1800ae 100644 --- a/src/vs/workbench/parts/git/electron-browser/gitApp.ts +++ b/src/vs/workbench/parts/git/electron-browser/gitApp.ts @@ -10,54 +10,37 @@ import uri from 'vs/base/common/uri'; import gitlib = require('vs/workbench/parts/git/node/git.lib'); import rawgitservice = require('vs/workbench/parts/git/node/rawGitService'); -import path = require('path'); -import fs = require('fs'); +import { join, dirname, normalize } from 'path'; +import { tmpdir } from 'os'; +import { writeFileSync } from 'fs'; -class NativeRawGitService extends rawgitservice.RawGitService { +class IPCRawGitService extends rawgitservice.RawGitService { constructor(gitPath: string, basePath: string, defaultEncoding: string, exePath: string) { if (!gitPath) { super(null); - return; - } + } else { + const gitRootPath = uri.parse(require.toUrl('vs/workbench/parts/git/electron-main')).fsPath; + const bootstrapPath = `${ uri.parse(require.toUrl('bootstrap')).fsPath }.js`; - var gitRootPath = uri.parse(require.toUrl('vs/workbench/parts/git/electron-main')).fsPath; + const env = objects.assign({}, process.env, { + GIT_ASKPASS: join(gitRootPath, 'askpass.sh'), + VSCODE_GIT_ASKPASS_BOOTSTRAP: bootstrapPath, + VSCODE_GIT_ASKPASS_NODE: exePath, + VSCODE_GIT_ASKPASS_MODULE_ID: 'vs/workbench/parts/git/electron-main/askpass' + }); - var env = objects.assign(objects.assign({}, process.env), { - GIT_ASKPASS: path.join(gitRootPath, 'askpass.sh'), - VSCODE_GIT_ASKPASS_BOOTSTRAP: path.join(path.dirname(path.dirname(path.dirname(path.dirname(path.dirname(gitRootPath))))), 'bootstrap.js'), - VSCODE_GIT_ASKPASS_NODE: exePath, - VSCODE_GIT_ASKPASS_MODULE_ID: 'vs/workbench/parts/git/electron-main/askpass' - }); + const git = new gitlib.Git({ + gitPath: gitPath, + tmpPath: tmpdir(), + defaultEncoding: defaultEncoding, + env: env + }); - var git = new gitlib.Git({ - gitPath: gitPath, - tmpPath: tmpdirSync(), // TODO@Joao os.tmpdir()??? - defaultEncoding: defaultEncoding, - env: env - }); - - super(git.open(path.normalize(basePath))); - } -} - -function tmpdirSync(): string { - var path: string; - var paths = /^win/i.test(process.platform) ? [process.env.TMP, process.env.TEMP] : ['/tmp', '/var/tmp', '/private/tmp', '/private/var/tmp']; - - for (var i = 0; i < paths.length; i++) { - path = paths[i]; - try { - if (fs.statSync(path).isDirectory()) { - return path; - } - } catch (e) { - // Ignore + super(git.open(normalize(basePath))); } } - - throw new Error('Temp dir not found'); } const server = new Server(); -server.registerService('GitService', new NativeRawGitService(process.argv[2], process.argv[3], process.argv[4], process.argv[5])); \ No newline at end of file +server.registerService('GitService', new IPCRawGitService(process.argv[2], process.argv[3], process.argv[4], process.argv[5])); \ No newline at end of file From 93cdd4740cc4c91945b0ab7a556303cedb66251e Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 26 Nov 2015 14:55:48 +0100 Subject: [PATCH 138/588] cleanup git lib --- src/vs/workbench/parts/git/node/git.lib.ts | 244 ++++++++++----------- 1 file changed, 121 insertions(+), 123 deletions(-) diff --git a/src/vs/workbench/parts/git/node/git.lib.ts b/src/vs/workbench/parts/git/node/git.lib.ts index e55d21b2aab..b8ae281c39a 100644 --- a/src/vs/workbench/parts/git/node/git.lib.ts +++ b/src/vs/workbench/parts/git/node/git.lib.ts @@ -2,10 +2,8 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import winjs = require('vs/base/common/winjs.base'); +import { Promise, TPromise } from 'vs/base/common/winjs.base'; import extfs = require('vs/base/node/extfs'); import { guessMimeTypes, isBinaryMime } from 'vs/base/common/mime'; import objects = require('vs/base/common/objects'); @@ -15,8 +13,7 @@ import strings = require('vs/base/common/strings'); import { IRawFileStatus, IHead, ITag, IBranch, GitErrorCodes } from 'vs/workbench/parts/git/common/git'; import { detectMimesFromStream } from 'vs/base/node/mime' import files = require('vs/platform/files/common/files'); - -import cp = require('child_process'); +import { spawn, ChildProcess } from 'child_process'; import iconv = require('iconv-lite'); export interface IExecutionResult { @@ -62,7 +59,7 @@ export class GitError { } public toString(): string { - var result = this.message + ' ' + JSON.stringify({ + let result = this.message + ' ' + JSON.stringify({ exitCode: this.exitCode, gitErrorCode: this.gitErrorCode, gitCommand: this.gitCommand, @@ -97,19 +94,19 @@ export class Git { this.gitPath = options.gitPath; this.tmpPath = options.tmpPath; - var encoding = options.defaultEncoding || 'utf8'; + const encoding = options.defaultEncoding || 'utf8'; this.defaultEncoding = iconv.encodingExists(encoding) ? encoding : 'utf8'; this.env = options.env || {}; this.outputListeners = []; } - public run(cwd: string, args: string[], options: any = {}): winjs.TPromise { + public run(cwd: string, args: string[], options: any = {}): TPromise { options = objects.assign({ cwd: cwd }, options || {}); return this.exec(args, options); } - public stream(cwd: string, args: string[], options: any = {}): cp.ChildProcess { + public stream(cwd: string, args: string[], options: any = {}): ChildProcess { options = objects.assign({ cwd: cwd }, options || {}); return this.spawn(args, options); } @@ -118,9 +115,9 @@ export class Git { return new Repository(this, repository, this.defaultEncoding, env); } - public clone(repository: string, repoURL: string): winjs.TPromise { + public clone(repository: string, repoURL: string): TPromise { return this.exec(['clone', repoURL, repository]).then(() => true, (err) => { - return new winjs.TPromise((c, e) => { + return new TPromise((c, e) => { // If there's any error, git will still leave the folder in the FS, // so we need to remove it. @@ -132,41 +129,41 @@ export class Git { }); } - public config(name: string, value: string): winjs.Promise { + public config(name: string, value: string): Promise { return this.exec(['config', '--global', name, value]); } - private exec(args: string[], options: any = {}): winjs.TPromise { - var child = this.spawn(args, options); + private exec(args: string[], options: any = {}): TPromise { + const child = this.spawn(args, options); if (options.input) { child.stdin.end(options.input, 'utf8'); } - return winjs.TPromise.join([ - new winjs.TPromise((c, e) => { - child.on('error', e); - child.on('exit', c); + return TPromise.join([ + new TPromise((c, e) => { + child.once('error', e); + child.once('exit', c); }), - new winjs.TPromise((c) => { - var buffer:string = ''; + new TPromise(c => { + let buffer:string = ''; child.stdout.setEncoding('utf8'); child.stdout.on('data', (data: string) => buffer += data); - child.stdout.on('close', () => c(buffer)); + child.stdout.once('close', () => c(buffer)); }), - new winjs.TPromise((c) => { - var buffer:string = ''; + new TPromise(c => { + let buffer:string = ''; child.stderr.setEncoding('utf8'); child.stderr.on('data', (data: string) => buffer += data); - child.stderr.on('close', () => c(buffer)); + child.stderr.once('close', () => c(buffer)); }) ]).then((values) => { - var exitCode = values[0]; - var stdout = values[1]; - var stderr = values[2]; + const exitCode = values[0]; + const stdout = values[1]; + const stderr = values[2]; if (exitCode) { - var gitErrorCode: string = null; + let gitErrorCode: string = null; if (/Authentication failed/.test(stderr)) { gitErrorCode = GitErrorCodes.AuthenticationFailed; @@ -184,7 +181,7 @@ export class Git { this.log(stderr); } - return winjs.TPromise.wrapError(new GitError({ + return TPromise.wrapError(new GitError({ message: 'Failed to execute git', stdout: stdout, stderr: stderr, @@ -194,7 +191,7 @@ export class Git { })); } - return winjs.TPromise.as({ + return TPromise.as({ code: values[0], stdout: values[1], stderr: values[2] @@ -202,7 +199,7 @@ export class Git { }); } - public spawn(args: string[], options: any = {}): cp.ChildProcess { + public spawn(args: string[], options: any = {}): ChildProcess { if (!this.gitPath) { throw new Error('git could not be found in the system.'); } @@ -227,7 +224,7 @@ export class Git { this.log(strings.format('git {0}\n', args.join(' '))); } - return cp.spawn(this.gitPath, args, options); + return spawn(this.gitPath, args, options); } public onOutput(listener: (output: string) => void): () => void { @@ -258,33 +255,33 @@ export class Repository { return this.repository; } - public run(args: string[], options: any = {}): winjs.TPromise { + public run(args: string[], options: any = {}): TPromise { options.env = objects.assign({}, options.env || {}); options.env = objects.assign(options.env, this.env); return this.git.run(this.repository, args, options); } - public stream(args: string[], options: any = {}): cp.ChildProcess { + public stream(args: string[], options: any = {}): ChildProcess { options.env = objects.assign({}, options.env || {}); options.env = objects.assign(options.env, this.env); return this.git.stream(this.repository, args, options); } - public spawn(args: string[], options: any = {}): cp.ChildProcess { + public spawn(args: string[], options: any = {}): ChildProcess { options.env = objects.assign({}, options.env || {}); options.env = objects.assign(options.env, this.env); return this.git.spawn(args, options); } - public init(): winjs.Promise { + public init(): Promise { return this.run(['init']); } - public config(scope: string, key:string, value:any, options:any): winjs.TPromise { - var args = ['config']; + public config(scope: string, key:string, value:any, options:any): TPromise { + const args = ['config']; if (scope) { args.push('--' + scope); @@ -299,14 +296,14 @@ export class Repository { return this.run(args, options).then((result) => result.stdout); } - public show(object: string): cp.ChildProcess { + public show(object: string): ChildProcess { return this.stream(['show', object]); } - public buffer(object: string): winjs.TPromise { - var child = this.show(object); + public buffer(object: string): TPromise { + const child = this.show(object); - return new winjs.Promise((c, e) => { + return new Promise((c, e) => { detectMimesFromStream(child.stdout, null, (err, result) => { if (err) { e(err); @@ -322,40 +319,40 @@ export class Repository { }); } - private doBuffer(object: string): winjs.TPromise { - var child = this.show(object); + private doBuffer(object: string): TPromise { + const child = this.show(object); - return winjs.TPromise.join([ - new winjs.TPromise((c, e) => { - child.on('error', e); - child.on('exit', c); + return TPromise.join([ + new TPromise((c, e) => { + child.once('error', e); + child.once('exit', c); }), - new winjs.TPromise((c) => { - var buffers: NodeBuffer[] = []; + new TPromise(c => { + const buffers: NodeBuffer[] = []; child.stdout.on('data', (b: NodeBuffer) => buffers.push(b)); - child.stdout.on('close', () => c(iconv.decode(Buffer.concat(buffers), this.defaultEncoding))); + child.stdout.once('close', () => c(iconv.decode(Buffer.concat(buffers), this.defaultEncoding))); }), - new winjs.Promise((c) => { + new Promise(c => { child.stderr.on('data', (data:string) => { /* Read to free buffer but do not handle */ }); - child.stderr.on('close', () => c(null)); + child.stderr.once('close', () => c(null)); }) ]).then((values) => { - var exitCode = values[0]; - var result = values[1]; + const exitCode = values[0]; + const result = values[1]; if (exitCode) { - return winjs.TPromise.wrapError(new GitError({ + return TPromise.wrapError(new GitError({ message: 'Could not buffer object.', exitCode: exitCode })); } - return winjs.TPromise.as(result); + return TPromise.as(result); }); } - public add(paths: string[]): winjs.Promise { - var args = ['add', '-A', '--']; + public add(paths: string[]): Promise { + const args = ['add', '-A', '--']; if (paths && paths.length) { args.push.apply(args, paths); @@ -366,31 +363,31 @@ export class Repository { return this.run(args); } - public stage(path: string, data: string): winjs.Promise { - var child = this.stream(['hash-object', '--stdin', '-w'], { stdio: [null, null, null] }); + public stage(path: string, data: string): Promise { + const child = this.stream(['hash-object', '--stdin', '-w'], { stdio: [null, null, null] }); child.stdin.end(data, 'utf8'); - return winjs.TPromise.join([ - new winjs.TPromise((c, e) => { - child.on('error', e); - child.on('exit', c); + return TPromise.join([ + new TPromise((c, e) => { + child.once('error', e); + child.once('exit', c); }), - new winjs.TPromise((c) => { - var id = ''; + new TPromise(c => { + let id = ''; child.stdout.setEncoding('utf8'); child.stdout.on('data', (data:string) => id += data); - child.stdout.on('close', () => c(id)); + child.stdout.once('close', () => c(id)); }), - new winjs.Promise((c) => { + new Promise(c => { child.stderr.on('data', (data:string) => { /* Read to free buffer but do not handle */ }); - child.stderr.on('close', () => c(null)); + child.stderr.once('close', () => c(null)); }) ]).then((values) => { - var exitCode = values[0]; - var id = values[1]; + const exitCode = values[0]; + const id = values[1]; if (exitCode) { - return winjs.TPromise.wrapError(new GitError({ + return TPromise.wrapError(new GitError({ message: 'Could not hash object.', exitCode: exitCode })); @@ -400,8 +397,8 @@ export class Repository { }); } - public checkout(treeish: string, paths: string[]): winjs.Promise { - var args = [ 'checkout', '-q' ]; + public checkout(treeish: string, paths: string[]): Promise { + const args = [ 'checkout', '-q' ]; if (treeish) { args.push(treeish); @@ -417,12 +414,12 @@ export class Repository { err.gitErrorCode = GitErrorCodes.DirtyWorkTree; } - return winjs.Promise.wrapError(err); + return Promise.wrapError(err); }); } - public commit(message: string, all: boolean, amend: boolean): winjs.Promise { - var args = ['commit', '--quiet', '--allow-empty-message', '--file', '-']; + public commit(message: string, all: boolean, amend: boolean): Promise { + const args = ['commit', '--quiet', '--allow-empty-message', '--file', '-']; if (all) { args.push('--all'); @@ -435,47 +432,47 @@ export class Repository { return this.run(args, { input: message || '' }).then(null, (commitErr: GitError) => { if (/not possible because you have unmerged files/.test(commitErr.stderr)) { commitErr.gitErrorCode = GitErrorCodes.UnmergedChanges; - return winjs.Promise.wrapError(commitErr); + return Promise.wrapError(commitErr); } return this.run(['config', '--get-all', 'user.name']).then(null, (err: GitError) => { err.gitErrorCode = GitErrorCodes.NoUserNameConfigured; - return winjs.Promise.wrapError(err); + return Promise.wrapError(err); }).then(() => { return this.run(['config', '--get-all', 'user.email']).then(null, (err: GitError) => { err.gitErrorCode = GitErrorCodes.NoUserEmailConfigured; - return winjs.Promise.wrapError(err); + return Promise.wrapError(err); }).then(() => { - return winjs.Promise.wrapError(commitErr); + return Promise.wrapError(commitErr); }); }); }); } - public branch(name: string, checkout: boolean): winjs.Promise { - var args = checkout ? ['checkout', '-q', '-b', name] : [ 'branch', '-q', name ]; + public branch(name: string, checkout: boolean): Promise { + const args = checkout ? ['checkout', '-q', '-b', name] : [ 'branch', '-q', name ]; return this.run(args); } - public clean(paths: string[]): winjs.Promise { - var args = [ 'clean', '-f', '-q', '--' ].concat(paths); + public clean(paths: string[]): Promise { + const args = [ 'clean', '-f', '-q', '--' ].concat(paths); return this.run(args); } - public undo(): winjs.Promise { + public undo(): Promise { return this.run([ 'clean', '-fd' ]).then(() => { return this.run([ 'checkout', '--', '.' ]).then(null, (err: GitError) => { if (/did not match any file\(s\) known to git\./.test(err.stderr)) { - return winjs.Promise.as(null); + return Promise.as(null); } - return winjs.Promise.wrapError(err); + return Promise.wrapError(err); }); }); } - public reset(treeish: string, hard: boolean = false): winjs.Promise { - var args = ['reset']; + public reset(treeish: string, hard: boolean = false): Promise { + const args = ['reset']; if (hard) { args.push('--hard'); @@ -486,9 +483,9 @@ export class Repository { return this.run(args); } - public revertFiles(treeish: string, paths: string[]): winjs.Promise { + public revertFiles(treeish: string, paths: string[]): Promise { return this.run([ 'branch' ]).then((result) => { - var args: string[]; + let args: string[]; // In case there are no branches, we must use rm --cached if (!result.stdout) { @@ -507,15 +504,15 @@ export class Repository { // In case there are merge conflicts to be resolved, git reset will output // some "needs merge" data. We try to get around that. if (/([^:]+: needs merge\n)+/m.test(err.stdout)) { - return winjs.Promise.as(null); + return Promise.as(null); } - return winjs.Promise.wrapError(err); + return Promise.wrapError(err); }); }); } - public fetch(): winjs.Promise { + public fetch(): Promise { return this.run(['fetch']).then(null, (err: GitError) => { if (/No remote repository specified\./.test(err.stderr)) { err.gitErrorCode = GitErrorCodes.NoRemoteRepositorySpecified; @@ -525,11 +522,11 @@ export class Repository { err.gitErrorCode = GitErrorCodes.RemoteConnectionError; } - return winjs.Promise.wrapError(err); + return Promise.wrapError(err); }); } - public pull(): winjs.Promise { + public pull(): Promise { return this.run(['pull']).then(null, (err: GitError) => { if (/^CONFLICT \([^)]+\): \b/m.test(err.stdout)) { err.gitErrorCode = GitErrorCodes.Conflict; @@ -541,11 +538,11 @@ export class Repository { err.gitErrorCode = GitErrorCodes.DirtyWorkTree; } - return winjs.Promise.wrapError(err); + return Promise.wrapError(err); }); } - public push(): winjs.Promise { + public push(): Promise { return this.run(['push']).then(null, (err: GitError) => { if (/^error: failed to push some refs to\b/m.test(err.stderr)) { err.gitErrorCode = GitErrorCodes.PushRejected; @@ -553,27 +550,28 @@ export class Repository { err.gitErrorCode = GitErrorCodes.RemoteConnectionError; } - return winjs.Promise.wrapError(err); + return Promise.wrapError(err); }); } - public sync(): winjs.Promise { + public sync(): Promise { return this.pull().then(() => this.push()); } - public getRoot(): winjs.TPromise { + public getRoot(): TPromise { return this.run(['rev-parse', '--show-toplevel'], { log: false }).then(result => result.stdout.trim()); } - public getStatus(): winjs.TPromise { + public getStatus(): TPromise { return this.run(['status', '-z', '-u'], { log: false }).then((executionResult) => { - var status = executionResult.stdout; - var result:IRawFileStatus[] = []; - var current:IRawFileStatus; - var i = 0; + const status = executionResult.stdout; + const result:IRawFileStatus[] = []; + let current:IRawFileStatus; + let i = 0; function readName():string { - var start = i, c:string; + const start = i; + let c:string; while ((c = status.charAt(i)) !== '\u0000') { i++; } return status.substring(start, i++); } @@ -603,29 +601,29 @@ export class Repository { result.push(current); } - return winjs.TPromise.as(result); + return TPromise.as(result); }); } - public getHEAD(): winjs.TPromise { + public getHEAD(): TPromise { return this.run(['symbolic-ref', '--short', 'HEAD'], { log: false }).then((result) => { if (!result.stdout) { - return winjs.TPromise.wrapError(new Error('Not in a branch')); + return TPromise.wrapError(new Error('Not in a branch')); } - return winjs.TPromise.as({ name: result.stdout.trim() }); + return TPromise.as({ name: result.stdout.trim() }); }, (err) => { return this.run(['rev-parse', 'HEAD'], { log: false }).then((result) => { if (!result.stdout) { - return winjs.TPromise.wrapError(new Error('Error parsing HEAD')); + return TPromise.wrapError(new Error('Error parsing HEAD')); } - return winjs.TPromise.as({ commit: result.stdout.trim() }); + return TPromise.as({ commit: result.stdout.trim() }); }); }); } - public getHeads(): winjs.TPromise { + public getHeads(): TPromise { return this.run(['for-each-ref', '--format', '%(refname:short) %(objectname)', 'refs/heads/'], { log: false }).then((result) => { return result.stdout.trim().split('\n') .filter(b => !!b) @@ -634,7 +632,7 @@ export class Repository { }); } - public getTags(): winjs.TPromise { + public getTags(): TPromise { return this.run(['for-each-ref', '--format', '%(refname:short) %(objectname)', 'refs/tags/'], { log: false }).then((result) => { return result.stdout.trim().split('\n') .filter(b => !!b) @@ -643,24 +641,24 @@ export class Repository { }); } - public getBranch(branch: string): winjs.TPromise { + public getBranch(branch: string): TPromise { if (branch === 'HEAD') { return this.getHEAD(); } return this.run(['rev-parse', branch], { log: false }).then((result) => { if (!result.stdout) { - return winjs.TPromise.wrapError(new Error('No such branch')); + return TPromise.wrapError(new Error('No such branch')); } - var commit = result.stdout.trim(); + const commit = result.stdout.trim(); return this.run(['rev-parse', '--symbolic-full-name', '--abbrev-ref', branch + '@{u}'], { log: false }).then((result: IExecutionResult) => { - var upstream = result.stdout.trim(); + const upstream = result.stdout.trim(); return this.run(['rev-list', '--left-right', branch + '...' + upstream], { log: false }).then((result) => { - var ahead = 0, behind = 0; - var i = 0; + let ahead = 0, behind = 0; + let i = 0; while (i < result.stdout.length) { switch (result.stdout.charAt(i)) { From a629490719573a02c2d1b3084140f4677494f7d4 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 26 Nov 2015 15:23:25 +0100 Subject: [PATCH 139/588] git lib: isolate exec --- src/vs/workbench/parts/git/node/git.lib.ts | 138 +++++++++------------ 1 file changed, 59 insertions(+), 79 deletions(-) diff --git a/src/vs/workbench/parts/git/node/git.lib.ts b/src/vs/workbench/parts/git/node/git.lib.ts index b8ae281c39a..102b012f8d5 100644 --- a/src/vs/workbench/parts/git/node/git.lib.ts +++ b/src/vs/workbench/parts/git/node/git.lib.ts @@ -6,6 +6,7 @@ import { Promise, TPromise } from 'vs/base/common/winjs.base'; import extfs = require('vs/base/node/extfs'); import { guessMimeTypes, isBinaryMime } from 'vs/base/common/mime'; +import { IDisposable, toDisposable, disposeAll } from 'vs/base/common/lifecycle'; import objects = require('vs/base/common/objects'); import uuid = require('vs/base/common/uuid'); import nls = require('vs/nls'); @@ -17,11 +18,50 @@ import { spawn, ChildProcess } from 'child_process'; import iconv = require('iconv-lite'); export interface IExecutionResult { - code: number; + exitCode: number; stdout: string; stderr: string; } +function exec(child: ChildProcess, encoding = 'utf8'): TPromise { + const disposables: IDisposable[] = []; + + const once = (ee: EventEmitter, name: string, fn: Function) => { + ee.once(name, fn); + disposables.push(toDisposable(() => ee.removeListener(name, fn))); + }; + + const on = (ee: EventEmitter, name: string, fn: Function) => { + ee.on(name, fn); + disposables.push(toDisposable(() => ee.removeListener(name, fn))); + }; + + return TPromise.join([ + new TPromise((c, e) => { + once(child, 'error', e); + once(child, 'exit', c); + }), + new TPromise(c => { + let buffers: Buffer[] = []; + on(child.stdout, 'data', b => buffers.push(b)); + once(child.stdout, 'close', () => c(Buffer.concat(buffers).toString(encoding))); + }), + new TPromise(c => { + let buffers: Buffer[] = []; + on(child.stderr, 'data', b => buffers.push(b)); + once(child.stderr, 'close', () => c(Buffer.concat(buffers).toString(encoding))); + }) + ]).then(values => { + disposeAll(disposables); + + return { + exitCode: values[0], + stdout: values[1], + stderr: values[2] + }; + }); +} + export interface IGitErrorData { error?: Error; message?: string; @@ -140,62 +180,37 @@ export class Git { child.stdin.end(options.input, 'utf8'); } - return TPromise.join([ - new TPromise((c, e) => { - child.once('error', e); - child.once('exit', c); - }), - new TPromise(c => { - let buffer:string = ''; - child.stdout.setEncoding('utf8'); - child.stdout.on('data', (data: string) => buffer += data); - child.stdout.once('close', () => c(buffer)); - }), - new TPromise(c => { - let buffer:string = ''; - child.stderr.setEncoding('utf8'); - child.stderr.on('data', (data: string) => buffer += data); - child.stderr.once('close', () => c(buffer)); - }) - ]).then((values) => { - const exitCode = values[0]; - const stdout = values[1]; - const stderr = values[2]; - - if (exitCode) { + return exec(child).then(result => { + if (result.exitCode) { let gitErrorCode: string = null; - if (/Authentication failed/.test(stderr)) { + if (/Authentication failed/.test(result.stderr)) { gitErrorCode = GitErrorCodes.AuthenticationFailed; - } else if (/bad config file/.test(stderr)) { + } else if (/bad config file/.test(result.stderr)) { gitErrorCode = GitErrorCodes.BadConfigFile; - } else if (/cannot make pipe for command substitution|cannot create standard input pipe/.test(stderr)) { + } else if (/cannot make pipe for command substitution|cannot create standard input pipe/.test(result.stderr)) { gitErrorCode = GitErrorCodes.CantCreatePipe; - } else if (/Repository not found/.test(stderr)) { + } else if (/Repository not found/.test(result.stderr)) { gitErrorCode = GitErrorCodes.RepositoryNotFound; - } else if (/unable to access/.test(stderr)) { + } else if (/unable to access/.test(result.stderr)) { gitErrorCode = GitErrorCodes.CantAccessRemote; } if (options.log !== false) { - this.log(stderr); + this.log(result.stderr); } return TPromise.wrapError(new GitError({ message: 'Failed to execute git', - stdout: stdout, - stderr: stderr, - exitCode: exitCode, - gitErrorCode: gitErrorCode, + stdout: result.stdout, + stderr: result.stderr, + exitCode: result.exitCode, + gitErrorCode, gitCommand: args[0] })); } - return TPromise.as({ - code: values[0], - stdout: values[1], - stderr: values[2] - }); + return result; }); } @@ -322,32 +337,15 @@ export class Repository { private doBuffer(object: string): TPromise { const child = this.show(object); - return TPromise.join([ - new TPromise((c, e) => { - child.once('error', e); - child.once('exit', c); - }), - new TPromise(c => { - const buffers: NodeBuffer[] = []; - child.stdout.on('data', (b: NodeBuffer) => buffers.push(b)); - child.stdout.once('close', () => c(iconv.decode(Buffer.concat(buffers), this.defaultEncoding))); - }), - new Promise(c => { - child.stderr.on('data', (data:string) => { /* Read to free buffer but do not handle */ }); - child.stderr.once('close', () => c(null)); - }) - ]).then((values) => { - const exitCode = values[0]; - const result = values[1]; - + return exec(child, this.defaultEncoding).then(({ exitCode, stdout }) => { if (exitCode) { return TPromise.wrapError(new GitError({ message: 'Could not buffer object.', - exitCode: exitCode + exitCode })); } - return TPromise.as(result); + return TPromise.as(stdout); }); } @@ -367,25 +365,7 @@ export class Repository { const child = this.stream(['hash-object', '--stdin', '-w'], { stdio: [null, null, null] }); child.stdin.end(data, 'utf8'); - return TPromise.join([ - new TPromise((c, e) => { - child.once('error', e); - child.once('exit', c); - }), - new TPromise(c => { - let id = ''; - child.stdout.setEncoding('utf8'); - child.stdout.on('data', (data:string) => id += data); - child.stdout.once('close', () => c(id)); - }), - new Promise(c => { - child.stderr.on('data', (data:string) => { /* Read to free buffer but do not handle */ }); - child.stderr.once('close', () => c(null)); - }) - ]).then((values) => { - const exitCode = values[0]; - const id = values[1]; - + return exec(child).then(({ exitCode, stdout }) => { if (exitCode) { return TPromise.wrapError(new GitError({ message: 'Could not hash object.', @@ -393,7 +373,7 @@ export class Repository { })); } - return this.run(['update-index', '--cacheinfo', '100644', id, path]); + return this.run(['update-index', '--cacheinfo', '100644', stdout, path]); }); } From b0e69a968f4d6c099cfb8cfd51bc9aa49bb9d62d Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 26 Nov 2015 15:45:57 +0100 Subject: [PATCH 140/588] isolate RawGitServiceWrapper --- .../electron-browser/electronGitService.ts | 96 +---------- .../workbench/parts/git/node/rawGitService.ts | 151 ++++++++++++++---- 2 files changed, 124 insertions(+), 123 deletions(-) diff --git a/src/vs/workbench/parts/git/electron-browser/electronGitService.ts b/src/vs/workbench/parts/git/electron-browser/electronGitService.ts index 2323c3ba04d..118ff966d2f 100644 --- a/src/vs/workbench/parts/git/electron-browser/electronGitService.ts +++ b/src/vs/workbench/parts/git/electron-browser/electronGitService.ts @@ -17,7 +17,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IMessageService } from 'vs/platform/message/common/message'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { Client } from 'vs/base/node/service.cp'; -import { RawGitService } from 'vs/workbench/parts/git/node/rawGitService'; +import { RawGitService, RawGitServiceWrapper } from 'vs/workbench/parts/git/node/rawGitService'; import URI from 'vs/base/common/uri'; import { spawn, exec } from 'child_process'; import { join } from 'path'; @@ -102,14 +102,14 @@ class DisabledRawGitService extends RawGitService { } } -export function createNativeRawGitService(basePath: string, gitPath: string, defaultEncoding: string): Promise { +export function createNativeRawGitService(workspaceRoot: string, gitPath: string, defaultEncoding: string): Promise { return findGit(gitPath).then(gitPath => { const client = new Client( URI.parse(require.toUrl('bootstrap')).fsPath, { serverName: 'Git', timeout: 1000 * 60, - args: [gitPath, basePath, defaultEncoding, remote.process.execPath], + args: [gitPath, workspaceRoot, defaultEncoding, remote.process.execPath], env: { ATOM_SHELL_INTERNAL_RUN_AS_NODE: 1, PIPE_LOGGING: 'true', @@ -122,12 +122,9 @@ export function createNativeRawGitService(basePath: string, gitPath: string, def }, () => new UnavailableRawGitService()); } -class ElectronRawGitService implements IRawGitService { - - private raw: TPromise; - - constructor(basePath: string, @IConfigurationService configurationService: IConfigurationService) { - this.raw = configurationService.loadConfiguration().then(conf => { +class ElectronRawGitService extends RawGitServiceWrapper { + constructor(workspaceRoot: string, @IConfigurationService configurationService: IConfigurationService) { + super(configurationService.loadConfiguration().then(conf => { var enabled = conf.git ? conf.git.enabled : true; if (!enabled) { @@ -137,89 +134,12 @@ class ElectronRawGitService implements IRawGitService { var gitPath = (conf.git && conf.git.path) || null; var encoding = (conf.files && conf.files.encoding) || 'utf8'; - return createNativeRawGitService(basePath, gitPath, encoding); - }); - } - - public serviceState(): TPromise { - return this.raw.then(raw => raw.serviceState()); - } - - public status(): TPromise { - return this.raw.then(raw => raw.status()); - } - - public init(): TPromise { - return this.raw.then(raw => raw.init()); - } - - public add(filesPaths?: string[]): TPromise { - return this.raw.then(raw => raw.add(filesPaths)); - } - - public stage(filePath: string, content: string): TPromise { - return this.raw.then(raw => raw.stage(filePath, content)); - } - - public branch(name: string, checkout?: boolean): TPromise { - return this.raw.then(raw => raw.branch(name, checkout)); - } - - public checkout(treeish?: string, filePaths?: string[]): TPromise { - return this.raw.then(raw => raw.checkout(treeish, filePaths)); - } - - public clean(filePaths: string[]): TPromise { - return this.raw.then(raw => raw.clean(filePaths)); - } - - public undo(): TPromise { - return this.raw.then(raw => raw.undo()); - } - - public reset(treeish: string, hard?: boolean): TPromise { - return this.raw.then(raw => raw.reset(treeish, hard)); - } - - public revertFiles(treeish: string, filePaths?: string[]): TPromise { - return this.raw.then(raw => raw.revertFiles(treeish, filePaths)); - } - - public fetch(): TPromise { - return this.raw.then(raw => raw.fetch()); - } - - public pull(): TPromise { - return this.raw.then(raw => raw.pull()); - } - - public push(): TPromise { - return this.raw.then(raw => raw.push()); - } - - public sync(): TPromise { - return this.raw.then(raw => raw.sync()); - } - - public commit(message: string, amend?: boolean, stage?: boolean): TPromise { - return this.raw.then(raw => raw.commit(message, amend, stage)); - } - - public detectMimetypes(path: string, treeish?: string): TPromise { - return this.raw.then(raw => raw.detectMimetypes(path, treeish)); - } - - public show(path: string, treeish?: string): TPromise { - return this.raw.then(raw => raw.show(path, treeish)); - } - - public onOutput(): Promise { - return this.raw.then(raw => raw.onOutput()); + return createNativeRawGitService(workspaceRoot, gitPath, encoding); + })); } } export class ElectronGitService extends GitService { - constructor( @IInstantiationService instantiationService: IInstantiationService, @IEventService eventService: IEventService, diff --git a/src/vs/workbench/parts/git/node/rawGitService.ts b/src/vs/workbench/parts/git/node/rawGitService.ts index 18cbd3c63b3..0ac864d54f9 100644 --- a/src/vs/workbench/parts/git/node/rawGitService.ts +++ b/src/vs/workbench/parts/git/node/rawGitService.ts @@ -5,7 +5,7 @@ 'use strict'; import path = require('path'); -import winjs = require('vs/base/common/winjs.base'); +import { TPromise, Promise } from 'vs/base/common/winjs.base'; import mime = require('vs/base/node/mime'); import pfs = require('vs/base/node/pfs'); import { Repository, GitError } from 'vs/workbench/parts/git/node/git.lib'; @@ -23,21 +23,21 @@ function pathsAreEqual(p1: string, p2: string): boolean { export class RawGitService implements IRawGitService { private repo: Repository; - private repoRealRootPath: winjs.TPromise; + private repoRealRootPath: TPromise; constructor(repo: Repository) { this.repo = repo; this.repoRealRootPath = null; } - public serviceState(): winjs.TPromise { - return winjs.TPromise.as(this.repo + public serviceState(): TPromise { + return TPromise.as(this.repo ? RawServiceState.OK : RawServiceState.GitNotFound ); } - public status(): winjs.TPromise { + public status(): TPromise { return this.checkRoot() .then(() => this.repo.getStatus()) .then(status => this.repo.getHEAD() @@ -48,7 +48,7 @@ export class RawGitService implements IRawGitService { return HEAD; } }, (): IHead => null) - .then(HEAD => winjs.Promise.join([this.repo.getHeads(), this.repo.getTags()]).then(r => { + .then(HEAD => Promise.join([this.repo.getHeads(), this.repo.getTags()]).then(r => { return { status: status, HEAD: HEAD, @@ -58,75 +58,75 @@ export class RawGitService implements IRawGitService { }))) .then(null, (err) => { if (err.gitErrorCode === GitErrorCodes.BadConfigFile) { - return winjs.Promise.wrapError(err); + return Promise.wrapError(err); } else if (err.gitErrorCode === GitErrorCodes.NotAtRepositoryRoot) { - return winjs.Promise.wrapError(err); + return Promise.wrapError(err); } return null; }); } - public init(): winjs.TPromise { + public init(): TPromise { return this.repo.init().then(() => this.status()); } - public add(filePaths?: string[]): winjs.TPromise { + public add(filePaths?: string[]): TPromise { return this.repo.add(filePaths).then(() => this.status()); } - public stage(filePath: string, content: string): winjs.TPromise { + public stage(filePath: string, content: string): TPromise { return this.repo.stage(filePath, content).then(() => this.status()); } - public branch(name: string, checkout?: boolean): winjs.TPromise { + public branch(name: string, checkout?: boolean): TPromise { return this.repo.branch(name, checkout).then(() => this.status()); } - public checkout(treeish?: string, filePaths?: string[]): winjs.TPromise { + public checkout(treeish?: string, filePaths?: string[]): TPromise { return this.repo.checkout(treeish, filePaths).then(() => this.status()); } - public clean(filePaths: string[]): winjs.TPromise { + public clean(filePaths: string[]): TPromise { return this.repo.clean(filePaths).then(() => this.status()); } - public undo(): winjs.TPromise { + public undo(): TPromise { return this.repo.undo().then(() => this.status()); } - public reset(treeish: string, hard?: boolean): winjs.TPromise { + public reset(treeish: string, hard?: boolean): TPromise { return this.repo.reset(treeish, hard).then(() => this.status()); } - public revertFiles(treeish: string, filePaths?: string[]): winjs.TPromise { + public revertFiles(treeish: string, filePaths?: string[]): TPromise { return this.repo.revertFiles(treeish, filePaths).then(() => this.status()); } - public fetch(): winjs.TPromise { + public fetch(): TPromise { return this.repo.fetch().then(null, (err) => { if (err.gitErrorCode === GitErrorCodes.NoRemoteRepositorySpecified) { - return winjs.Promise.as(null); + return Promise.as(null); } - return winjs.Promise.wrapError(err); + return Promise.wrapError(err); }).then(() => this.status()); } - public pull(): winjs.TPromise { + public pull(): TPromise { return this.repo.pull().then(() => this.status()); } - public push(): winjs.TPromise { + public push(): TPromise { return this.repo.push().then(() => this.status()); } - public sync(): winjs.TPromise { + public sync(): TPromise { return this.repo.sync().then(() => this.status()); } - public commit(message:string, amend?: boolean, stage?: boolean): winjs.TPromise { - var promise: winjs.Promise = winjs.Promise.as(null); + public commit(message:string, amend?: boolean, stage?: boolean): TPromise { + var promise: Promise = Promise.as(null); if (stage) { promise = this.repo.add(null); @@ -137,10 +137,10 @@ export class RawGitService implements IRawGitService { .then(() => this.status()); } - public detectMimetypes(filePath: string, treeish?: string): winjs.TPromise { + public detectMimetypes(filePath: string, treeish?: string): TPromise { return pfs.exists(path.join(this.repo.path, filePath)).then((exists) => { if (exists) { - return new winjs.TPromise((c, e) => { + return new TPromise((c, e) => { mime.detectMimesFromFile(path.join(this.repo.path, filePath), (err, result) => { if (err) { e(err); } else { c(result.mimes); } @@ -150,7 +150,7 @@ export class RawGitService implements IRawGitService { var child = this.repo.show(treeish + ':' + filePath); - return new winjs.TPromise((c, e) => { + return new TPromise((c, e) => { mime.detectMimesFromStream(child.stdout, filePath, (err, result) => { if (err) { e(err); } else { c(result.mimes); } @@ -160,37 +160,37 @@ export class RawGitService implements IRawGitService { } // careful, this buffers the whole object into memory - public show(filePath: string, treeish?: string): winjs.TPromise { + public show(filePath: string, treeish?: string): TPromise { treeish = treeish === '~' ? '' : treeish; return this.repo.buffer(treeish + ':' + filePath).then(null, e => { if (e instanceof GitError) { return ''; // mostly untracked files end up in a git error } - return winjs.TPromise.wrapError(e); + return TPromise.wrapError(e); }); } - public onOutput(): winjs.Promise { + public onOutput(): Promise { var cancel: () => void; - return new winjs.Promise((c, e, p) => { + return new Promise((c, e, p) => { cancel = this.repo.onOutput(p); }, () => cancel()); } - private checkRoot(): winjs.Promise { + private checkRoot(): Promise { if (!this.repoRealRootPath) { this.repoRealRootPath = pfs.realpath(this.repo.path); } return this.repo.getRoot().then(root => { - return winjs.Promise.join([ + return Promise.join([ this.repoRealRootPath, pfs.realpath(root) ]).then(paths => { if (!pathsAreEqual(paths[0], paths[1])) { - return winjs.Promise.wrapError(new GitError({ + return Promise.wrapError(new GitError({ message: 'Not at the repository root', gitErrorCode: GitErrorCodes.NotAtRepositoryRoot })); @@ -199,3 +199,84 @@ export class RawGitService implements IRawGitService { }); } } + +export class RawGitServiceWrapper implements IRawGitService { + + constructor(private raw: TPromise) { } + + public serviceState(): TPromise { + return this.raw.then(raw => raw.serviceState()); + } + + public status(): TPromise { + return this.raw.then(raw => raw.status()); + } + + public init(): TPromise { + return this.raw.then(raw => raw.init()); + } + + public add(filesPaths?: string[]): TPromise { + return this.raw.then(raw => raw.add(filesPaths)); + } + + public stage(filePath: string, content: string): TPromise { + return this.raw.then(raw => raw.stage(filePath, content)); + } + + public branch(name: string, checkout?: boolean): TPromise { + return this.raw.then(raw => raw.branch(name, checkout)); + } + + public checkout(treeish?: string, filePaths?: string[]): TPromise { + return this.raw.then(raw => raw.checkout(treeish, filePaths)); + } + + public clean(filePaths: string[]): TPromise { + return this.raw.then(raw => raw.clean(filePaths)); + } + + public undo(): TPromise { + return this.raw.then(raw => raw.undo()); + } + + public reset(treeish: string, hard?: boolean): TPromise { + return this.raw.then(raw => raw.reset(treeish, hard)); + } + + public revertFiles(treeish: string, filePaths?: string[]): TPromise { + return this.raw.then(raw => raw.revertFiles(treeish, filePaths)); + } + + public fetch(): TPromise { + return this.raw.then(raw => raw.fetch()); + } + + public pull(): TPromise { + return this.raw.then(raw => raw.pull()); + } + + public push(): TPromise { + return this.raw.then(raw => raw.push()); + } + + public sync(): TPromise { + return this.raw.then(raw => raw.sync()); + } + + public commit(message: string, amend?: boolean, stage?: boolean): TPromise { + return this.raw.then(raw => raw.commit(message, amend, stage)); + } + + public detectMimetypes(path: string, treeish?: string): TPromise { + return this.raw.then(raw => raw.detectMimetypes(path, treeish)); + } + + public show(path: string, treeish?: string): TPromise { + return this.raw.then(raw => raw.show(path, treeish)); + } + + public onOutput(): Promise { + return this.raw.then(raw => raw.onOutput()); + } +} \ No newline at end of file From ccb4e3a3586d53f7a834cc8bb02f4bb5ea690d4e Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 26 Nov 2015 18:41:15 +0100 Subject: [PATCH 141/588] stop log piping for git service --- .../workbench/parts/git/electron-browser/electronGitService.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/parts/git/electron-browser/electronGitService.ts b/src/vs/workbench/parts/git/electron-browser/electronGitService.ts index 118ff966d2f..1979e4373ff 100644 --- a/src/vs/workbench/parts/git/electron-browser/electronGitService.ts +++ b/src/vs/workbench/parts/git/electron-browser/electronGitService.ts @@ -112,7 +112,6 @@ export function createNativeRawGitService(workspaceRoot: string, gitPath: string args: [gitPath, workspaceRoot, defaultEncoding, remote.process.execPath], env: { ATOM_SHELL_INTERNAL_RUN_AS_NODE: 1, - PIPE_LOGGING: 'true', AMD_ENTRYPOINT: 'vs/workbench/parts/git/electron-browser/gitApp' } } From 8acd3bbd01bd644205502dc553d6419d27fb7349 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 26 Nov 2015 18:44:03 +0100 Subject: [PATCH 142/588] add repositoryRoot to git.IRawStatus --- src/vs/workbench/parts/git/common/git.ts | 1 + src/vs/workbench/parts/git/common/gitModel.ts | 1 + .../parts/git/common/noopGitService.ts | 1 + .../electron-browser/electronGitService.ts | 7 ++-- .../parts/git/electron-browser/gitApp.ts | 21 ++++++---- .../workbench/parts/git/node/rawGitService.ts | 39 ++++++------------- 6 files changed, 31 insertions(+), 39 deletions(-) diff --git a/src/vs/workbench/parts/git/common/git.ts b/src/vs/workbench/parts/git/common/git.ts index 9d40c76d5b6..bbf438f3a18 100644 --- a/src/vs/workbench/parts/git/common/git.ts +++ b/src/vs/workbench/parts/git/common/git.ts @@ -38,6 +38,7 @@ export interface ITag { } export interface IRawStatus { + repositoryRoot: string; state?: ServiceState; status: IRawFileStatus[]; HEAD: IBranch; diff --git a/src/vs/workbench/parts/git/common/gitModel.ts b/src/vs/workbench/parts/git/common/gitModel.ts index f535be16ff1..6b3a2229982 100644 --- a/src/vs/workbench/parts/git/common/gitModel.ts +++ b/src/vs/workbench/parts/git/common/gitModel.ts @@ -349,6 +349,7 @@ export class Model extends EventEmitter.EventEmitter implements Git.IModel { public update(status: Git.IRawStatus): void { if (!status) { status = { + repositoryRoot: null, status: [], HEAD: null, heads: [], diff --git a/src/vs/workbench/parts/git/common/noopGitService.ts b/src/vs/workbench/parts/git/common/noopGitService.ts index 9a160826506..295df50a36a 100644 --- a/src/vs/workbench/parts/git/common/noopGitService.ts +++ b/src/vs/workbench/parts/git/common/noopGitService.ts @@ -9,6 +9,7 @@ import winjs = require('vs/base/common/winjs.base'); export class NoOpGitService implements git.IRawGitService { private static STATUS:git.IRawStatus = { + repositoryRoot: null, state: git.ServiceState.NotAWorkspace, status: [], HEAD: null, diff --git a/src/vs/workbench/parts/git/electron-browser/electronGitService.ts b/src/vs/workbench/parts/git/electron-browser/electronGitService.ts index 1979e4373ff..cef426839e7 100644 --- a/src/vs/workbench/parts/git/electron-browser/electronGitService.ts +++ b/src/vs/workbench/parts/git/electron-browser/electronGitService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Promise, TPromise } from 'vs/base/common/winjs.base'; -import { IRawGitService, IRawStatus, RawServiceState } from 'vs/workbench/parts/git/common/git'; +import { RawServiceState } from 'vs/workbench/parts/git/common/git'; import { NoOpGitService } from 'vs/workbench/parts/git/common/noopGitService'; import { GitService } from 'vs/workbench/parts/git/browser/gitServices'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; @@ -12,12 +12,11 @@ import { IOutputService } from 'vs/workbench/parts/output/common/output'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IEventService } from 'vs/platform/event/common/event'; -import { IFileService } from 'vs/platform/files/common/files'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IMessageService } from 'vs/platform/message/common/message'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { Client } from 'vs/base/node/service.cp'; -import { RawGitService, RawGitServiceWrapper } from 'vs/workbench/parts/git/node/rawGitService'; +import { RawGitService, DelayedRawGitService } from 'vs/workbench/parts/git/node/rawGitService'; import URI from 'vs/base/common/uri'; import { spawn, exec } from 'child_process'; import { join } from 'path'; @@ -121,7 +120,7 @@ export function createNativeRawGitService(workspaceRoot: string, gitPath: string }, () => new UnavailableRawGitService()); } -class ElectronRawGitService extends RawGitServiceWrapper { +class ElectronRawGitService extends DelayedRawGitService { constructor(workspaceRoot: string, @IConfigurationService configurationService: IConfigurationService) { super(configurationService.loadConfiguration().then(conf => { var enabled = conf.git ? conf.git.enabled : true; diff --git a/src/vs/workbench/parts/git/electron-browser/gitApp.ts b/src/vs/workbench/parts/git/electron-browser/gitApp.ts index 6de5d1800ae..aa031d25ce6 100644 --- a/src/vs/workbench/parts/git/electron-browser/gitApp.ts +++ b/src/vs/workbench/parts/git/electron-browser/gitApp.ts @@ -4,21 +4,22 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; +import { TPromise } from 'vs/base/common/winjs.base'; import { Server } from 'vs/base/node/service.cp'; import objects = require('vs/base/common/objects'); import uri from 'vs/base/common/uri'; +import { IRawGitService } from 'vs/workbench/parts/git/common/git'; import gitlib = require('vs/workbench/parts/git/node/git.lib'); -import rawgitservice = require('vs/workbench/parts/git/node/rawGitService'); - +import { RawGitService, DelayedRawGitService } from 'vs/workbench/parts/git/node/rawGitService'; import { join, dirname, normalize } from 'path'; import { tmpdir } from 'os'; -import { writeFileSync } from 'fs'; +import { realpath } from 'vs/base/node/pfs'; -class IPCRawGitService extends rawgitservice.RawGitService { +class IPCRawGitService extends DelayedRawGitService { - constructor(gitPath: string, basePath: string, defaultEncoding: string, exePath: string) { + constructor(gitPath: string, workspaceRoot: string, defaultEncoding: string, exePath: string) { if (!gitPath) { - super(null); + super(TPromise.as(new RawGitService(null))); } else { const gitRootPath = uri.parse(require.toUrl('vs/workbench/parts/git/electron-main')).fsPath; const bootstrapPath = `${ uri.parse(require.toUrl('bootstrap')).fsPath }.js`; @@ -37,7 +38,13 @@ class IPCRawGitService extends rawgitservice.RawGitService { env: env }); - super(git.open(normalize(basePath))); + const repo = git.open(normalize(workspaceRoot)); + const promise = repo.getRoot() + .then(root => realpath(root)) + .then(root => git.open(root)) + .then(repo => new RawGitService(repo)); + + super(promise); } } } diff --git a/src/vs/workbench/parts/git/node/rawGitService.ts b/src/vs/workbench/parts/git/node/rawGitService.ts index 0ac864d54f9..0cb084750c5 100644 --- a/src/vs/workbench/parts/git/node/rawGitService.ts +++ b/src/vs/workbench/parts/git/node/rawGitService.ts @@ -23,11 +23,14 @@ function pathsAreEqual(p1: string, p2: string): boolean { export class RawGitService implements IRawGitService { private repo: Repository; - private repoRealRootPath: TPromise; + private _repositoryRoot: TPromise; constructor(repo: Repository) { this.repo = repo; - this.repoRealRootPath = null; + } + + private getRepositoryRoot(): TPromise { + return this._repositoryRoot || (this._repositoryRoot = pfs.realpath(this.repo.path)); } public serviceState(): TPromise { @@ -38,8 +41,7 @@ export class RawGitService implements IRawGitService { } public status(): TPromise { - return this.checkRoot() - .then(() => this.repo.getStatus()) + return this.repo.getStatus() .then(status => this.repo.getHEAD() .then(HEAD => { if (HEAD.name) { @@ -48,12 +50,13 @@ export class RawGitService implements IRawGitService { return HEAD; } }, (): IHead => null) - .then(HEAD => Promise.join([this.repo.getHeads(), this.repo.getTags()]).then(r => { + .then(HEAD => Promise.join([this.getRepositoryRoot(), this.repo.getHeads(), this.repo.getTags()]).then(r => { return { + repositoryRoot: r[0], status: status, HEAD: HEAD, - heads: r[0], - tags: r[1] + heads: r[1], + tags: r[2] }; }))) .then(null, (err) => { @@ -178,29 +181,9 @@ export class RawGitService implements IRawGitService { cancel = this.repo.onOutput(p); }, () => cancel()); } - - private checkRoot(): Promise { - if (!this.repoRealRootPath) { - this.repoRealRootPath = pfs.realpath(this.repo.path); - } - - return this.repo.getRoot().then(root => { - return Promise.join([ - this.repoRealRootPath, - pfs.realpath(root) - ]).then(paths => { - if (!pathsAreEqual(paths[0], paths[1])) { - return Promise.wrapError(new GitError({ - message: 'Not at the repository root', - gitErrorCode: GitErrorCodes.NotAtRepositoryRoot - })); - } - }); - }); - } } -export class RawGitServiceWrapper implements IRawGitService { +export class DelayedRawGitService implements IRawGitService { constructor(private raw: TPromise) { } From bb123ee62104297977e29e0f3c782317a5d30d40 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 26 Nov 2015 18:50:20 +0100 Subject: [PATCH 143/588] Fix AppVeyor failing build. --- src/vs/workbench/parts/debug/test/common/debugSource.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/test/common/debugSource.test.ts b/src/vs/workbench/parts/debug/test/common/debugSource.test.ts index 60bf576fccf..fcb65962c30 100644 --- a/src/vs/workbench/parts/debug/test/common/debugSource.test.ts +++ b/src/vs/workbench/parts/debug/test/common/debugSource.test.ts @@ -32,7 +32,7 @@ suite('Debug - Source', () => { assert.equal(source.name, rawSource.name); assert.equal(source.inMemory, false); assert.equal(source.reference, rawSource.sourceReference); - assert.equal(source.uri.fsPath, rawSource.path); + assert.equal(source.uri.toString(), uri.file(rawSource.path).toString()); }); test('from raw internal source', () => { From df04b1f090d038f813fcf7914021c904723dd7f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Thu, 26 Nov 2015 19:07:12 +0100 Subject: [PATCH 144/588] fix appveyor badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 24095f6f5c8..f3ef3ceca03 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Visual Studio Code - Open Source -[![Build Status](https://travis-ci.org/Microsoft/vscode.svg?branch=master)](https://travis-ci.org/Microsoft/vscode) [![Build status](https://ci.appveyor.com/api/projects/status/njqjjghtcsb3xhje?svg=true)](https://ci.appveyor.com/project/joaomoreno/vscode) +[![Build Status](https://travis-ci.org/Microsoft/vscode.svg?branch=master)](https://travis-ci.org/Microsoft/vscode) [![Build status](https://ci.appveyor.com/api/projects/status/vuhlhg80tj3e2a0l?svg=true)](https://ci.appveyor.com/project/VSCode/vscode) [VS Code](http://code.visualstudio.com) is a new type of tool that combines the simplicity of a code editor with what developers need for their core edit-build-debug cycle. Code provides comprehensive editing and debugging support, an extensibility model, and lightweight integration with existing tools. From 85269f1fe80b5ab04c0506f183111e30273abfa1 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 26 Nov 2015 19:42:42 +0100 Subject: [PATCH 145/588] debug: introduce ConfigurationManager for better code structure. --- src/vs/workbench/parts/debug/common/debug.ts | 111 ------ .../debug/electron-browser/debugService.ts | 263 +++---------- .../debug/node/debugConfigurationManager.ts | 348 ++++++++++++++++++ 3 files changed, 392 insertions(+), 330 deletions(-) create mode 100644 src/vs/workbench/parts/debug/node/debugConfigurationManager.ts diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index 232f4a64e96..efda43f0ea9 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -8,9 +8,7 @@ import uri from 'vs/base/common/uri'; import { TPromise, Promise } from 'vs/base/common/winjs.base'; import ee = require('vs/base/common/eventEmitter'); import severity from 'vs/base/common/severity'; -import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; -import pluginsRegistry = require('vs/platform/plugins/common/pluginsRegistry'); import editor = require('vs/editor/common/editorCommon'); import { Source } from 'vs/workbench/parts/debug/common/debugSource'; @@ -257,112 +255,3 @@ export function formatPII(value:string, excludePII: boolean, args: {[key: string match; }) } - -// Debuggers extension point - -export var debuggersExtPoint = pluginsRegistry.PluginsRegistry.registerExtensionPoint('debuggers', { - description: nls.localize('vscode.extension.contributes.debuggers', 'Contributes debug adapters.'), - type: 'array', - default: [{ type: '', extensions: [] }], - items: { - type: 'object', - default: { type: '', program: '', runtime: '', enableBreakpointsFor: { languageIds: [ '' ] } }, - properties: { - type: { - description: nls.localize('vscode.extension.contributes.debuggers.type', "Unique identifier for this debug adapter."), - type: 'string' - }, - label: { - description: nls.localize('vscode.extension.contributes.debuggers.label', "Display name for this debug adapter."), - type: 'string' - }, - enableBreakpointsFor: { - description: nls.localize('vscode.extension.contributes.debuggers.enableBreakpointsFor', "Allow breakpoints for these languages."), - type: 'object', - properties: { - languageIds : { - description: nls.localize('vscode.extension.contributes.debuggers.enableBreakpointsFor.languageIds', "List of languages."), - type: 'array', - items: { - type: 'string' - } - } - } - }, - program: { - description: nls.localize('vscode.extension.contributes.debuggers.program', "Path to the debug adapter program. Path is either absolute or relative to the extension folder."), - type: 'string' - }, - runtime : { - description: nls.localize('vscode.extension.contributes.debuggers.runtime', "Optional runtime in case the program attribute is not an executable but requires a runtime."), - type: 'string' - }, - runtimeArgs : { - description: nls.localize('vscode.extension.contributes.debuggers.runtimeArgs', "Optional runtime arguments."), - type: 'array' - }, - initialConfigurations: { - description: nls.localize('vscode.extension.contributes.debuggers.initialConfigurations', "Configurations for generating the initial \'launch.json\'."), - type: 'array', - }, - configurationAttributes: { - description: nls.localize('vscode.extension.contributes.debuggers.configurationAttributes', "JSON schema configurations for validating \'launch.json\'."), - type: 'object' - }, - windows: { - description: nls.localize('vscode.extension.contributes.debuggers.windows', "Windows specific settings."), - type: 'object', - properties: { - runtime : { - description: nls.localize('vscode.extension.contributes.debuggers.windows.runtime', "Runtime used for Windows."), - type: 'string' - } - } - }, - osx: { - description: nls.localize('vscode.extension.contributes.debuggers.osx', "OS X specific settings."), - type: 'object', - properties: { - runtime : { - description: nls.localize('vscode.extension.contributes.debuggers.osx.runtime', "Runtime used for OSX."), - type: 'string' - } - } - }, - linux: { - description: nls.localize('vscode.extension.contributes.debuggers.linux', "Linux specific settings."), - type: 'object', - properties: { - runtime : { - description: nls.localize('vscode.extension.contributes.debuggers.linux.runtime', "Runtime used for Linux."), - type: 'string' - } - } - } - } - } -}); - -// Debug General Schema - -export var schemaId = 'local://schemas/launch'; -export var schema: IJSONSchema = { - id: schemaId, - type: 'object', - title: nls.localize('app.launch.json.title', "Launch configuration"), - required: ['version', 'configurations'], - properties: { - version: { - type: 'string', - description: nls.localize('app.launch.json.version', "Version of this file format."), - default: '0.2.0' - }, - configurations: { - type: 'array', - description: nls.localize('app.launch.json.configurations', "List of configurations. Add new configurations or edit existing ones."), - items: { - oneOf: [] - } - } - } -} diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index cc8f53dd6ac..d0e10072c9b 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -3,33 +3,26 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import path = require('path'); import nls = require('vs/nls'); import lifecycle = require('vs/base/common/lifecycle'); import mime = require('vs/base/common/mime'); -import paths = require('vs/base/common/paths'); import ee = require('vs/base/common/eventEmitter'); import uri from 'vs/base/common/uri'; import arrays = require('vs/base/common/arrays'); -import actions = require('vs/base/common/actions'); -import json = require('vs/base/common/json'); import types = require('vs/base/common/types'); import errors = require('vs/base/common/errors'); import severity from 'vs/base/common/severity'; import { Promise, TPromise } from 'vs/base/common/winjs.base'; -import platformplatform = require('vs/platform/platform'); import editor = require('vs/editor/common/editorCommon'); import editorbrowser = require('vs/editor/browser/editorBrowser'); -import jsonContributionRegistry = require('vs/languages/json/common/jsonContributionRegistry'); import wbeditorcommon = require('vs/workbench/common/editor'); -import { SystemVariables } from 'vs/workbench/parts/lib/node/systemVariables'; import debug = require('vs/workbench/parts/debug/common/debug'); import session = require('vs/workbench/parts/debug/node/rawDebugSession'); import model = require('vs/workbench/parts/debug/common/debugModel'); import debuginputs = require('vs/workbench/parts/debug/browser/debugEditorInputs'); import viewmodel = require('vs/workbench/parts/debug/common/debugViewModel'); import debugactions = require('vs/workbench/parts/debug/browser/debugActions'); -import { Adapter } from 'vs/workbench/parts/debug/node/debugAdapter'; +import { ConfigurationManager } from 'vs/workbench/parts/debug/node/debugConfigurationManager'; import { Repl } from 'vs/workbench/parts/debug/browser/replEditor'; import { Source } from 'vs/workbench/parts/debug/common/debugSource'; import { Position } from 'vs/platform/editor/common/editor'; @@ -50,7 +43,6 @@ import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IPluginService, IPluginDescription } from 'vs/platform/plugins/common/plugins'; import { IOutputService } from 'vs/workbench/parts/output/common/output'; import { IKeybindingService, IKeybindingContextKey } from 'vs/platform/keybinding/common/keybindingService'; -import { IQuickOpenService } from 'vs/workbench/services/quickopen/browser/quickOpenService'; import { IWindowService, IBroadcast } from 'vs/workbench/services/window/electron-browser/windowService'; import { ILogEntry, PLUGIN_LOG_BROADCAST_CHANNEL } from 'vs/workbench/services/thread/electron-browser/threadService'; @@ -60,10 +52,6 @@ var DEBUG_EXCEPTION_BREAKPOINTS_KEY = 'debug.exceptionbreakpoint'; var DEBUG_WATCH_EXPRESSIONS_KEY = 'debug.watchexpressions'; var DEBUG_SELECTED_CONFIG_NAME_KEY = 'debug.selectedconfigname'; -var jsonRegistry = platformplatform.Registry.as(jsonContributionRegistry.Extensions.JSONContribution); -jsonRegistry.registerSchema(debug.schemaId, debug.schema); -jsonRegistry.addSchemaFileAssociation('/.vscode/launch.json', debug.schemaId); - export class DebugService extends ee.EventEmitter implements debug.IDebugService { public serviceId = debug.IDebugService; @@ -72,104 +60,55 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService private session: session.RawDebugSession; private model: model.Model; private viewModel: viewmodel.ViewModel; - private toDispose: lifecycle.IDisposable[]; + private configurationManager: ConfigurationManager; private debugStringEditorInputs: debuginputs.DebugStringEditorInput[]; - private systemVariables: SystemVariables; - private adapters: Adapter[]; - private allModeIdsForBreakpoints: { [key: string]: boolean }; private lastTaskEvent: TaskEvent; - private configuration: debug.IConfig; - + private toDispose: lifecycle.IDisposable[]; private inDebugMode: IKeybindingContextKey; constructor( @IStorageService private storageService: IStorageService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService, - @ITextFileService private textFileService:ITextFileService, - @IViewletService private viewletService:IViewletService, + @ITextFileService private textFileService: ITextFileService, + @IViewletService private viewletService: IViewletService, @IFileService private fileService: IFileService, @IMessageService private messageService: IMessageService, @IPartService private partService: IPartService, - @IConfigurationService private configurationService: IConfigurationService, @IWindowService private windowService: IWindowService, @ITelemetryService private telemetryService: ITelemetryService, @IWorkspaceContextService private contextService: IWorkspaceContextService, - @IKeybindingService private keybindingService: IKeybindingService, - @IEventService private eventService: IEventService, + @IKeybindingService keybindingService: IKeybindingService, + @IEventService eventService: IEventService, @ILifecycleService private lifecycleService: ILifecycleService, @IInstantiationService private instantiationService:IInstantiationService, @IPluginService private pluginService: IPluginService, - @IOutputService private outputService: IOutputService, - @IQuickOpenService private quickOpenService: IQuickOpenService + @IOutputService private outputService: IOutputService ) { super(); this.toDispose = []; this.debugStringEditorInputs = []; - this.adapters = []; - this.allModeIdsForBreakpoints = {}; this.session = null; this.state = debug.State.Inactive; // There is a cycle if taskService gets injected, use a workaround. this.taskService = this.instantiationService.getInstance(ITaskService); - if (this.contextService.getWorkspace()) { - this.systemVariables = new SystemVariables(this.editorService, this.contextService); - } else { + if (!this.contextService.getWorkspace()) { this.state = debug.State.Disabled; } + this.configurationManager = this.instantiationService.createInstance(ConfigurationManager, this.storageService.get(DEBUG_SELECTED_CONFIG_NAME_KEY, StorageScope.WORKSPACE, 'null')); this.inDebugMode = keybindingService.createKey(debug.CONTEXT_IN_DEBUG_MODE, false); this.model = new model.Model(this.loadBreakpoints(), this.storageService.getBoolean(DEBUG_BREAKPOINTS_ACTIVATED_KEY, StorageScope.WORKSPACE, true), this.loadExceptionBreakpoints(), this.loadWatchExpressions()); this.viewModel = new viewmodel.ViewModel(); - this.setConfiguration(this.storageService.get(DEBUG_SELECTED_CONFIG_NAME_KEY, StorageScope.WORKSPACE, 'null')); + this.registerListeners(eventService, lifecycleService); } private registerListeners(eventService: IEventService, lifecycleService: ILifecycleService): void { this.toDispose.push(eventService.addListener2(EventType.FILE_CHANGES, (e: FileChangesEvent) => this.onFileChanges(e))); - debug.debuggersExtPoint.setHandler((extensions) => { - extensions.forEach(extension => { - extension.value.forEach(rawAdapter => { - const adapter = new Adapter(rawAdapter, this.systemVariables, extension.description.extensionFolderPath); - const duplicate = this.adapters.filter(a => a.type === adapter.type)[0]; - if (!rawAdapter.type || (typeof rawAdapter.type !== 'string')) { - extension.collector.error(nls.localize('debugNoType', "Debug adapter 'type' can not be omitted and must be of type 'string'.")); - } - - if (duplicate) { - Object.keys(adapter).forEach(attribute => { - if (adapter[attribute]) { - if (attribute === 'enableBreakpointsFor') { - Object.keys(adapter.enableBreakpointsFor).forEach(languageId => duplicate.enableBreakpointsFor[languageId] = true); - } else if (duplicate[attribute] && attribute !== 'type') { - extension.collector.warn(nls.localize('duplicateDebuggerType', "Debug type '{0}' is already registered and has attribute '{1}', ignoring attribute '{1}'.", adapter.type, attribute)); - } else { - duplicate[attribute] = adapter[attribute]; - } - } - }); - } else { - this.adapters.push(adapter); - } - - adapter.enableBreakpointsFor.languageIds.forEach(modeId => { - this.allModeIdsForBreakpoints[modeId] = true; - }); - }); - }); - - // Update the schema to include all attributes and types from extensions. - // debug.schema.properties['configurations'].items.properties.type.enum = this.adapters.map(adapter => adapter.type); - this.adapters.forEach(adapter => { - const schemaAttributes = adapter.getSchemaAttributes(); - if (schemaAttributes) { - debug.schema.properties['configurations'].items.oneOf.push(...schemaAttributes); - } - }); - }); if (this.taskService) { this.toDispose.push(this.taskService.addListener2(TaskServiceEvents.Active, (e: TaskEvent) => { @@ -397,20 +336,6 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService } } - public canSetBreakpointsIn(model: editor.IModel, lineNumber: number): boolean { - if (model.getLineLastNonWhitespaceColumn(lineNumber) === 0) { - return false; - } - if (model.getAssociatedResource().isInMemory()) { - return false; - } - - var mode = model ? model.getMode() : null; - var modeId = mode ? mode.getId() : null; - - return !!this.allModeIdsForBreakpoints[modeId]; - } - public getState(): debug.State { return this.state; } @@ -420,120 +345,10 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService this.emit(debug.ServiceEvents.STATE_CHANGED, data); } - public openConfigFile(sideBySide: boolean): TPromise { - const resource = uri.file(paths.join(this.contextService.getWorkspace().resource.fsPath, '/.vscode/launch.json')); - - return this.fileService.resolveContent(resource).then(content => true, err => - this.getInitialConfigFileContent().then(content => { - if (!content) { - return false; - } - - return this.fileService.updateContent(resource, content).then(() => true); - } - )).then(configFileCreated => { - if (!configFileCreated) { - return false; - } - this.telemetryService.publicLog('debugConfigure'); - - return this.editorService.openEditor({ - resource: resource, - options: { - forceOpen: true - } - }, sideBySide).then(() => true); - }, (error) => { - throw new Error(nls.localize('DebugConfig.failed', "Unable to create 'launch.json' file inside the '.vscode' folder ({0}).", error)); - }); - } - public get enabled(): boolean { return !!this.contextService.getWorkspace(); } - public getConfiguration(): debug.IConfig { - return this.configuration; - } - - public setConfiguration(name: string, extensionHostData: any = null): Promise { - return this.loadLaunchConfig().then(config => { - if (!config || !config.configurations) { - this.configuration = null; - return; - } - - // If the configuration name is not set yet, take the first launch config (can happen if debug viewlet has not been opened yet). - const filtered = name ? config.configurations.filter(cfg => cfg.name === name) : [config.configurations[0]]; - - // Massage configuration attributes - append workspace path to relatvie paths, substitute variables in paths. - this.configuration = filtered.length === 1 ? filtered[0] : null; - if (this.configuration && this.systemVariables) { - this.configuration.debugServer = config.debugServer; - this.configuration.outDir = this.resolvePath(this.systemVariables.resolve(this.configuration.outDir)); - this.configuration.address = this.configuration.address || 'localhost'; - this.configuration.program = this.resolvePath(this.systemVariables.resolve(this.configuration.program)); - this.configuration.stopOnEntry = this.configuration.stopOnEntry === undefined ? false : this.configuration.stopOnEntry; - this.configuration.args = this.configuration.args && this.configuration.args.length > 0 ? this.systemVariables.resolve(this.configuration.args) : null; - this.configuration.env = <{ [key: string]: string; }> this.systemVariables.resolve(this.configuration.env); - this.configuration.cwd = this.resolvePath(this.systemVariables.resolve(this.configuration.cwd) || '.', false); - this.configuration.runtimeExecutable = this.resolvePath(this.systemVariables.resolve(this.configuration.runtimeExecutable)); - this.configuration.runtimeArgs = this.configuration.runtimeArgs && this.configuration.runtimeArgs.length > 0 ? this.systemVariables.resolve(this.configuration.runtimeArgs) : null; - this.configuration.outDir = this.resolvePath(this.configuration.outDir); - // send opaque data back as part of the (undocumented) arguments of the launch request. - this.configuration.extensionHostData = extensionHostData; - } - }); - } - - private getInitialConfigFileContent(): TPromise { - return this.quickOpenService.pick(this.adapters, { placeHolder: nls.localize('selectDebug', "Select Debug Environment") }) - .then(adapter => { - if (!adapter) { - return null; - } - - return this.massageInitialConfigurations(adapter).then(() => - JSON.stringify({ - version: '0.2.0', - configurations: adapter.initialConfigurations ? adapter.initialConfigurations : [] - }, null, '\t') - ) - }); - } - - private massageInitialConfigurations(adapter: Adapter): Promise { - if (!adapter || !adapter.initialConfigurations || adapter.type !== 'node') { - return Promise.as(true); - } - - // Check package.json for 'main' or 'scripts' so we generate a more pecise 'program' attribute in launch.json. - const packageJsonUri = uri.file(paths.join(this.contextService.getWorkspace().resource.fsPath, '/package.json')); - return this.fileService.resolveContent(packageJsonUri).then(jsonContent => { - try { - const jsonObject = JSON.parse(jsonContent.value); - if (jsonObject.main) { - return jsonObject.main; - } else if (jsonObject.scripts && typeof jsonObject.scripts.start === 'string') { - return (jsonObject.scripts.start).split(' ').pop(); - } - - } catch (error) { } - - return null; - }, err => null).then(program => { - adapter.initialConfigurations.forEach(config => { - if (program && config["program"]) { - config["program"] = program; - } - }); - }); - } - - public loadLaunchConfig(): TPromise { - return this.configurationService.loadConfiguration('launch'); - } - public setFocusedStackFrameAndEvaluate(focusedStackFrame: debug.IStackFrame): void { this.viewModel.setFocusedStackFrame(focusedStackFrame); if (focusedStackFrame) { @@ -616,31 +431,32 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService this.clearReplExpressions(); } - return this.pluginService.onReady().then(() => this.setConfiguration(this.configuration ? this.configuration.name : null, extensionHostData)).then(() => { - if (!this.configuration) { - return this.openConfigFile(false).then(openend => { + return this.pluginService.onReady().then(() => this.configurationManager.setConfiguration(this.configurationManager.getConfigurationName(), extensionHostData)).then(() => { + const configuration = this.configurationManager.getConfiguration(); + if (!configuration) { + return this.configurationManager.openConfigFile(false).then(openend => { if (openend) { this.messageService.show(severity.Info, nls.localize('NewLaunchConfig', "Please set up the launch configuration file to debug your application.")); } }); } - var adapter = this.adapters.filter(adapter => adapter.type === this.configuration.type).pop(); + const adapter = this.configurationManager.getAdapter(); if (!adapter) { - return Promise.wrapError(new Error(`Configured debug type '${ this.configuration.type }' is not supported.`)); + return Promise.wrapError(new Error(`Configured debug type '${ configuration.type }' is not supported.`)); } - return this.runPreLaunchTask(this.configuration).then(() => { - this.session = new session.RawDebugSession(this.messageService, this.telemetryService, this.configuration.debugServer, adapter); + return this.runPreLaunchTask(configuration).then(() => { + this.session = new session.RawDebugSession(this.messageService, this.telemetryService, configuration.debugServer, adapter); this.registerSessionListeners(); return this.session.initialize({ - adapterID: this.configuration.type, + adapterID: configuration.type, linesStartAt1: true, pathFormat: 'path' }).then((result: DebugProtocol.InitializeResponse) => { this.setStateAndEmit(debug.State.Initializing); - return this.configuration.request === 'attach' ? this.session.attach(this.configuration) : this.session.launch(this.configuration); + return configuration.request === 'attach' ? this.session.attach(configuration) : this.session.launch(configuration); }).then((result: DebugProtocol.Response) => { if (openViewlet) { this.viewletService.openViewlet(debug.VIEWLET_ID); @@ -651,9 +467,9 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService }); this.inDebugMode.set(true); - this.telemetryService.publicLog('debugSessionStart', { type: this.configuration.type, breakpointCount: this.model.getBreakpoints().length, exceptionBreakpoints: this.model.getExceptionBreakpoints() }); + this.telemetryService.publicLog('debugSessionStart', { type: configuration.type, breakpointCount: this.model.getBreakpoints().length, exceptionBreakpoints: this.model.getExceptionBreakpoints() }); }).then(undefined, (error: Error) => { - this.telemetryService.publicLog('debugMisconfiguration', { type: this.configuration ? this.configuration.type : undefined }); + this.telemetryService.publicLog('debugMisconfiguration', { type: configuration ? configuration.type : undefined }); if (this.session) { this.session.disconnect(); } @@ -845,6 +661,26 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService }); } + public canSetBreakpointsIn(model: editor.IModel, lineNumber: number): boolean { + return this.configurationManager.canSetBreakpointsIn(model, lineNumber); + } + + public getConfiguration(): debug.IConfig { + return this.configurationManager.getConfiguration(); + } + + public setConfiguration(name: string): Promise { + return this.configurationManager.setConfiguration(name); + } + + public openConfigFile(sideBySide: boolean): TPromise { + return this.configurationManager.openConfigFile(sideBySide); + } + + public loadLaunchConfig(): TPromise { + return this.configurationManager.loadLaunchConfig(); + } + private getDebugStringEditorInput(source: Source, value: string, mtype: string): debuginputs.DebugStringEditorInput { var filtered = this.debugStringEditorInputs.filter(input => input.getResource().toString() === source.uri.toString()); @@ -857,17 +693,6 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService } } - private resolvePath(p: string, showError = true): string { - if (!p) { - return null; - } - if (path.isAbsolute(p)) { - return paths.normalize(p, true); - } - - return paths.normalize(uri.file(paths.join(this.contextService.getWorkspace().resource.fsPath, p)).fsPath, true); - } - public sendAllBreakpoints(): Promise { return Promise.join(arrays.distinct(this.model.getBreakpoints(), bp => bp.source.uri.toString()).map(bp => this.sendBreakpoints(bp.source.uri))); } @@ -916,7 +741,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService this.storageService.store(DEBUG_BREAKPOINTS_KEY, JSON.stringify(this.model.getBreakpoints()), StorageScope.WORKSPACE); this.storageService.store(DEBUG_BREAKPOINTS_ACTIVATED_KEY, this.model.areBreakpointsActivated() ? 'true' : 'false', StorageScope.WORKSPACE); this.storageService.store(DEBUG_EXCEPTION_BREAKPOINTS_KEY, JSON.stringify(this.model.getExceptionBreakpoints()), StorageScope.WORKSPACE); - this.storageService.store(DEBUG_SELECTED_CONFIG_NAME_KEY, this.configuration ? this.configuration.name : null, StorageScope.WORKSPACE); + this.storageService.store(DEBUG_SELECTED_CONFIG_NAME_KEY, this.configurationManager.getConfigurationName(), StorageScope.WORKSPACE); this.storageService.store(DEBUG_WATCH_EXPRESSIONS_KEY, JSON.stringify(this.model.getWatchExpressions()), StorageScope.WORKSPACE); } diff --git a/src/vs/workbench/parts/debug/node/debugConfigurationManager.ts b/src/vs/workbench/parts/debug/node/debugConfigurationManager.ts new file mode 100644 index 00000000000..ec35680b64c --- /dev/null +++ b/src/vs/workbench/parts/debug/node/debugConfigurationManager.ts @@ -0,0 +1,348 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import path = require('path'); +import nls = require('vs/nls'); +import { Promise, TPromise } from 'vs/base/common/winjs.base'; +import uri from 'vs/base/common/uri'; +import paths = require('vs/base/common/paths'); +import { IJSONSchema } from 'vs/base/common/jsonSchema'; +import platform = require('vs/platform/platform'); +import pluginsRegistry = require('vs/platform/plugins/common/pluginsRegistry'); +import editor = require('vs/editor/common/editorCommon'); +import jsonContributionRegistry = require('vs/languages/json/common/jsonContributionRegistry'); +import debug = require('vs/workbench/parts/debug/common/debug'); +import { SystemVariables } from 'vs/workbench/parts/lib/node/systemVariables'; +import { Adapter } from 'vs/workbench/parts/debug/node/debugAdapter'; +import { IWorkspaceContextService } from 'vs/workbench/services/workspace/common/contextService'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IFileService } from 'vs/platform/files/common/files'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IQuickOpenService } from 'vs/workbench/services/quickopen/browser/quickOpenService'; + +// Debuggers extension point + +export var debuggersExtPoint = pluginsRegistry.PluginsRegistry.registerExtensionPoint('debuggers', { + description: nls.localize('vscode.extension.contributes.debuggers', 'Contributes debug adapters.'), + type: 'array', + default: [{ type: '', extensions: [] }], + items: { + type: 'object', + default: { type: '', program: '', runtime: '', enableBreakpointsFor: { languageIds: [ '' ] } }, + properties: { + type: { + description: nls.localize('vscode.extension.contributes.debuggers.type', "Unique identifier for this debug adapter."), + type: 'string' + }, + label: { + description: nls.localize('vscode.extension.contributes.debuggers.label', "Display name for this debug adapter."), + type: 'string' + }, + enableBreakpointsFor: { + description: nls.localize('vscode.extension.contributes.debuggers.enableBreakpointsFor', "Allow breakpoints for these languages."), + type: 'object', + properties: { + languageIds : { + description: nls.localize('vscode.extension.contributes.debuggers.enableBreakpointsFor.languageIds', "List of languages."), + type: 'array', + items: { + type: 'string' + } + } + } + }, + program: { + description: nls.localize('vscode.extension.contributes.debuggers.program', "Path to the debug adapter program. Path is either absolute or relative to the extension folder."), + type: 'string' + }, + runtime : { + description: nls.localize('vscode.extension.contributes.debuggers.runtime', "Optional runtime in case the program attribute is not an executable but requires a runtime."), + type: 'string' + }, + runtimeArgs : { + description: nls.localize('vscode.extension.contributes.debuggers.runtimeArgs', "Optional runtime arguments."), + type: 'array' + }, + initialConfigurations: { + description: nls.localize('vscode.extension.contributes.debuggers.initialConfigurations', "Configurations for generating the initial \'launch.json\'."), + type: 'array', + }, + configurationAttributes: { + description: nls.localize('vscode.extension.contributes.debuggers.configurationAttributes', "JSON schema configurations for validating \'launch.json\'."), + type: 'object' + }, + windows: { + description: nls.localize('vscode.extension.contributes.debuggers.windows', "Windows specific settings."), + type: 'object', + properties: { + runtime : { + description: nls.localize('vscode.extension.contributes.debuggers.windows.runtime', "Runtime used for Windows."), + type: 'string' + } + } + }, + osx: { + description: nls.localize('vscode.extension.contributes.debuggers.osx', "OS X specific settings."), + type: 'object', + properties: { + runtime : { + description: nls.localize('vscode.extension.contributes.debuggers.osx.runtime', "Runtime used for OSX."), + type: 'string' + } + } + }, + linux: { + description: nls.localize('vscode.extension.contributes.debuggers.linux', "Linux specific settings."), + type: 'object', + properties: { + runtime : { + description: nls.localize('vscode.extension.contributes.debuggers.linux.runtime', "Runtime used for Linux."), + type: 'string' + } + } + } + } + } +}); + +// Debug General Schema + +export var schemaId = 'local://schemas/launch'; +var schema: IJSONSchema = { + id: schemaId, + type: 'object', + title: nls.localize('app.launch.json.title', "Launch configuration"), + required: ['version', 'configurations'], + properties: { + version: { + type: 'string', + description: nls.localize('app.launch.json.version', "Version of this file format."), + default: '0.2.0' + }, + configurations: { + type: 'array', + description: nls.localize('app.launch.json.configurations', "List of configurations. Add new configurations or edit existing ones."), + items: { + oneOf: [] + } + } + } +} + +var jsonRegistry = platform.Registry.as(jsonContributionRegistry.Extensions.JSONContribution); +jsonRegistry.registerSchema(schemaId, schema); +jsonRegistry.addSchemaFileAssociation('/.vscode/launch.json', schemaId); + +export class ConfigurationManager { + + private configuration: debug.IConfig; + private systemVariables: SystemVariables; + private adapters: Adapter[]; + private allModeIdsForBreakpoints: { [key: string]: boolean }; + + constructor( + configName: string, + @IWorkspaceContextService private contextService: IWorkspaceContextService, + @IFileService private fileService: IFileService, + @ITelemetryService private telemetryService: ITelemetryService, + @IWorkbenchEditorService private editorService: IWorkbenchEditorService, + @IConfigurationService private configurationService: IConfigurationService, + @IQuickOpenService private quickOpenService: IQuickOpenService + ) { + this.systemVariables = new SystemVariables(this.editorService, this.contextService); + this.setConfiguration(configName); + this.adapters = []; + this.registerListeners(); + this.allModeIdsForBreakpoints = {}; + } + + private registerListeners(): void { + debuggersExtPoint.setHandler((extensions) => { + + extensions.forEach(extension => { + extension.value.forEach(rawAdapter => { + const adapter = new Adapter(rawAdapter, this.systemVariables, extension.description.extensionFolderPath); + const duplicate = this.adapters.filter(a => a.type === adapter.type)[0]; + if (!rawAdapter.type || (typeof rawAdapter.type !== 'string')) { + extension.collector.error(nls.localize('debugNoType', "Debug adapter 'type' can not be omitted and must be of type 'string'.")); + } + + if (duplicate) { + Object.keys(adapter).forEach(attribute => { + if (adapter[attribute]) { + if (attribute === 'enableBreakpointsFor') { + Object.keys(adapter.enableBreakpointsFor).forEach(languageId => duplicate.enableBreakpointsFor[languageId] = true); + } else if (duplicate[attribute] && attribute !== 'type') { + extension.collector.warn(nls.localize('duplicateDebuggerType', "Debug type '{0}' is already registered and has attribute '{1}', ignoring attribute '{1}'.", adapter.type, attribute)); + } else { + duplicate[attribute] = adapter[attribute]; + } + } + }); + } else { + this.adapters.push(adapter); + } + + adapter.enableBreakpointsFor.languageIds.forEach(modeId => { + this.allModeIdsForBreakpoints[modeId] = true; + }); + }); + }); + + // Update the schema to include all attributes and types from extensions. + // debug.schema.properties['configurations'].items.properties.type.enum = this.adapters.map(adapter => adapter.type); + this.adapters.forEach(adapter => { + const schemaAttributes = adapter.getSchemaAttributes(); + if (schemaAttributes) { + schema.properties['configurations'].items.oneOf.push(...schemaAttributes); + } + }); + }); + } + + public getConfiguration(): debug.IConfig { + return this.configuration; + } + + public getConfigurationName(): string { + return this.configuration ? this.configuration.name : null; + } + + public getAdapter(): Adapter { + return this.adapters.filter(adapter => adapter.type === this.configuration.type).pop(); + } + + public setConfiguration(name: string, extensionHostData: any = null): Promise { + return this.loadLaunchConfig().then(config => { + if (!config || !config.configurations) { + this.configuration = null; + return; + } + + // If the configuration name is not set yet, take the first launch config (can happen if debug viewlet has not been opened yet). + const filtered = name ? config.configurations.filter(cfg => cfg.name === name) : [config.configurations[0]]; + + // Massage configuration attributes - append workspace path to relatvie paths, substitute variables in paths. + this.configuration = filtered.length === 1 ? filtered[0] : null; + if (this.configuration && this.systemVariables) { + this.configuration.debugServer = config.debugServer; + this.configuration.outDir = this.resolvePath(this.systemVariables.resolve(this.configuration.outDir)); + this.configuration.address = this.configuration.address || 'localhost'; + this.configuration.program = this.resolvePath(this.systemVariables.resolve(this.configuration.program)); + this.configuration.stopOnEntry = this.configuration.stopOnEntry === undefined ? false : this.configuration.stopOnEntry; + this.configuration.args = this.configuration.args && this.configuration.args.length > 0 ? this.systemVariables.resolve(this.configuration.args) : null; + this.configuration.env = <{ [key: string]: string; }> this.systemVariables.resolve(this.configuration.env); + this.configuration.cwd = this.resolvePath(this.systemVariables.resolve(this.configuration.cwd) || '.', false); + this.configuration.runtimeExecutable = this.resolvePath(this.systemVariables.resolve(this.configuration.runtimeExecutable)); + this.configuration.runtimeArgs = this.configuration.runtimeArgs && this.configuration.runtimeArgs.length > 0 ? this.systemVariables.resolve(this.configuration.runtimeArgs) : null; + this.configuration.outDir = this.resolvePath(this.configuration.outDir); + // send opaque data back as part of the (undocumented) arguments of the launch request. + this.configuration.extensionHostData = extensionHostData; + } + }); + } + + public openConfigFile(sideBySide: boolean): TPromise { + const resource = uri.file(paths.join(this.contextService.getWorkspace().resource.fsPath, '/.vscode/launch.json')); + + return this.fileService.resolveContent(resource).then(content => true, err => + this.getInitialConfigFileContent().then(content => { + if (!content) { + return false; + } + + return this.fileService.updateContent(resource, content).then(() => true); + } + )).then(configFileCreated => { + if (!configFileCreated) { + return false; + } + this.telemetryService.publicLog('debugConfigure'); + + return this.editorService.openEditor({ + resource: resource, + options: { + forceOpen: true + } + }, sideBySide).then(() => true); + }, (error) => { + throw new Error(nls.localize('DebugConfig.failed', "Unable to create 'launch.json' file inside the '.vscode' folder ({0}).", error)); + }); + } + + private getInitialConfigFileContent(): TPromise { + return this.quickOpenService.pick(this.adapters, { placeHolder: nls.localize('selectDebug', "Select Debug Environment") }) + .then(adapter => { + if (!adapter) { + return null; + } + + return this.massageInitialConfigurations(adapter).then(() => + JSON.stringify({ + version: '0.2.0', + configurations: adapter.initialConfigurations ? adapter.initialConfigurations : [] + }, null, '\t') + ) + }); + } + + private massageInitialConfigurations(adapter: Adapter): Promise { + if (!adapter || !adapter.initialConfigurations || adapter.type !== 'node') { + return Promise.as(true); + } + + // Check package.json for 'main' or 'scripts' so we generate a more pecise 'program' attribute in launch.json. + const packageJsonUri = uri.file(paths.join(this.contextService.getWorkspace().resource.fsPath, '/package.json')); + return this.fileService.resolveContent(packageJsonUri).then(jsonContent => { + try { + const jsonObject = JSON.parse(jsonContent.value); + if (jsonObject.main) { + return jsonObject.main; + } else if (jsonObject.scripts && typeof jsonObject.scripts.start === 'string') { + return (jsonObject.scripts.start).split(' ').pop(); + } + + } catch (error) { } + + return null; + }, err => null).then(program => { + adapter.initialConfigurations.forEach(config => { + if (program && config["program"]) { + config["program"] = program; + } + }); + }); + } + + public canSetBreakpointsIn(model: editor.IModel, lineNumber: number): boolean { + if (model.getLineLastNonWhitespaceColumn(lineNumber) === 0) { + return false; + } + if (model.getAssociatedResource().isInMemory()) { + return false; + } + + var mode = model ? model.getMode() : null; + var modeId = mode ? mode.getId() : null; + + return !!this.allModeIdsForBreakpoints[modeId]; + } + + private resolvePath(p: string, showError = true): string { + if (!p) { + return null; + } + if (path.isAbsolute(p)) { + return paths.normalize(p, true); + } + + return paths.normalize(uri.file(paths.join(this.contextService.getWorkspace().resource.fsPath, p)).fsPath, true); + } + + public loadLaunchConfig(): TPromise { + return this.configurationService.loadConfiguration('launch'); + } +} From b7ab6624ac51d20b137ba635a1b52c278ce4d5f2 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 26 Nov 2015 19:44:18 +0100 Subject: [PATCH 146/588] debug: remove taskService creation workaround. --- .../workbench/parts/debug/electron-browser/debugService.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index d0e10072c9b..031ded64319 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -55,7 +55,6 @@ var DEBUG_SELECTED_CONFIG_NAME_KEY = 'debug.selectedconfigname'; export class DebugService extends ee.EventEmitter implements debug.IDebugService { public serviceId = debug.IDebugService; - private taskService: ITaskService; private state: debug.State; private session: session.RawDebugSession; private model: model.Model; @@ -82,7 +81,8 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService @ILifecycleService private lifecycleService: ILifecycleService, @IInstantiationService private instantiationService:IInstantiationService, @IPluginService private pluginService: IPluginService, - @IOutputService private outputService: IOutputService + @IOutputService private outputService: IOutputService, + @ITaskService private taskService: ITaskService ) { super(); @@ -90,8 +90,6 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService this.debugStringEditorInputs = []; this.session = null; this.state = debug.State.Inactive; - // There is a cycle if taskService gets injected, use a workaround. - this.taskService = this.instantiationService.getInstance(ITaskService); if (!this.contextService.getWorkspace()) { this.state = debug.State.Disabled; From 66d55c2e01b992d9da819dd5cfb52e6233600d14 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2015 19:52:17 +0100 Subject: [PATCH 147/588] Maintain File Permissions when Copying Directories/Files on Linux and MacOS (fixes #634) --- src/vs/base/node/extfs.ts | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/vs/base/node/extfs.ts b/src/vs/base/node/extfs.ts index d3393340d2d..8c81a8f1da2 100644 --- a/src/vs/base/node/extfs.ts +++ b/src/vs/base/node/extfs.ts @@ -45,10 +45,11 @@ function readdirNormalize(path: string, callback: (error: Error, files: string[] return callback(error, null); } - // In some environments we get "." and ".." as entries from the call to readdir(). + // Bug in node: In some environments we get "." and ".." as entries from the call to readdir(). // For example Sharepoint via WebDav on Windows includes them. We never want those // entries in the result set though because they are not valid children of the folder // for our concerns. + // See https://github.com/nodejs/node/issues/4002 return callback(null, children.filter(c => c !== '.' && c !== '..')); }) } @@ -73,7 +74,13 @@ export function mkdirp(path: string, mode: number, callback: (error: Error) => v if (err) { callback(err); return; } if (mode) { - fs.mkdir(path, mode, callback); + fs.mkdir(path, mode, (error) => { + if (error) { + return callback(error); + } + + fs.chmod(path, mode, callback); // we need to explicitly chmod because of https://github.com/nodejs/node/issues/1104 + }); } else { fs.mkdir(path, null, callback); } @@ -96,7 +103,7 @@ export function copy(source: string, target: string, callback: (error: Error) => fs.stat(source, (error, stat) => { if (error) { return callback(error); } - if (!stat.isDirectory()) { return pipeFs(source, target, callback); } + if (!stat.isDirectory()) { return pipeFs(source, target, stat.mode & 511, callback); } if (copiedSources[source]) { return callback(null); // escape when there are cycles (can happen with symlinks) @@ -114,11 +121,11 @@ export function copy(source: string, target: string, callback: (error: Error) => }); } -function pipeFs(source: string, target: string, callback: (error: Error) => void): void { +function pipeFs(source: string, target: string, mode: number, callback: (error: Error) => void): void { var callbackHandled = false; var readStream = fs.createReadStream(source); - var writeStream = fs.createWriteStream(target); + var writeStream = fs.createWriteStream(target, { mode: mode }); var onError = (error: Error) => { if (!callbackHandled) { @@ -134,7 +141,8 @@ function pipeFs(source: string, target: string, callback: (error: Error) => void (writeStream).end(() => { // In this case the write stream is known to have an end signature with callback if (!callbackHandled) { callbackHandled = true; - callback(null); + + fs.chmod(target, mode, callback); // we need to explicitly chmod because of https://github.com/nodejs/node/issues/1104 } }); }); @@ -151,7 +159,7 @@ function pipeFs(source: string, target: string, callback: (error: Error) => void // after the rename, the contents are out of the workspace although not yet deleted. The greater benefit however is that this operation // will fail in case any file is used by another process. fs.unlink() in node will not bail if a file unlinked is used by another process. // However, the consequences are bad as outlined in all the related bugs from https://github.com/joyent/node/issues/7164 -export function del(path: string, tmpFolder: string, callback: (error: Error) => void, done?: (error:Error) => void): void { +export function del(path: string, tmpFolder: string, callback: (error: Error) => void, done?: (error: Error) => void): void { fs.exists(path, (exists) => { if (!exists) { return callback(null); From 45c9a93d871dd3626e4b29eca3d16a7ad9a6aed0 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Nov 2015 20:33:24 +0100 Subject: [PATCH 148/588] add upper bound for recent paths to save to storage --- src/vs/workbench/electron-main/menus.ts | 10 ++++++++-- src/vs/workbench/electron-main/windows.ts | 6 ++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/electron-main/menus.ts b/src/vs/workbench/electron-main/menus.ts index c8b51c2b871..f7814f9f4e6 100644 --- a/src/vs/workbench/electron-main/menus.ts +++ b/src/vs/workbench/electron-main/menus.ts @@ -37,6 +37,8 @@ export class VSCodeMenu { private static lastKnownKeybindingsMapStorageKey = 'lastKnownKeybindings'; + private static MAX_RECENT_ENTRIES = 10; + private static AUTO_SAVE_DELAY_DEFAULT = 1000; // in ms private static AUTO_SAVE_DISABLED = -1; @@ -257,6 +259,10 @@ export class VSCodeMenu { mru.folders = arrays.distinct(mru.folders); } + // Make sure its bounded + mru.folders = mru.folders.slice(0, VSCodeMenu.MAX_RECENT_ENTRIES); + mru.files = mru.files.slice(0, VSCodeMenu.MAX_RECENT_ENTRIES); + storage.setItem(windows.WindowsManager.openedPathsListStorageKey, mru); } @@ -422,7 +428,7 @@ export class VSCodeMenu { // Folders recentList.folders.forEach((folder, index) => { - if (index < windows.WindowsManager.MAX_RECENT_ENTRIES) { + if (index < VSCodeMenu.MAX_RECENT_ENTRIES) { openRecentMenu.append(this.createOpenRecentMenuItem(folder)); } }); @@ -434,7 +440,7 @@ export class VSCodeMenu { } recentList.files.forEach((file, index) => { - if (index < windows.WindowsManager.MAX_RECENT_ENTRIES) { + if (index < VSCodeMenu.MAX_RECENT_ENTRIES) { openRecentMenu.append(this.createOpenRecentMenuItem(file)); } }); diff --git a/src/vs/workbench/electron-main/windows.ts b/src/vs/workbench/electron-main/windows.ts index f7e8ebdb77b..36f1729fc35 100644 --- a/src/vs/workbench/electron-main/windows.ts +++ b/src/vs/workbench/electron-main/windows.ts @@ -95,8 +95,6 @@ export class WindowsManager { public static autoSaveDelayStorageKey = 'autoSaveDelay'; public static openedPathsListStorageKey = 'openedPathsList'; - public static MAX_RECENT_ENTRIES = 10; - private static workingDirPickerStorageKey = 'pickerWorkingDir'; private static windowsStateStorageKey = 'windowsState'; private static themeStorageKey = 'theme'; // TODO@Ben this key is only used to find out if a window can be shown instantly because of light theme, remove once we have support for bg color @@ -565,11 +563,11 @@ export class WindowsManager { recentPaths.unshift(workspacePath); } - // Clear those dupes + // Clear those dupes recentPaths = arrays.distinct(recentPaths); // Make sure it is bounded - return recentPaths.slice(0, WindowsManager.MAX_RECENT_ENTRIES); + return recentPaths.slice(0, 10); // TODO@Ben remove in a couple of versions, it should be ok then because we limited storage } private toIPath(anyPath: string, ignoreFileNotFound?: boolean, gotoLineMode?: boolean): window.IPath { From c022d638ac1939a8725de3c649501d21fcfe4d2c Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 26 Nov 2015 23:52:08 +0100 Subject: [PATCH 149/588] debug: move debugEditorContribution to own file. --- .../parts/debug/browser/debug.contribution.ts | 165 +----------------- .../debug/browser/debugEditorContribution.ts | 153 ++++++++++++++++ 2 files changed, 161 insertions(+), 157 deletions(-) create mode 100644 src/vs/workbench/parts/debug/browser/debugEditorContribution.ts diff --git a/src/vs/workbench/parts/debug/browser/debug.contribution.ts b/src/vs/workbench/parts/debug/browser/debug.contribution.ts index 73509a30614..243e77722bc 100644 --- a/src/vs/workbench/parts/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/parts/debug/browser/debug.contribution.ts @@ -5,36 +5,28 @@ import 'vs/css!./media/debug.contribution'; import nls = require('vs/nls'); -import env = require('vs/base/common/platform'); -import lifecycle = require('vs/base/common/lifecycle'); -import keyboard = require('vs/base/browser/keyboardEvent'); -import editorbrowser = require('vs/editor/browser/editorBrowser'); -import editorcommon = require('vs/editor/common/editorCommon'); -import { EditorBrowserRegistry } from 'vs/editor/browser/editorBrowserExtensions'; import { CommonEditorRegistry, ContextKey, EditorActionDescriptor } from 'vs/editor/common/editorCommonExtensions'; +import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import platform = require('vs/platform/platform'); -import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { IKeybindings } from 'vs/platform/keybinding/common/keybindingService'; +import { EditorBrowserRegistry } from 'vs/editor/browser/editorBrowserExtensions'; import wbaregistry = require('vs/workbench/browser/actionRegistry'); import actionbarregistry = require('vs/workbench/browser/actionBarRegistry'); import viewlet = require('vs/workbench/browser/viewlet'); import wbext = require('vs/workbench/common/contributions'); -import files = require('vs/workbench/parts/files/browser/files'); import baseeditor = require('vs/workbench/browser/parts/editor/baseEditor'); -import filesCommon = require('vs/workbench/parts/files/common/files'); -import manager = require('vs/workbench/parts/debug/browser/debugEditorModelManager'); import * as debug from 'vs/workbench/parts/debug/common/debug'; +import { DebugEditorModelManager } from 'vs/workbench/parts/debug/browser/debugEditorModelManager' import dbgactions = require('vs/workbench/parts/debug/browser/debugActions'); import editorinputs = require('vs/workbench/parts/debug/browser/debugEditorInputs'); import repleditor = require('vs/workbench/parts/debug/browser/replEditor'); import debugwidget = require('vs/workbench/parts/debug/browser/debugActionsWidget'); -import debughover = require('vs/workbench/parts/debug/browser/debugHoverWidget'); -import { IKeybindings } from 'vs/platform/keybinding/common/keybindingService'; +import { DebugEditorContribution } from 'vs/workbench/parts/debug/browser/debugEditorContribution'; import { IViewletService } from 'vs/workbench/services/viewlet/common/viewletService'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { IWorkspaceContextService } from 'vs/workbench/services/workspace/common/contextService'; -import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import IDebugService = debug.IDebugService; @@ -52,148 +44,7 @@ class OpenDebugViewletAction extends viewlet.ToggleViewletAction { } } -class DebugEditorContrib implements editorcommon.IEditorContribution { - - static ID = 'editor.contrib.debug'; - - private editor: editorbrowser.ICodeEditor; - private toDispose: lifecycle.IDisposable[]; - private breakpointHintDecoration: string[]; - private hoverWidget: debughover.DebugHoverWidget; - - constructor(edtr: editorbrowser.ICodeEditor, - @IDebugService private debugService: IDebugService, - @IWorkspaceContextService private contextService: IWorkspaceContextService - ) { - this.editor = edtr; - this.breakpointHintDecoration = []; - this.toDispose = []; - this.registerListeners(); - this.hoverWidget = new debughover.DebugHoverWidget(this.editor, this.debugService); - } - - private registerListeners(): void { - this.toDispose.push(this.editor.addListener2(editorcommon.EventType.MouseDown, (e: editorbrowser.IMouseEvent) => { - if (e.target.type !== editorcommon.MouseTargetType.GUTTER_GLYPH_MARGIN || /* after last line */ e.target.detail) { - return; - } - if (!this.debugService.canSetBreakpointsIn(this.editor.getModel(), e.target.position.lineNumber)) { - return; - } - - var modelUrl = this.editor.getModel().getAssociatedResource(); - this.debugService.toggleBreakpoint(modelUrl, e.target.position.lineNumber); - })); - this.toDispose.push(this.editor.addListener2(editorcommon.EventType.MouseMove, (e: editorbrowser.IMouseEvent) => { - var showBreakpointHintAtLineNumber = -1; - if (e.target.type === editorcommon.MouseTargetType.GUTTER_GLYPH_MARGIN && this.debugService.canSetBreakpointsIn(this.editor.getModel(), e.target.position.lineNumber)) { - if (!e.target.detail) { - // is not after last line - showBreakpointHintAtLineNumber = e.target.position.lineNumber; - } - } - this.ensureBreakpointHintDecoration(showBreakpointHintAtLineNumber); - })); - this.toDispose.push(this.editor.addListener2(editorcommon.EventType.MouseLeave, (e: editorbrowser.IMouseEvent) => { - this.ensureBreakpointHintDecoration(-1); - })); - this.toDispose.push(this.debugService.addListener2(debug.ServiceEvents.STATE_CHANGED, () => this.onDebugStateUpdate())); - - // hover listeners & hover widget - this.toDispose.push(this.editor.addListener2(editorcommon.EventType.MouseDown, (e: editorbrowser.IMouseEvent) => this.onEditorMouseDown(e))); - this.toDispose.push(this.editor.addListener2(editorcommon.EventType.MouseMove, (e: editorbrowser.IMouseEvent) => this.onEditorMouseMove(e))); - this.toDispose.push(this.editor.addListener2(editorcommon.EventType.MouseLeave, (e: editorbrowser.IMouseEvent) => this.hoverWidget.hide())); - this.toDispose.push(this.editor.addListener2(editorcommon.EventType.KeyDown, (e: keyboard.StandardKeyboardEvent) => this.onKeyDown(e))); - this.toDispose.push(this.editor.addListener2(editorcommon.EventType.ModelChanged, () => this.onModelChanged())); - this.toDispose.push(this.editor.addListener2('scroll', () => this.hoverWidget.hide())); - } - - public getId(): string { - return DebugEditorContrib.ID; - } - - private ensureBreakpointHintDecoration(showBreakpointHintAtLineNumber: number): void { - var newDecoration: editorcommon.IModelDeltaDecoration[] = []; - if (showBreakpointHintAtLineNumber !== -1) { - newDecoration.push({ - options: DebugEditorContrib.BREAKPOINT_HELPER_DECORATION, - range: { - startLineNumber: showBreakpointHintAtLineNumber, - startColumn: 1, - endLineNumber: showBreakpointHintAtLineNumber, - endColumn: 1 - } - }); - } - - this.breakpointHintDecoration = this.editor.deltaDecorations(this.breakpointHintDecoration, newDecoration); - } - - private onDebugStateUpdate(): void { - if (this.debugService.getState() !== debug.State.Stopped) { - this.hoverWidget.hide(); - } - this.contextService.updateOptions('editor', { - hover: this.debugService.getState() !== debug.State.Stopped - }); - } - - private onModelChanged(): void { - this.hoverWidget.hide(); - } - - // hover business - - private onEditorMouseDown(mouseEvent: editorbrowser.IMouseEvent): void { - var targetType = mouseEvent.target.type; - if (targetType === editorcommon.MouseTargetType.CONTENT_WIDGET && mouseEvent.target.detail === debughover.DebugHoverWidget.ID) { - return; - } - - this.hoverWidget.hide(); - } - - private onEditorMouseMove(mouseEvent: editorbrowser.IMouseEvent): void { - if (this.debugService.getState() !== debug.State.Stopped) { - return; - } - - var targetType = mouseEvent.target.type; - var stopKey = env.isMacintosh ? 'metaKey' : 'ctrlKey'; - - if (targetType === editorcommon.MouseTargetType.CONTENT_WIDGET && mouseEvent.target.detail === debughover.DebugHoverWidget.ID && !(mouseEvent.event)[stopKey]) { - // mouse moved on top of content hover widget - return; - } - - if (targetType === editorcommon.MouseTargetType.CONTENT_TEXT) { - this.hoverWidget.showAt(mouseEvent.target.range); - } else { - this.hoverWidget.hide(); - } - } - - private onKeyDown(e: keyboard.StandardKeyboardEvent): void { - var stopKey = env.isMacintosh ? KeyCode.Meta : KeyCode.Ctrl; - if (e.keyCode !== stopKey) { - // Do not hide hover when Ctrl/Meta is pressed - this.hoverWidget.hide(); - } - } - - // end hover business - - private static BREAKPOINT_HELPER_DECORATION: editorcommon.IModelDecorationOptions = { - glyphMarginClassName: 'debug-breakpoint-glyph-hint', - stickiness: editorcommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges - }; - - public dispose(): void { - this.toDispose = lifecycle.disposeAll(this.toDispose); - } -} - -EditorBrowserRegistry.registerEditorContribution(DebugEditorContrib); +EditorBrowserRegistry.registerEditorContribution(DebugEditorContribution); CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(dbgactions.ToggleBreakpointAction, dbgactions.ToggleBreakpointAction.ID, nls.localize('toggleBreakpointAction', "Debug: Toggle Breakpoint"), { context: ContextKey.EditorTextFocus, primary: KeyCode.F9 @@ -229,7 +80,7 @@ actionBarRegistry.registerActionBarContributor(actionbarregistry.Scope.EDITOR, r var registry = ( platform.Registry.as(wbaregistry.Extensions.WorkbenchActions)); registry.registerWorkbenchAction(new SyncActionDescriptor(OpenDebugViewletAction, OpenDebugViewletAction.ID, OpenDebugViewletAction.LABEL, openViewletKb), nls.localize('view', "View")); -(platform.Registry.as(wbext.Extensions.Workbench)).registerWorkbenchContribution(manager.DebugEditorModelManager); +(platform.Registry.as(wbext.Extensions.Workbench)).registerWorkbenchContribution(DebugEditorModelManager); (platform.Registry.as(wbext.Extensions.Workbench)).registerWorkbenchContribution(debugwidget.DebugActionsWidget); var debugCategory = nls.localize('debugCategory', "Debug"); diff --git a/src/vs/workbench/parts/debug/browser/debugEditorContribution.ts b/src/vs/workbench/parts/debug/browser/debugEditorContribution.ts new file mode 100644 index 00000000000..16c453bb05f --- /dev/null +++ b/src/vs/workbench/parts/debug/browser/debugEditorContribution.ts @@ -0,0 +1,153 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import lifecycle = require('vs/base/common/lifecycle'); +import env = require('vs/base/common/platform'); +import { KeyCode } from 'vs/base/common/keyCodes'; +import keyboard = require('vs/base/browser/keyboardEvent'); +import editorbrowser = require('vs/editor/browser/editorBrowser'); +import editorcommon = require('vs/editor/common/editorCommon'); +import { DebugHoverWidget } from 'vs/workbench/parts/debug/browser/debugHoverWidget'; +import debug = require('vs/workbench/parts/debug/common/debug'); +import { IWorkspaceContextService } from 'vs/workbench/services/workspace/common/contextService'; + +export class DebugEditorContribution implements editorcommon.IEditorContribution { + + static ID = 'editor.contrib.debug'; + + private toDispose: lifecycle.IDisposable[]; + private breakpointHintDecoration: string[]; + private hoverWidget: DebugHoverWidget; + + constructor( + private editor: editorbrowser.ICodeEditor, + @debug.IDebugService private debugService: debug.IDebugService, + @IWorkspaceContextService private contextService: IWorkspaceContextService + ) { + this.breakpointHintDecoration = []; + this.toDispose = []; + this.hoverWidget = new DebugHoverWidget(this.editor, this.debugService); + this.registerListeners(); + } + + private registerListeners(): void { + this.toDispose.push(this.editor.addListener2(editorcommon.EventType.MouseDown, (e: editorbrowser.IMouseEvent) => { + if (e.target.type !== editorcommon.MouseTargetType.GUTTER_GLYPH_MARGIN || /* after last line */ e.target.detail) { + return; + } + if (!this.debugService.canSetBreakpointsIn(this.editor.getModel(), e.target.position.lineNumber)) { + return; + } + + var modelUrl = this.editor.getModel().getAssociatedResource(); + this.debugService.toggleBreakpoint(modelUrl, e.target.position.lineNumber); + })); + this.toDispose.push(this.editor.addListener2(editorcommon.EventType.MouseMove, (e: editorbrowser.IMouseEvent) => { + var showBreakpointHintAtLineNumber = -1; + if (e.target.type === editorcommon.MouseTargetType.GUTTER_GLYPH_MARGIN && this.debugService.canSetBreakpointsIn(this.editor.getModel(), e.target.position.lineNumber)) { + if (!e.target.detail) { + // is not after last line + showBreakpointHintAtLineNumber = e.target.position.lineNumber; + } + } + this.ensureBreakpointHintDecoration(showBreakpointHintAtLineNumber); + })); + this.toDispose.push(this.editor.addListener2(editorcommon.EventType.MouseLeave, (e: editorbrowser.IMouseEvent) => { + this.ensureBreakpointHintDecoration(-1); + })); + this.toDispose.push(this.debugService.addListener2(debug.ServiceEvents.STATE_CHANGED, () => this.onDebugStateUpdate())); + + // hover listeners & hover widget + this.toDispose.push(this.editor.addListener2(editorcommon.EventType.MouseDown, (e: editorbrowser.IMouseEvent) => this.onEditorMouseDown(e))); + this.toDispose.push(this.editor.addListener2(editorcommon.EventType.MouseMove, (e: editorbrowser.IMouseEvent) => this.onEditorMouseMove(e))); + this.toDispose.push(this.editor.addListener2(editorcommon.EventType.MouseLeave, (e: editorbrowser.IMouseEvent) => this.hoverWidget.hide())); + this.toDispose.push(this.editor.addListener2(editorcommon.EventType.KeyDown, (e: keyboard.StandardKeyboardEvent) => this.onKeyDown(e))); + this.toDispose.push(this.editor.addListener2(editorcommon.EventType.ModelChanged, () => this.onModelChanged())); + this.toDispose.push(this.editor.addListener2('scroll', () => this.hoverWidget.hide())); + } + + public getId(): string { + return DebugEditorContribution.ID; + } + + private ensureBreakpointHintDecoration(showBreakpointHintAtLineNumber: number): void { + var newDecoration: editorcommon.IModelDeltaDecoration[] = []; + if (showBreakpointHintAtLineNumber !== -1) { + newDecoration.push({ + options: DebugEditorContribution.BREAKPOINT_HELPER_DECORATION, + range: { + startLineNumber: showBreakpointHintAtLineNumber, + startColumn: 1, + endLineNumber: showBreakpointHintAtLineNumber, + endColumn: 1 + } + }); + } + + this.breakpointHintDecoration = this.editor.deltaDecorations(this.breakpointHintDecoration, newDecoration); + } + + private onDebugStateUpdate(): void { + if (this.debugService.getState() !== debug.State.Stopped) { + this.hoverWidget.hide(); + } + this.contextService.updateOptions('editor', { + hover: this.debugService.getState() !== debug.State.Stopped + }); + } + + private onModelChanged(): void { + this.hoverWidget.hide(); + } + + // hover business + + private onEditorMouseDown(mouseEvent: editorbrowser.IMouseEvent): void { + if (mouseEvent.target.type === editorcommon.MouseTargetType.CONTENT_WIDGET && mouseEvent.target.detail === DebugHoverWidget.ID) { + return; + } + + this.hoverWidget.hide(); + } + + private onEditorMouseMove(mouseEvent: editorbrowser.IMouseEvent): void { + if (this.debugService.getState() !== debug.State.Stopped) { + return; + } + + const targetType = mouseEvent.target.type; + const stopKey = env.isMacintosh ? 'metaKey' : 'ctrlKey'; + + if (targetType === editorcommon.MouseTargetType.CONTENT_WIDGET && mouseEvent.target.detail === DebugHoverWidget.ID && !(mouseEvent.event)[stopKey]) { + // mouse moved on top of content hover widget + return; + } + + if (targetType === editorcommon.MouseTargetType.CONTENT_TEXT) { + this.hoverWidget.showAt(mouseEvent.target.range); + } else { + this.hoverWidget.hide(); + } + } + + private onKeyDown(e: keyboard.StandardKeyboardEvent): void { + const stopKey = env.isMacintosh ? KeyCode.Meta : KeyCode.Ctrl; + if (e.keyCode !== stopKey) { + // Do not hide hover when Ctrl/Meta is pressed + this.hoverWidget.hide(); + } + } + + // end hover business + + private static BREAKPOINT_HELPER_DECORATION: editorcommon.IModelDecorationOptions = { + glyphMarginClassName: 'debug-breakpoint-glyph-hint', + stickiness: editorcommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges + }; + + public dispose(): void { + this.toDispose = lifecycle.disposeAll(this.toDispose); + } +} From 89295e16c8da0e3e894c58a3769360b478ecefe0 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2015 00:35:09 +0100 Subject: [PATCH 150/588] debug: polish --- .../parts/debug/browser/debugViewer.ts | 40 +++++++++---------- .../parts/debug/node/rawDebugSession.ts | 6 +-- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index c911ced374f..5a60da69030 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -23,7 +23,7 @@ import renderer = require('vs/base/parts/tree/browser/actionsRenderer'); import debug = require('vs/workbench/parts/debug/common/debug'); import model = require('vs/workbench/parts/debug/common/debugModel'); import viewmodel = require('vs/workbench/parts/debug/common/debugViewModel'); -import dbgactions = require('vs/workbench/parts/debug/browser/debugActions'); +import debugactions = require('vs/workbench/parts/debug/browser/debugActions'); import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; @@ -287,9 +287,9 @@ export class VariablesActionProvider extends SimpleActionProvider { public getSecondaryActions(tree: tree.ITree, element: any): Promise { let actions: actions.Action[] = []; const variable = element; - actions.push(this.instantiationService.createInstance(dbgactions.AddToWatchExpressionsAction, dbgactions.AddToWatchExpressionsAction.ID, dbgactions.AddToWatchExpressionsAction.LABEL, variable)); + actions.push(this.instantiationService.createInstance(debugactions.AddToWatchExpressionsAction, debugactions.AddToWatchExpressionsAction.ID, debugactions.AddToWatchExpressionsAction.LABEL, variable)); if (variable.reference === 0) { - actions.push(this.instantiationService.createInstance(dbgactions.CopyValueAction, dbgactions.CopyValueAction.ID, dbgactions.CopyValueAction.LABEL, variable)); + actions.push(this.instantiationService.createInstance(debugactions.CopyValueAction, debugactions.CopyValueAction.ID, debugactions.CopyValueAction.LABEL, variable)); } return Promise.as(actions); @@ -421,32 +421,32 @@ export class WatchExpressionsActionProvider extends SimpleActionProvider { } public getExpressionActions(): actions.IAction[] { - return [this.instantiationService.createInstance(dbgactions.RemoveWatchExpressionAction, dbgactions.RemoveWatchExpressionAction.ID, dbgactions.RemoveWatchExpressionAction.LABEL)]; + return [this.instantiationService.createInstance(debugactions.RemoveWatchExpressionAction, debugactions.RemoveWatchExpressionAction.ID, debugactions.RemoveWatchExpressionAction.LABEL)]; } public getSecondaryActions(tree: tree.ITree, element: any): Promise { var actions: actions.Action[] = []; if (element instanceof model.Expression) { const expression = element; - actions.push(this.instantiationService.createInstance(dbgactions.AddWatchExpressionAction, dbgactions.AddWatchExpressionAction.ID, dbgactions.AddWatchExpressionAction.LABEL)); - actions.push(this.instantiationService.createInstance(dbgactions.RenameWatchExpressionAction, dbgactions.RenameWatchExpressionAction.ID, dbgactions.RenameWatchExpressionAction.LABEL, expression)); + actions.push(this.instantiationService.createInstance(debugactions.AddWatchExpressionAction, debugactions.AddWatchExpressionAction.ID, debugactions.AddWatchExpressionAction.LABEL)); + actions.push(this.instantiationService.createInstance(debugactions.RenameWatchExpressionAction, debugactions.RenameWatchExpressionAction.ID, debugactions.RenameWatchExpressionAction.LABEL, expression)); if (expression.reference === 0) { - actions.push(this.instantiationService.createInstance(dbgactions.CopyValueAction, dbgactions.CopyValueAction.ID, dbgactions.CopyValueAction.LABEL, expression.value)); + actions.push(this.instantiationService.createInstance(debugactions.CopyValueAction, debugactions.CopyValueAction.ID, debugactions.CopyValueAction.LABEL, expression.value)); } actions.push(new actionbar.Separator()); - actions.push(this.instantiationService.createInstance(dbgactions.RemoveWatchExpressionAction, dbgactions.RemoveWatchExpressionAction.ID, dbgactions.RemoveWatchExpressionAction.LABEL)); - actions.push(this.instantiationService.createInstance(dbgactions.RemoveAllWatchExpressionsAction, dbgactions.RemoveAllWatchExpressionsAction.ID, dbgactions.RemoveAllWatchExpressionsAction.LABEL)); + actions.push(this.instantiationService.createInstance(debugactions.RemoveWatchExpressionAction, debugactions.RemoveWatchExpressionAction.ID, debugactions.RemoveWatchExpressionAction.LABEL)); + actions.push(this.instantiationService.createInstance(debugactions.RemoveAllWatchExpressionsAction, debugactions.RemoveAllWatchExpressionsAction.ID, debugactions.RemoveAllWatchExpressionsAction.LABEL)); } else { - actions.push(this.instantiationService.createInstance(dbgactions.AddWatchExpressionAction, dbgactions.AddWatchExpressionAction.ID, dbgactions.AddWatchExpressionAction.LABEL)); + actions.push(this.instantiationService.createInstance(debugactions.AddWatchExpressionAction, debugactions.AddWatchExpressionAction.ID, debugactions.AddWatchExpressionAction.LABEL)); if (element instanceof model.Variable) { const variable = element; if (variable.reference === 0) { - actions.push(this.instantiationService.createInstance(dbgactions.CopyValueAction, dbgactions.CopyValueAction.ID, dbgactions.CopyValueAction.LABEL, variable.value)); + actions.push(this.instantiationService.createInstance(debugactions.CopyValueAction, debugactions.CopyValueAction.ID, debugactions.CopyValueAction.LABEL, variable.value)); } actions.push(new actionbar.Separator()); } - actions.push(this.instantiationService.createInstance(dbgactions.RemoveAllWatchExpressionsAction, dbgactions.RemoveAllWatchExpressionsAction.ID, dbgactions.RemoveAllWatchExpressionsAction.LABEL)); + actions.push(this.instantiationService.createInstance(debugactions.RemoveAllWatchExpressionsAction, debugactions.RemoveAllWatchExpressionsAction.ID, debugactions.RemoveAllWatchExpressionsAction.LABEL)); } return Promise.as(actions); @@ -685,25 +685,25 @@ export class BreakpointsActionProvider extends SimpleActionProvider { } public getBreakpointActions(): actions.IAction[] { - return [this.instantiationService.createInstance(dbgactions.RemoveBreakpointAction, dbgactions.RemoveBreakpointAction.ID, dbgactions.RemoveBreakpointAction.LABEL)]; + return [this.instantiationService.createInstance(debugactions.RemoveBreakpointAction, debugactions.RemoveBreakpointAction.ID, debugactions.RemoveBreakpointAction.LABEL)]; } public getSecondaryActions(tree: tree.ITree, element: any): TPromise { - var actions: actions.Action[] = [this.instantiationService.createInstance(dbgactions.ToggleEnablementAction, dbgactions.ToggleEnablementAction.ID, dbgactions.ToggleEnablementAction.LABEL)]; + var actions: actions.Action[] = [this.instantiationService.createInstance(debugactions.ToggleEnablementAction, debugactions.ToggleEnablementAction.ID, debugactions.ToggleEnablementAction.LABEL)]; actions.push(new actionbar.Separator()); - actions.push(this.instantiationService.createInstance(dbgactions.RemoveBreakpointAction, dbgactions.RemoveBreakpointAction.ID, dbgactions.RemoveBreakpointAction.LABEL)); - actions.push(this.instantiationService.createInstance(dbgactions.RemoveAllBreakpointsAction, dbgactions.RemoveAllBreakpointsAction.ID, dbgactions.RemoveAllBreakpointsAction.LABEL)); + actions.push(this.instantiationService.createInstance(debugactions.RemoveBreakpointAction, debugactions.RemoveBreakpointAction.ID, debugactions.RemoveBreakpointAction.LABEL)); + actions.push(this.instantiationService.createInstance(debugactions.RemoveAllBreakpointsAction, debugactions.RemoveAllBreakpointsAction.ID, debugactions.RemoveAllBreakpointsAction.LABEL)); actions.push(new actionbar.Separator()); - actions.push(this.instantiationService.createInstance(dbgactions.ToggleBreakpointsActivatedAction, dbgactions.ToggleBreakpointsActivatedAction.ID, dbgactions.ToggleBreakpointsActivatedAction.LABEL)); + actions.push(this.instantiationService.createInstance(debugactions.ToggleBreakpointsActivatedAction, debugactions.ToggleBreakpointsActivatedAction.ID, debugactions.ToggleBreakpointsActivatedAction.LABEL)); actions.push(new actionbar.Separator()); - actions.push(this.instantiationService.createInstance(dbgactions.EnableAllBreakpointsAction, dbgactions.EnableAllBreakpointsAction.ID, dbgactions.EnableAllBreakpointsAction.LABEL)); - actions.push(this.instantiationService.createInstance(dbgactions.DisableAllBreakpointsAction, dbgactions.DisableAllBreakpointsAction.ID, dbgactions.DisableAllBreakpointsAction.LABEL)); + actions.push(this.instantiationService.createInstance(debugactions.EnableAllBreakpointsAction, debugactions.EnableAllBreakpointsAction.ID, debugactions.EnableAllBreakpointsAction.LABEL)); + actions.push(this.instantiationService.createInstance(debugactions.DisableAllBreakpointsAction, debugactions.DisableAllBreakpointsAction.ID, debugactions.DisableAllBreakpointsAction.LABEL)); actions.push(new actionbar.Separator()); - actions.push(this.instantiationService.createInstance(dbgactions.ReapplyBreakpointsAction, dbgactions.ReapplyBreakpointsAction.ID, dbgactions.ReapplyBreakpointsAction.LABEL)); + actions.push(this.instantiationService.createInstance(debugactions.ReapplyBreakpointsAction, debugactions.ReapplyBreakpointsAction.ID, debugactions.ReapplyBreakpointsAction.LABEL)); return Promise.as(actions); } diff --git a/src/vs/workbench/parts/debug/node/rawDebugSession.ts b/src/vs/workbench/parts/debug/node/rawDebugSession.ts index 8ba4f45275b..81df5433dc1 100644 --- a/src/vs/workbench/parts/debug/node/rawDebugSession.ts +++ b/src/vs/workbench/parts/debug/node/rawDebugSession.ts @@ -5,21 +5,17 @@ import cp = require('child_process'); import fs = require('fs'); -import path = require('path'); import net = require('net'); import remote = require('remote'); -import nls = require('vs/nls'); -import uri from 'vs/base/common/uri'; import platform = require('vs/base/common/platform'); import errors = require('vs/base/common/errors'); import { Promise, TPromise} from 'vs/base/common/winjs.base'; import severity from 'vs/base/common/severity'; -import actions = require('vs/base/common/actions'); import debug = require('vs/workbench/parts/debug/common/debug'); import { Adapter } from 'vs/workbench/parts/debug/node/debugAdapter'; import v8 = require('vs/workbench/parts/debug/node/v8Protocol'); import stdfork = require('vs/base/node/stdFork'); -import { IMessageService, CloseAction } from 'vs/platform/message/common/message'; +import { IMessageService } from 'vs/platform/message/common/message'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; var shell = remote.require('shell'); From c03d38e14876962fa9172554cefd8b42c017d761 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2015 00:38:24 +0100 Subject: [PATCH 151/588] debug: show breakpoint context menu on right click in editor margin. --- .../debug/browser/debugEditorContribution.ts | 47 +++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugEditorContribution.ts b/src/vs/workbench/parts/debug/browser/debugEditorContribution.ts index 16c453bb05f..c324a3d0837 100644 --- a/src/vs/workbench/parts/debug/browser/debugEditorContribution.ts +++ b/src/vs/workbench/parts/debug/browser/debugEditorContribution.ts @@ -3,15 +3,22 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import nls = require('vs/nls'); +import { TPromise } from 'vs/base/common/winjs.base'; import lifecycle = require('vs/base/common/lifecycle'); import env = require('vs/base/common/platform'); +import uri from 'vs/base/common/uri'; +import { IAction, Action } from 'vs/base/common/actions'; import { KeyCode } from 'vs/base/common/keyCodes'; import keyboard = require('vs/base/browser/keyboardEvent'); import editorbrowser = require('vs/editor/browser/editorBrowser'); import editorcommon = require('vs/editor/common/editorCommon'); import { DebugHoverWidget } from 'vs/workbench/parts/debug/browser/debugHoverWidget'; +import debugactions = require('vs/workbench/parts/debug/browser/debugActions'); import debug = require('vs/workbench/parts/debug/common/debug'); import { IWorkspaceContextService } from 'vs/workbench/services/workspace/common/contextService'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; export class DebugEditorContribution implements editorcommon.IEditorContribution { @@ -24,7 +31,9 @@ export class DebugEditorContribution implements editorcommon.IEditorContribution constructor( private editor: editorbrowser.ICodeEditor, @debug.IDebugService private debugService: debug.IDebugService, - @IWorkspaceContextService private contextService: IWorkspaceContextService + @IWorkspaceContextService private contextService: IWorkspaceContextService, + @IContextMenuService private contextMenuService: IContextMenuService, + @IInstantiationService private instantiationService:IInstantiationService ) { this.breakpointHintDecoration = []; this.toDispose = []; @@ -32,6 +41,24 @@ export class DebugEditorContribution implements editorcommon.IEditorContribution this.registerListeners(); } + private getContextMenuActions(breakpoint: debug.IBreakpoint, uri: uri, lineNumber: number): TPromise { + const actions = []; + if (breakpoint) { + actions.push(this.instantiationService.createInstance(debugactions.RemoveBreakpointAction, debugactions.RemoveBreakpointAction.ID, debugactions.RemoveBreakpointAction.LABEL)); + actions.push(this.instantiationService.createInstance(debugactions.ToggleEnablementAction, debugactions.ToggleEnablementAction.ID, debugactions.ToggleEnablementAction.LABEL)); + } else { + actions.push(new Action( + 'addBreakpoint', + nls.localize('addBreakpoint', "Add Breakpoint"), + null, + true, + () => this.debugService.toggleBreakpoint(uri, lineNumber) + )); + } + + return TPromise.as(actions); + } + private registerListeners(): void { this.toDispose.push(this.editor.addListener2(editorcommon.EventType.MouseDown, (e: editorbrowser.IMouseEvent) => { if (e.target.type !== editorcommon.MouseTargetType.GUTTER_GLYPH_MARGIN || /* after last line */ e.target.detail) { @@ -41,9 +68,23 @@ export class DebugEditorContribution implements editorcommon.IEditorContribution return; } - var modelUrl = this.editor.getModel().getAssociatedResource(); - this.debugService.toggleBreakpoint(modelUrl, e.target.position.lineNumber); + const lineNumber = e.target.position.lineNumber; + const uri = this.editor.getModel().getAssociatedResource(); + + if (e.event.rightButton) { + const anchor = { x: e.event.posx + 1, y: e.event.posy }; + const breakpoint = this.debugService.getModel().getBreakpoints().filter(bp => bp.lineNumber === lineNumber && bp.source.uri.toString() === uri.toString()).pop(); + + this.contextMenuService.showContextMenu({ + getAnchor: () => anchor, + getActions: () => this.getContextMenuActions(breakpoint, uri, lineNumber), + getActionsContext: () => breakpoint + }); + } else { + this.debugService.toggleBreakpoint(uri, lineNumber); + } })); + this.toDispose.push(this.editor.addListener2(editorcommon.EventType.MouseMove, (e: editorbrowser.IMouseEvent) => { var showBreakpointHintAtLineNumber = -1; if (e.target.type === editorcommon.MouseTargetType.GUTTER_GLYPH_MARGIN && this.debugService.canSetBreakpointsIn(this.editor.getModel(), e.target.position.lineNumber)) { From 2fcbb073a6804b2708934d29a2e7d933d4d588d3 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 26 Nov 2015 18:38:46 -0800 Subject: [PATCH 152/588] Add documentationLabel's for HTML tags Part of #323. Moves the tag data structure away from a simple string[] to a complex type in preparation for smart intellisense (#375). --- src/vs/languages/html/common/htmlTags.ts | 485 +++++++++++++++------ src/vs/languages/html/common/htmlWorker.ts | 10 +- 2 files changed, 368 insertions(+), 127 deletions(-) diff --git a/src/vs/languages/html/common/htmlTags.ts b/src/vs/languages/html/common/htmlTags.ts index a1fbbae2389..3da9d99e5fc 100644 --- a/src/vs/languages/html/common/htmlTags.ts +++ b/src/vs/languages/html/common/htmlTags.ts @@ -13,132 +13,371 @@ export function isEmptyElement(e: string) : boolean { } export interface IHTMLTagProvider { - collectTags(collector: (tag:string) => void): void; + collectTags(collector: (tag:string, label:string) => void): void; collectAttributes(tag: string, collector: (attribute: string, type: string) => void): void; collectValues(tag: string, attribute: string, collector: (value: string) => void): void; } +class TagSpecification { + constructor(public label: string, public attributes: string[]) {} +} + export function getHTML5TagProvider(): IHTMLTagProvider { var none: string[] = []; - var html5Tags : { [tag:string]: string[]} = { - html: ['manifest'], - head: none, - title: none, - noscript: none, - main: none, - section: none, - nav: none, - article: none, - aside: none, - h1: none, - h2: none, - h3: none, - h4: none, - h5: none, - h6: none, - hgroup: none, - header: none, - footer: none, - address: none, - p: none, - hr: none, - pre: none, - blockquote: ['cite'], - ol: ['reversed:v', 'start', 'type:lt'], - ul: none, - li: ['value'], - dl: none, - dt: none, - dd: none, - figure: none, - figcaption: none, - div: none, - a: ['href', 'target', 'download', 'ping', 'rel', 'hreflang', 'type'], - em: none, - strong: none, - small: none, - s: none, - cite: none, - q: ['cite'], - dfn: none, - abbr: none, - data: ['value'], - time: ['datetime'], - code: none, - var: none, - samp: none, - kbd: none, - sub: none, - sup: none, - i: none, - b: none, - u: none, - mark: none, - ruby: none, - rb: none, - rp: none, - rt: none, - rtc: none, - bdi: none, - bdo: none, - span: none, - br: none, - wbr: none, - ins: ['cite', 'datetime'], - del: ['cite', 'datetime'], - img: ['alt', 'src', 'srcset', 'crossorigin:xo', 'usemap', 'ismap:v', 'width', 'height'], - iframe: ['src', 'srcdoc', 'name', 'sandbox:sb', 'seamless:v', 'allowfullscreen:v', 'width', 'height'], - embed: ['src', 'type', 'width', 'height'], - object: ['data', 'type', 'typemustmatch:v', 'name', 'usemap', 'form', 'width', 'height'], - param: ['name', 'value'], - video: ['src', 'crossorigin:xo', 'poster', 'preload:pl', 'autoplay:v', 'mediagroup', 'loop:v', 'muted:v', 'controls:v', 'width', 'height'], - audio: ['src', 'crossorigin:xo', 'preload:pl', 'autoplay:v', 'mediagroup', 'loop:v', 'muted:v', 'controls:v'], - source: ['src', 'type'], - track: ['default:v', 'kind:tk', 'label', 'src', 'srclang'], - canvas: ['width', 'height'], - map: ['name'], - area: ['alt', 'coords', 'shape:sh', 'href', 'target', 'download', 'ping', 'rel', 'hreflang', 'type'], - base: ['href', 'target'], - link: ['href', 'crossorigin:xo', 'rel', 'media', 'hreflang', 'type', 'sizes'], - meta: ['name', 'http-equiv', 'content', 'charset'], - style: ['media', 'nonce', 'type', 'scoped:v'], - script: ['src', 'type', 'charset', 'async:v', 'defer:v', 'crossorigin:xo', 'nonce'], - template: none, - body: ['onafterprint', 'onbeforeprint', 'onbeforeunload', 'onhashchange', 'onlanguagechange', 'onmessage', 'onoffline', 'ononline', 'onpagehide', - 'onpageshow', 'onpopstate', 'onstorage', 'onunload'], - table: ['sortable:v', 'border'], - caption: none, - colgroup: ['span'], - col: ['span'], - tbody: none, - thead: none, - tfoot: none, - tr: none, - td: ['colspan', 'rowspan', 'headers'], - th: ['colspan', 'rowspan', 'headers', 'scope:s', 'sorted', 'abbr'], - form: ['accept-charset', 'action', 'autocomplete:o', 'enctype:et', 'method:m', 'name', 'novalidate:v', 'target'], - fieldset: ['disabled:v', 'form', 'name'], - legend: none, - label: ['form', 'for'], - input: ['accept', 'alt', 'autocomplete:o', 'autofocus:v', 'checked:v', 'dirname', 'disabled:v', 'form', 'formaction', 'formenctype:et', - 'formmethod:fm', 'formnovalidate:v', 'formtarget', 'height', 'inputmode:im', 'list', 'max', 'maxlength', 'min', 'minlength', 'multiple:v', 'name', - 'pattern', 'placeholder', 'readonly:v', 'required:v', 'size', 'src', 'step', 'type:t', 'value', 'width'], - button: ['autofocus:v', 'disabled:v', 'form', 'formaction', 'formenctype:et', 'formmethod:fm', 'formnovalidate:v', 'formtarget', 'name', 'type:bt', 'value'], - select: ['autocomplete:o', 'autofocus:v', 'disabled:v', 'form', 'multiple:v', 'name', 'required:v', 'size'], - datalist: none, - optgroup: ['disabled:v', 'label'], - option: ['disabled:v', 'label', 'selected:v', 'value'], - textarea: ['autocomplete:o', 'autofocus:v', 'cols', 'dirname', 'disabled:v', 'form', 'inputmode:im', 'maxlength', 'minlength', 'name', 'placeholder', 'readonly:v', 'required:v', 'rows', 'wrap:w'], - keygen: ['autofocus:v', 'challenge', 'disabled:v', 'form', 'keytype', 'name'], - output: ['for', 'form', 'name'], - progress: ['value', 'max'], - meter: ['value', 'min', 'max', 'low', 'high', 'optimum'], - details: ['open:v'], - summary: none, - menu: ['type:mt', 'label'], - menuitem: ['type:mit', 'label', 'icon', 'disabled:v', 'checked:v', 'radiogroup', 'default:v', 'command'], - dialog: ['open:v'] + // HTML tag information sourced from http://www.w3.org/TR/2015/WD-html51-20151008/ + var html5Tags : { [tag:string]: TagSpecification } = { + // The root element + html: new TagSpecification( + 'The html element represents the root of an HTML document.', + ['manifest']), + // Document metadata + head: new TagSpecification( + 'The head element represents a collection of metadata for the Document.', + none), + title: new TagSpecification( + 'The title element represents the document\'s title or name. Authors should use titles that identify their documents even when they are used out of context, for example in a user\'s history or bookmarks, or in search results. The document\'s title is often different from its first heading, since the first heading does not have to stand alone when taken out of context.', + none), + base: new TagSpecification( + 'The base element allows authors to specify the document base URL for the purposes of resolving relative URLs, and the name of the default browsing context for the purposes of following hyperlinks. The element does not represent any content beyond this information.', + ['href', 'target']), + link: new TagSpecification( + 'The link element allows authors to link their document to other resources.', + ['href', 'crossorigin:xo', 'rel', 'media', 'hreflang', 'type', 'sizes']), + meta: new TagSpecification( + 'The meta element represents various kinds of metadata that cannot be expressed using the title, base, link, style, and script elements.', + ['name', 'http-equiv', 'content', 'charset']), + style: new TagSpecification( + 'The style element allows authors to embed style information in their documents. The style element is one of several inputs to the styling processing model. The element does not represent content for the user.', + ['media', 'nonce', 'type', 'scoped:v']), + // Sections + body: new TagSpecification( + 'The body element represents the content of the document.', + ['onafterprint', 'onbeforeprint', 'onbeforeunload', 'onhashchange', 'onlanguagechange', 'onmessage', 'onoffline', 'ononline', 'onpagehide', 'onpageshow', 'onpopstate', 'onstorage', 'onunload']), + article: new TagSpecification( + 'The article element represents a complete, or self-contained, composition in a document, page, application, or site and that is, in principle, independently distributable or reusable, e.g. in syndication. This could be a forum post, a magazine or newspaper article, a blog entry, a user-submitted comment, an interactive widget or gadget, or any other independent item of content. Each article should be identified, typically by including a heading (h1–h6 element) as a child of the article element.', + none), + section: new TagSpecification( + 'The section element represents a generic section of a document or application. A section, in this context, is a thematic grouping of content. Each section should be identified, typically by including a heading ( h1- h6 element) as a child of the section element.', + none), + nav: new TagSpecification( + 'The nav element represents a section of a page that links to other pages or to parts within the page: a section with navigation links.', + none), + aside: new TagSpecification( + 'The aside element represents a section of a page that consists of content that is tangentially related to the content around the aside element, and which could be considered separate from that content. Such sections are often represented as sidebars in printed typography.', + none), + h1: new TagSpecification( + 'The h1 element represents a section heading.', + none), + h2: new TagSpecification( + 'The h2 element represents a section heading.', + none), + h3: new TagSpecification( + 'The h3 element represents a section heading.', + none), + h4: new TagSpecification( + 'The h4 element represents a section heading.', + none), + h5: new TagSpecification( + 'The h5 element represents a section heading.', + none), + h6: new TagSpecification( + 'The h6 element represents a section heading.', + none), + header: new TagSpecification( + 'The header element represents introductory content for its nearest ancestor sectioning content or sectioning root element. A header typically contains a group of introductory or navigational aids. When the nearest ancestor sectioning content or sectioning root element is the body element, then it applies to the whole page.', + none), + footer: new TagSpecification( + 'The footer element represents a footer for its nearest ancestor sectioning content or sectioning root element. A footer typically contains information about its section such as who wrote it, links to related documents, copyright data, and the like.', + none), + address: new TagSpecification( + 'The address element represents the contact information for its nearest article or body element ancestor. If that is the body element, then the contact information applies to the document as a whole.', + none), + // Grouping content + p: new TagSpecification( + 'The p element represents a paragraph.', + none), + hr: new TagSpecification( + 'The hr element represents a paragraph-level thematic break, e.g. a scene change in a story, or a transition to another topic within a section of a reference book.', + none), + pre: new TagSpecification( + 'The pre element represents a block of preformatted text, in which structure is represented by typographic conventions rather than by elements.', + none), + blockquote: new TagSpecification( + 'The blockquote element represents content that is quoted from another source, optionally with a citation which must be within a footer or cite element, and optionally with in-line changes such as annotations and abbreviations.', + ['cite']), + ol: new TagSpecification( + 'The ol element represents a list of items, where the items have been intentionally ordered, such that changing the order would change the meaning of the document.', + ['reversed:v', 'start', 'type:lt']), + ul: new TagSpecification( + 'The ul element represents a list of items, where the order of the items is not important — that is, where changing the order would not materially change the meaning of the document.', + none), + li: new TagSpecification( + 'The li element represents a list item. If its parent element is an ol, ul, or menu element, then the element is an item of the parent element\'s list, as defined for those elements. Otherwise, the list item has no defined list-related relationship to any other li element.', + ['value']), + dl: new TagSpecification( + 'The dl element represents an association list consisting of zero or more name-value groups (a description list). A name-value group consists of one or more names (dt elements) followed by one or more values (dd elements), ignoring any nodes other than dt and dd elements. Within a single dl element, there should not be more than one dt element for each name.', + none), + dt: new TagSpecification( + 'The dt element represents the term, or name, part of a term-description group in a description list (dl element).', + none), + dd: new TagSpecification( + 'The dd element represents the description, definition, or value, part of a term-description group in a description list (dl element).', + none), + figure: new TagSpecification( + 'The figure element represents some flow content, optionally with a caption, that is self-contained (like a complete sentence) and is typically referenced as a single unit from the main flow of the document.', + none), + figcaption: new TagSpecification( + 'The figcaption element represents a caption or legend for the rest of the contents of the figcaption element\'s parent figure element, if any.', + none), + main: new TagSpecification( + 'The main element represents the main content of the body of a document or application. The main content area consists of content that is directly related to or expands upon the central topic of a document or central functionality of an application.', + none), + div: new TagSpecification( + 'The div element has no special meaning at all. It represents its children. It can be used with the class, lang, and title attributes to mark up semantics common to a group of consecutive elements.', + none), + // Text-level semantics + a: new TagSpecification( + 'If the a element has an href attribute, then it represents a hyperlink (a hypertext anchor) labeled by its contents.', + ['href', 'target', 'download', 'ping', 'rel', 'hreflang', 'type']), + em: new TagSpecification( + 'The em element represents stress emphasis of its contents.', + none), + strong: new TagSpecification( + 'The strong element represents strong importance, seriousness, or urgency for its contents.', + none), + small: new TagSpecification( + 'The small element represents side comments such as small print.', + none), + s: new TagSpecification( + 'The s element represents contents that are no longer accurate or no longer relevant.', + none), + cite: new TagSpecification( + 'The cite element represents a reference to a creative work. It must include the title of the work or the name of the author(person, people or organization) or an URL reference, or a reference in abbreviated form as per the conventions used for the addition of citation metadata.', + none), + q: new TagSpecification( + 'The q element represents some phrasing content quoted from another source.', + ['cite']), + dfn: new TagSpecification( + 'The dfn element represents the defining instance of a term. The paragraph, description list group, or section that is the nearest ancestor of the dfn element must also contain the definition(s) for the term given by the dfn element.', + none), + abbr: new TagSpecification( + 'The abbr element represents an abbreviation or acronym, optionally with its expansion. The title attribute may be used to provide an expansion of the abbreviation. The attribute, if specified, must contain an expansion of the abbreviation, and nothing else.', + none), + ruby: new TagSpecification( + 'The ruby element allows one or more spans of phrasing content to be marked with ruby annotations. Ruby annotations are short runs of text presented alongside base text, primarily used in East Asian typography as a guide for pronunciation or to include other annotations. In Japanese, this form of typography is also known as furigana. Ruby text can appear on either side, and sometimes both sides, of the base text, and it is possible to control its position using CSS. A more complete introduction to ruby can be found in the Use Cases & Exploratory Approaches for Ruby Markup document as well as in CSS Ruby Module Level 1. [RUBY-UC] [CSSRUBY]', + none), + rb: new TagSpecification( + 'The rb element marks the base text component of a ruby annotation. When it is the child of a ruby element, it doesn\'t represent anything itself, but its parent ruby element uses it as part of determining what it represents.', + none), + rt: new TagSpecification( + 'The rt element marks the ruby text component of a ruby annotation. When it is the child of a ruby element or of an rtc element that is itself the child of a ruby element, it doesn\'t represent anything itself, but its ancestor ruby element uses it as part of determining what it represents.', + none), + rtc: new TagSpecification( + 'The rtc element marks a ruby text container for ruby text components in a ruby annotation. When it is the child of a ruby element it doesn\'t represent anything itself, but its parent ruby element uses it as part of determining what it represents.', + none), + rp: new TagSpecification( + 'The rp element is used to provide fallback text to be shown by user agents that don\'t support ruby annotations. One widespread convention is to provide parentheses around the ruby text component of a ruby annotation.', + none), + data: new TagSpecification( + 'The data element represents its contents, along with a machine-readable form of those contents in the value attribute.', + none), + time: new TagSpecification( + 'The time element represents its contents, along with a machine-readable form of those contents in the datetime attribute. The kind of content is limited to various kinds of dates, times, time-zone offsets, and durations, as described below.', + ['datetime']), + code: new TagSpecification( + 'The code element represents a fragment of computer code. This could be an XML element name, a file name, a computer program, or any other string that a computer would recognize.', + none), + var: new TagSpecification( + 'The var element represents a variable. This could be an actual variable in a mathematical expression or programming context, an identifier representing a constant, a symbol identifying a physical quantity, a function parameter, or just be a term used as a placeholder in prose.', + none), + samp: new TagSpecification( + 'The samp element represents sample or quoted output from another program or computing system.', + none), + kbd: new TagSpecification( + 'The kbd element represents user input (typically keyboard input, although it may also be used to represent other input, such as voice commands).', + none), + sub: new TagSpecification( + 'The sub element represents a subscript.', + none), + sup: new TagSpecification( + 'The sup element represents a superscript.', + none), + i: new TagSpecification( + 'The i element represents a span of text in an alternate voice or mood, or otherwise offset from the normal prose in a manner indicating a different quality of text, such as a taxonomic designation, a technical term, an idiomatic phrase from another language, transliteration, a thought, or a ship name in Western texts.', + none), + b: new TagSpecification( + 'The b element represents a span of text to which attention is being drawn for utilitarian purposes without conveying any extra importance and with no implication of an alternate voice or mood, such as key words in a document abstract, product names in a review, actionable words in interactive text-driven software, or an article lede.', + none), + u: new TagSpecification( + 'The u element represents a span of text with an unarticulated, though explicitly rendered, non-textual annotation, such as labeling the text as being a proper name in Chinese text (a Chinese proper name mark), or labeling the text as being misspelt.', + none), + mark: new TagSpecification( + 'The mark element represents a run of text in one document marked or highlighted for reference purposes, due to its relevance in another context. When used in a quotation or other block of text referred to from the prose, it indicates a highlight that was not originally present but which has been added to bring the reader\'s attention to a part of the text that might not have been considered important by the original author when the block was originally written, but which is now under previously unexpected scrutiny. When used in the main prose of a document, it indicates a part of the document that has been highlighted due to its likely relevance to the user\'s current activity.', + none), + bdi: new TagSpecification( + 'The bdi element represents a span of text that is to be isolated from its surroundings for the purposes of bidirectional text formatting. [BIDI]', + none), + bdo: new TagSpecification( + 'The bdo element represents explicit text directionality formatting control for its children. It allows authors to override the Unicode bidirectional algorithm by explicitly specifying a direction override. [BIDI]', + none), + span: new TagSpecification( + 'The span element doesn\'t mean anything on its own, but can be useful when used together with the global attributes, e.g. class, lang, or dir. It represents its children.', + none), + br: new TagSpecification( + 'The br element represents a line break.', + none), + wbr: new TagSpecification( + 'The wbr element represents a line break opportunity.', + none), + // Edits + ins: new TagSpecification( + 'The ins element represents an addition to the document.', + none), + del: new TagSpecification( + 'The del element represents a removal from the document.', + ['cite', 'datetime']), + // Embedded content + picture: new TagSpecification( + 'The picture element is a container which provides multiple sources to its contained img element to allow authors to declaratively control or give hints to the user agent about which image resource to use, based on the screen pixel density, viewport size, image format, and other factors. It represents its children.', + none), + img: new TagSpecification( + 'An img element represents an image.', + ['alt', 'src', 'srcset', 'crossorigin:xo', 'usemap', 'ismap:v', 'width', 'height']), + iframe: new TagSpecification( + 'The iframe element represents a nested browsing context.', + ['src', 'srcdoc', 'name', 'sandbox:sb', 'seamless:v', 'allowfullscreen:v', 'width', 'height']), + embed: new TagSpecification( + 'The embed element provides an integration point for an external (typically non-HTML) application or interactive content.', + ['src', 'type', 'width', 'height']), + object: new TagSpecification( + 'The object element can represent an external resource, which, depending on the type of the resource, will either be treated as an image, as a nested browsing context, or as an external resource to be processed by a plugin.', + ['data', 'type', 'typemustmatch:v', 'name', 'usemap', 'form', 'width', 'height']), + param: new TagSpecification( + 'The param element defines parameters for plugins invoked by object elements. It does not represent anything on its own.', + ['name', 'value']), + video: new TagSpecification( + 'A video element is used for playing videos or movies, and audio files with captions.', + ['src', 'crossorigin:xo', 'poster', 'preload:pl', 'autoplay:v', 'mediagroup', 'loop:v', 'muted:v', 'controls:v', 'width', 'height']), + audio: new TagSpecification( + 'An audio element represents a sound or audio stream.', + ['src', 'crossorigin:xo', 'preload:pl', 'autoplay:v', 'mediagroup', 'loop:v', 'muted:v', 'controls:v']), + source: new TagSpecification( + 'The source element allows authors to specify multiple alternative media resources for media elements. It does not represent anything on its own.', + // 'When the source element has a parent that is a picture element, the source element allows authors to specify multiple alternative source sets for img elements.' + ['src', 'type']), + track: new TagSpecification( + 'The track element allows authors to specify explicit external timed text tracks for media elements. It does not represent anything on its own.', + ['default:v', 'kind:tk', 'label', 'src', 'srclang']), + map: new TagSpecification( + 'The map element, in conjunction with an img element and any area element descendants, defines an image map. The element represents its children.', + ['name']), + area: new TagSpecification( + 'The area element represents either a hyperlink with some text and a corresponding area on an image map, or a dead area on an image map.', + ['alt', 'coords', 'shape:sh', 'href', 'target', 'download', 'ping', 'rel', 'hreflang', 'type']), + // Tabular data + table: new TagSpecification( + 'The table element represents data with more than one dimension, in the form of a table.', + ['sortable:v', 'border']), + caption: new TagSpecification( + 'The caption element represents the title of the table that is its parent, if it has a parent and that is a table element.', + none), + colgroup: new TagSpecification( + 'The colgroup element represents a group of one or more columns in the table that is its parent, if it has a parent and that is a table element.', + ['span']), + col: new TagSpecification( + 'If a col element has a parent and that is a colgroup element that itself has a parent that is a table element, then the col element represents one or more columns in the column group represented by that colgroup.', + ['span']), + tbody: new TagSpecification( + 'The tbody element represents a block of rows that consist of a body of data for the parent table element, if the tbody element has a parent and it is a table.', + none), + thead: new TagSpecification( + 'The thead element represents the block of rows that consist of the column labels (headers) for the parent table element, if the thead element has a parent and it is a table.', + none), + tfoot: new TagSpecification( + 'The tfoot element represents the block of rows that consist of the column summaries (footers) for the parent table element, if the tfoot element has a parent and it is a table.', + none), + tr: new TagSpecification( + 'The tr element represents a row of cells in a table.', + none), + td: new TagSpecification( + 'The td element represents a data cell in a table.', + ['colspan', 'rowspan', 'headers']), + th: new TagSpecification( + 'The th element represents a header cell in a table.', + ['colspan', 'rowspan', 'headers', 'scope:s', 'sorted', 'abbr']), + // Forms + form: new TagSpecification( + 'The form element represents a collection of form-associated elements, some of which can represent editable values that can be submitted to a server for processing.', + ['accept-charset', 'action', 'autocomplete:o', 'enctype:et', 'method:m', 'name', 'novalidate:v', 'target']), + label: new TagSpecification( + 'The label element represents a caption in a user interface. The caption can be associated with a specific form control, known as the label element\'s labeled control, either using the for attribute, or by putting the form control inside the label element itself.', + ['form', 'for']), + input: new TagSpecification( + 'The input element represents a typed data field, usually with a form control to allow the user to edit the data.', + ['accept', 'alt', 'autocomplete:o', 'autofocus:v', 'checked:v', 'dirname', 'disabled:v', 'form', 'formaction', 'formenctype:et', 'formmethod:fm', 'formnovalidate:v', 'formtarget', 'height', 'inputmode:im', 'list', 'max', 'maxlength', 'min', 'minlength', 'multiple:v', 'name', 'pattern', 'placeholder', 'readonly:v', 'required:v', 'size', 'src', 'step', 'type:t', 'value', 'width']), + button: new TagSpecification( + 'The button element represents a button labeled by its contents.', + ['autofocus:v', 'disabled:v', 'form', 'formaction', 'formenctype:et', 'formmethod:fm', 'formnovalidate:v', 'formtarget', 'name', 'type:bt', 'value']), + select: new TagSpecification( + 'The select element represents a control for selecting amongst a set of options.', + ['autocomplete:o', 'autofocus:v', 'disabled:v', 'form', 'multiple:v', 'name', 'required:v', 'size']), + datalist: new TagSpecification( + 'The datalist element represents a set of option elements that represent predefined options for other controls. In the rendering, the datalist element represents nothing and it, along with its children, should be hidden.', + none), + optgroup: new TagSpecification( + 'The optgroup element represents a group of option elements with a common label.', + ['disabled:v', 'label']), + option: new TagSpecification( + 'The option element represents an option in a select element or as part of a list of suggestions in a datalist element.', + ['disabled:v', 'label', 'selected:v', 'value']), + textarea: new TagSpecification( + 'The textarea element represents a multiline plain text edit control for the element\'s raw value. The contents of the control represent the control\'s default value.', + ['autocomplete:o', 'autofocus:v', 'cols', 'dirname', 'disabled:v', 'form', 'inputmode:im', 'maxlength', 'minlength', 'name', 'placeholder', 'readonly:v', 'required:v', 'rows', 'wrap:w']), + output: new TagSpecification( + 'The output element represents the result of a calculation performed by the application, or the result of a user action.', + ['for', 'form', 'name']), + progress: new TagSpecification( + 'The progress element represents the completion progress of a task. The progress is either indeterminate, indicating that progress is being made but that it is not clear how much more work remains to be done before the task is complete (e.g. because the task is waiting for a remote host to respond), or the progress is a number in the range zero to a maximum, giving the fraction of work that has so far been completed.', + ['value', 'max']), + meter: new TagSpecification( + 'The meter element represents a scalar measurement within a known range, or a fractional value; for example disk usage, the relevance of a query result, or the fraction of a voting population to have selected a particular candidate.', + ['value', 'min', 'max', 'low', 'high', 'optimum']), + fieldset: new TagSpecification( + 'The fieldset element represents a set of form controls optionally grouped under a common name.', + ['disabled:v', 'form', 'name']), + legend: new TagSpecification( + 'The legend element represents a caption for the rest of the contents of the legend element\'s parent fieldset element, if any.', + none), + // Interactive elements + details: new TagSpecification( + 'The details element represents a disclosure widget from which the user can obtain additional information or controls.', + ['open:v']), + summary: new TagSpecification( + 'The summary element represents a summary, caption, or legend for the rest of the contents of the summary element\'s parent details element, if any.', + none), + menu: new TagSpecification( + 'The menu element represents a list of commands.', + ['type:mt', 'label']), + menuitem: new TagSpecification( + 'The menuitem element represents a command that the user can invoke from a popup menu (either a context menu or the menu of a menu button).', + none), + dialog: new TagSpecification( + 'The dialog element represents a part of an application that a user interacts with to perform a task, for example a dialog box, inspector, or window.', + none), + // Scripting + script: new TagSpecification( + 'The script element allows authors to include dynamic script and data blocks in their documents. The element does not represent content for the user.', + ['src', 'type', 'charset', 'async:v', 'defer:v', 'crossorigin:xo', 'nonce']), + noscript: new TagSpecification( + 'The noscript element represents nothing if scripting is enabled, and represents its children if scripting is disabled. It is used to present different markup to user agents that support scripting and those that don\'t support scripting, by affecting how the document is parsed.', + none), + template: new TagSpecification( + 'The template element is used to declare fragments of HTML that can be cloned and inserted in the document by script.', + none), + canvas: new TagSpecification( + 'The canvas element provides scripts with a resolution-dependent bitmap canvas, which can be used for rendering graphs, game graphics, art, or other visual images on the fly.', + ['width', 'height']) }; var globalAttributes = [ @@ -193,9 +432,9 @@ export function getHTML5TagProvider(): IHTMLTagProvider { }; return { - collectTags: (collector: (tag: string) => void) => { + collectTags: (collector: (tag: string, label: string) => void) => { for (var tag in html5Tags) { - collector(tag); + collector(tag, html5Tags[tag].label); } }, collectAttributes: (tag: string, collector: (attribute: string, type: string) => void) => { @@ -207,7 +446,7 @@ export function getHTML5TagProvider(): IHTMLTagProvider { collector(handler, 'event'); }); if (tag) { - var attributes = html5Tags[tag]; + var attributes = html5Tags[tag].attributes; if (attributes) { attributes.forEach(attr => { var segments = attr.split(':'); @@ -233,7 +472,7 @@ export function getHTML5TagProvider(): IHTMLTagProvider { } }); }; - var attributes = html5Tags[tag]; + var attributes = html5Tags[tag].attributes; if (attributes) { processAttributes(attributes); } diff --git a/src/vs/languages/html/common/htmlWorker.ts b/src/vs/languages/html/common/htmlWorker.ts index 8a765294aa7..6cc202ec386 100644 --- a/src/vs/languages/html/common/htmlWorker.ts +++ b/src/vs/languages/html/common/htmlWorker.ts @@ -231,11 +231,12 @@ export class HTMLWorker extends AbstractModeWorker { this._tagProviders.forEach((provider) => { - provider.collectTags((tag) => { + provider.collectTags((tag, label) => { suggestions.suggestions.push({ label: '/' + tag, codeSnippet: '/' + tag + closeTag, - type: 'property' + type: 'property', + documentationLabel: label }); }); }); @@ -244,11 +245,12 @@ export class HTMLWorker extends AbstractModeWorker { collectClosingTagSuggestion(false); this._tagProviders.forEach((provider) => { - provider.collectTags((tag) => { + provider.collectTags((tag, label) => { suggestions.suggestions.push({ label: tag, codeSnippet: tag, - type: 'property' + type: 'property', + documentationLabel: label }); }); }); From a8b32ee6800681be5c11563406200a349c31b2b2 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 26 Nov 2015 18:45:50 -0800 Subject: [PATCH 153/588] Rename TagSpecification to HTMLTagSpecification --- .../html/common/htmlTagSpecifications.ts | 290 ++++++++++++++ src/vs/languages/html/common/htmlTags.ts | 370 +----------------- 2 files changed, 295 insertions(+), 365 deletions(-) create mode 100644 src/vs/languages/html/common/htmlTagSpecifications.ts diff --git a/src/vs/languages/html/common/htmlTagSpecifications.ts b/src/vs/languages/html/common/htmlTagSpecifications.ts new file mode 100644 index 00000000000..765a1f658c8 --- /dev/null +++ b/src/vs/languages/html/common/htmlTagSpecifications.ts @@ -0,0 +1,290 @@ +export class HTMLTagSpecification { + constructor(public label: string, public attributes: string[] = []) {} +} + +// HTML tag information sourced from http://www.w3.org/TR/2015/WD-html51-20151008/ +export const HTML_TAGS : { [tag:string]: HTMLTagSpecification } = { + // The root element + html: new HTMLTagSpecification( + 'The html element represents the root of an HTML document.', + ['manifest']), + // Document metadata + head: new HTMLTagSpecification( + 'The head element represents a collection of metadata for the Document.'), + title: new HTMLTagSpecification( + 'The title element represents the document\'s title or name. Authors should use titles that identify their documents even when they are used out of context, for example in a user\'s history or bookmarks, or in search results. The document\'s title is often different from its first heading, since the first heading does not have to stand alone when taken out of context.'), + base: new HTMLTagSpecification( + 'The base element allows authors to specify the document base URL for the purposes of resolving relative URLs, and the name of the default browsing context for the purposes of following hyperlinks. The element does not represent any content beyond this information.', + ['href', 'target']), + link: new HTMLTagSpecification( + 'The link element allows authors to link their document to other resources.', + ['href', 'crossorigin:xo', 'rel', 'media', 'hreflang', 'type', 'sizes']), + meta: new HTMLTagSpecification( + 'The meta element represents various kinds of metadata that cannot be expressed using the title, base, link, style, and script elements.', + ['name', 'http-equiv', 'content', 'charset']), + style: new HTMLTagSpecification( + 'The style element allows authors to embed style information in their documents. The style element is one of several inputs to the styling processing model. The element does not represent content for the user.', + ['media', 'nonce', 'type', 'scoped:v']), + // Sections + body: new HTMLTagSpecification( + 'The body element represents the content of the document.', + ['onafterprint', 'onbeforeprint', 'onbeforeunload', 'onhashchange', 'onlanguagechange', 'onmessage', 'onoffline', 'ononline', 'onpagehide', 'onpageshow', 'onpopstate', 'onstorage', 'onunload']), + article: new HTMLTagSpecification( + 'The article element represents a complete, or self-contained, composition in a document, page, application, or site and that is, in principle, independently distributable or reusable, e.g. in syndication. This could be a forum post, a magazine or newspaper article, a blog entry, a user-submitted comment, an interactive widget or gadget, or any other independent item of content. Each article should be identified, typically by including a heading (h1–h6 element) as a child of the article element.'), + section: new HTMLTagSpecification( + 'The section element represents a generic section of a document or application. A section, in this context, is a thematic grouping of content. Each section should be identified, typically by including a heading ( h1- h6 element) as a child of the section element.'), + nav: new HTMLTagSpecification( + 'The nav element represents a section of a page that links to other pages or to parts within the page: a section with navigation links.'), + aside: new HTMLTagSpecification( + 'The aside element represents a section of a page that consists of content that is tangentially related to the content around the aside element, and which could be considered separate from that content. Such sections are often represented as sidebars in printed typography.'), + h1: new HTMLTagSpecification( + 'The h1 element represents a section heading.'), + h2: new HTMLTagSpecification( + 'The h2 element represents a section heading.'), + h3: new HTMLTagSpecification( + 'The h3 element represents a section heading.'), + h4: new HTMLTagSpecification( + 'The h4 element represents a section heading.'), + h5: new HTMLTagSpecification( + 'The h5 element represents a section heading.'), + h6: new HTMLTagSpecification( + 'The h6 element represents a section heading.'), + header: new HTMLTagSpecification( + 'The header element represents introductory content for its nearest ancestor sectioning content or sectioning root element. A header typically contains a group of introductory or navigational aids. When the nearest ancestor sectioning content or sectioning root element is the body element, then it applies to the whole page.'), + footer: new HTMLTagSpecification( + 'The footer element represents a footer for its nearest ancestor sectioning content or sectioning root element. A footer typically contains information about its section such as who wrote it, links to related documents, copyright data, and the like.'), + address: new HTMLTagSpecification( + 'The address element represents the contact information for its nearest article or body element ancestor. If that is the body element, then the contact information applies to the document as a whole.'), + // Grouping content + p: new HTMLTagSpecification( + 'The p element represents a paragraph.'), + hr: new HTMLTagSpecification( + 'The hr element represents a paragraph-level thematic break, e.g. a scene change in a story, or a transition to another topic within a section of a reference book.'), + pre: new HTMLTagSpecification( + 'The pre element represents a block of preformatted text, in which structure is represented by typographic conventions rather than by elements.'), + blockquote: new HTMLTagSpecification( + 'The blockquote element represents content that is quoted from another source, optionally with a citation which must be within a footer or cite element, and optionally with in-line changes such as annotations and abbreviations.', + ['cite']), + ol: new HTMLTagSpecification( + 'The ol element represents a list of items, where the items have been intentionally ordered, such that changing the order would change the meaning of the document.', + ['reversed:v', 'start', 'type:lt']), + ul: new HTMLTagSpecification( + 'The ul element represents a list of items, where the order of the items is not important — that is, where changing the order would not materially change the meaning of the document.'), + li: new HTMLTagSpecification( + 'The li element represents a list item. If its parent element is an ol, ul, or menu element, then the element is an item of the parent element\'s list, as defined for those elements. Otherwise, the list item has no defined list-related relationship to any other li element.', + ['value']), + dl: new HTMLTagSpecification( + 'The dl element represents an association list consisting of zero or more name-value groups (a description list). A name-value group consists of one or more names (dt elements) followed by one or more values (dd elements), ignoring any nodes other than dt and dd elements. Within a single dl element, there should not be more than one dt element for each name.'), + dt: new HTMLTagSpecification( + 'The dt element represents the term, or name, part of a term-description group in a description list (dl element).'), + dd: new HTMLTagSpecification( + 'The dd element represents the description, definition, or value, part of a term-description group in a description list (dl element).'), + figure: new HTMLTagSpecification( + 'The figure element represents some flow content, optionally with a caption, that is self-contained (like a complete sentence) and is typically referenced as a single unit from the main flow of the document.'), + figcaption: new HTMLTagSpecification( + 'The figcaption element represents a caption or legend for the rest of the contents of the figcaption element\'s parent figure element, if any.'), + main: new HTMLTagSpecification( + 'The main element represents the main content of the body of a document or application. The main content area consists of content that is directly related to or expands upon the central topic of a document or central functionality of an application.'), + div: new HTMLTagSpecification( + 'The div element has no special meaning at all. It represents its children. It can be used with the class, lang, and title attributes to mark up semantics common to a group of consecutive elements.'), + // Text-level semantics + a: new HTMLTagSpecification( + 'If the a element has an href attribute, then it represents a hyperlink (a hypertext anchor) labeled by its contents.', + ['href', 'target', 'download', 'ping', 'rel', 'hreflang', 'type']), + em: new HTMLTagSpecification( + 'The em element represents stress emphasis of its contents.'), + strong: new HTMLTagSpecification( + 'The strong element represents strong importance, seriousness, or urgency for its contents.'), + small: new HTMLTagSpecification( + 'The small element represents side comments such as small print.'), + s: new HTMLTagSpecification( + 'The s element represents contents that are no longer accurate or no longer relevant.'), + cite: new HTMLTagSpecification( + 'The cite element represents a reference to a creative work. It must include the title of the work or the name of the author(person, people or organization) or an URL reference, or a reference in abbreviated form as per the conventions used for the addition of citation metadata.'), + q: new HTMLTagSpecification( + 'The q element represents some phrasing content quoted from another source.', + ['cite']), + dfn: new HTMLTagSpecification( + 'The dfn element represents the defining instance of a term. The paragraph, description list group, or section that is the nearest ancestor of the dfn element must also contain the definition(s) for the term given by the dfn element.'), + abbr: new HTMLTagSpecification( + 'The abbr element represents an abbreviation or acronym, optionally with its expansion. The title attribute may be used to provide an expansion of the abbreviation. The attribute, if specified, must contain an expansion of the abbreviation, and nothing else.'), + ruby: new HTMLTagSpecification( + 'The ruby element allows one or more spans of phrasing content to be marked with ruby annotations. Ruby annotations are short runs of text presented alongside base text, primarily used in East Asian typography as a guide for pronunciation or to include other annotations. In Japanese, this form of typography is also known as furigana. Ruby text can appear on either side, and sometimes both sides, of the base text, and it is possible to control its position using CSS. A more complete introduction to ruby can be found in the Use Cases & Exploratory Approaches for Ruby Markup document as well as in CSS Ruby Module Level 1. [RUBY-UC] [CSSRUBY]'), + rb: new HTMLTagSpecification( + 'The rb element marks the base text component of a ruby annotation. When it is the child of a ruby element, it doesn\'t represent anything itself, but its parent ruby element uses it as part of determining what it represents.'), + rt: new HTMLTagSpecification( + 'The rt element marks the ruby text component of a ruby annotation. When it is the child of a ruby element or of an rtc element that is itself the child of a ruby element, it doesn\'t represent anything itself, but its ancestor ruby element uses it as part of determining what it represents.'), + rtc: new HTMLTagSpecification( + 'The rtc element marks a ruby text container for ruby text components in a ruby annotation. When it is the child of a ruby element it doesn\'t represent anything itself, but its parent ruby element uses it as part of determining what it represents.'), + rp: new HTMLTagSpecification( + 'The rp element is used to provide fallback text to be shown by user agents that don\'t support ruby annotations. One widespread convention is to provide parentheses around the ruby text component of a ruby annotation.'), + data: new HTMLTagSpecification( + 'The data element represents its contents, along with a machine-readable form of those contents in the value attribute.'), + time: new HTMLTagSpecification( + 'The time element represents its contents, along with a machine-readable form of those contents in the datetime attribute. The kind of content is limited to various kinds of dates, times, time-zone offsets, and durations, as described below.', + ['datetime']), + code: new HTMLTagSpecification( + 'The code element represents a fragment of computer code. This could be an XML element name, a file name, a computer program, or any other string that a computer would recognize.'), + var: new HTMLTagSpecification( + 'The var element represents a variable. This could be an actual variable in a mathematical expression or programming context, an identifier representing a constant, a symbol identifying a physical quantity, a function parameter, or just be a term used as a placeholder in prose.'), + samp: new HTMLTagSpecification( + 'The samp element represents sample or quoted output from another program or computing system.'), + kbd: new HTMLTagSpecification( + 'The kbd element represents user input (typically keyboard input, although it may also be used to represent other input, such as voice commands).'), + sub: new HTMLTagSpecification( + 'The sub element represents a subscript.'), + sup: new HTMLTagSpecification( + 'The sup element represents a superscript.'), + i: new HTMLTagSpecification( + 'The i element represents a span of text in an alternate voice or mood, or otherwise offset from the normal prose in a manner indicating a different quality of text, such as a taxonomic designation, a technical term, an idiomatic phrase from another language, transliteration, a thought, or a ship name in Western texts.'), + b: new HTMLTagSpecification( + 'The b element represents a span of text to which attention is being drawn for utilitarian purposes without conveying any extra importance and with no implication of an alternate voice or mood, such as key words in a document abstract, product names in a review, actionable words in interactive text-driven software, or an article lede.'), + u: new HTMLTagSpecification( + 'The u element represents a span of text with an unarticulated, though explicitly rendered, non-textual annotation, such as labeling the text as being a proper name in Chinese text (a Chinese proper name mark), or labeling the text as being misspelt.'), + mark: new HTMLTagSpecification( + 'The mark element represents a run of text in one document marked or highlighted for reference purposes, due to its relevance in another context. When used in a quotation or other block of text referred to from the prose, it indicates a highlight that was not originally present but which has been added to bring the reader\'s attention to a part of the text that might not have been considered important by the original author when the block was originally written, but which is now under previously unexpected scrutiny. When used in the main prose of a document, it indicates a part of the document that has been highlighted due to its likely relevance to the user\'s current activity.'), + bdi: new HTMLTagSpecification( + 'The bdi element represents a span of text that is to be isolated from its surroundings for the purposes of bidirectional text formatting. [BIDI]'), + bdo: new HTMLTagSpecification( + 'The bdo element represents explicit text directionality formatting control for its children. It allows authors to override the Unicode bidirectional algorithm by explicitly specifying a direction override. [BIDI]'), + span: new HTMLTagSpecification( + 'The span element doesn\'t mean anything on its own, but can be useful when used together with the global attributes, e.g. class, lang, or dir. It represents its children.'), + br: new HTMLTagSpecification( + 'The br element represents a line break.'), + wbr: new HTMLTagSpecification( + 'The wbr element represents a line break opportunity.'), + // Edits + ins: new HTMLTagSpecification( + 'The ins element represents an addition to the document.'), + del: new HTMLTagSpecification( + 'The del element represents a removal from the document.', + ['cite', 'datetime']), + // Embedded content + picture: new HTMLTagSpecification( + 'The picture element is a container which provides multiple sources to its contained img element to allow authors to declaratively control or give hints to the user agent about which image resource to use, based on the screen pixel density, viewport size, image format, and other factors. It represents its children.'), + img: new HTMLTagSpecification( + 'An img element represents an image.', + ['alt', 'src', 'srcset', 'crossorigin:xo', 'usemap', 'ismap:v', 'width', 'height']), + iframe: new HTMLTagSpecification( + 'The iframe element represents a nested browsing context.', + ['src', 'srcdoc', 'name', 'sandbox:sb', 'seamless:v', 'allowfullscreen:v', 'width', 'height']), + embed: new HTMLTagSpecification( + 'The embed element provides an integration point for an external (typically non-HTML) application or interactive content.', + ['src', 'type', 'width', 'height']), + object: new HTMLTagSpecification( + 'The object element can represent an external resource, which, depending on the type of the resource, will either be treated as an image, as a nested browsing context, or as an external resource to be processed by a plugin.', + ['data', 'type', 'typemustmatch:v', 'name', 'usemap', 'form', 'width', 'height']), + param: new HTMLTagSpecification( + 'The param element defines parameters for plugins invoked by object elements. It does not represent anything on its own.', + ['name', 'value']), + video: new HTMLTagSpecification( + 'A video element is used for playing videos or movies, and audio files with captions.', + ['src', 'crossorigin:xo', 'poster', 'preload:pl', 'autoplay:v', 'mediagroup', 'loop:v', 'muted:v', 'controls:v', 'width', 'height']), + audio: new HTMLTagSpecification( + 'An audio element represents a sound or audio stream.', + ['src', 'crossorigin:xo', 'preload:pl', 'autoplay:v', 'mediagroup', 'loop:v', 'muted:v', 'controls:v']), + source: new HTMLTagSpecification( + 'The source element allows authors to specify multiple alternative media resources for media elements. It does not represent anything on its own.', + // 'When the source element has a parent that is a picture element, the source element allows authors to specify multiple alternative source sets for img elements.' + ['src', 'type']), + track: new HTMLTagSpecification( + 'The track element allows authors to specify explicit external timed text tracks for media elements. It does not represent anything on its own.', + ['default:v', 'kind:tk', 'label', 'src', 'srclang']), + map: new HTMLTagSpecification( + 'The map element, in conjunction with an img element and any area element descendants, defines an image map. The element represents its children.', + ['name']), + area: new HTMLTagSpecification( + 'The area element represents either a hyperlink with some text and a corresponding area on an image map, or a dead area on an image map.', + ['alt', 'coords', 'shape:sh', 'href', 'target', 'download', 'ping', 'rel', 'hreflang', 'type']), + // Tabular data + table: new HTMLTagSpecification( + 'The table element represents data with more than one dimension, in the form of a table.', + ['sortable:v', 'border']), + caption: new HTMLTagSpecification( + 'The caption element represents the title of the table that is its parent, if it has a parent and that is a table element.'), + colgroup: new HTMLTagSpecification( + 'The colgroup element represents a group of one or more columns in the table that is its parent, if it has a parent and that is a table element.', + ['span']), + col: new HTMLTagSpecification( + 'If a col element has a parent and that is a colgroup element that itself has a parent that is a table element, then the col element represents one or more columns in the column group represented by that colgroup.', + ['span']), + tbody: new HTMLTagSpecification( + 'The tbody element represents a block of rows that consist of a body of data for the parent table element, if the tbody element has a parent and it is a table.'), + thead: new HTMLTagSpecification( + 'The thead element represents the block of rows that consist of the column labels (headers) for the parent table element, if the thead element has a parent and it is a table.'), + tfoot: new HTMLTagSpecification( + 'The tfoot element represents the block of rows that consist of the column summaries (footers) for the parent table element, if the tfoot element has a parent and it is a table.'), + tr: new HTMLTagSpecification( + 'The tr element represents a row of cells in a table.'), + td: new HTMLTagSpecification( + 'The td element represents a data cell in a table.', + ['colspan', 'rowspan', 'headers']), + th: new HTMLTagSpecification( + 'The th element represents a header cell in a table.', + ['colspan', 'rowspan', 'headers', 'scope:s', 'sorted', 'abbr']), + // Forms + form: new HTMLTagSpecification( + 'The form element represents a collection of form-associated elements, some of which can represent editable values that can be submitted to a server for processing.', + ['accept-charset', 'action', 'autocomplete:o', 'enctype:et', 'method:m', 'name', 'novalidate:v', 'target']), + label: new HTMLTagSpecification( + 'The label element represents a caption in a user interface. The caption can be associated with a specific form control, known as the label element\'s labeled control, either using the for attribute, or by putting the form control inside the label element itself.', + ['form', 'for']), + input: new HTMLTagSpecification( + 'The input element represents a typed data field, usually with a form control to allow the user to edit the data.', + ['accept', 'alt', 'autocomplete:o', 'autofocus:v', 'checked:v', 'dirname', 'disabled:v', 'form', 'formaction', 'formenctype:et', 'formmethod:fm', 'formnovalidate:v', 'formtarget', 'height', 'inputmode:im', 'list', 'max', 'maxlength', 'min', 'minlength', 'multiple:v', 'name', 'pattern', 'placeholder', 'readonly:v', 'required:v', 'size', 'src', 'step', 'type:t', 'value', 'width']), + button: new HTMLTagSpecification( + 'The button element represents a button labeled by its contents.', + ['autofocus:v', 'disabled:v', 'form', 'formaction', 'formenctype:et', 'formmethod:fm', 'formnovalidate:v', 'formtarget', 'name', 'type:bt', 'value']), + select: new HTMLTagSpecification( + 'The select element represents a control for selecting amongst a set of options.', + ['autocomplete:o', 'autofocus:v', 'disabled:v', 'form', 'multiple:v', 'name', 'required:v', 'size']), + datalist: new HTMLTagSpecification( + 'The datalist element represents a set of option elements that represent predefined options for other controls. In the rendering, the datalist element represents nothing and it, along with its children, should be hidden.'), + optgroup: new HTMLTagSpecification( + 'The optgroup element represents a group of option elements with a common label.', + ['disabled:v', 'label']), + option: new HTMLTagSpecification( + 'The option element represents an option in a select element or as part of a list of suggestions in a datalist element.', + ['disabled:v', 'label', 'selected:v', 'value']), + textarea: new HTMLTagSpecification( + 'The textarea element represents a multiline plain text edit control for the element\'s raw value. The contents of the control represent the control\'s default value.', + ['autocomplete:o', 'autofocus:v', 'cols', 'dirname', 'disabled:v', 'form', 'inputmode:im', 'maxlength', 'minlength', 'name', 'placeholder', 'readonly:v', 'required:v', 'rows', 'wrap:w']), + output: new HTMLTagSpecification( + 'The output element represents the result of a calculation performed by the application, or the result of a user action.', + ['for', 'form', 'name']), + progress: new HTMLTagSpecification( + 'The progress element represents the completion progress of a task. The progress is either indeterminate, indicating that progress is being made but that it is not clear how much more work remains to be done before the task is complete (e.g. because the task is waiting for a remote host to respond), or the progress is a number in the range zero to a maximum, giving the fraction of work that has so far been completed.', + ['value', 'max']), + meter: new HTMLTagSpecification( + 'The meter element represents a scalar measurement within a known range, or a fractional value; for example disk usage, the relevance of a query result, or the fraction of a voting population to have selected a particular candidate.', + ['value', 'min', 'max', 'low', 'high', 'optimum']), + fieldset: new HTMLTagSpecification( + 'The fieldset element represents a set of form controls optionally grouped under a common name.', + ['disabled:v', 'form', 'name']), + legend: new HTMLTagSpecification( + 'The legend element represents a caption for the rest of the contents of the legend element\'s parent fieldset element, if any.'), + // Interactive elements + details: new HTMLTagSpecification( + 'The details element represents a disclosure widget from which the user can obtain additional information or controls.', + ['open:v']), + summary: new HTMLTagSpecification( + 'The summary element represents a summary, caption, or legend for the rest of the contents of the summary element\'s parent details element, if any.'), + menu: new HTMLTagSpecification( + 'The menu element represents a list of commands.', + ['type:mt', 'label']), + menuitem: new HTMLTagSpecification( + 'The menuitem element represents a command that the user can invoke from a popup menu (either a context menu or the menu of a menu button).'), + dialog: new HTMLTagSpecification( + 'The dialog element represents a part of an application that a user interacts with to perform a task, for example a dialog box, inspector, or window.'), + // Scripting + script: new HTMLTagSpecification( + 'The script element allows authors to include dynamic script and data blocks in their documents. The element does not represent content for the user.', + ['src', 'type', 'charset', 'async:v', 'defer:v', 'crossorigin:xo', 'nonce']), + noscript: new HTMLTagSpecification( + 'The noscript element represents nothing if scripting is enabled, and represents its children if scripting is disabled. It is used to present different markup to user agents that support scripting and those that don\'t support scripting, by affecting how the document is parsed.'), + template: new HTMLTagSpecification( + 'The template element is used to declare fragments of HTML that can be cloned and inserted in the document by script.'), + canvas: new HTMLTagSpecification( + 'The canvas element provides scripts with a resolution-dependent bitmap canvas, which can be used for rendering graphs, game graphics, art, or other visual images on the fly.', + ['width', 'height']) +}; \ No newline at end of file diff --git a/src/vs/languages/html/common/htmlTags.ts b/src/vs/languages/html/common/htmlTags.ts index 3da9d99e5fc..34078133565 100644 --- a/src/vs/languages/html/common/htmlTags.ts +++ b/src/vs/languages/html/common/htmlTags.ts @@ -5,6 +5,7 @@ import strings = require('vs/base/common/strings'); import arrays = require('vs/base/common/arrays'); +import {HTML_TAGS} from 'vs/languages/html/common/htmlTagSpecifications'; var emptyElements:string[] = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr']; @@ -18,368 +19,7 @@ export interface IHTMLTagProvider { collectValues(tag: string, attribute: string, collector: (value: string) => void): void; } -class TagSpecification { - constructor(public label: string, public attributes: string[]) {} -} - export function getHTML5TagProvider(): IHTMLTagProvider { - var none: string[] = []; - - // HTML tag information sourced from http://www.w3.org/TR/2015/WD-html51-20151008/ - var html5Tags : { [tag:string]: TagSpecification } = { - // The root element - html: new TagSpecification( - 'The html element represents the root of an HTML document.', - ['manifest']), - // Document metadata - head: new TagSpecification( - 'The head element represents a collection of metadata for the Document.', - none), - title: new TagSpecification( - 'The title element represents the document\'s title or name. Authors should use titles that identify their documents even when they are used out of context, for example in a user\'s history or bookmarks, or in search results. The document\'s title is often different from its first heading, since the first heading does not have to stand alone when taken out of context.', - none), - base: new TagSpecification( - 'The base element allows authors to specify the document base URL for the purposes of resolving relative URLs, and the name of the default browsing context for the purposes of following hyperlinks. The element does not represent any content beyond this information.', - ['href', 'target']), - link: new TagSpecification( - 'The link element allows authors to link their document to other resources.', - ['href', 'crossorigin:xo', 'rel', 'media', 'hreflang', 'type', 'sizes']), - meta: new TagSpecification( - 'The meta element represents various kinds of metadata that cannot be expressed using the title, base, link, style, and script elements.', - ['name', 'http-equiv', 'content', 'charset']), - style: new TagSpecification( - 'The style element allows authors to embed style information in their documents. The style element is one of several inputs to the styling processing model. The element does not represent content for the user.', - ['media', 'nonce', 'type', 'scoped:v']), - // Sections - body: new TagSpecification( - 'The body element represents the content of the document.', - ['onafterprint', 'onbeforeprint', 'onbeforeunload', 'onhashchange', 'onlanguagechange', 'onmessage', 'onoffline', 'ononline', 'onpagehide', 'onpageshow', 'onpopstate', 'onstorage', 'onunload']), - article: new TagSpecification( - 'The article element represents a complete, or self-contained, composition in a document, page, application, or site and that is, in principle, independently distributable or reusable, e.g. in syndication. This could be a forum post, a magazine or newspaper article, a blog entry, a user-submitted comment, an interactive widget or gadget, or any other independent item of content. Each article should be identified, typically by including a heading (h1–h6 element) as a child of the article element.', - none), - section: new TagSpecification( - 'The section element represents a generic section of a document or application. A section, in this context, is a thematic grouping of content. Each section should be identified, typically by including a heading ( h1- h6 element) as a child of the section element.', - none), - nav: new TagSpecification( - 'The nav element represents a section of a page that links to other pages or to parts within the page: a section with navigation links.', - none), - aside: new TagSpecification( - 'The aside element represents a section of a page that consists of content that is tangentially related to the content around the aside element, and which could be considered separate from that content. Such sections are often represented as sidebars in printed typography.', - none), - h1: new TagSpecification( - 'The h1 element represents a section heading.', - none), - h2: new TagSpecification( - 'The h2 element represents a section heading.', - none), - h3: new TagSpecification( - 'The h3 element represents a section heading.', - none), - h4: new TagSpecification( - 'The h4 element represents a section heading.', - none), - h5: new TagSpecification( - 'The h5 element represents a section heading.', - none), - h6: new TagSpecification( - 'The h6 element represents a section heading.', - none), - header: new TagSpecification( - 'The header element represents introductory content for its nearest ancestor sectioning content or sectioning root element. A header typically contains a group of introductory or navigational aids. When the nearest ancestor sectioning content or sectioning root element is the body element, then it applies to the whole page.', - none), - footer: new TagSpecification( - 'The footer element represents a footer for its nearest ancestor sectioning content or sectioning root element. A footer typically contains information about its section such as who wrote it, links to related documents, copyright data, and the like.', - none), - address: new TagSpecification( - 'The address element represents the contact information for its nearest article or body element ancestor. If that is the body element, then the contact information applies to the document as a whole.', - none), - // Grouping content - p: new TagSpecification( - 'The p element represents a paragraph.', - none), - hr: new TagSpecification( - 'The hr element represents a paragraph-level thematic break, e.g. a scene change in a story, or a transition to another topic within a section of a reference book.', - none), - pre: new TagSpecification( - 'The pre element represents a block of preformatted text, in which structure is represented by typographic conventions rather than by elements.', - none), - blockquote: new TagSpecification( - 'The blockquote element represents content that is quoted from another source, optionally with a citation which must be within a footer or cite element, and optionally with in-line changes such as annotations and abbreviations.', - ['cite']), - ol: new TagSpecification( - 'The ol element represents a list of items, where the items have been intentionally ordered, such that changing the order would change the meaning of the document.', - ['reversed:v', 'start', 'type:lt']), - ul: new TagSpecification( - 'The ul element represents a list of items, where the order of the items is not important — that is, where changing the order would not materially change the meaning of the document.', - none), - li: new TagSpecification( - 'The li element represents a list item. If its parent element is an ol, ul, or menu element, then the element is an item of the parent element\'s list, as defined for those elements. Otherwise, the list item has no defined list-related relationship to any other li element.', - ['value']), - dl: new TagSpecification( - 'The dl element represents an association list consisting of zero or more name-value groups (a description list). A name-value group consists of one or more names (dt elements) followed by one or more values (dd elements), ignoring any nodes other than dt and dd elements. Within a single dl element, there should not be more than one dt element for each name.', - none), - dt: new TagSpecification( - 'The dt element represents the term, or name, part of a term-description group in a description list (dl element).', - none), - dd: new TagSpecification( - 'The dd element represents the description, definition, or value, part of a term-description group in a description list (dl element).', - none), - figure: new TagSpecification( - 'The figure element represents some flow content, optionally with a caption, that is self-contained (like a complete sentence) and is typically referenced as a single unit from the main flow of the document.', - none), - figcaption: new TagSpecification( - 'The figcaption element represents a caption or legend for the rest of the contents of the figcaption element\'s parent figure element, if any.', - none), - main: new TagSpecification( - 'The main element represents the main content of the body of a document or application. The main content area consists of content that is directly related to or expands upon the central topic of a document or central functionality of an application.', - none), - div: new TagSpecification( - 'The div element has no special meaning at all. It represents its children. It can be used with the class, lang, and title attributes to mark up semantics common to a group of consecutive elements.', - none), - // Text-level semantics - a: new TagSpecification( - 'If the a element has an href attribute, then it represents a hyperlink (a hypertext anchor) labeled by its contents.', - ['href', 'target', 'download', 'ping', 'rel', 'hreflang', 'type']), - em: new TagSpecification( - 'The em element represents stress emphasis of its contents.', - none), - strong: new TagSpecification( - 'The strong element represents strong importance, seriousness, or urgency for its contents.', - none), - small: new TagSpecification( - 'The small element represents side comments such as small print.', - none), - s: new TagSpecification( - 'The s element represents contents that are no longer accurate or no longer relevant.', - none), - cite: new TagSpecification( - 'The cite element represents a reference to a creative work. It must include the title of the work or the name of the author(person, people or organization) or an URL reference, or a reference in abbreviated form as per the conventions used for the addition of citation metadata.', - none), - q: new TagSpecification( - 'The q element represents some phrasing content quoted from another source.', - ['cite']), - dfn: new TagSpecification( - 'The dfn element represents the defining instance of a term. The paragraph, description list group, or section that is the nearest ancestor of the dfn element must also contain the definition(s) for the term given by the dfn element.', - none), - abbr: new TagSpecification( - 'The abbr element represents an abbreviation or acronym, optionally with its expansion. The title attribute may be used to provide an expansion of the abbreviation. The attribute, if specified, must contain an expansion of the abbreviation, and nothing else.', - none), - ruby: new TagSpecification( - 'The ruby element allows one or more spans of phrasing content to be marked with ruby annotations. Ruby annotations are short runs of text presented alongside base text, primarily used in East Asian typography as a guide for pronunciation or to include other annotations. In Japanese, this form of typography is also known as furigana. Ruby text can appear on either side, and sometimes both sides, of the base text, and it is possible to control its position using CSS. A more complete introduction to ruby can be found in the Use Cases & Exploratory Approaches for Ruby Markup document as well as in CSS Ruby Module Level 1. [RUBY-UC] [CSSRUBY]', - none), - rb: new TagSpecification( - 'The rb element marks the base text component of a ruby annotation. When it is the child of a ruby element, it doesn\'t represent anything itself, but its parent ruby element uses it as part of determining what it represents.', - none), - rt: new TagSpecification( - 'The rt element marks the ruby text component of a ruby annotation. When it is the child of a ruby element or of an rtc element that is itself the child of a ruby element, it doesn\'t represent anything itself, but its ancestor ruby element uses it as part of determining what it represents.', - none), - rtc: new TagSpecification( - 'The rtc element marks a ruby text container for ruby text components in a ruby annotation. When it is the child of a ruby element it doesn\'t represent anything itself, but its parent ruby element uses it as part of determining what it represents.', - none), - rp: new TagSpecification( - 'The rp element is used to provide fallback text to be shown by user agents that don\'t support ruby annotations. One widespread convention is to provide parentheses around the ruby text component of a ruby annotation.', - none), - data: new TagSpecification( - 'The data element represents its contents, along with a machine-readable form of those contents in the value attribute.', - none), - time: new TagSpecification( - 'The time element represents its contents, along with a machine-readable form of those contents in the datetime attribute. The kind of content is limited to various kinds of dates, times, time-zone offsets, and durations, as described below.', - ['datetime']), - code: new TagSpecification( - 'The code element represents a fragment of computer code. This could be an XML element name, a file name, a computer program, or any other string that a computer would recognize.', - none), - var: new TagSpecification( - 'The var element represents a variable. This could be an actual variable in a mathematical expression or programming context, an identifier representing a constant, a symbol identifying a physical quantity, a function parameter, or just be a term used as a placeholder in prose.', - none), - samp: new TagSpecification( - 'The samp element represents sample or quoted output from another program or computing system.', - none), - kbd: new TagSpecification( - 'The kbd element represents user input (typically keyboard input, although it may also be used to represent other input, such as voice commands).', - none), - sub: new TagSpecification( - 'The sub element represents a subscript.', - none), - sup: new TagSpecification( - 'The sup element represents a superscript.', - none), - i: new TagSpecification( - 'The i element represents a span of text in an alternate voice or mood, or otherwise offset from the normal prose in a manner indicating a different quality of text, such as a taxonomic designation, a technical term, an idiomatic phrase from another language, transliteration, a thought, or a ship name in Western texts.', - none), - b: new TagSpecification( - 'The b element represents a span of text to which attention is being drawn for utilitarian purposes without conveying any extra importance and with no implication of an alternate voice or mood, such as key words in a document abstract, product names in a review, actionable words in interactive text-driven software, or an article lede.', - none), - u: new TagSpecification( - 'The u element represents a span of text with an unarticulated, though explicitly rendered, non-textual annotation, such as labeling the text as being a proper name in Chinese text (a Chinese proper name mark), or labeling the text as being misspelt.', - none), - mark: new TagSpecification( - 'The mark element represents a run of text in one document marked or highlighted for reference purposes, due to its relevance in another context. When used in a quotation or other block of text referred to from the prose, it indicates a highlight that was not originally present but which has been added to bring the reader\'s attention to a part of the text that might not have been considered important by the original author when the block was originally written, but which is now under previously unexpected scrutiny. When used in the main prose of a document, it indicates a part of the document that has been highlighted due to its likely relevance to the user\'s current activity.', - none), - bdi: new TagSpecification( - 'The bdi element represents a span of text that is to be isolated from its surroundings for the purposes of bidirectional text formatting. [BIDI]', - none), - bdo: new TagSpecification( - 'The bdo element represents explicit text directionality formatting control for its children. It allows authors to override the Unicode bidirectional algorithm by explicitly specifying a direction override. [BIDI]', - none), - span: new TagSpecification( - 'The span element doesn\'t mean anything on its own, but can be useful when used together with the global attributes, e.g. class, lang, or dir. It represents its children.', - none), - br: new TagSpecification( - 'The br element represents a line break.', - none), - wbr: new TagSpecification( - 'The wbr element represents a line break opportunity.', - none), - // Edits - ins: new TagSpecification( - 'The ins element represents an addition to the document.', - none), - del: new TagSpecification( - 'The del element represents a removal from the document.', - ['cite', 'datetime']), - // Embedded content - picture: new TagSpecification( - 'The picture element is a container which provides multiple sources to its contained img element to allow authors to declaratively control or give hints to the user agent about which image resource to use, based on the screen pixel density, viewport size, image format, and other factors. It represents its children.', - none), - img: new TagSpecification( - 'An img element represents an image.', - ['alt', 'src', 'srcset', 'crossorigin:xo', 'usemap', 'ismap:v', 'width', 'height']), - iframe: new TagSpecification( - 'The iframe element represents a nested browsing context.', - ['src', 'srcdoc', 'name', 'sandbox:sb', 'seamless:v', 'allowfullscreen:v', 'width', 'height']), - embed: new TagSpecification( - 'The embed element provides an integration point for an external (typically non-HTML) application or interactive content.', - ['src', 'type', 'width', 'height']), - object: new TagSpecification( - 'The object element can represent an external resource, which, depending on the type of the resource, will either be treated as an image, as a nested browsing context, or as an external resource to be processed by a plugin.', - ['data', 'type', 'typemustmatch:v', 'name', 'usemap', 'form', 'width', 'height']), - param: new TagSpecification( - 'The param element defines parameters for plugins invoked by object elements. It does not represent anything on its own.', - ['name', 'value']), - video: new TagSpecification( - 'A video element is used for playing videos or movies, and audio files with captions.', - ['src', 'crossorigin:xo', 'poster', 'preload:pl', 'autoplay:v', 'mediagroup', 'loop:v', 'muted:v', 'controls:v', 'width', 'height']), - audio: new TagSpecification( - 'An audio element represents a sound or audio stream.', - ['src', 'crossorigin:xo', 'preload:pl', 'autoplay:v', 'mediagroup', 'loop:v', 'muted:v', 'controls:v']), - source: new TagSpecification( - 'The source element allows authors to specify multiple alternative media resources for media elements. It does not represent anything on its own.', - // 'When the source element has a parent that is a picture element, the source element allows authors to specify multiple alternative source sets for img elements.' - ['src', 'type']), - track: new TagSpecification( - 'The track element allows authors to specify explicit external timed text tracks for media elements. It does not represent anything on its own.', - ['default:v', 'kind:tk', 'label', 'src', 'srclang']), - map: new TagSpecification( - 'The map element, in conjunction with an img element and any area element descendants, defines an image map. The element represents its children.', - ['name']), - area: new TagSpecification( - 'The area element represents either a hyperlink with some text and a corresponding area on an image map, or a dead area on an image map.', - ['alt', 'coords', 'shape:sh', 'href', 'target', 'download', 'ping', 'rel', 'hreflang', 'type']), - // Tabular data - table: new TagSpecification( - 'The table element represents data with more than one dimension, in the form of a table.', - ['sortable:v', 'border']), - caption: new TagSpecification( - 'The caption element represents the title of the table that is its parent, if it has a parent and that is a table element.', - none), - colgroup: new TagSpecification( - 'The colgroup element represents a group of one or more columns in the table that is its parent, if it has a parent and that is a table element.', - ['span']), - col: new TagSpecification( - 'If a col element has a parent and that is a colgroup element that itself has a parent that is a table element, then the col element represents one or more columns in the column group represented by that colgroup.', - ['span']), - tbody: new TagSpecification( - 'The tbody element represents a block of rows that consist of a body of data for the parent table element, if the tbody element has a parent and it is a table.', - none), - thead: new TagSpecification( - 'The thead element represents the block of rows that consist of the column labels (headers) for the parent table element, if the thead element has a parent and it is a table.', - none), - tfoot: new TagSpecification( - 'The tfoot element represents the block of rows that consist of the column summaries (footers) for the parent table element, if the tfoot element has a parent and it is a table.', - none), - tr: new TagSpecification( - 'The tr element represents a row of cells in a table.', - none), - td: new TagSpecification( - 'The td element represents a data cell in a table.', - ['colspan', 'rowspan', 'headers']), - th: new TagSpecification( - 'The th element represents a header cell in a table.', - ['colspan', 'rowspan', 'headers', 'scope:s', 'sorted', 'abbr']), - // Forms - form: new TagSpecification( - 'The form element represents a collection of form-associated elements, some of which can represent editable values that can be submitted to a server for processing.', - ['accept-charset', 'action', 'autocomplete:o', 'enctype:et', 'method:m', 'name', 'novalidate:v', 'target']), - label: new TagSpecification( - 'The label element represents a caption in a user interface. The caption can be associated with a specific form control, known as the label element\'s labeled control, either using the for attribute, or by putting the form control inside the label element itself.', - ['form', 'for']), - input: new TagSpecification( - 'The input element represents a typed data field, usually with a form control to allow the user to edit the data.', - ['accept', 'alt', 'autocomplete:o', 'autofocus:v', 'checked:v', 'dirname', 'disabled:v', 'form', 'formaction', 'formenctype:et', 'formmethod:fm', 'formnovalidate:v', 'formtarget', 'height', 'inputmode:im', 'list', 'max', 'maxlength', 'min', 'minlength', 'multiple:v', 'name', 'pattern', 'placeholder', 'readonly:v', 'required:v', 'size', 'src', 'step', 'type:t', 'value', 'width']), - button: new TagSpecification( - 'The button element represents a button labeled by its contents.', - ['autofocus:v', 'disabled:v', 'form', 'formaction', 'formenctype:et', 'formmethod:fm', 'formnovalidate:v', 'formtarget', 'name', 'type:bt', 'value']), - select: new TagSpecification( - 'The select element represents a control for selecting amongst a set of options.', - ['autocomplete:o', 'autofocus:v', 'disabled:v', 'form', 'multiple:v', 'name', 'required:v', 'size']), - datalist: new TagSpecification( - 'The datalist element represents a set of option elements that represent predefined options for other controls. In the rendering, the datalist element represents nothing and it, along with its children, should be hidden.', - none), - optgroup: new TagSpecification( - 'The optgroup element represents a group of option elements with a common label.', - ['disabled:v', 'label']), - option: new TagSpecification( - 'The option element represents an option in a select element or as part of a list of suggestions in a datalist element.', - ['disabled:v', 'label', 'selected:v', 'value']), - textarea: new TagSpecification( - 'The textarea element represents a multiline plain text edit control for the element\'s raw value. The contents of the control represent the control\'s default value.', - ['autocomplete:o', 'autofocus:v', 'cols', 'dirname', 'disabled:v', 'form', 'inputmode:im', 'maxlength', 'minlength', 'name', 'placeholder', 'readonly:v', 'required:v', 'rows', 'wrap:w']), - output: new TagSpecification( - 'The output element represents the result of a calculation performed by the application, or the result of a user action.', - ['for', 'form', 'name']), - progress: new TagSpecification( - 'The progress element represents the completion progress of a task. The progress is either indeterminate, indicating that progress is being made but that it is not clear how much more work remains to be done before the task is complete (e.g. because the task is waiting for a remote host to respond), or the progress is a number in the range zero to a maximum, giving the fraction of work that has so far been completed.', - ['value', 'max']), - meter: new TagSpecification( - 'The meter element represents a scalar measurement within a known range, or a fractional value; for example disk usage, the relevance of a query result, or the fraction of a voting population to have selected a particular candidate.', - ['value', 'min', 'max', 'low', 'high', 'optimum']), - fieldset: new TagSpecification( - 'The fieldset element represents a set of form controls optionally grouped under a common name.', - ['disabled:v', 'form', 'name']), - legend: new TagSpecification( - 'The legend element represents a caption for the rest of the contents of the legend element\'s parent fieldset element, if any.', - none), - // Interactive elements - details: new TagSpecification( - 'The details element represents a disclosure widget from which the user can obtain additional information or controls.', - ['open:v']), - summary: new TagSpecification( - 'The summary element represents a summary, caption, or legend for the rest of the contents of the summary element\'s parent details element, if any.', - none), - menu: new TagSpecification( - 'The menu element represents a list of commands.', - ['type:mt', 'label']), - menuitem: new TagSpecification( - 'The menuitem element represents a command that the user can invoke from a popup menu (either a context menu or the menu of a menu button).', - none), - dialog: new TagSpecification( - 'The dialog element represents a part of an application that a user interacts with to perform a task, for example a dialog box, inspector, or window.', - none), - // Scripting - script: new TagSpecification( - 'The script element allows authors to include dynamic script and data blocks in their documents. The element does not represent content for the user.', - ['src', 'type', 'charset', 'async:v', 'defer:v', 'crossorigin:xo', 'nonce']), - noscript: new TagSpecification( - 'The noscript element represents nothing if scripting is enabled, and represents its children if scripting is disabled. It is used to present different markup to user agents that support scripting and those that don\'t support scripting, by affecting how the document is parsed.', - none), - template: new TagSpecification( - 'The template element is used to declare fragments of HTML that can be cloned and inserted in the document by script.', - none), - canvas: new TagSpecification( - 'The canvas element provides scripts with a resolution-dependent bitmap canvas, which can be used for rendering graphs, game graphics, art, or other visual images on the fly.', - ['width', 'height']) - }; - var globalAttributes = [ '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', @@ -433,8 +73,8 @@ export function getHTML5TagProvider(): IHTMLTagProvider { return { collectTags: (collector: (tag: string, label: string) => void) => { - for (var tag in html5Tags) { - collector(tag, html5Tags[tag].label); + for (var tag in HTML_TAGS) { + collector(tag, HTML_TAGS[tag].label); } }, collectAttributes: (tag: string, collector: (attribute: string, type: string) => void) => { @@ -446,7 +86,7 @@ export function getHTML5TagProvider(): IHTMLTagProvider { collector(handler, 'event'); }); if (tag) { - var attributes = html5Tags[tag].attributes; + var attributes = HTML_TAGS[tag].attributes; if (attributes) { attributes.forEach(attr => { var segments = attr.split(':'); @@ -472,7 +112,7 @@ export function getHTML5TagProvider(): IHTMLTagProvider { } }); }; - var attributes = html5Tags[tag].attributes; + var attributes = HTML_TAGS[tag].attributes; if (attributes) { processAttributes(attributes); } From 5e39bad6c830803d5b230d656dccad0dbf5175eb Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 26 Nov 2015 19:37:07 -0800 Subject: [PATCH 154/588] Add copyright to htmlTagSpecifications --- src/vs/languages/html/common/htmlTagSpecifications.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/vs/languages/html/common/htmlTagSpecifications.ts b/src/vs/languages/html/common/htmlTagSpecifications.ts index 765a1f658c8..89b2246c111 100644 --- a/src/vs/languages/html/common/htmlTagSpecifications.ts +++ b/src/vs/languages/html/common/htmlTagSpecifications.ts @@ -1,3 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + export class HTMLTagSpecification { constructor(public label: string, public attributes: string[] = []) {} } @@ -287,4 +292,4 @@ export const HTML_TAGS : { [tag:string]: HTMLTagSpecification } = { canvas: new HTMLTagSpecification( 'The canvas element provides scripts with a resolution-dependent bitmap canvas, which can be used for rendering graphs, game graphics, art, or other visual images on the fly.', ['width', 'height']) -}; \ No newline at end of file +}; From eb291ec18361e8b56c0d2107830262d47482c8ec Mon Sep 17 00:00:00 2001 From: Bae Hyun Seung Date: Fri, 27 Nov 2015 14:41:09 +0900 Subject: [PATCH 155/588] Add CSS Gradient snippet. --- extensions/css/snippets/css.json | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/extensions/css/snippets/css.json b/extensions/css/snippets/css.json index 73065292a81..b470172f3ff 100644 --- a/extensions/css/snippets/css.json +++ b/extensions/css/snippets/css.json @@ -14,5 +14,15 @@ "border: ${width} ${border-style} ${color};$0" ], "description": "[width] [border-style] [color]" + }, + "gradient": { + "prefix": "gradient", + "body": [ + "background-image: -moz-linear-gradient(top, ${start-color}, ${end-color});", + "background-image: -webkit-gradient(linear, left top, left bottom, from(${start-color}), to(${end-color}));", + "background-image: -webkit-linear-gradient(top, ${start-color}, ${end-color});", + "background-image: linear-gradient(top, ${start-color}, ${end-color});" + ], + "description": "Set the 'background-image' property to a linear gradient" } -} \ No newline at end of file +} From 59990425dd50928487c68c114d2b91a9eb9cc388 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 27 Nov 2015 08:58:16 +0100 Subject: [PATCH 156/588] adjust rejection log message --- src/vs/workbench/node/pluginHostProcess.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/node/pluginHostProcess.ts b/src/vs/workbench/node/pluginHostProcess.ts index c62d4267abb..15af96acb6e 100644 --- a/src/vs/workbench/node/pluginHostProcess.ts +++ b/src/vs/workbench/node/pluginHostProcess.ts @@ -36,7 +36,7 @@ function connectToRenderer(): TPromise { process.on('unhandledRejection', function(reason, promise) { // 'promise' seems to be undefined all the time and // that's why we cannot use the rejectionhandled event - console.error('unhandled rejected promise', promise); + console.error('potentially unhandled rejected promise', promise); onUnexpectedError(reason); }); From 8f0ec19a6fbab099fecf94feb043b77ecda2fbcb Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 27 Nov 2015 09:00:32 +0100 Subject: [PATCH 157/588] don't scare people #693 --- src/vs/workbench/node/pluginHostProcess.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/node/pluginHostProcess.ts b/src/vs/workbench/node/pluginHostProcess.ts index 15af96acb6e..03b9c9bd746 100644 --- a/src/vs/workbench/node/pluginHostProcess.ts +++ b/src/vs/workbench/node/pluginHostProcess.ts @@ -36,7 +36,7 @@ function connectToRenderer(): TPromise { process.on('unhandledRejection', function(reason, promise) { // 'promise' seems to be undefined all the time and // that's why we cannot use the rejectionhandled event - console.error('potentially unhandled rejected promise', promise); + console.warn('potentially unhandled rejected promise', promise); onUnexpectedError(reason); }); From bedec88327174e5d755bc1510dfa3e5aa2dd3f9f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 27 Nov 2015 09:26:00 +0100 Subject: [PATCH 158/588] Make executeCommand return a promise --- .../keybinding/browser/keybindingServiceImpl.ts | 12 +++++------- .../platform/keybinding/common/keybindingService.ts | 4 +++- src/vs/workbench/api/common/pluginHostCommands.ts | 2 +- src/vs/workbench/test/browser/servicesTestUtils.ts | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/vs/platform/keybinding/browser/keybindingServiceImpl.ts b/src/vs/platform/keybinding/browser/keybindingServiceImpl.ts index af0ccb3dd24..048a81e0334 100644 --- a/src/vs/platform/keybinding/browser/keybindingServiceImpl.ts +++ b/src/vs/platform/keybinding/browser/keybindingServiceImpl.ts @@ -142,7 +142,7 @@ export class AbstractKeybindingService { throw new Error('Not implemented'); } - public executeCommand(commandId: string, args:any): void { + public executeCommand(commandId: string, args:any): TPromise { throw new Error('Not implemented'); } } @@ -300,7 +300,7 @@ export class KeybindingService extends AbstractKeybindingService implements IKey delete this._contexts[String(contextId)]; } - public executeCommand(commandId: string, args:any = {}): any { + public executeCommand(commandId: string, args:any = {}): TPromise { if (!args.context) { var contextId = this._findContextAttr(document.activeElement); var context = this.getContext(contextId); @@ -309,9 +309,7 @@ export class KeybindingService extends AbstractKeybindingService implements IKey args.context = contextValue; } - return this._invokeHandler(commandId, args).done(undefined, err => { - this._messageService.show(Severity.Warning, err); - }); + return this._invokeHandler(commandId, args); } } @@ -356,8 +354,8 @@ class ScopedKeybindingService extends AbstractKeybindingService { this._parent.disposeContext(contextId); } - public executeCommand(commandId: string, args:any): void { - this._parent.executeCommand(commandId, args); + public executeCommand(commandId: string, args:any): TPromise { + return this._parent.executeCommand(commandId, args); } } diff --git a/src/vs/platform/keybinding/common/keybindingService.ts b/src/vs/platform/keybinding/common/keybindingService.ts index 634383082b1..5d33814597c 100644 --- a/src/vs/platform/keybinding/common/keybindingService.ts +++ b/src/vs/platform/keybinding/common/keybindingService.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; +import {TPromise} from 'vs/base/common/winjs.base'; import {createDecorator, IInstantiationService, ServiceIdentifier, ServicesAccessor} from 'vs/platform/instantiation/common/instantiation'; import {Keybinding} from 'vs/base/common/keyCodes'; @@ -82,5 +83,6 @@ export interface IKeybindingService { lookupKeybindings(commandId: string): Keybinding[]; customKeybindingsCount(): number; - executeCommand(commandId: string, args?: any): any; + executeCommand(commandId: string, args?: any): TPromise; + executeCommand(commandId: string, args?: any): TPromise; } diff --git a/src/vs/workbench/api/common/pluginHostCommands.ts b/src/vs/workbench/api/common/pluginHostCommands.ts index 20d9ca171a5..43e01007d31 100644 --- a/src/vs/workbench/api/common/pluginHostCommands.ts +++ b/src/vs/workbench/api/common/pluginHostCommands.ts @@ -148,7 +148,7 @@ export class MainThreadCommands { } _executeCommand(id: string, args: any[]): Thenable { - return TPromise.as(this._keybindingService.executeCommand(id, args)); + return this._keybindingService.executeCommand(id, args); } _getCommands(): Thenable { diff --git a/src/vs/workbench/test/browser/servicesTestUtils.ts b/src/vs/workbench/test/browser/servicesTestUtils.ts index 44c226bc3c2..fc87c3db398 100644 --- a/src/vs/workbench/test/browser/servicesTestUtils.ts +++ b/src/vs/workbench/test/browser/servicesTestUtils.ts @@ -153,7 +153,7 @@ export class TestKeybindingService implements IKeybindingService { public setInstantiationService(instantiationService: IInstantiationService): void { } public setContext(key: string, value: any): void { } public removeContext(key: string): void { } - public executeCommand(commandId: string, args: any): void { } + public executeCommand(commandId: string, args: any): TPromise { return; } public createKey(key: string, defaultValue: T): IKeybindingContextKey { return null; From e33335236ce11c772d591eb4f6712d6fd91ff26f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 27 Nov 2015 09:37:05 +0100 Subject: [PATCH 159/588] adopt executeCommand returning a promise --- .../contrib/codelens/browser/codelens.ts | 21 ++++++++++++------- .../platform/actions/common/actionsService.ts | 2 +- .../browser/parts/statusbar/statusbarPart.ts | 2 +- .../workbench/electron-browser/integration.ts | 7 +++++-- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/vs/editor/contrib/codelens/browser/codelens.ts b/src/vs/editor/contrib/codelens/browser/codelens.ts index b65a862004e..a4497c8de36 100644 --- a/src/vs/editor/contrib/codelens/browser/codelens.ts +++ b/src/vs/editor/contrib/codelens/browser/codelens.ts @@ -11,6 +11,7 @@ import nls = require('vs/nls'); import {format} from 'vs/base/common/strings'; import lifecycle = require('vs/base/common/lifecycle'); import schedulers = require('vs/base/common/async'); +import Severity from 'vs/base/common/severity'; import dom = require('vs/base/browser/dom'); import errors = require('vs/base/common/errors'); import EditorBrowser = require('vs/editor/browser/editorBrowser'); @@ -21,6 +22,7 @@ import referenceSearch = require('vs/editor/contrib/referenceSearch/browser/refe import {IModelService} from 'vs/editor/common/services/modelService'; import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; +import {IMessageService} from 'vs/platform/message/common/message'; import {Range} from 'vs/editor/common/core/range'; import {CodeLensRegistry, ICodeLensData, getCodeLensData} from '../common/codelens'; @@ -61,7 +63,7 @@ class CodeLensContentWidget implements EditorBrowser.IContentWidget { private _commands: { [id: string]: Modes.ICommand } = Object.create(null); public constructor(editor: EditorBrowser.ICodeEditor, symbolRange: EditorCommon.IEditorRange, - keybindingService: IKeybindingService) { + keybindingService: IKeybindingService, messageService: IMessageService) { this._id = 'codeLensWidget' + (++CodeLensContentWidget.ID); this._editor = editor; @@ -79,7 +81,9 @@ class CodeLensContentWidget implements EditorBrowser.IContentWidget { let command = this._commands[element.id]; if (command) { editor.focus(); - keybindingService.executeCommand(command.id, command.arguments); + keybindingService.executeCommand(command.id, command.arguments).done(undefined, err => { + messageService.show(Severity.Error, err); + }); } } }); @@ -226,7 +230,7 @@ class CodeLens { public constructor(data: ICodeLensData[], editor: EditorBrowser.ICodeEditor, helper: CodeLensHelper, viewZoneChangeAccessor: EditorBrowser.IViewZoneChangeAccessor, - keybindingService: IKeybindingService) { + keybindingService: IKeybindingService, messageService: IMessageService) { this._editor = editor; this._data = data; @@ -251,7 +255,7 @@ class CodeLens { }); this._viewZone = new CodeLensViewZone(range.startLineNumber - 1); - this._contentWidget = new CodeLensContentWidget(editor, Range.lift(range), keybindingService); + this._contentWidget = new CodeLensContentWidget(editor, Range.lift(range), keybindingService, messageService); this._viewZoneId = viewZoneChangeAccessor.addZone(this._viewZone); this._editor.addContentWidget(this._contentWidget); @@ -343,19 +347,22 @@ export class CodeLensContribution implements EditorCommon.IEditorContribution { private _modelChangeCounter: number; private _configurationService: IConfigurationService; private _keybindingService: IKeybindingService; + private _messageService: IMessageService; private _codeLenseDisabledByMode: boolean; private _currentFindOccPromise:TPromise; constructor(editor: EditorBrowser.ICodeEditor, @IModelService modelService: IModelService, @IConfigurationService configurationService: IConfigurationService, - @IKeybindingService keybindingService: IKeybindingService) { + @IKeybindingService keybindingService: IKeybindingService, + @IMessageService messageService: IMessageService) { this._instanceCount = (++CodeLensContribution.INSTANCE_COUNT); this._editor = editor; this._modelService = modelService; this._configurationService = configurationService; this._keybindingService = keybindingService; + this._messageService = messageService; this._globalToDispose = []; this._localToDispose = []; @@ -553,7 +560,7 @@ export class CodeLensContribution implements EditorCommon.IEditorContribution { groupsIndex++; codeLensIndex++; } else { - this._lenses.splice(codeLensIndex, 0, new CodeLens(groups[groupsIndex], this._editor, helper, accessor, this._keybindingService)); + this._lenses.splice(codeLensIndex, 0, new CodeLens(groups[groupsIndex], this._editor, helper, accessor, this._keybindingService, this._messageService)); codeLensIndex++; groupsIndex++; } @@ -567,7 +574,7 @@ export class CodeLensContribution implements EditorCommon.IEditorContribution { // Create extra symbols while (groupsIndex < groups.length) { - this._lenses.push(new CodeLens(groups[groupsIndex], this._editor, helper, accessor, this._keybindingService)); + this._lenses.push(new CodeLens(groups[groupsIndex], this._editor, helper, accessor, this._keybindingService, this._messageService)); groupsIndex++; } diff --git a/src/vs/platform/actions/common/actionsService.ts b/src/vs/platform/actions/common/actionsService.ts index f36f506668c..06d63b3b8bb 100644 --- a/src/vs/platform/actions/common/actionsService.ts +++ b/src/vs/platform/actions/common/actionsService.ts @@ -116,7 +116,7 @@ export default class ActionsService implements IActionsService { let label = command.category ? localize('category.label', "{0}: {1}", command.category, command.title) : command.title; let action = new Action(command.command, label, undefined, true, () => { return this._pluginService.activateByEvent(activationEvent).then(() => { - this._keybindingsService.executeCommand(command.command); + return this._keybindingsService.executeCommand(command.command); }); }); this._extensionsActions.push(action); diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 7a6bb6a791b..aae2b2dd78f 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -285,7 +285,7 @@ class StatusBarEntryItem implements IStatusbarItem { // Fallback to the keybinding service for any other case else { - this.keybindingService.executeCommand(id); + this.keybindingService.executeCommand(id).done(undefined, err => this.messageService.show(Severity.Error, toErrorMessage(err))); } } } \ No newline at end of file diff --git a/src/vs/workbench/electron-browser/integration.ts b/src/vs/workbench/electron-browser/integration.ts index cd4829ebbdf..d1e8699007e 100644 --- a/src/vs/workbench/electron-browser/integration.ts +++ b/src/vs/workbench/electron-browser/integration.ts @@ -8,8 +8,10 @@ import {TPromise} from 'vs/base/common/winjs.base'; import errors = require('vs/base/common/errors'); import arrays = require('vs/base/common/arrays'); +import Severity from 'vs/base/common/severity'; import {IPartService} from 'vs/workbench/services/part/common/partService'; import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage'; +import {IMessageService} from 'vs/platform/message/common/message'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; @@ -30,7 +32,8 @@ export class ElectronIntegration { @IWorkspaceContextService private contextService: IWorkspaceContextService, @ITelemetryService private telemetryService: ITelemetryService, @IKeybindingService private keybindingService: IKeybindingService, - @IStorageService private storageService: IStorageService + @IStorageService private storageService: IStorageService, + @IMessageService private messageService: IMessageService ) { } @@ -42,7 +45,7 @@ export class ElectronIntegration { // Support runAction event ipc.on('vscode:runAction', (actionId: string) => { - this.keybindingService.executeCommand(actionId, { from: 'menu' }); + this.keybindingService.executeCommand(actionId, { from: 'menu' }).done(undefined, err => this.messageService.show(Severity.Error, err)); }); // Support options change From 9be10be999a3e1dc39b15ab60afe108ee7627dab Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 27 Nov 2015 10:35:21 +0100 Subject: [PATCH 160/588] Extract nls calls --- .../defineKeybinding/browser/defineKeybinding.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts b/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts index d2c49f89160..750e2d54bc4 100644 --- a/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts +++ b/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts @@ -21,6 +21,10 @@ import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/edito import {TPromise} from 'vs/base/common/winjs.base'; import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; +const NLS_LAUNCH_MESSAGE = nls.localize('defineKeybinding.start', "Define Keybinding"); +const NLS_DEFINE_MESSAGE = nls.localize('defineKeybinding.initial', "Press desired key combination and ENTER"); +const NLS_DEFINE_ACTION_LABEL = nls.localize('DefineKeybindingAction',"Define Keybinding"); + export class DefineKeybindingController implements EditorCommon.IEditorContribution { static ID = 'editor.contrib.defineKeybinding'; @@ -102,7 +106,7 @@ class DefineKeybindingLauncherWidget implements EditorBrowser.IOverlayWidget { if (keybinding.length > 0) { extra += ' ('+keybinding[0].toLabel()+')'; } - this._domNode.appendChild(document.createTextNode(nls.localize('defineKeybinding.start', "Define Keybinding" + extra))); + this._domNode.appendChild(document.createTextNode(NLS_LAUNCH_MESSAGE + extra)); this._toDispose = []; this._toDispose.push(DomUtils.addDisposableListener(this._domNode, 'click', (e) => { @@ -171,7 +175,7 @@ class DefineKeybindingWidget implements EditorBrowser.IContentWidget { this._messageNode = document.createElement('div'); this._messageNode.className = 'message'; - this._messageNode.innerText = nls.localize('defineKeybinding.initial', "Press desired key combination and ENTER"); + this._messageNode.innerText = NLS_DEFINE_MESSAGE; this._domNode.appendChild(this._messageNode); this._inputNode = document.createElement('input'); @@ -290,7 +294,7 @@ function isInterestingEditorModel(editor:EditorCommon.ICommonCodeEditor): boolea } EditorBrowserRegistry.registerEditorContribution(DefineKeybindingController); -CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(DefineKeybindingAction, DefineKeybindingAction.ID, nls.localize('DefineKeybindingAction',"Define Keybinding"), { +CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(DefineKeybindingAction, DefineKeybindingAction.ID, NLS_DEFINE_ACTION_LABEL, { context: ContextKey.EditorFocus, primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_K) })); \ No newline at end of file From 68f34021b49f022b2193b9fcf87991c4a8b01a08 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 27 Nov 2015 07:21:38 +0100 Subject: [PATCH 161/588] input cleanup - extract binary editor model --- .../ui/resourceviewer/resourceViewer.ts | 13 ++++--- .../browser/parts/editor/binaryDiffEditor.ts | 17 +++++---- .../browser/parts/editor/binaryEditor.ts | 10 ++--- .../browser/parts/editor/binaryEditorModel.ts | 37 +++++++++++++++++++ .../parts/editor/resourceEditorInput.ts | 5 ++- .../parts/editor/resourceEditorModel.ts | 29 --------------- .../files/browser/editors/fileEditorInput.ts | 6 +-- .../files/browser/editors/textFileEditor.ts | 6 +-- .../parts/editor/resourceEditorInput.test.ts | 4 +- 9 files changed, 69 insertions(+), 58 deletions(-) create mode 100644 src/vs/workbench/browser/parts/editor/binaryEditorModel.ts diff --git a/src/vs/base/browser/ui/resourceviewer/resourceViewer.ts b/src/vs/base/browser/ui/resourceviewer/resourceViewer.ts index 00dad2a38ea..bfc83c0b89b 100644 --- a/src/vs/base/browser/ui/resourceviewer/resourceViewer.ts +++ b/src/vs/base/browser/ui/resourceviewer/resourceViewer.ts @@ -9,6 +9,7 @@ import 'vs/css!./resourceviewer'; import nls = require('vs/nls'); import strings = require('vs/base/common/strings'); import mimes = require('vs/base/common/mime'); +import URI from 'vs/base/common/uri'; import paths = require('vs/base/common/paths'); import {Builder, $} from 'vs/base/browser/builder'; import DOM = require('vs/base/browser/dom'); @@ -69,14 +70,14 @@ const mapExtToMediaMimes = { */ export class ResourceViewer { - public static show(name: string, url: string, container: Builder, scrollbar?: IScrollableElement): void { + public static show(name: string, resource: URI, container: Builder, scrollbar?: IScrollableElement): void { // Ensure CSS class $(container).addClass('monaco-resource-viewer'); // Lookup media mime if any let mime: string; - const ext = paths.extname(url); + const ext = paths.extname(resource.toString()); if (ext) { mime = mapExtToMediaMimes[ext]; } @@ -91,7 +92,7 @@ export class ResourceViewer { .empty() .style({ paddingLeft: '20px' }) // restore CSS value in case the user saw a PDF before where we remove padding .img({ - src: url + '?' + new Date().getTime() // We really want to avoid the browser from caching this resource, so we add a fake query param that is unique + src: resource.toString() + '?' + new Date().getTime() // We really want to avoid the browser from caching this resource, so we add a fake query param that is unique }).on(DOM.EventType.LOAD, () => { if (scrollbar) { scrollbar.onElementInternalDimensions(); @@ -106,7 +107,7 @@ export class ResourceViewer { .style({ padding: 0, margin: 0 }) // We really do not want any paddings or margins when displaying PDFs .element('object') .attr({ - data: url + '?' + new Date().getTime(), // We really want to avoid the browser from caching this resource, so we add a fake query param that is unique + data: resource.toString() + '?' + new Date().getTime(), // We really want to avoid the browser from caching this resource, so we add a fake query param that is unique width: '100%', height: '100%', type: mime @@ -120,7 +121,7 @@ export class ResourceViewer { .style({ paddingLeft: '20px' }) // restore CSS value in case the user saw a PDF before where we remove padding .element('audio') .attr({ - src: url + '?' + new Date().getTime(), // We really want to avoid the browser from caching this resource, so we add a fake query param that is unique + src: resource.toString() + '?' + new Date().getTime(), // We really want to avoid the browser from caching this resource, so we add a fake query param that is unique text: nls.localize('missingAudioSupport', "Sorry but playback of audio files is not supported."), controls: 'controls' }).on(DOM.EventType.LOAD, () => { @@ -137,7 +138,7 @@ export class ResourceViewer { .style({ paddingLeft: '20px' }) // restore CSS value in case the user saw a PDF before where we remove padding .element('video') .attr({ - src: url + '?' + new Date().getTime(), // We really want to avoid the browser from caching this resource, so we add a fake query param that is unique + src: resource.toString() + '?' + new Date().getTime(), // We really want to avoid the browser from caching this resource, so we add a fake query param that is unique text: nls.localize('missingVideoSupport', "Sorry but playback of video files is not supported."), controls: 'controls' }).on(DOM.EventType.LOAD, () => { diff --git a/src/vs/workbench/browser/parts/editor/binaryDiffEditor.ts b/src/vs/workbench/browser/parts/editor/binaryDiffEditor.ts index abb8ef57f42..f9b17d312c8 100644 --- a/src/vs/workbench/browser/parts/editor/binaryDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/binaryDiffEditor.ts @@ -8,6 +8,7 @@ import 'vs/css!./media/binarydiffeditor'; import {TPromise} from 'vs/base/common/winjs.base'; import nls = require('vs/nls'); +import URI from 'vs/base/common/uri'; import {Sash, ISashEvent, IVerticalSashLayoutProvider} from 'vs/base/browser/ui/sash/sash'; import {Dimension, Builder, $} from 'vs/base/browser/builder'; import {ResourceViewer} from 'vs/base/browser/ui/resourceviewer/resourceViewer'; @@ -15,7 +16,7 @@ import {IScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElement import {ScrollableElement} from 'vs/base/browser/ui/scrollbar/impl/scrollableElement'; import {BaseEditor} from 'vs/workbench/browser/parts/editor/baseEditor'; import {EditorInput, EditorOptions} from 'vs/workbench/common/editor'; -import {BinaryResourceEditorModel} from 'vs/workbench/browser/parts/editor/resourceEditorModel'; +import {BinaryEditorModel} from 'vs/workbench/browser/parts/editor/binaryEditorModel'; import {DiffEditorModel} from 'vs/workbench/browser/parts/editor/diffEditorModel'; import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; @@ -96,7 +97,7 @@ export class BinaryResourceDiffEditor extends BaseEditor implements IVerticalSas return this.editorService.resolveEditorModel(input, true /* Reload */).then((resolvedModel: DiffEditorModel) => { // Assert model instance - if (!(resolvedModel.originalModel instanceof BinaryResourceEditorModel) || !(resolvedModel.modifiedModel instanceof BinaryResourceEditorModel)) { + if (!(resolvedModel.originalModel instanceof BinaryEditorModel) || !(resolvedModel.modifiedModel instanceof BinaryEditorModel)) { return TPromise.wrapError(nls.localize('cannotDiffTextToBinary', "Comparing binary files to non binary files is currently not supported")); } @@ -106,16 +107,16 @@ export class BinaryResourceDiffEditor extends BaseEditor implements IVerticalSas } // Render original - let original = resolvedModel.originalModel; - this.renderInput(original.getName(), original.getUrl(), true); + let original = resolvedModel.originalModel; + this.renderInput(original.getName(), original.getResource(), true); // Render modified - let modified = resolvedModel.modifiedModel; - this.renderInput(modified.getName(), modified.getUrl(), false); + let modified = resolvedModel.modifiedModel; + this.renderInput(modified.getName(), modified.getResource(), false); }); } - private renderInput(name: string, url: string, isOriginal: boolean): void { + private renderInput(name: string, resource: URI, isOriginal: boolean): void { // Reset Sash to default 50/50 ratio if needed if (this.leftContainerWidth && this.dimension && this.leftContainerWidth !== this.dimension.width / 2) { @@ -128,7 +129,7 @@ export class BinaryResourceDiffEditor extends BaseEditor implements IVerticalSas let container = isOriginal ? this.leftBinaryContainer : this.rightBinaryContainer; let scrollbar = isOriginal ? this.leftScrollbar : this.rightScrollbar; - ResourceViewer.show(name, url, container, scrollbar); + ResourceViewer.show(name, resource, container, scrollbar); } public clearInput(): void { diff --git a/src/vs/workbench/browser/parts/editor/binaryEditor.ts b/src/vs/workbench/browser/parts/editor/binaryEditor.ts index 641f995e208..aca73ffa0f4 100644 --- a/src/vs/workbench/browser/parts/editor/binaryEditor.ts +++ b/src/vs/workbench/browser/parts/editor/binaryEditor.ts @@ -13,7 +13,7 @@ import {Dimension, Builder, $} from 'vs/base/browser/builder'; import {ResourceViewer} from 'vs/base/browser/ui/resourceviewer/resourceViewer'; import {EditorModel, EditorInput, EditorOptions} from 'vs/workbench/common/editor'; import {BaseEditor} from 'vs/workbench/browser/parts/editor/baseEditor'; -import {BinaryResourceEditorModel} from 'vs/workbench/browser/parts/editor/resourceEditorModel'; +import {BinaryEditorModel} from 'vs/workbench/browser/parts/editor/binaryEditorModel'; import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; @@ -61,8 +61,8 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { return this._editorService.resolveEditorModel(input, true /* Reload */).then((resolvedModel: EditorModel) => { // Assert Model instance - if (!(resolvedModel instanceof BinaryResourceEditorModel)) { - return TPromise.wrapError('Invalid editor input. Binary resource editor requires a model instance of BinaryResourceEditorModel.'); + if (!(resolvedModel instanceof BinaryEditorModel)) { + return TPromise.wrapError('Invalid editor input. Binary resource editor requires a model instance of BinaryEditorModel.'); } // Assert that the current input is still the one we expect. This prevents a race condition when loading takes long and another input was set meanwhile @@ -71,8 +71,8 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { } // Render Input - let binaryResourceModel = resolvedModel; - ResourceViewer.show(binaryResourceModel.getName(), binaryResourceModel.getUrl(), this.binaryContainer); + let binaryResourceModel = resolvedModel; + ResourceViewer.show(binaryResourceModel.getName(), binaryResourceModel.getResource(), this.binaryContainer); return TPromise.as(null); }); diff --git a/src/vs/workbench/browser/parts/editor/binaryEditorModel.ts b/src/vs/workbench/browser/parts/editor/binaryEditorModel.ts new file mode 100644 index 00000000000..58b3c6cdc98 --- /dev/null +++ b/src/vs/workbench/browser/parts/editor/binaryEditorModel.ts @@ -0,0 +1,37 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import {EditorModel} from 'vs/workbench/common/editor'; +import URI from 'vs/base/common/uri'; + +/** + * An editor model that just represents a URL and mime for a resource that can be loaded. + */ +export class BinaryEditorModel extends EditorModel { + private name: string; + private resource: URI; + + constructor(resource: URI, name: string) { + super(); + + this.name = name; + this.resource = resource; + } + + /** + * The name of the binary resource. + */ + public getName(): string { + return this.name; + } + + /** + * The resource of the binary resource. + */ + public getResource(): URI { + return this.resource; + } +} \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/editor/resourceEditorInput.ts b/src/vs/workbench/browser/parts/editor/resourceEditorInput.ts index 8bd974a392d..59ff2d881da 100644 --- a/src/vs/workbench/browser/parts/editor/resourceEditorInput.ts +++ b/src/vs/workbench/browser/parts/editor/resourceEditorInput.ts @@ -10,7 +10,8 @@ import {isBinaryMime} from 'vs/base/common/mime'; import objects = require('vs/base/common/objects'); import {IEditorRegistry, Extensions} from 'vs/workbench/browser/parts/editor/baseEditor'; import {EditorModel, EditorInput} from 'vs/workbench/common/editor'; -import {TextResourceEditorModel, BinaryResourceEditorModel} from 'vs/workbench/browser/parts/editor/resourceEditorModel'; +import {TextResourceEditorModel} from 'vs/workbench/browser/parts/editor/resourceEditorModel'; +import {BinaryEditorModel} from 'vs/workbench/browser/parts/editor/binaryEditorModel'; import URI from 'vs/base/common/uri'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; @@ -141,7 +142,7 @@ export class ResourceEditorInput extends EditorInput { // Binary model if editor is binary editor let model: EditorModel; if (descriptor.getId() === BINARY_EDITOR_ID) { - model = new BinaryResourceEditorModel(this.name, this.url); + model = new BinaryEditorModel(URI.parse(this.url), this.name); } // Otherwise use text model diff --git a/src/vs/workbench/browser/parts/editor/resourceEditorModel.ts b/src/vs/workbench/browser/parts/editor/resourceEditorModel.ts index 0a7de903808..398c39a1d83 100644 --- a/src/vs/workbench/browser/parts/editor/resourceEditorModel.ts +++ b/src/vs/workbench/browser/parts/editor/resourceEditorModel.ts @@ -135,33 +135,4 @@ export class TextResourceEditorModel extends BaseTextEditorModel { return TPromise.wrapError(new errors.ConnectionError(error)); }); } -} - -/** - * An editor model that just represents a URL and mime for a resource that can be loaded. - */ -export class BinaryResourceEditorModel extends EditorModel { - private name: string; - private url: string; - - constructor(name: string, url: string) { - super(); - - this.name = name; - this.url = url; - } - - /** - * The name of the binary resource. - */ - public getName(): string { - return this.name; - } - - /** - * The url of the binary resource. - */ - public getUrl(): string { - return this.url; - } } \ No newline at end of file diff --git a/src/vs/workbench/parts/files/browser/editors/fileEditorInput.ts b/src/vs/workbench/parts/files/browser/editors/fileEditorInput.ts index 8cc2fa1e886..5ff6698b4ef 100644 --- a/src/vs/workbench/parts/files/browser/editors/fileEditorInput.ts +++ b/src/vs/workbench/parts/files/browser/editors/fileEditorInput.ts @@ -16,7 +16,7 @@ import strings = require('vs/base/common/strings'); import assert = require('vs/base/common/assert'); import {EditorModel, IInputStatus, EncodingMode} from 'vs/workbench/common/editor'; import {IEditorRegistry, Extensions, EditorDescriptor} from 'vs/workbench/browser/parts/editor/baseEditor'; -import {BinaryResourceEditorModel} from 'vs/workbench/browser/parts/editor/resourceEditorModel'; +import {BinaryEditorModel} from 'vs/workbench/browser/parts/editor/binaryEditorModel'; import {FileEditorDescriptor} from 'vs/workbench/parts/files/browser/files'; import {BINARY_FILE_EDITOR_ID, FILE_EDITOR_INPUT_ID, FileEditorInput as CommonFileEditorInput} from 'vs/workbench/parts/files/common/files'; import {CACHE, TextFileEditorModel, State} from 'vs/workbench/parts/files/browser/editors/textFileEditorModel'; @@ -242,7 +242,7 @@ export class FileEditorInput extends CommonFileEditorInput { FileEditorInput.FILE_EDITOR_MODEL_LOADERS[this.resource.toString()] = modelPromise; } - return modelPromise.then((resolvedModel: TextFileEditorModel | BinaryResourceEditorModel) => { + return modelPromise.then((resolvedModel: TextFileEditorModel | BinaryEditorModel) => { if (resolvedModel instanceof TextFileEditorModel) { CACHE.add(this.resource, resolvedModel); // Store into the text model cache unless this file is binary } @@ -278,7 +278,7 @@ export class FileEditorInput extends CommonFileEditorInput { // Binary model if editor is binary editor let model: EditorModel; if (descriptor.getId() === BINARY_FILE_EDITOR_ID) { - model = new BinaryResourceEditorModel(this.getName(), this.resource.toString()); + model = new BinaryEditorModel(this.resource, this.getName()); } // Otherwise use text model diff --git a/src/vs/workbench/parts/files/browser/editors/textFileEditor.ts b/src/vs/workbench/parts/files/browser/editors/textFileEditor.ts index bfe7ebc23cc..cf5f89aa7aa 100644 --- a/src/vs/workbench/parts/files/browser/editors/textFileEditor.ts +++ b/src/vs/workbench/parts/files/browser/editors/textFileEditor.ts @@ -17,7 +17,7 @@ import {SaveErrorHandler} from 'vs/workbench/parts/files/browser/saveErrorHandle import {BaseTextEditor} from 'vs/workbench/browser/parts/editor/textEditor'; import {EditorInput, EditorOptions, TextEditorOptions, EditorModel} from 'vs/workbench/common/editor'; import {TextFileEditorModel} from 'vs/workbench/parts/files/browser/editors/textFileEditorModel'; -import {BinaryResourceEditorModel} from 'vs/workbench/browser/parts/editor/resourceEditorModel'; +import {BinaryEditorModel} from 'vs/workbench/browser/parts/editor/binaryEditorModel'; import {FileEditorInput} from 'vs/workbench/parts/files/browser/editors/fileEditorInput'; import {ExplorerViewlet} from 'vs/workbench/parts/files/browser/explorerViewlet'; import {IQuickOpenService} from 'vs/workbench/services/quickopen/browser/quickOpenService'; @@ -102,9 +102,9 @@ export class TextFileEditor extends BaseTextEditor { return this.editorService.resolveEditorModel(input, true /* Reload */).then((resolvedModel: EditorModel) => { // There is a special case where the text editor has to handle binary file editor input: if a file with application/unknown - // mime has been resolved and cached before, it maybe an actual instance of BinaryResourceEditorModel. In this case our text + // mime has been resolved and cached before, it maybe an actual instance of BinaryEditorModel. In this case our text // editor has to open this model using the binary editor. We return early in this case. - if (resolvedModel instanceof BinaryResourceEditorModel && this.openAsBinary(input, options)) { + if (resolvedModel instanceof BinaryEditorModel && this.openAsBinary(input, options)) { return null; } diff --git a/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts b/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts index 1f50ea58345..ca5a49849e1 100644 --- a/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts @@ -8,7 +8,7 @@ import * as assert from 'assert'; import {create} from 'vs/platform/instantiation/common/instantiationService'; import {ResourceEditorInput} from 'vs/workbench/browser/parts/editor/resourceEditorInput'; -import {BinaryResourceEditorModel} from 'vs/workbench/browser/parts/editor/resourceEditorModel'; +import {BinaryEditorModel} from 'vs/workbench/browser/parts/editor/binaryEditorModel'; import {BaseTextEditorModel} from 'vs/workbench/browser/parts/editor/textEditorModel'; import {MockRequestService, TestWorkspace, TestEditorService, TestContextService, TestMessageService, TestEventService} from 'vs/workbench/test/browser/servicesTestUtils'; import Severity from 'vs/base/common/severity'; @@ -106,7 +106,7 @@ suite('Workbench - ResourceEditorInput', () => { return c1.resolve().then((m1) => { assert(m1.isResolved()); - assert(m1 instanceof BinaryResourceEditorModel); + assert(m1 instanceof BinaryEditorModel); done(); }); }); From 6fe1566fe0b8792739729f0ce8963d4782e141ac Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 27 Nov 2015 10:42:38 +0100 Subject: [PATCH 162/588] inputs - get rid of legacy resource editor input and model --- .../browser/parts/editor/binaryEditor.ts | 2 +- .../browser/parts/editor/diffEditorInput.ts | 14 +- .../parts/editor/editor.contribution.ts | 27 +-- .../parts/editor/readOnlyEditorInput.ts | 6 +- .../parts/editor/resourceEditorInput.ts | 192 ------------------ .../parts/editor/resourceEditorModel.ts | 138 ------------- .../browser/parts/editor/textDiffEditor.ts | 4 +- .../parts/files/browser/saveErrorHandler.ts | 73 ++++++- .../parts/git/browser/gitEditorInputs.ts | 28 +-- .../parts/git/browser/gitServices.ts | 4 +- .../git/browser/views/changes/changesView.ts | 4 - .../browser/parts/editor/editorInput.test.ts | 50 ----- .../parts/editor/resourceEditorInput.test.ts | 178 ---------------- .../parts/editor/resourceEditorModel.test.ts | 137 ------------- .../parts/editor/stringEditorInput.test.ts | 5 +- 15 files changed, 83 insertions(+), 779 deletions(-) delete mode 100644 src/vs/workbench/browser/parts/editor/resourceEditorInput.ts delete mode 100644 src/vs/workbench/browser/parts/editor/resourceEditorModel.ts delete mode 100644 src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts delete mode 100644 src/vs/workbench/test/browser/parts/editor/resourceEditorModel.test.ts diff --git a/src/vs/workbench/browser/parts/editor/binaryEditor.ts b/src/vs/workbench/browser/parts/editor/binaryEditor.ts index aca73ffa0f4..63a61cbf43f 100644 --- a/src/vs/workbench/browser/parts/editor/binaryEditor.ts +++ b/src/vs/workbench/browser/parts/editor/binaryEditor.ts @@ -106,7 +106,7 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { } /** - * An implementation of editor for binary files like images or videos leveraging the ResourceEditorInput. + * An implementation of editor for binary files like images or videos. */ export class BinaryResourceEditor extends BaseBinaryResourceEditor { diff --git a/src/vs/workbench/browser/parts/editor/diffEditorInput.ts b/src/vs/workbench/browser/parts/editor/diffEditorInput.ts index ef0e42c6d07..dae16c51df6 100644 --- a/src/vs/workbench/browser/parts/editor/diffEditorInput.ts +++ b/src/vs/workbench/browser/parts/editor/diffEditorInput.ts @@ -13,7 +13,6 @@ import {BaseTextEditorModel} from 'vs/workbench/browser/parts/editor/textEditorM import {DiffEditorModel} from 'vs/workbench/browser/parts/editor/diffEditorModel'; import {TextDiffEditor} from 'vs/workbench/browser/parts/editor/textDiffEditor'; import {TextDiffEditorModel} from 'vs/workbench/browser/parts/editor/textDiffEditorModel'; -import {ResourceEditorInput} from 'vs/workbench/browser/parts/editor/resourceEditorInput'; import {BinaryResourceDiffEditor} from 'vs/workbench/browser/parts/editor/binaryDiffEditor'; /** @@ -138,17 +137,10 @@ export class DiffEditorInput extends BaseDiffEditorInput { private isBinary(input: EditorInput): boolean { let mime: string; - // Find mime from instancesof ResourceEditorInput - if (input instanceof ResourceEditorInput) { - mime = (input).getMime(); - } - // Find mime by checking for IFileEditorInput implementors - else { - let fileInput = (input); - if (types.isFunction(fileInput.getMime)) { - mime = fileInput.getMime(); - } + let fileInput = (input); + if (types.isFunction(fileInput.getMime)) { + mime = fileInput.getMime(); } return mime && isBinaryMime(mime); diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index 4aba215fdc7..f7536efbcd1 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -15,7 +15,6 @@ import {UntitledEditorInput} from 'vs/workbench/browser/parts/editor/untitledEdi import {ReadOnlyEditorInput} from 'vs/workbench/browser/parts/editor/readOnlyEditorInput'; import {TextDiffEditor} from 'vs/workbench/browser/parts/editor/textDiffEditor'; import {BinaryResourceDiffEditor} from 'vs/workbench/browser/parts/editor/binaryDiffEditor'; -import {ResourceEditorInput} from 'vs/workbench/browser/parts/editor/resourceEditorInput'; import {BinaryResourceEditor} from 'vs/workbench/browser/parts/editor/binaryEditor'; import {IFrameEditor} from 'vs/workbench/browser/parts/editor/iframeEditor'; import {IFrameEditorInput} from 'vs/workbench/browser/parts/editor/iframeEditorInput'; @@ -32,10 +31,9 @@ import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; nls.localize('textEditor', "Text Editor"), 'vs/workbench/browser/parts/editor/stringEditor', 'StringEditor' - ), + ), [ new SyncDescriptor(StringEditorInput), - new SyncDescriptor(ResourceEditorInput), new SyncDescriptor(UntitledEditorInput), new SyncDescriptor(ReadOnlyEditorInput) ] @@ -48,7 +46,7 @@ import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; nls.localize('textDiffEditor', "Text Diff Editor"), 'vs/workbench/browser/parts/editor/textDiffEditor', 'TextDiffEditor' - ), + ), [ new SyncDescriptor(DiffEditorInput) ] @@ -61,25 +59,12 @@ import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; nls.localize('binaryDiffEditor', "Binary Diff Editor"), 'vs/workbench/browser/parts/editor/binaryDiffEditor', 'BinaryResourceDiffEditor' - ), + ), [ new SyncDescriptor(DiffEditorInput) ] ); -// Register Binary Resource Editor -(Registry.as(EditorExtensions.Editors)).registerEditor( - new EditorDescriptor( - BinaryResourceEditor.ID, - nls.localize('binaryEditor', "Binary Resource Editor"), - 'vs/workbench/browser/parts/editor/binaryEditor', - 'BinaryResourceEditor' - ), - [ - new SyncDescriptor(ResourceEditorInput) - ] -); - // Register IFrame Editor (Registry.as(EditorExtensions.Editors)).registerEditor( new EditorDescriptor( @@ -87,18 +72,18 @@ import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; nls.localize('iframeEditor', "IFrame Editor"), 'vs/workbench/browser/parts/editor/iframeEditor', 'IFrameEditor' - ), + ), [ new SyncDescriptor(IFrameEditorInput) ] ); // Register Editor Status -let statusBar = ( Registry.as(StatusExtensions.Statusbar)); +let statusBar = (Registry.as(StatusExtensions.Statusbar)); statusBar.registerStatusbarItem(new StatusbarItemDescriptor(EditorStatus, StatusbarAlignment.RIGHT, 100 /* High Priority */)); // Register Actions -let registry = Registry.as(ActionExtensions.WorkbenchActions); +let registry = Registry.as(ActionExtensions.WorkbenchActions); registry.registerWorkbenchAction(new SyncActionDescriptor(ChangeModeAction, ChangeModeAction.ID, ChangeModeAction.LABEL, { primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_M) })); registry.registerWorkbenchAction(new SyncActionDescriptor(ChangeEOLAction, ChangeEOLAction.ID, ChangeEOLAction.LABEL)); registry.registerWorkbenchAction(new SyncActionDescriptor(ChangeEncodingAction, ChangeEncodingAction.ID, ChangeEncodingAction.LABEL)); \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/editor/readOnlyEditorInput.ts b/src/vs/workbench/browser/parts/editor/readOnlyEditorInput.ts index a3a3e71bf8b..98364cb545a 100644 --- a/src/vs/workbench/browser/parts/editor/readOnlyEditorInput.ts +++ b/src/vs/workbench/browser/parts/editor/readOnlyEditorInput.ts @@ -21,17 +21,17 @@ export class ReadOnlyEditorInput extends EditorInput { public static ID = 'workbench.editors.readOnlyEditorInput'; protected cachedModel: ReadOnlyEditorModel; + protected resource: URI; private name: string; private description: string; - private resource: URI; constructor( name: string, description: string, resource: URI, - @IModelService private modelService: IModelService, - @IInstantiationService private instantiationService: IInstantiationService + @IModelService protected modelService: IModelService, + @IInstantiationService protected instantiationService: IInstantiationService ) { super(); diff --git a/src/vs/workbench/browser/parts/editor/resourceEditorInput.ts b/src/vs/workbench/browser/parts/editor/resourceEditorInput.ts deleted file mode 100644 index 59ff2d881da..00000000000 --- a/src/vs/workbench/browser/parts/editor/resourceEditorInput.ts +++ /dev/null @@ -1,192 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import {TPromise} from 'vs/base/common/winjs.base'; -import {Registry} from 'vs/platform/platform'; -import {isBinaryMime} from 'vs/base/common/mime'; -import objects = require('vs/base/common/objects'); -import {IEditorRegistry, Extensions} from 'vs/workbench/browser/parts/editor/baseEditor'; -import {EditorModel, EditorInput} from 'vs/workbench/common/editor'; -import {TextResourceEditorModel} from 'vs/workbench/browser/parts/editor/resourceEditorModel'; -import {BinaryEditorModel} from 'vs/workbench/browser/parts/editor/binaryEditorModel'; -import URI from 'vs/base/common/uri'; -import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; - -const TEXT_EDITOR_ID = 'workbench.editors.stringEditor'; -const BINARY_EDITOR_ID = 'workbench.editors.binaryResourceEditor'; - -/** - * A read-only editor input whos contents are just a mime and url to display either in a text editor or in a binary viewer. The - * decision of using a binary or text editor is made by checking the provided mime type for common textual and binary mime types - * (image, audio, video, application/octet-stream). - */ -export class ResourceEditorInput extends EditorInput { - - public static ID: string = 'workbench.editors.resourceEditorInput'; - - private name: string; - private description: string; - private url: string; - private mime: string; - private method: string; - private headers: any; - private isMimeEnforced: boolean; - private singleton: boolean; - private cachedModel: EditorModel; - - constructor( - name: string, - description: string, - url: string, - mime: string, - method: string, - headers: any, - singleton: boolean, - @IInstantiationService private instantiationService: IInstantiationService - ) { - super(); - - this.name = name; - this.description = description; - this.url = url; - this.mime = mime; - this.method = method; - this.headers = headers; - this.singleton = singleton; - } - - public getId(): string { - return ResourceEditorInput.ID; - } - - public getName(): string { - return this.name; - } - - public getDescription(): string { - return this.description; - } - - public getUrl(): string { - return this.url; - } - - public getMethod(): string { - return this.method; - } - - public getHeaders(): any { - return this.headers; - } - - public getMime(): string { - return this.mime; - } - - /** - * Will cause this editor input and the associated model to use the mime that was given in to the constructor and will - * ignore any mime that is returned from downloading the resource from the net. This is useful to enforce a certain mime - * to be used for this resource even though it might be served differently. - */ - public setMimeEnforced(): void { - this.isMimeEnforced = true; - } - - protected getResource(): URI { - // Subclasses can implement to associate a resource URL with the input - return null; - } - - public getPreferredEditorId(candidates: string[]): string { - - // Find the right editor for the given isBinary/isText state - let isBinary = isBinaryMime(this.mime); - - return !isBinary ? TEXT_EDITOR_ID : BINARY_EDITOR_ID; - } - - public resolve(refresh?: boolean): TPromise { - let modelPromise: TPromise; - - // Use Cached Model - if (this.cachedModel && !refresh) { - modelPromise = TPromise.as(this.cachedModel); - } - - // Refresh Cached Model - else if (this.cachedModel && refresh) { - modelPromise = this.cachedModel.load(); - } - - // Create Model and Load - else { - modelPromise = this.createModel().load(); - } - - return modelPromise.then((resolvedModel: EditorModel) => { - this.cachedModel = resolvedModel; - - return this.cachedModel; - }); - } - - private createModel(): EditorModel { - let descriptor = (Registry.as(Extensions.Editors)).getEditor(this); - if (!descriptor) { - throw new Error('Unable to find an editor in the registry for this input.'); - } - - // Binary model if editor is binary editor - let model: EditorModel; - if (descriptor.getId() === BINARY_EDITOR_ID) { - model = new BinaryEditorModel(URI.parse(this.url), this.name); - } - - // Otherwise use text model - else { - model = this.instantiationService.createInstance(TextResourceEditorModel, this.url, this.mime, this.method, this.headers, this.getResource()); - if (this.isMimeEnforced) { - (model).setMimeEnforced(); - } - } - - return model; - } - - public matches(otherInput: any): boolean { - if (super.matches(otherInput) === true) { - return true; - } - - if (otherInput instanceof ResourceEditorInput) { - let otherResourceEditorInput = otherInput; - - // If both inputs are singletons, check on the mime for equalness - if (otherResourceEditorInput.singleton && this.singleton && otherResourceEditorInput.mime === this.mime) { - return true; - } - - // Otherwise compare by properties - return otherResourceEditorInput.url === this.url && - otherResourceEditorInput.mime === this.mime && - otherResourceEditorInput.name === this.name && - otherResourceEditorInput.description === this.description && - otherResourceEditorInput.method === this.method && - objects.equals(otherResourceEditorInput.headers, this.headers); - } - - return false; - } - - public dispose(): void { - if (this.cachedModel) { - this.cachedModel.dispose(); - this.cachedModel = null; - } - - super.dispose(); - } -} \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/editor/resourceEditorModel.ts b/src/vs/workbench/browser/parts/editor/resourceEditorModel.ts deleted file mode 100644 index 398c39a1d83..00000000000 --- a/src/vs/workbench/browser/parts/editor/resourceEditorModel.ts +++ /dev/null @@ -1,138 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import {TPromise} from 'vs/base/common/winjs.base'; -import errors = require('vs/base/common/errors'); -import {MIME_UNKNOWN} from 'vs/base/common/mime'; -import types = require('vs/base/common/types'); -import {Header, IXHRResponse} from 'vs/base/common/http'; -import {EditorModel} from 'vs/workbench/common/editor'; -import {BaseTextEditorModel} from 'vs/workbench/browser/parts/editor/textEditorModel'; -import URI from 'vs/base/common/uri'; -import {IFileService, IContent} from 'vs/platform/files/common/files'; -import {IRequestService} from 'vs/platform/request/common/request'; -import {IModeService} from 'vs/editor/common/services/modeService'; -import {IModelService} from 'vs/editor/common/services/modelService'; - -/** - * An editor model whith a readonly content that can be resolved through the provided URL. - */ -export class TextResourceEditorModel extends BaseTextEditorModel { - private url: string; - private method: string; - private headers: any; - private mime: string; - private lastModified: number; - private isMimeEnforced: boolean; - private resource: URI; - - constructor( - url: string, - mime: string, - method: string, - headers: any, - resource: URI, - @IModeService modeService: IModeService, - @IModelService modelService: IModelService, - @IRequestService private requestService: IRequestService, - @IFileService private fileService: IFileService - ) { - super(modelService, modeService); - - this.url = url; - this.mime = mime; - this.method = method; - this.headers = headers; - this.resource = resource; - } - - /** - * Will cause this editor model to use the mime that was given in to the constructor and will - * ignore any mime that is returned from downloading the resource from the net. This is useful to enforce a certain mime - * to be used for this resource even though it might be served differently. - */ - public setMimeEnforced(): void { - this.isMimeEnforced = !!this.mime; // Only enforce if a mime is set - } - - /** - * When the model is loaded, will return the last modified header value as millies since 1970 for the resource if it is provided. - */ - public getLastModified(): number { - return this.lastModified; - } - - public load(): TPromise { - - // We can load file:// URIs through the file service - let isFileResource: boolean; - try { - isFileResource = URI.parse(this.url).scheme === 'file'; - } catch (error) { - isFileResource = false; - } - - let loadPromise: TPromise; - if (isFileResource) { - loadPromise = this.fileService.resolveContent(URI.parse(this.url)); - } else { - loadPromise = this.requestService.makeRequest({ url: this.url, type: this.method, headers: this.headers }); - } - - return loadPromise.then((result) => { - let mtime: number; - let mime = this.mime; - let value: string; - - // Handle XHR - if (types.isFunction((result).getResponseHeader)) { - let xhr = result; - let lastModifiedValue = xhr.getResponseHeader(Header.LAST_MODIFIED); - if (lastModifiedValue) { - mtime = new Date(lastModifiedValue).getTime(); - } - - let contentType = xhr.getResponseHeader(Header.X_CONTENT_TYPES) || xhr.getResponseHeader(Header.CONTENT_TYPE); - if (contentType && contentType.indexOf('; charset') >= 0) { - contentType = contentType.substring(0, contentType.indexOf(';')); - } - - if (contentType && contentType !== MIME_UNKNOWN) { - mime = contentType; - } - - value = xhr.responseText; - } - - // Handle IContent - else { - let content = result; - mtime = content.mtime; - mime = content.mime; - value = content.value; - } - - // Keep this meta data - this.lastModified = mtime; - - // Create text editor model if not yet done - if (!this.textEditorModel) { - return this.createTextEditorModel(value, !this.isMimeEnforced ? mime : this.mime, this.resource); - } - - // Otherwise update - this.updateTextEditorModel(value, !this.isMimeEnforced ? mime : undefined /* do not update mime from previous load */); - - return TPromise.as(this); - }, (error) => { - if (error instanceof Error) { - return TPromise.wrapError(error); - } - - return TPromise.wrapError(new errors.ConnectionError(error)); - }); - } -} \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts index d4e05c29fa0..e735cbb2896 100644 --- a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts @@ -17,7 +17,7 @@ import {BaseEditor} from 'vs/workbench/browser/parts/editor/baseEditor'; import {BaseTextEditor} from 'vs/workbench/browser/parts/editor/textEditor'; import {TextEditorOptions, TextDiffEditorOptions, EditorModel, EditorInput, EditorOptions} from 'vs/workbench/common/editor'; import {StringEditorInput} from 'vs/workbench/browser/parts/editor/stringEditorInput'; -import {ResourceEditorInput} from 'vs/workbench/browser/parts/editor/resourceEditorInput'; +import {ReadOnlyEditorInput} from 'vs/workbench/browser/parts/editor/readOnlyEditorInput'; import {DiffEditorInput} from 'vs/workbench/browser/parts/editor/diffEditorInput'; import {DiffNavigator} from 'vs/editor/contrib/diffNavigator/common/diffNavigator'; import {DiffEditorWidget} from 'vs/editor/browser/widget/diffEditorWidget'; @@ -190,7 +190,7 @@ export class TextDiffEditor extends BaseTextEditor { let input = this.input; if (input && types.isFunction((input).getModifiedInput)) { let modifiedInput = (input).getModifiedInput(); - let readOnly = modifiedInput instanceof StringEditorInput || modifiedInput instanceof ResourceEditorInput; + let readOnly = modifiedInput instanceof StringEditorInput || modifiedInput instanceof ReadOnlyEditorInput; options.readOnly = readOnly; } diff --git a/src/vs/workbench/parts/files/browser/saveErrorHandler.ts b/src/vs/workbench/parts/files/browser/saveErrorHandler.ts index be6f38d28a6..d595739c3e0 100644 --- a/src/vs/workbench/parts/files/browser/saveErrorHandler.ts +++ b/src/vs/workbench/parts/files/browser/saveErrorHandler.ts @@ -4,26 +4,30 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {Promise} from 'vs/base/common/winjs.base'; +import {Promise, TPromise} from 'vs/base/common/winjs.base'; import nls = require('vs/nls'); import errors = require('vs/base/common/errors'); import paths = require('vs/base/common/paths'); import {Action} from 'vs/base/common/actions'; +import URI from 'vs/base/common/uri'; +import {URL} from 'vs/base/common/network'; +import {EditorModel, EditorInput} from 'vs/workbench/common/editor'; import {guessMimeTypes} from 'vs/base/common/mime'; import {EditorInputAction} from 'vs/workbench/browser/parts/editor/baseEditor'; -import {ResourceEditorInput} from 'vs/workbench/browser/parts/editor/resourceEditorInput'; -import {TextResourceEditorModel} from 'vs/workbench/browser/parts/editor/resourceEditorModel'; +import {ReadOnlyEditorInput} from 'vs/workbench/browser/parts/editor/readOnlyEditorInput'; import {DiffEditorInput} from 'vs/workbench/browser/parts/editor/diffEditorInput'; import {DiffEditorModel} from 'vs/workbench/browser/parts/editor/diffEditorModel'; import {FileEditorInput} from 'vs/workbench/parts/files/browser/editors/fileEditorInput'; import {SaveFileAsAction, RevertFileAction, SaveFileAction} from 'vs/workbench/parts/files/browser/fileActions'; -import {IFileOperationResult, FileOperationResult} from 'vs/platform/files/common/files'; +import {IFileService, IFileOperationResult, FileOperationResult} from 'vs/platform/files/common/files'; import {TextFileEditorModel, ISaveErrorHandler} from 'vs/workbench/parts/files/browser/editors/textFileEditorModel'; import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; import {IEventService} from 'vs/platform/event/common/event'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IMessageService, IMessageWithAction, Severity, CancelAction} from 'vs/platform/message/common/message'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; +import {IModeService} from 'vs/editor/common/services/modeService'; +import {IModelService} from 'vs/editor/common/services/modelService'; // A handler for save error happening with conflict resolution actions export class SaveErrorHandler implements ISaveErrorHandler { @@ -114,7 +118,7 @@ export class ConflictResolutionDiffEditorInput extends DiffEditorInput { model: TextFileEditorModel, name: string, description: string, - originalInput: ResourceEditorInput, + originalInput: FileOnDiskEditorInput, modifiedInput: FileEditorInput, @IMessageService private messageService: IMessageService, @IInstantiationService private instantiationService: IInstantiationService, @@ -135,6 +139,52 @@ export class ConflictResolutionDiffEditorInput extends DiffEditorInput { } } +class FileOnDiskEditorInput extends ReadOnlyEditorInput { + private fileResource: URI; + private lastModified: number; + private mime: string; + + constructor( + fileResource: URI, + mime: string, + name: string, + description: string, + @IModelService modelService: IModelService, + @IModeService private modeService: IModeService, + @IInstantiationService instantiationService: IInstantiationService, + @IFileService private fileService: IFileService + ) { + // We create a new resource URI here that is different from the file resource because we represent the state of + // the file as it is on disk and not as it is (potentially cached) in Code. That allows us to have a different + // model for the left-hand comparision compared to the conflicting one in Code to the right. + super(name, description, URI.create('disk', null, fileResource.fsPath), modelService, instantiationService); + + this.fileResource = fileResource; + this.mime = mime; + } + + public getLastModified(): number { + return this.lastModified; + } + + public resolve(refresh?: boolean): TPromise { + + // Make sure our file from disk is resolved up to date + return this.fileService.resolveContent(this.fileResource).then(content => { + this.lastModified = content.mtime; + + let codeEditorModel = this.modelService.getModel(this.resource); + if (!codeEditorModel) { + this.modelService.createModel(content.value, this.modeService.getOrCreateMode(this.mime), URL.fromUri(this.resource)); + } else { + codeEditorModel.setValue(content.value); + } + + return super.resolve(refresh); + }); + } +} + // A message with action to resolve a 412 save conflict class ResolveSaveConflictMessage implements IMessageWithAction { public message: string; @@ -152,18 +202,19 @@ class ResolveSaveConflictMessage implements IMessageWithAction { ) { this.model = model; + const resource = model.getResource(); if (message) { this.message = message; } else { - this.message = nls.localize('staleSaveError', "Failed to save '{0}': The content on disk is newer. Click on **Compare** to compare your version with the one on disk.", paths.basename(this.model.getResource().fsPath)); + this.message = nls.localize('staleSaveError', "Failed to save '{0}': The content on disk is newer. Click on **Compare** to compare your version with the one on disk.", paths.basename(resource.fsPath)); } this.actions = [ new Action('workbench.files.action.resolveConflict', nls.localize('compareChanges', "Compare"), null, true, () => { if (!this.model.isDisposed()) { - let mime = guessMimeTypes(this.model.getResource().fsPath).join(', '); - let originalInput = this.instantiationService.createInstance(ResourceEditorInput, paths.basename(this.model.getResource().fsPath), this.model.getResource().fsPath, this.model.getResource().toString(), mime, void 0, void 0, void 0); - let modifiedInput = this.instantiationService.createInstance(FileEditorInput, this.model.getResource(), mime, void 0); + let mime = guessMimeTypes(resource.fsPath).join(', '); + let originalInput = this.instantiationService.createInstance(FileOnDiskEditorInput, resource, mime, paths.basename(resource.fsPath), resource.fsPath); + let modifiedInput = this.instantiationService.createInstance(FileEditorInput, resource, mime, void 0); let conflictInput = this.instantiationService.createInstance(ConflictResolutionDiffEditorInput, this.model, nls.localize('saveConflictDiffLabel', "{0} - on disk ↔ in {1}", modifiedInput.getName(), this.contextService.getConfiguration().env.appName), nls.localize('resolveSaveConflict', "{0} - Resolve save conflict", modifiedInput.getDescription()), originalInput, modifiedInput); return this.editorService.openEditor(conflictInput).then(() => { @@ -203,7 +254,7 @@ export class AcceptLocalChangesAction extends EditorInputAction { // 1.) Get the diff editor model from cache (resolve(false)) to have access to the mtime of the file we currently show to the left return conflictInput.resolve(false).then((diffModel: DiffEditorModel) => { - let knownLastModified = (diffModel.originalModel).getLastModified(); + let knownLastModified = (conflictInput.originalInput).getLastModified(); // 2.) Revert the model to get the latest copy from disk and to have access to the mtime of the file now return model.revert().then(() => { @@ -243,7 +294,7 @@ export class AcceptLocalChangesAction extends EditorInputAction { model.textEditorModel.setValue(localModelValue); // Reload the left hand side of the diff editor to show the up to date version and inform the user that he has to redo the action - return (diffModel.originalModel).load().then(() => { + return conflictInput.originalInput.resolve(true).then(() => { this.messagesToHide.push(this.messageService.show(Severity.Info, nls.localize('conflictingFileHasChanged', "The content of the file on disk has changed and the left hand side of the compare editor was refreshed. Please review and resolve again."))); }); } diff --git a/src/vs/workbench/parts/git/browser/gitEditorInputs.ts b/src/vs/workbench/parts/git/browser/gitEditorInputs.ts index 0b11e24eec9..aa9c04e9d06 100644 --- a/src/vs/workbench/parts/git/browser/gitEditorInputs.ts +++ b/src/vs/workbench/parts/git/browser/gitEditorInputs.ts @@ -8,7 +8,6 @@ import winjs = require('vs/base/common/winjs.base'); import lifecycle = require('vs/base/common/lifecycle'); import async = require('vs/base/common/async'); import WorkbenchEditorCommon = require('vs/workbench/common/editor'); -import resourceei = require('vs/workbench/browser/parts/editor/resourceEditorInput'); import stringei = require('vs/workbench/browser/parts/editor/stringEditorInput'); import diffei = require('vs/workbench/browser/parts/editor/diffEditorInput'); import git = require('vs/workbench/parts/git/common/git'); @@ -23,7 +22,7 @@ export interface IEditorInputWithStatus { } export function isGitEditorInput(input: IEditorInput): boolean { - return input instanceof GitDiffEditorInput || input instanceof GitIndexEditorInput || input instanceof NativeGitIndexStringEditorInput; + return input instanceof GitDiffEditorInput || input instanceof NativeGitIndexStringEditorInput; } export class GitDiffEditorInput @@ -91,29 +90,6 @@ export class GitIndexDiffEditorInput extends GitDiffEditorInput { } } -export class GitIndexEditorInput - extends resourceei.ResourceEditorInput - implements IEditorInputWithStatus -{ - public static ID = 'Monaco.IDE.UI.Viewlets.GitViewlet.GitIndexEditorInput'; - - private status: git.IFileStatus; - - constructor(name: any, description:string, url: string, mime: string, status: git.IFileStatus, @IInstantiationService instantiationService: IInstantiationService) { - super(name, description, url, mime, void 0, void 0, void 0, instantiationService); - - this.status = status; - } - - public getId(): string { - return GitIndexEditorInput.ID; - } - - public getFileStatus(): git.IFileStatus { - return this.status; - } -} - export class NativeGitIndexStringEditorInput extends stringei.StringEditorInput implements IEditorInputWithStatus @@ -148,7 +124,7 @@ export class NativeGitIndexStringEditorInput } public getId(): string { - return GitIndexEditorInput.ID; + return NativeGitIndexStringEditorInput.ID; } public getFileStatus(): git.IFileStatus { diff --git a/src/vs/workbench/parts/git/browser/gitServices.ts b/src/vs/workbench/parts/git/browser/gitServices.ts index e8c8e392540..713fb2eb7a9 100644 --- a/src/vs/workbench/parts/git/browser/gitServices.ts +++ b/src/vs/workbench/parts/git/browser/gitServices.ts @@ -686,13 +686,13 @@ export class GitService extends ee.EventEmitter mimetypes = mime.guessMimeTypes(path); // guess from path if our detection did not yield results } - // Binary: our story is weak here for binary files on the index. Since we run nativelyx, we do not have a way currently + // Binary: our story is weak here for binary files on the index. Since we run natively, we do not have a way currently // to e.g. show images as binary inside the renderer because images need to be served through a URL to show. We could revisit this by // allowing to use data URLs for resource inputs to render them. However, this would mean potentially loading a large file into memory // // Our solution now is to detect binary files and immediately return an input that is flagged as binary unknown mime type. if (mime.isBinaryMime(mime.guessMimeTypes(path)) || mimetypes.indexOf(mime.MIME_BINARY) >= 0) { - return winjs.Promise.as(this.instantiationService.createInstance(giteditorinputs.GitIndexEditorInput, fileSegment, description, null /* no URL */, mime.MIME_BINARY, status)); + return winjs.Promise.wrapError(new Error('The resource seems to be binary and cannot be displayed')); } // Text diff --git a/src/vs/workbench/parts/git/browser/views/changes/changesView.ts b/src/vs/workbench/parts/git/browser/views/changes/changesView.ts index f454db50a1b..ddd4cc5450f 100644 --- a/src/vs/workbench/parts/git/browser/views/changes/changesView.ts +++ b/src/vs/workbench/parts/git/browser/views/changes/changesView.ts @@ -395,10 +395,6 @@ export class ChangesView extends EventEmitter.EventEmitter implements GitView.IV return ( input).getFileStatus(); } - if (input instanceof GitEditorInputs.GitIndexEditorInput) { - return ( input).getFileStatus() || null; - } - if (input instanceof GitEditorInputs.NativeGitIndexStringEditorInput) { return ( input).getFileStatus() || null; } diff --git a/src/vs/workbench/test/browser/parts/editor/editorInput.test.ts b/src/vs/workbench/test/browser/parts/editor/editorInput.test.ts index e99fd794f08..54c318f1b16 100644 --- a/src/vs/workbench/test/browser/parts/editor/editorInput.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editorInput.test.ts @@ -9,7 +9,6 @@ import * as assert from 'assert'; import {EditorInput} from 'vs/workbench/common/editor'; import {EditorDescriptor} from 'vs/workbench/browser/parts/editor/baseEditor'; import {DiffEditorInput} from 'vs/workbench/browser/parts/editor/diffEditorInput'; -import {ResourceEditorInput} from 'vs/workbench/browser/parts/editor/resourceEditorInput'; class MyEditorInput extends EditorInput { getMime() { @@ -97,53 +96,4 @@ suite("Workbench - EditorInput", () => { otherInput.dispose(); assert.equal(counter, 2); }); - - test("DiffEditorInput - get preferred editor", function() { - let input: EditorInput = new ResourceEditorInput("name", "description", "url", "text/css", void 0, void 0, void 0, null); - let otherInput: EditorInput = new ResourceEditorInput("name2", "description", "url2", "text/html", void 0, void 0, void 0, null); - let diffInput = new DiffEditorInput("name", "description", input, otherInput); - - assert.strictEqual(diffInput.getPreferredEditorId([]), 'workbench.editors.textDiffEditor'); - - input = new ResourceEditorInput("name", "description", "url", "text/css", void 0, void 0, void 0, null); - otherInput = new ResourceEditorInput("name2", "description", "url2", "application/zip, application/octet-stream", void 0, void 0, void 0, null); - diffInput = new DiffEditorInput("name", "description", input, otherInput); - - assert.strictEqual(diffInput.getPreferredEditorId([]), 'workbench.editors.binaryResourceDiffEditor'); - - input = new MyEditorInput(); - otherInput = new MyEditorInput(); - - diffInput = new DiffEditorInput("name", "description", input, otherInput); - - assert.strictEqual(diffInput.getPreferredEditorId([]), 'workbench.editors.textDiffEditor'); - }); - - test("ResourceEditorInput", function() { - let input = new ResourceEditorInput("name", "description", "url", "mime", void 0, void 0, void 0, null); - let otherInput = new ResourceEditorInput("name2", "description", "url2", "mime2", void 0, void 0, void 0, null); - - assert(input.matches(input)); - assert(!input.matches(otherInput)); - assert(!input.matches(null)); - }); - - test("ResourceEditorInput#getPreferredEditorId", function() { - let editors = ['workbench.editors.stringEditor', 'workbench.editors.binaryResourceEditor']; - - let input = new ResourceEditorInput("name", "description", "url", "text/plain", void 0, void 0, void 0, null); - assert(input.getPreferredEditorId(editors) === 'workbench.editors.stringEditor'); - - input = new ResourceEditorInput("name", "description", "url", "application/foo, text/plain", void 0, void 0, void 0, null); - assert(input.getPreferredEditorId(editors) === 'workbench.editors.stringEditor'); - - input = new ResourceEditorInput("name", "description", "url", "application/xml, text/plain", void 0, void 0, void 0, null); - assert(input.getPreferredEditorId(editors) === 'workbench.editors.stringEditor'); - - input = new ResourceEditorInput("name", "description", "url", "application/octet-stream", void 0, void 0, void 0, null); - assert(input.getPreferredEditorId(editors) === 'workbench.editors.binaryResourceEditor'); - - input = new ResourceEditorInput("name", "description", "url", "image/png, application/octet-stream", void 0, void 0, void 0, null); - assert(input.getPreferredEditorId(editors) === 'workbench.editors.binaryResourceEditor'); - }); }); \ No newline at end of file diff --git a/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts b/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts deleted file mode 100644 index ca5a49849e1..00000000000 --- a/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts +++ /dev/null @@ -1,178 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import * as assert from 'assert'; -import {create} from 'vs/platform/instantiation/common/instantiationService'; -import {ResourceEditorInput} from 'vs/workbench/browser/parts/editor/resourceEditorInput'; -import {BinaryEditorModel} from 'vs/workbench/browser/parts/editor/binaryEditorModel'; -import {BaseTextEditorModel} from 'vs/workbench/browser/parts/editor/textEditorModel'; -import {MockRequestService, TestWorkspace, TestEditorService, TestContextService, TestMessageService, TestEventService} from 'vs/workbench/test/browser/servicesTestUtils'; -import Severity from 'vs/base/common/severity'; -import {IEventService} from 'vs/platform/event/common/event'; -import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; -import * as Html from 'vs/languages/html/common/html.contribution'; -import {IMessageService, IConfirmation} from 'vs/platform/message/common/message'; -import {createMockModelService, createMockModeService} from 'vs/editor/test/common/servicesTestUtils'; - -let jsContent = "console.log('Hello World');"; -let cssContent = "body { background-color: red; }"; - -suite('Workbench - ResourceEditorInput', () => { - let file = function(name, mime) { - return { - "isDirectory": false, - "size": 16192, - "mtime": new Date().getTime(), - "name": name, - "mime": mime - }; - }; - - let baseInstantiationService: IInstantiationService; - let eventService: TestEventService; - let messageService: IMessageService; - let saveAttempt: number; - - setup(() => { - eventService = new TestEventService(); - messageService = new TestMessageService(); - saveAttempt = 0; - let services = { - eventService: eventService, - messageService: messageService, - requestService: new MockRequestService(TestWorkspace, (url) => { - if (/index\.html$/.test(url)) { - return { - responseText: 'Hello Html', - getResponseHeader: key => ({ - 'content-length': '1000', - 'last-modified': new Date().toUTCString(), - 'content-type': 'text/html' - })[key.toLowerCase()] - }; - } - - return null; - }), - contextService: new TestContextService(TestWorkspace, null, { autoSaveDelay: 0 }), - modeService: createMockModeService(), - modelService: createMockModelService() - }; - - baseInstantiationService = create(services); - }); - - teardown(() => { - eventService.dispose(); - }); - - test('ResourceEditorInput - Load takes mime from server', (done) => { - let c1 = baseInstantiationService.createInstance(ResourceEditorInput, "name", "description", "/files/index.html", "text/plain", void 0, void 0, void 0); - - return c1.resolve().then((m1: BaseTextEditorModel) => { - assert(m1.isResolved()); - - return m1.textEditorModel.whenModeIsReady().then(() => { - assert.strictEqual("html", m1.textEditorModel.getMode().getId()); - done(); - }).then(() => { - m1.dispose(); - }); - }); - }); - - test('ResourceEditorInput - Enforce mime', (done) => { - let c1 = baseInstantiationService.createInstance(ResourceEditorInput, "name", "description", "/files/index.html", "text/plain", void 0, void 0, void 0); - c1.setMimeEnforced(); - - return c1.resolve().then((m1: BaseTextEditorModel) => { - assert(m1.isResolved()); - - return m1.textEditorModel.whenModeIsReady().then(() => { - assert.strictEqual('plaintext', m1.textEditorModel.getMode().getId()); - done(); - }).then(() => { - m1.dispose(); - }); - }); - }); - - test('ResourceEditorInput - Binary', (done) => { - let c1 = baseInstantiationService.createInstance(ResourceEditorInput, "name", "description", "/files/index.foo", "application/octet-stream", void 0, void 0, void 0); - - return c1.resolve().then((m1) => { - assert(m1.isResolved()); - assert(m1 instanceof BinaryEditorModel); - done(); - }); - }); - - test("ResourceEditorInput", function(done) { - let editorService = new TestEditorService(function() { }); - let requestService = new MockRequestService(TestWorkspace, (url) => { - switch (true) { - case /\.json$/.test(url): return jsContent; - case /\.css$/.test(url): return cssContent; - } - - return null; - }); - - let inst = create({ - requestService: requestService, - editorService: editorService, - modeService: createMockModeService(), - modelService: createMockModelService() - }); - - let input = inst.createInstance(ResourceEditorInput, "name", "description", "/monaco.jsrules.json", "application/json", "GET", { Accept: "application/json" }, false); - let otherInput = inst.createInstance(ResourceEditorInput, "name", "description", "/site.css", "application/json", "GET", { Accept: "application/json" }, false); - let otherInputSame = inst.createInstance(ResourceEditorInput, "name", "description", "/monaco.jsrules.json", "application/json", "GET", { Accept: "application/json" }, false); - - assert(input.matches(input)); - assert(input.matches(otherInputSame)); - assert(!input.matches(otherInput)); - assert(!input.matches(null)); - assert(input.getName()); - - input = inst.createInstance(ResourceEditorInput, "name", "description", "/monaco.jsrules.json", "mime", "GET", { Accept: "application/json" }, false); - - let url = "/site.css"; - let method = "GET"; - let headers = { - "Accept": "application/octet-stream" - }; - - input = inst.createInstance(ResourceEditorInput, "name", "description", url, "text/plain", method, headers, false); - - editorService.resolveEditorModel(input, true).then(function(resolved) { - let resolvedModelA = resolved; - return editorService.resolveEditorModel(input, true).then(function(resolved) { - assert(resolvedModelA === resolved); // assert: Resolved Model cached per instance - - input.dispose(); - - return editorService.resolveEditorModel(input, true).then(function(resolved) { - assert(resolvedModelA !== resolved); // Different instance, because input got disposed - - let model = (resolved).textEditorModel; - return editorService.resolveEditorModel(input, true).then(function(againResolved) { - assert(model === (againResolved).textEditorModel); // Same models from each resolve - model = (againResolved).textEditorModel; - - return editorService.resolveEditorModel(input, false).then(function(againResolved) { - assert(model === (againResolved).textEditorModel); // Same models if not refreshing - }); - }); - }); - }); - }).done(() => { - input.dispose(); - done(); - }); - }); -}); \ No newline at end of file diff --git a/src/vs/workbench/test/browser/parts/editor/resourceEditorModel.test.ts b/src/vs/workbench/test/browser/parts/editor/resourceEditorModel.test.ts deleted file mode 100644 index 8b10ba85207..00000000000 --- a/src/vs/workbench/test/browser/parts/editor/resourceEditorModel.test.ts +++ /dev/null @@ -1,137 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import * as assert from 'assert'; -import {TextResourceEditorModel} from 'vs/workbench/browser/parts/editor/resourceEditorModel'; -import {MockRequestService, TestWorkspace, TestMessageService, TestEventService} from 'vs/workbench/test/browser/servicesTestUtils'; -import Severity from 'vs/base/common/severity'; -import {IEventService} from 'vs/platform/event/common/event'; -import * as Html from 'vs/languages/html/common/html.contribution'; -import {IMessageService, IConfirmation} from 'vs/platform/message/common/message'; -import {IModeService} from 'vs/editor/common/services/modeService'; -import {IModelService} from 'vs/editor/common/services/modelService'; -import {createMockModelService, createMockModeService} from 'vs/editor/test/common/servicesTestUtils'; - -suite('Workbench - ResourceEditorModel', () => { - let file = function(name, mime) { - return { - "isDirectory": false, - "size": 16192, - "mtime": new Date().getTime(), - "name": name, - "mime": mime - }; - }; - - let requestService: MockRequestService; - let eventService: TestEventService; - let messageService: IMessageService; - let modeService: IModeService; - let modelService: IModelService; - let counter; - - setup(() => { - eventService = new TestEventService(); - messageService = new TestMessageService(); - modeService = createMockModeService(); - modelService = createMockModelService(); - counter = 0; - - requestService = new MockRequestService(TestWorkspace, (url) => { - counter++; - - if (/index\.html$/.test(url)) { - return { - responseText: 'Hello Html', - getResponseHeader: key => ({ - 'last-modified': counter === 1 ? new Date().toUTCString() : new Date(new Date().getTime() + 1000).toUTCString(), - 'content-type': 'text/html' - })[key.toLowerCase()] - }; - } else if (/index_changes\.html$/.test(url)) { - return { - responseText: counter === 1 ? 'Hello Html' : 'Hello Changed Html', - getResponseHeader: key => ({ - 'last-modified': counter === 1 ? new Date().toUTCString() : new Date(new Date().getTime() + 1000).toUTCString(), - 'content-type': 'text/html' - })[key.toLowerCase()] - }; - } - - return null; - }); - }); - - teardown(() => { - eventService.dispose(); - }); - - test('TextResourceEditorModel - Load takes mime from server', function(done) { - let m1 = new TextResourceEditorModel("/files/index.html", "text/plain", null, null, null, modeService, modelService, requestService, null); - - return m1.load().then(() => { - assert(m1.isResolved()); - - return m1.textEditorModel.whenModeIsReady().then(() => { - assert.strictEqual("html", m1.textEditorModel.getMode().getId()); - }); - }).done(() => { - m1.dispose(); - done(); - }); - }); - - test('TextResourceEditorModel - Enforce mime', function(done) { - let m1 = new TextResourceEditorModel("/files/index.html", "text/plain", null, null, null, modeService, modelService, requestService, null); - m1.setMimeEnforced(); - - return m1.load().then(() => { - assert(m1.isResolved()); - - return m1.textEditorModel.whenModeIsReady().then(() => { - assert.strictEqual('plaintext', m1.textEditorModel.getMode().getId()); - }); - }).done(() => { - m1.dispose(); - done(); - }); - }); - - test('TextResourceEditorModel - Load keeps text editor model if already present', function(done) { - let m1 = new TextResourceEditorModel("/files/index.html", "text/plain", null, null, null, modeService, modelService, requestService, null); - - return m1.load().then(() => { - assert(m1.isResolved()); - let model = m1.textEditorModel; - - return m1.load().then(() => { - assert.strictEqual(m1.textEditorModel, model); - }); - }).done(() => { - m1.dispose(); - done(); - }); - }); - - test('TextResourceEditorModel - Load updates properly and provides mtime', function(done) { - let m1 = new TextResourceEditorModel("/files/index_changes.html", "text/plain", null, null, null, modeService, modelService, requestService, null); - - return m1.load().then(() => { - let mtime = m1.getLastModified(); - assert(mtime > 0); - assert.equal(m1.getValue(), 'Hello Html'); - - return m1.load().then(() => { - assert(mtime < m1.getLastModified()); - assert.equal(m1.getValue(), 'Hello Changed Html'); - }); - }).done(() => { - m1.dispose(); - done(); - }); - }); -}); \ No newline at end of file diff --git a/src/vs/workbench/test/browser/parts/editor/stringEditorInput.test.ts b/src/vs/workbench/test/browser/parts/editor/stringEditorInput.test.ts index 9103acb8ad0..694bbec4a41 100644 --- a/src/vs/workbench/test/browser/parts/editor/stringEditorInput.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/stringEditorInput.test.ts @@ -12,7 +12,6 @@ import URI from 'vs/base/common/uri'; import {URL} from 'vs/base/common/network'; import {StringEditorInput} from 'vs/workbench/browser/parts/editor/stringEditorInput'; import {LogEditorInput} from 'vs/workbench/browser/parts/editor/logEditorInput'; -import {ResourceEditorInput} from 'vs/workbench/browser/parts/editor/resourceEditorInput'; import {ReadOnlyEditorInput} from 'vs/workbench/browser/parts/editor/readOnlyEditorInput'; import {ReadOnlyEditorModel} from 'vs/workbench/browser/parts/editor/readOnlyEditorModel'; import {TestWorkspace, TestEditorService, MockRequestService} from 'vs/workbench/test/browser/servicesTestUtils'; @@ -98,10 +97,10 @@ suite("Workbench - StringEditorInput", () => { let promise = Promise.as("value"); let stringEditorInput = inst.createInstance(StringEditorInput, "name", 'description', "value", "mime", false); - let promiseEditorInput = new ResourceEditorInput("name", "description", "url", "mime", void 0, void 0, void 0, void 0); + let promiseEditorInput = inst.createInstance(ReadOnlyEditorInput, "name", "description", URI.create('inMemory', null, 'thePath')); let stringEditorInput2 = inst.createInstance(StringEditorInput, "name", 'description', "value", "mime", false); - let promiseEditorInput2 = new ResourceEditorInput("name", "description", "url", "mime", void 0, void 0, void 0, void 0); + let promiseEditorInput2 = inst.createInstance(ReadOnlyEditorInput, "name", "description", URI.create('inMemory', null, 'thePath')); assert.strictEqual(stringEditorInput.matches(null), false); assert.strictEqual(promiseEditorInput.matches(null), false); From b555a4a90a81e8e61df65ac9f49bec5e8c2f69ce Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 27 Nov 2015 10:51:25 +0100 Subject: [PATCH 163/588] readonlyinput/model => resourcinput/model --- .../parts/editor/editor.contribution.ts | 4 ++-- ...yEditorInput.ts => resourceEditorInput.ts} | 20 +++++++++---------- ...yEditorModel.ts => resourceEditorModel.ts} | 2 +- .../browser/parts/editor/textDiffEditor.ts | 4 ++-- .../parts/files/browser/saveErrorHandler.ts | 4 ++-- .../parts/editor/stringEditorInput.test.ts | 14 ++++++------- 6 files changed, 24 insertions(+), 24 deletions(-) rename src/vs/workbench/browser/parts/editor/{readOnlyEditorInput.ts => resourceEditorInput.ts} (79%) rename src/vs/workbench/browser/parts/editor/{readOnlyEditorModel.ts => resourceEditorModel.ts} (95%) diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index f7536efbcd1..742991c1433 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -12,7 +12,7 @@ import {StringEditorInput} from 'vs/workbench/browser/parts/editor/stringEditorI import {StringEditor} from 'vs/workbench/browser/parts/editor/stringEditor'; import {DiffEditorInput} from 'vs/workbench/browser/parts/editor/diffEditorInput'; import {UntitledEditorInput} from 'vs/workbench/browser/parts/editor/untitledEditorInput'; -import {ReadOnlyEditorInput} from 'vs/workbench/browser/parts/editor/readOnlyEditorInput'; +import {ResourceEditorInput} from 'vs/workbench/browser/parts/editor/resourceEditorInput'; import {TextDiffEditor} from 'vs/workbench/browser/parts/editor/textDiffEditor'; import {BinaryResourceDiffEditor} from 'vs/workbench/browser/parts/editor/binaryDiffEditor'; import {BinaryResourceEditor} from 'vs/workbench/browser/parts/editor/binaryEditor'; @@ -35,7 +35,7 @@ import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; [ new SyncDescriptor(StringEditorInput), new SyncDescriptor(UntitledEditorInput), - new SyncDescriptor(ReadOnlyEditorInput) + new SyncDescriptor(ResourceEditorInput) ] ); diff --git a/src/vs/workbench/browser/parts/editor/readOnlyEditorInput.ts b/src/vs/workbench/browser/parts/editor/resourceEditorInput.ts similarity index 79% rename from src/vs/workbench/browser/parts/editor/readOnlyEditorInput.ts rename to src/vs/workbench/browser/parts/editor/resourceEditorInput.ts index 98364cb545a..3f49c3598f7 100644 --- a/src/vs/workbench/browser/parts/editor/readOnlyEditorInput.ts +++ b/src/vs/workbench/browser/parts/editor/resourceEditorInput.ts @@ -7,7 +7,7 @@ import {TPromise} from 'vs/base/common/winjs.base'; import {MIME_TEXT} from 'vs/base/common/mime'; import {EditorModel, EditorInput} from 'vs/workbench/common/editor'; -import {ReadOnlyEditorModel} from 'vs/workbench/browser/parts/editor/readOnlyEditorModel'; +import {ResourceEditorModel} from 'vs/workbench/browser/parts/editor/resourceEditorModel'; import URI from 'vs/base/common/uri'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IModelService} from 'vs/editor/common/services/modelService'; @@ -16,11 +16,11 @@ import {IModelService} from 'vs/editor/common/services/modelService'; * A read-only text editor input whos contents are made of the provided resource that points to an existing * code editor model. */ -export class ReadOnlyEditorInput extends EditorInput { +export class ResourceEditorInput extends EditorInput { - public static ID = 'workbench.editors.readOnlyEditorInput'; + public static ID = 'workbench.editors.resourceEditorInput'; - protected cachedModel: ReadOnlyEditorModel; + protected cachedModel: ResourceEditorModel; protected resource: URI; private name: string; @@ -41,7 +41,7 @@ export class ReadOnlyEditorInput extends EditorInput { } public getId(): string { - return ReadOnlyEditorInput.ID; + return ResourceEditorInput.ID; } public getName(): string { @@ -65,8 +65,8 @@ export class ReadOnlyEditorInput extends EditorInput { } //Otherwise Create Model and Load - let model = this.instantiationService.createInstance(ReadOnlyEditorModel, this.resource); - return model.load().then((resolvedModel: ReadOnlyEditorModel) => { + let model = this.instantiationService.createInstance(ResourceEditorModel, this.resource); + return model.load().then((resolvedModel: ResourceEditorModel) => { this.cachedModel = resolvedModel; return this.cachedModel; @@ -78,11 +78,11 @@ export class ReadOnlyEditorInput extends EditorInput { return true; } - if (otherInput instanceof ReadOnlyEditorInput) { - let otherReadOnlyEditorInput = otherInput; + if (otherInput instanceof ResourceEditorInput) { + let otherResourceEditorInput = otherInput; // Compare by properties - return otherReadOnlyEditorInput.resource.toString() === this.resource.toString(); + return otherResourceEditorInput.resource.toString() === this.resource.toString(); } return false; diff --git a/src/vs/workbench/browser/parts/editor/readOnlyEditorModel.ts b/src/vs/workbench/browser/parts/editor/resourceEditorModel.ts similarity index 95% rename from src/vs/workbench/browser/parts/editor/readOnlyEditorModel.ts rename to src/vs/workbench/browser/parts/editor/resourceEditorModel.ts index a7fbd41cdc1..b74f6b32e60 100644 --- a/src/vs/workbench/browser/parts/editor/readOnlyEditorModel.ts +++ b/src/vs/workbench/browser/parts/editor/resourceEditorModel.ts @@ -19,7 +19,7 @@ import {EditOperation} from 'vs/editor/common/core/editOperation'; /** * An editor model whith an in-memory, readonly content that is backed by an existing editor model. */ -export class ReadOnlyEditorModel extends BaseTextEditorModel { +export class ResourceEditorModel extends BaseTextEditorModel { private resource: URI; constructor( diff --git a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts index e735cbb2896..d4e05c29fa0 100644 --- a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts @@ -17,7 +17,7 @@ import {BaseEditor} from 'vs/workbench/browser/parts/editor/baseEditor'; import {BaseTextEditor} from 'vs/workbench/browser/parts/editor/textEditor'; import {TextEditorOptions, TextDiffEditorOptions, EditorModel, EditorInput, EditorOptions} from 'vs/workbench/common/editor'; import {StringEditorInput} from 'vs/workbench/browser/parts/editor/stringEditorInput'; -import {ReadOnlyEditorInput} from 'vs/workbench/browser/parts/editor/readOnlyEditorInput'; +import {ResourceEditorInput} from 'vs/workbench/browser/parts/editor/resourceEditorInput'; import {DiffEditorInput} from 'vs/workbench/browser/parts/editor/diffEditorInput'; import {DiffNavigator} from 'vs/editor/contrib/diffNavigator/common/diffNavigator'; import {DiffEditorWidget} from 'vs/editor/browser/widget/diffEditorWidget'; @@ -190,7 +190,7 @@ export class TextDiffEditor extends BaseTextEditor { let input = this.input; if (input && types.isFunction((input).getModifiedInput)) { let modifiedInput = (input).getModifiedInput(); - let readOnly = modifiedInput instanceof StringEditorInput || modifiedInput instanceof ReadOnlyEditorInput; + let readOnly = modifiedInput instanceof StringEditorInput || modifiedInput instanceof ResourceEditorInput; options.readOnly = readOnly; } diff --git a/src/vs/workbench/parts/files/browser/saveErrorHandler.ts b/src/vs/workbench/parts/files/browser/saveErrorHandler.ts index d595739c3e0..73e8759dc22 100644 --- a/src/vs/workbench/parts/files/browser/saveErrorHandler.ts +++ b/src/vs/workbench/parts/files/browser/saveErrorHandler.ts @@ -14,7 +14,7 @@ import {URL} from 'vs/base/common/network'; import {EditorModel, EditorInput} from 'vs/workbench/common/editor'; import {guessMimeTypes} from 'vs/base/common/mime'; import {EditorInputAction} from 'vs/workbench/browser/parts/editor/baseEditor'; -import {ReadOnlyEditorInput} from 'vs/workbench/browser/parts/editor/readOnlyEditorInput'; +import {ResourceEditorInput} from 'vs/workbench/browser/parts/editor/resourceEditorInput'; import {DiffEditorInput} from 'vs/workbench/browser/parts/editor/diffEditorInput'; import {DiffEditorModel} from 'vs/workbench/browser/parts/editor/diffEditorModel'; import {FileEditorInput} from 'vs/workbench/parts/files/browser/editors/fileEditorInput'; @@ -139,7 +139,7 @@ export class ConflictResolutionDiffEditorInput extends DiffEditorInput { } } -class FileOnDiskEditorInput extends ReadOnlyEditorInput { +export class FileOnDiskEditorInput extends ResourceEditorInput { private fileResource: URI; private lastModified: number; private mime: string; diff --git a/src/vs/workbench/test/browser/parts/editor/stringEditorInput.test.ts b/src/vs/workbench/test/browser/parts/editor/stringEditorInput.test.ts index 694bbec4a41..c8aac5d0404 100644 --- a/src/vs/workbench/test/browser/parts/editor/stringEditorInput.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/stringEditorInput.test.ts @@ -12,8 +12,8 @@ import URI from 'vs/base/common/uri'; import {URL} from 'vs/base/common/network'; import {StringEditorInput} from 'vs/workbench/browser/parts/editor/stringEditorInput'; import {LogEditorInput} from 'vs/workbench/browser/parts/editor/logEditorInput'; -import {ReadOnlyEditorInput} from 'vs/workbench/browser/parts/editor/readOnlyEditorInput'; -import {ReadOnlyEditorModel} from 'vs/workbench/browser/parts/editor/readOnlyEditorModel'; +import {ResourceEditorInput} from 'vs/workbench/browser/parts/editor/resourceEditorInput'; +import {ResourceEditorModel} from 'vs/workbench/browser/parts/editor/resourceEditorModel'; import {TestWorkspace, TestEditorService, MockRequestService} from 'vs/workbench/test/browser/servicesTestUtils'; import * as InstantiationService from 'vs/platform/instantiation/common/instantiationService'; import {createMockModelService, createMockModeService} from 'vs/editor/test/common/servicesTestUtils'; @@ -97,10 +97,10 @@ suite("Workbench - StringEditorInput", () => { let promise = Promise.as("value"); let stringEditorInput = inst.createInstance(StringEditorInput, "name", 'description', "value", "mime", false); - let promiseEditorInput = inst.createInstance(ReadOnlyEditorInput, "name", "description", URI.create('inMemory', null, 'thePath')); + let promiseEditorInput = inst.createInstance(ResourceEditorInput, "name", "description", URI.create('inMemory', null, 'thePath')); let stringEditorInput2 = inst.createInstance(StringEditorInput, "name", 'description', "value", "mime", false); - let promiseEditorInput2 = inst.createInstance(ReadOnlyEditorInput, "name", "description", URI.create('inMemory', null, 'thePath')); + let promiseEditorInput2 = inst.createInstance(ResourceEditorInput, "name", "description", URI.create('inMemory', null, 'thePath')); assert.strictEqual(stringEditorInput.matches(null), false); assert.strictEqual(promiseEditorInput.matches(null), false); @@ -123,7 +123,7 @@ suite("Workbench - StringEditorInput", () => { assert.strictEqual(logEditorInput.matches(logEditorInput2), true); }); - test("ReadOnlyEditorInput", function(done) { + test("ResourceEditorInput", function(done) { let modelService = createMockModelService(); let modeService = createMockModeService(); let inst = InstantiationService.create({ @@ -133,9 +133,9 @@ suite("Workbench - StringEditorInput", () => { let resource = URI.create('inMemory', null, 'thePath'); let model = modelService.createModel('function test() {}', modeService.getOrCreateMode('text'), URL.fromUri(resource)); - let input:ReadOnlyEditorInput = inst.createInstance(ReadOnlyEditorInput, 'The Name', 'The Description', resource); + let input:ResourceEditorInput = inst.createInstance(ResourceEditorInput, 'The Name', 'The Description', resource); - input.resolve().then((model:ReadOnlyEditorModel) => { + input.resolve().then((model:ResourceEditorModel) => { assert.ok(model); assert.equal(model.getValue(), 'function test() {}'); From 4a97fd5b7754561959129f1dfb926efe8795ae37 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2015 11:00:06 +0100 Subject: [PATCH 164/588] debug: add breakpoint.condition to model. --- .../debug/browser/debugEditorModelManager.ts | 22 ++++++++++++------- src/vs/workbench/parts/debug/common/debug.ts | 5 +++-- .../parts/debug/common/debugModel.ts | 12 +++++----- .../debug/electron-browser/debugService.ts | 8 +++---- 4 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts b/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts index 1e348e74514..30570b2e132 100644 --- a/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts +++ b/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts @@ -196,14 +196,16 @@ export class DebugEditorModelManager implements wbext.IWorkbenchContribution { return; } - var model = modelData.model, - modelUrl = model.getAssociatedResource(), - data: { lineNumber: number; enabled: boolean; }[] = []; + const model = modelData.model; + const data: { lineNumber: number; enabled: boolean; condition: string }[] = []; - var breakpoints = this.debugService.getModel().getBreakpoints().filter(bp => bp.source.uri.toString() === modelUrlStr); - var enabled: { [key: number]: boolean } = {}; + const breakpoints = this.debugService.getModel().getBreakpoints().filter(bp => bp.source.uri.toString() === modelUrlStr); + const enabledAndConditions: { [key: number]: { enabled: boolean, condition: string } } = {}; for (var i = 0; i < breakpoints.length; i++) { - enabled[breakpoints[i].lineNumber] = breakpoints[i].enabled; + enabledAndConditions[breakpoints[i].lineNumber] = { + enabled: breakpoints[i].enabled, + condition: breakpoints[i].condition + }; } for (var i = 0, len = modelData.breakpointDecorationIds.length; i < len; i++) { @@ -211,11 +213,15 @@ export class DebugEditorModelManager implements wbext.IWorkbenchContribution { // Check if the line got deleted. if (decorationRange.endColumn - decorationRange.startColumn > 0) { // Since we know it is collapsed, it cannot grow to multiple lines - data.push({ lineNumber: decorationRange.startLineNumber, enabled: enabled[modelData.breakpointLines[i]] }); + data.push({ + lineNumber: decorationRange.startLineNumber, + enabled: enabledAndConditions[modelData.breakpointLines[i]].enabled, + condition: enabledAndConditions[modelData.breakpointLines[i]].condition + }); } } - this.debugService.setBreakpointsForModel(modelUrl, data); + this.debugService.setBreakpointsForModel(model.getAssociatedResource(), data); } private onModelRemoved(model: editorcommon.IModel): void { diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index efda43f0ea9..b20f7356cfb 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -71,6 +71,7 @@ export interface IBreakpoint extends IEnablement { source: Source; lineNumber: number; desiredLineNumber: number; + condition: string; } export interface IExceptionBreakpoint extends IEnablement { @@ -209,8 +210,8 @@ export interface IDebugService extends ee.IEventEmitter { setFocusedStackFrameAndEvaluate(focusedStackFrame: IStackFrame): void; - setBreakpointsForModel(modelUri: uri, data: { lineNumber: number; enabled: boolean; }[]): Promise; - toggleBreakpoint(modelUri: uri, lineNumber: number): Promise; + setBreakpointsForModel(modelUri: uri, data: { lineNumber: number; enabled: boolean; condition: string }[]): Promise; + toggleBreakpoint(modelUri: uri, lineNumber: number, condition?: string): Promise; enableOrDisableAllBreakpoints(enabled: boolean): Promise; toggleEnablement(element: IEnablement): Promise; clearBreakpoints(modelUri?: uri): Promise; diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index d9f1828420c..1094bf447d3 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -257,7 +257,7 @@ export class Breakpoint implements debug.IBreakpoint { public lineNumber: number; private id: string; - constructor(public source: Source, public desiredLineNumber: number, public enabled: boolean) { + constructor(public source: Source, public desiredLineNumber: number, public enabled: boolean, public condition: string) { this.lineNumber = this.desiredLineNumber; this.id = uuid.generateUuid(); } @@ -344,7 +344,7 @@ export class Model extends ee.EventEmitter implements debug.IModel { this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); } - public toggleBreakpoint(modelUri: uri, lineNumber: number): void { + public toggleBreakpoint(modelUri: uri, lineNumber: number, condition?: string): void { var found = false; for (var i = 0, len = this.breakpoints.length; i < len && !found; i++) { if (this.breakpoints[i].lineNumber === lineNumber && this.breakpoints[i].source.uri.toString() === modelUri.toString()) { @@ -354,7 +354,7 @@ export class Model extends ee.EventEmitter implements debug.IModel { } if (!found) { - this.breakpoints.push(new Breakpoint(Source.fromUri(modelUri), lineNumber, true)); + this.breakpoints.push(new Breakpoint(Source.fromUri(modelUri), lineNumber, true, condition)); this.breakpointsActivated = true; } @@ -389,16 +389,16 @@ export class Model extends ee.EventEmitter implements debug.IModel { breakpoint.lineNumber = actualLineNumber; var duplicates = this.breakpoints.filter(bp => bp.lineNumber === breakpoint.lineNumber && bp.desiredLineNumber === breakpoint.desiredLineNumber); if (duplicates.length > 1) { - this.toggleBreakpoint(breakpoint.source.uri, breakpoint.lineNumber); + this.toggleBreakpoint(breakpoint.source.uri, breakpoint.lineNumber, breakpoint.condition); } else { this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); } } - public setBreakpointsForModel(modelUri: uri, data: { lineNumber: number; enabled: boolean; }[]): void { + public setBreakpointsForModel(modelUri: uri, data: { lineNumber: number; enabled: boolean; condition?: string; }[]): void { this.clearBreakpoints(modelUri); for (var i = 0, len = data.length; i < len; i++) { - this.breakpoints.push(new Breakpoint(Source.fromUri(modelUri), data[i].lineNumber, data[i].enabled)); + this.breakpoints.push(new Breakpoint(Source.fromUri(modelUri), data[i].lineNumber, data[i].enabled, data[i].condition)); } this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 031ded64319..a2db2fb0093 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -304,7 +304,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService private loadBreakpoints(): debug.IBreakpoint[] { try { return JSON.parse(this.storageService.get(DEBUG_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((breakpoint: any) => { - return new model.Breakpoint(new Source(breakpoint.source.name, breakpoint.source.uri, breakpoint.source.reference), breakpoint.desiredLineNumber || breakpoint.lineNumber, breakpoint.enabled); + return new model.Breakpoint(new Source(breakpoint.source.name, breakpoint.source.uri, breakpoint.source.reference), breakpoint.desiredLineNumber || breakpoint.lineNumber, breakpoint.enabled, breakpoint.condition); }); } catch (e) { return []; @@ -356,13 +356,13 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService } } - public setBreakpointsForModel(modelUri: uri, data: { lineNumber: number; enabled: boolean; }[]): Promise { + public setBreakpointsForModel(modelUri: uri, data: { lineNumber: number; enabled: boolean; condition: string; }[]): Promise { this.model.setBreakpointsForModel(modelUri, data); return this.sendBreakpoints(modelUri); } - public toggleBreakpoint(modelUri: uri, lineNumber: number): Promise { - this.model.toggleBreakpoint(modelUri, lineNumber); + public toggleBreakpoint(modelUri: uri, lineNumber: number, condition: string = null): Promise { + this.model.toggleBreakpoint(modelUri, lineNumber, condition); return this.sendBreakpoints(modelUri); } From 53c0599c3a8419469ea383c74de9d37216091153 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 27 Nov 2015 11:05:00 +0100 Subject: [PATCH 165/588] inputs - some cleanup --- .../workbench/browser/parts/editor/resourceEditorModel.ts | 6 ------ .../workbench/browser/parts/editor/stringEditorModel.ts | 8 ++------ src/vs/workbench/browser/parts/editor/textEditorModel.ts | 2 +- .../parts/files/browser/editors/textFileEditorModel.ts | 2 +- .../test/browser/parts/editor/editorModel.test.ts | 2 +- 5 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/resourceEditorModel.ts b/src/vs/workbench/browser/parts/editor/resourceEditorModel.ts index b74f6b32e60..35646d5d0e3 100644 --- a/src/vs/workbench/browser/parts/editor/resourceEditorModel.ts +++ b/src/vs/workbench/browser/parts/editor/resourceEditorModel.ts @@ -4,17 +4,11 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {TPromise} from 'vs/base/common/winjs.base'; import {BaseTextEditorModel} from 'vs/workbench/browser/parts/editor/textEditorModel'; -import {IIdentifiedSingleEditOperation} from 'vs/editor/common/editorCommon'; -import {EditorModel} from 'vs/workbench/common/editor'; import URI from 'vs/base/common/uri'; import {URL} from 'vs/base/common/network'; -import {Position} from 'vs/editor/common/core/position'; -import {Range} from 'vs/editor/common/core/range'; import {IModeService} from 'vs/editor/common/services/modeService'; import {IModelService} from 'vs/editor/common/services/modelService'; -import {EditOperation} from 'vs/editor/common/core/editOperation'; /** * An editor model whith an in-memory, readonly content that is backed by an existing editor model. diff --git a/src/vs/workbench/browser/parts/editor/stringEditorModel.ts b/src/vs/workbench/browser/parts/editor/stringEditorModel.ts index 56feb1e5970..9ae7491dd0e 100644 --- a/src/vs/workbench/browser/parts/editor/stringEditorModel.ts +++ b/src/vs/workbench/browser/parts/editor/stringEditorModel.ts @@ -100,10 +100,6 @@ export class StringEditorModel extends BaseTextEditorModel { return null; } - public setMime(mime: string): void { - this.mime = mime; - } - public getMime(): string { return this.mime; } @@ -112,12 +108,12 @@ export class StringEditorModel extends BaseTextEditorModel { // Create text editor model if not yet done if (!this.textEditorModel) { - return this.createTextEditorModel(this.value, this.mime, this.resource); + return this.createTextEditorModel(this.value, this.resource, this.mime); } // Otherwise update else { - this.updateTextEditorModel(this.value, this.mime); + this.updateTextEditorModel(this.value); } return TPromise.as(this); diff --git a/src/vs/workbench/browser/parts/editor/textEditorModel.ts b/src/vs/workbench/browser/parts/editor/textEditorModel.ts index 23ecb533070..f14f8bbfbf3 100644 --- a/src/vs/workbench/browser/parts/editor/textEditorModel.ts +++ b/src/vs/workbench/browser/parts/editor/textEditorModel.ts @@ -41,7 +41,7 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd /** * Creates the text editor model with the provided value, mime (can be comma separated for multiple values) and optional resource URL. */ - protected createTextEditorModel(value: string, mime?: string, resource?: URI): TPromise { + protected createTextEditorModel(value: string, resource?: URI, mime?: string): TPromise { let firstLineText = this.getFirstLineText(value); // To avoid flickering, give the mode at most 50ms to load. If the mode doesn't load in 50ms, proceed creating the model with a mode promise diff --git a/src/vs/workbench/parts/files/browser/editors/textFileEditorModel.ts b/src/vs/workbench/parts/files/browser/editors/textFileEditorModel.ts index c6abef3c064..52bfd91a20c 100644 --- a/src/vs/workbench/parts/files/browser/editors/textFileEditorModel.ts +++ b/src/vs/workbench/parts/files/browser/editors/textFileEditorModel.ts @@ -289,7 +289,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements IEncodin else { diag('load() - created text editor model', this.resource, new Date()); - this.createTextEditorModelPromise = this.createTextEditorModel(content.value, null, content.resource).then(() => { + this.createTextEditorModelPromise = this.createTextEditorModel(content.value, content.resource).then(() => { this.createTextEditorModelPromise = null; this.setDirty(false); // Ensure we are not tracking a stale state diff --git a/src/vs/workbench/test/browser/parts/editor/editorModel.test.ts b/src/vs/workbench/test/browser/parts/editor/editorModel.test.ts index f507681903c..2a0f2af2546 100644 --- a/src/vs/workbench/test/browser/parts/editor/editorModel.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editorModel.test.ts @@ -35,7 +35,7 @@ suite("Workbench - EditorModel", () => { let m = new MyTextEditorModel(modelService, modeService); m.load().then(function(model: any) { assert(model === m); - return model.createTextEditorModel("foo", "text/plain").then(function() { + return model.createTextEditorModel("foo", null, "text/plain").then(function() { assert.strictEqual(m.isResolved(), true); }); }).done(() => { From cc888d5455f3da003be6948f9c73de2819836cd7 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2015 11:09:43 +0100 Subject: [PATCH 166/588] Revert "debug: remove taskService creation workaround." This reverts commit b7ab6624ac51d20b137ba635a1b52c278ce4d5f2. --- .../workbench/parts/debug/electron-browser/debugService.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index a2db2fb0093..56a324afa9f 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -55,6 +55,7 @@ var DEBUG_SELECTED_CONFIG_NAME_KEY = 'debug.selectedconfigname'; export class DebugService extends ee.EventEmitter implements debug.IDebugService { public serviceId = debug.IDebugService; + private taskService: ITaskService; private state: debug.State; private session: session.RawDebugSession; private model: model.Model; @@ -81,8 +82,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService @ILifecycleService private lifecycleService: ILifecycleService, @IInstantiationService private instantiationService:IInstantiationService, @IPluginService private pluginService: IPluginService, - @IOutputService private outputService: IOutputService, - @ITaskService private taskService: ITaskService + @IOutputService private outputService: IOutputService ) { super(); @@ -90,6 +90,8 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService this.debugStringEditorInputs = []; this.session = null; this.state = debug.State.Inactive; + // There is a cycle if taskService gets injected, use a workaround. + this.taskService = this.instantiationService.getInstance(ITaskService); if (!this.contextService.getWorkspace()) { this.state = debug.State.Disabled; From bf7bdc3ba1aa67ba041396b2bc56b47953992926 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2015 11:22:13 +0100 Subject: [PATCH 167/588] debug: only create SystemVariables if there is a workspace. --- src/vs/workbench/parts/debug/node/debugConfigurationManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/node/debugConfigurationManager.ts b/src/vs/workbench/parts/debug/node/debugConfigurationManager.ts index ec35680b64c..14a46325a3b 100644 --- a/src/vs/workbench/parts/debug/node/debugConfigurationManager.ts +++ b/src/vs/workbench/parts/debug/node/debugConfigurationManager.ts @@ -152,7 +152,7 @@ export class ConfigurationManager { @IConfigurationService private configurationService: IConfigurationService, @IQuickOpenService private quickOpenService: IQuickOpenService ) { - this.systemVariables = new SystemVariables(this.editorService, this.contextService); + this.systemVariables = this.contextService.getWorkspace() ? new SystemVariables(this.editorService, this.contextService) : null; this.setConfiguration(configName); this.adapters = []; this.registerListeners(); From e7f4060c9aa8bba2e619eeef144f99c2fba58949 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 27 Nov 2015 11:45:54 +0100 Subject: [PATCH 168/588] model.getRepositoryRoot --- .../parts/git/browser/gitServices.ts | 24 +++++++++++++------ src/vs/workbench/parts/git/common/git.ts | 1 + src/vs/workbench/parts/git/common/gitModel.ts | 7 ++++++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/parts/git/browser/gitServices.ts b/src/vs/workbench/parts/git/browser/gitServices.ts index e8c8e392540..0fc45af1101 100644 --- a/src/vs/workbench/parts/git/browser/gitServices.ts +++ b/src/vs/workbench/parts/git/browser/gitServices.ts @@ -32,6 +32,7 @@ import {IInstantiationService} from 'vs/platform/instantiation/common/instantiat import {IMessageService} from 'vs/platform/message/common/message'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {ILifecycleService} from 'vs/platform/lifecycle/common/lifecycle'; +import URI from 'vs/base/common/uri'; function toReadablePath(path: string): string { if (!platform.isWindows) { @@ -158,9 +159,9 @@ class EditorInputCache } private createRightInput(status: git.IFileStatus): winjs.Promise { - var path = status.getPath(); - var resource = this.contextService.toResource(path); - var model = this.gitService.getModel(); + const model = this.gitService.getModel(); + const path = status.getPath(); + let resource = URI.file(paths.join(model.getRepositoryRoot(), path)); switch (status.getStatus()) { case git.Status.INDEX_MODIFIED: @@ -181,13 +182,13 @@ class EditorInputCache var indexStatus = model.getStatus().find(path, git.StatusType.INDEX); if (indexStatus && indexStatus.getStatus() === git.Status.INDEX_RENAMED) { - return this.editorService.inputToType({ resource: this.contextService.toResource(indexStatus.getRename()) }); + resource = URI.file(paths.join(model.getRepositoryRoot(), indexStatus.getRename())); } - return this.editorService.inputToType({ resource: resource }); + return this.editorService.inputToType({ resource }); case git.Status.BOTH_MODIFIED: - return this.editorService.inputToType({ resource: resource }); + return this.editorService.inputToType({ resource }); default: return winjs.Promise.as(null); @@ -391,7 +392,16 @@ export class GitService extends ee.EventEmitter private refreshDelayer: async.ThrottledDelayer; private autoFetcher: AutoFetcher; - constructor(raw: git.IRawGitService, @IInstantiationService instantiationService: IInstantiationService, @IEventService eventService: IEventService, @IMessageService messageService: IMessageService, @IWorkbenchEditorService editorService: IWorkbenchEditorService, @IOutputService outputService: IOutputService, @IWorkspaceContextService contextService: IWorkspaceContextService, @ILifecycleService lifecycleService: ILifecycleService) { + constructor( + raw: git.IRawGitService, + @IInstantiationService instantiationService: IInstantiationService, + @IEventService eventService: IEventService, + @IMessageService messageService: IMessageService, + @IWorkbenchEditorService editorService: IWorkbenchEditorService, + @IOutputService outputService: IOutputService, + @IWorkspaceContextService contextService: IWorkspaceContextService, + @ILifecycleService lifecycleService: ILifecycleService + ) { super(); this.instantiationService = instantiationService; diff --git a/src/vs/workbench/parts/git/common/git.ts b/src/vs/workbench/parts/git/common/git.ts index bbf438f3a18..35777c785da 100644 --- a/src/vs/workbench/parts/git/common/git.ts +++ b/src/vs/workbench/parts/git/common/git.ts @@ -123,6 +123,7 @@ export interface IStatusModel extends EventEmitter.IEventEmitter { } export interface IModel extends EventEmitter.IEventEmitter { + getRepositoryRoot(): string; getStatus(): IStatusModel; getHEAD(): IBranch; getHeads(): IBranch[]; diff --git a/src/vs/workbench/parts/git/common/gitModel.ts b/src/vs/workbench/parts/git/common/gitModel.ts index 6b3a2229982..fc80a8f2465 100644 --- a/src/vs/workbench/parts/git/common/gitModel.ts +++ b/src/vs/workbench/parts/git/common/gitModel.ts @@ -311,6 +311,7 @@ export class StatusModel extends EventEmitter.EventEmitter implements Git.IStatu export class Model extends EventEmitter.EventEmitter implements Git.IModel { + private repositoryRoot: string; private status: Git.IStatusModel; private HEAD: Git.IBranch; private heads: Git.IBranch[]; @@ -322,6 +323,7 @@ export class Model extends EventEmitter.EventEmitter implements Git.IModel { this.toDispose = []; + this.repositoryRoot = null; this.status = new StatusModel(); this.toDispose.push(this.addEmitter2(this.status)); @@ -330,6 +332,10 @@ export class Model extends EventEmitter.EventEmitter implements Git.IModel { this.tags = []; } + public getRepositoryRoot(): string { + return this.repositoryRoot; + } + public getStatus(): Git.IStatusModel { return this.status; } @@ -357,6 +363,7 @@ export class Model extends EventEmitter.EventEmitter implements Git.IModel { }; } + this.repositoryRoot = status.repositoryRoot; this.status.update(status.status); this.HEAD = status.HEAD; From a900882ba4907702dfc3549a3401eb8fbeaf1f6c Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 27 Nov 2015 11:46:00 +0100 Subject: [PATCH 169/588] cleanup --- src/vs/workbench/parts/git/common/git.ts | 2 +- src/vs/workbench/parts/git/common/gitModel.ts | 44 +++++++++---------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/vs/workbench/parts/git/common/git.ts b/src/vs/workbench/parts/git/common/git.ts index 35777c785da..0e006bd1db4 100644 --- a/src/vs/workbench/parts/git/common/git.ts +++ b/src/vs/workbench/parts/git/common/git.ts @@ -114,7 +114,7 @@ export interface IStatusSummary { export interface IStatusModel extends EventEmitter.IEventEmitter { getSummary(): IStatusSummary; - update(rawStatuses: IRawFileStatus[]): void; + update(status: IRawFileStatus[]): void; getIndexStatus(): IStatusGroup; getWorkingTreeStatus(): IStatusGroup; getMergeStatus(): IStatusGroup; diff --git a/src/vs/workbench/parts/git/common/gitModel.ts b/src/vs/workbench/parts/git/common/gitModel.ts index fc80a8f2465..0a74d1d1139 100644 --- a/src/vs/workbench/parts/git/common/gitModel.ts +++ b/src/vs/workbench/parts/git/common/gitModel.ts @@ -12,19 +12,17 @@ import Git = require('vs/workbench/parts/git/common/git'); export class FileStatus implements Git.IFileStatus { private id: string; - private path: string; private pathComponents: string[]; - private mimetype: string; - private status: Git.Status; - private rename: string; - constructor(path: string, mimetype: string, status: Git.Status, rename?: string, isModifiedInIndex?: boolean) { + constructor( + private path: string, + private mimetype: string, + private status: Git.Status, + private rename?: string, + isModifiedInIndex?: boolean + ) { this.id = FileStatus.typeOf(status) + ':' + path + (rename ? ':' + rename : '') + (isModifiedInIndex ? '$' : ''); - this.path = path; this.pathComponents = path.split('/'); - this.mimetype = mimetype; - this.rename = rename; - this.status = status; } public getPath(): string { @@ -211,27 +209,25 @@ export class StatusModel extends EventEmitter.EventEmitter implements Git.IStatu }; } - public update(rawStatuses: Git.IRawFileStatus[]): void { + public update(status: Git.IRawFileStatus[]): void { var index: FileStatus[] = []; var workingTree: FileStatus[] = []; var merge: FileStatus[] = []; - for (var i = 0; i < rawStatuses.length; i++) { - var raw = rawStatuses[i]; - + status.forEach(raw => { switch(raw.x + raw.y) { - case '??': workingTree.push(new FileStatus(raw.path, raw.mimetype, Git.Status.UNTRACKED)); continue; - case '!!': workingTree.push(new FileStatus(raw.path, raw.mimetype, Git.Status.IGNORED)); continue; - case 'DD': merge.push(new FileStatus(raw.path, raw.mimetype, Git.Status.BOTH_DELETED)); continue; - case 'AU': merge.push(new FileStatus(raw.path, raw.mimetype, Git.Status.ADDED_BY_US)); continue; - case 'UD': merge.push(new FileStatus(raw.path, raw.mimetype, Git.Status.DELETED_BY_THEM)); continue; - case 'UA': merge.push(new FileStatus(raw.path, raw.mimetype, Git.Status.ADDED_BY_THEM)); continue; - case 'DU': merge.push(new FileStatus(raw.path, raw.mimetype, Git.Status.DELETED_BY_US)); continue; - case 'AA': merge.push(new FileStatus(raw.path, raw.mimetype, Git.Status.BOTH_ADDED)); continue; - case 'UU': merge.push(new FileStatus(raw.path, raw.mimetype, Git.Status.BOTH_MODIFIED)); continue; + case '??': return workingTree.push(new FileStatus(raw.path, raw.mimetype, Git.Status.UNTRACKED)); + case '!!': return workingTree.push(new FileStatus(raw.path, raw.mimetype, Git.Status.IGNORED)); + case 'DD': return merge.push(new FileStatus(raw.path, raw.mimetype, Git.Status.BOTH_DELETED)); + case 'AU': return merge.push(new FileStatus(raw.path, raw.mimetype, Git.Status.ADDED_BY_US)); + case 'UD': return merge.push(new FileStatus(raw.path, raw.mimetype, Git.Status.DELETED_BY_THEM)); + case 'UA': return merge.push(new FileStatus(raw.path, raw.mimetype, Git.Status.ADDED_BY_THEM)); + case 'DU': return merge.push(new FileStatus(raw.path, raw.mimetype, Git.Status.DELETED_BY_US)); + case 'AA': return merge.push(new FileStatus(raw.path, raw.mimetype, Git.Status.BOTH_ADDED)); + case 'UU': return merge.push(new FileStatus(raw.path, raw.mimetype, Git.Status.BOTH_MODIFIED)); } - var isModifiedInIndex = false; + let isModifiedInIndex = false; switch (raw.x) { case 'M': index.push(new FileStatus(raw.path, raw.mimetype, Git.Status.INDEX_MODIFIED)); isModifiedInIndex = true; break; @@ -245,7 +241,7 @@ export class StatusModel extends EventEmitter.EventEmitter implements Git.IStatu case 'M': workingTree.push(new FileStatus(raw.path, raw.mimetype, Git.Status.MODIFIED, raw.rename, isModifiedInIndex)); break; case 'D': workingTree.push(new FileStatus(raw.path, raw.mimetype, Git.Status.DELETED, raw.rename)); break; } - } + }); this.indexStatus.update(index); this.workingTreeStatus.update(workingTree); From 429886c99f31aa63f21949d208b9ded6ae1c85d1 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 27 Nov 2015 12:03:24 +0100 Subject: [PATCH 170/588] diff - restore ability to diff 2 binary files --- .../browser/parts/editor/diffEditorInput.ts | 10 +++---- .../browser/parts/editor/textDiffEditor.ts | 26 +++++++++++++---- .../files/browser/editors/fileEditorInput.ts | 28 +++++++++++-------- 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/diffEditorInput.ts b/src/vs/workbench/browser/parts/editor/diffEditorInput.ts index dae16c51df6..77c1841c5f6 100644 --- a/src/vs/workbench/browser/parts/editor/diffEditorInput.ts +++ b/src/vs/workbench/browser/parts/editor/diffEditorInput.ts @@ -11,9 +11,7 @@ import {EventType} from 'vs/base/common/events'; import {EditorModel, IFileEditorInput, EditorInput, IInputStatus, BaseDiffEditorInput} from 'vs/workbench/common/editor'; import {BaseTextEditorModel} from 'vs/workbench/browser/parts/editor/textEditorModel'; import {DiffEditorModel} from 'vs/workbench/browser/parts/editor/diffEditorModel'; -import {TextDiffEditor} from 'vs/workbench/browser/parts/editor/textDiffEditor'; import {TextDiffEditorModel} from 'vs/workbench/browser/parts/editor/textDiffEditorModel'; -import {BinaryResourceDiffEditor} from 'vs/workbench/browser/parts/editor/binaryDiffEditor'; /** * The base editor input for the diff editor. It is made up of two editor inputs, the original version @@ -27,12 +25,14 @@ export class DiffEditorInput extends BaseDiffEditorInput { private name: string; private description: string; private cachedModel: DiffEditorModel; + private forceOpenAsBinary: boolean; - constructor(name: string, description: string, originalInput: EditorInput, modifiedInput: EditorInput) { + constructor(name: string, description: string, originalInput: EditorInput, modifiedInput: EditorInput, forceOpenAsBinary?: boolean) { super(originalInput, modifiedInput); this.name = name; this.description = description; + this.forceOpenAsBinary = forceOpenAsBinary; this._toUnbind = []; @@ -129,9 +129,9 @@ export class DiffEditorInput extends BaseDiffEditorInput { public getPreferredEditorId(candidates: string[]): string { // Find the right diff editor for the given isBinary/isText state - let useBinaryEditor = this.isBinary(this.originalInput) || this.isBinary(this.modifiedInput); + let useBinaryEditor = this.forceOpenAsBinary || this.isBinary(this.originalInput) || this.isBinary(this.modifiedInput); - return !useBinaryEditor ? TextDiffEditor.ID : BinaryResourceDiffEditor.ID; + return !useBinaryEditor ? 'workbench.editors.textDiffEditor' : 'workbench.editors.binaryResourceDiffEditor'; } private isBinary(input: EditorInput): boolean { diff --git a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts index d4e05c29fa0..449888aa908 100644 --- a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts @@ -10,6 +10,7 @@ import {Promise, TPromise} from 'vs/base/common/winjs.base'; import nls = require('vs/nls'); import {Builder} from 'vs/base/browser/builder'; import {Action, IAction} from 'vs/base/common/actions'; +import {onUnexpectedError} from 'vs/base/common/errors'; import types = require('vs/base/common/types'); import {IDiffEditor} from 'vs/editor/browser/editorBrowser'; import {IDiffEditorOptions, IEditorOptions} from 'vs/editor/common/editorCommon'; @@ -136,8 +137,8 @@ export class TextDiffEditor extends BaseTextEditor { return this.editorService.resolveEditorModel(input, true /* Reload */).then((resolvedModel: EditorModel) => { // Assert Model Instance - if (!(resolvedModel instanceof TextDiffEditorModel)) { - return TPromise.wrapError(nls.localize('cannotDiffBinary', "At least one of the resources to compare seems to be binary and this is currently not supported")); + if (!(resolvedModel instanceof TextDiffEditorModel) && this.openAsBinary(input, options)) { + return null; } // Assert that the current input is still the one we expect. This prevents a race condition when loading a diff takes long and another input was set meanwhile @@ -174,9 +175,9 @@ export class TextDiffEditor extends BaseTextEditor { diffEditor.updateOptions(this.getCodeEditorOptions()); }, (error) => { - // In case we tried to open a file and the response indicates that this is not a text file, bail out to the user. - if (this.isFileBinaryError(error)) { - return Promise.wrapError(nls.localize('cannotDiffBinary', "At least one of the resources to compare seems to be binary and this is currently not supported")); + // In case we tried to open a file and the response indicates that this is not a text file, fallback to binary diff. + if (this.isFileBinaryError(error) && this.openAsBinary(input, options)) { + return null; } // Otherwise make sure the error bubbles up @@ -184,6 +185,21 @@ export class TextDiffEditor extends BaseTextEditor { }); } + private openAsBinary(input: EditorInput, options: EditorOptions): boolean { + if (input instanceof DiffEditorInput) { + let originalInput = input.originalInput; + let modifiedInput = input.modifiedInput; + + let binaryDiffInput = new DiffEditorInput(input.getName(), input.getDescription(), originalInput, modifiedInput, true); + + this.editorService.openEditor(binaryDiffInput, options, this.position).done(null, onUnexpectedError); + + return true; + } + + return false; + } + protected getCodeEditorOptions(): IEditorOptions { let options: IDiffEditorOptions = super.getCodeEditorOptions(); diff --git a/src/vs/workbench/parts/files/browser/editors/fileEditorInput.ts b/src/vs/workbench/parts/files/browser/editors/fileEditorInput.ts index 5ff6698b4ef..a9480382cff 100644 --- a/src/vs/workbench/parts/files/browser/editors/fileEditorInput.ts +++ b/src/vs/workbench/parts/files/browser/editors/fileEditorInput.ts @@ -17,6 +17,7 @@ import assert = require('vs/base/common/assert'); import {EditorModel, IInputStatus, EncodingMode} from 'vs/workbench/common/editor'; import {IEditorRegistry, Extensions, EditorDescriptor} from 'vs/workbench/browser/parts/editor/baseEditor'; import {BinaryEditorModel} from 'vs/workbench/browser/parts/editor/binaryEditorModel'; +import {IFileOperationResult, FileOperationResult} from 'vs/platform/files/common/files'; import {FileEditorDescriptor} from 'vs/workbench/parts/files/browser/files'; import {BINARY_FILE_EDITOR_ID, FILE_EDITOR_INPUT_ID, FileEditorInput as CommonFileEditorInput} from 'vs/workbench/parts/files/common/files'; import {CACHE, TextFileEditorModel, State} from 'vs/workbench/parts/files/browser/editors/textFileEditorModel'; @@ -238,7 +239,7 @@ export class FileEditorInput extends CommonFileEditorInput { // Otherwise Create Model and Load else { - modelPromise = this.createModel().load(); + modelPromise = this.createAndLoadModel(); FileEditorInput.FILE_EDITOR_MODEL_LOADERS[this.resource.toString()] = modelPromise; } @@ -269,24 +270,27 @@ export class FileEditorInput extends CommonFileEditorInput { return -1; } - private createModel(): EditorModel { + private createAndLoadModel(): TPromise { let descriptor = (Registry.as(Extensions.Editors)).getEditor(this); if (!descriptor) { throw new Error('Unable to find an editor in the registry for this input.'); } - // Binary model if editor is binary editor - let model: EditorModel; - if (descriptor.getId() === BINARY_FILE_EDITOR_ID) { - model = new BinaryEditorModel(this.resource, this.getName()); - } + // Optimistically create a text model assuming that the file is not binary + let textModel = this.instantiationService.createInstance(TextFileEditorModel, this.resource, this.preferredEncoding); + return textModel.load().then(() => textModel, (error) => { - // Otherwise use text model - else { - model = this.instantiationService.createInstance(TextFileEditorModel, this.resource, this.preferredEncoding); - } + // In case of an error that indicates that the file is binary, just return with the binary editor model + if ((error).fileOperationResult === FileOperationResult.FILE_IS_BINARY) { + textModel.dispose(); - return model; + let binaryModel = new BinaryEditorModel(this.resource, this.getName()); + return binaryModel.load(); + } + + // Bubble any other error up + return Promise.wrapError(error); + }); } public dispose(force?: boolean): void { From c96af39bfbc9369b3cfc1d26873f45007eb0d0bc Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 27 Nov 2015 12:04:31 +0100 Subject: [PATCH 171/588] Improve default linux keybindings for move lines and add cursors --- src/vs/editor/common/config/config.ts | 6 ++++-- .../contrib/linesOperations/common/linesOperations.ts | 4 ++-- .../editor/contrib/multicursor/common/multicursor.ts | 10 ++++++++-- .../platform/keybinding/common/keybindingsRegistry.ts | 5 ----- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/vs/editor/common/config/config.ts b/src/vs/editor/common/config/config.ts index 1f8133a8907..0d9e02fe0dd 100644 --- a/src/vs/editor/common/config/config.ts +++ b/src/vs/editor/common/config/config.ts @@ -155,7 +155,8 @@ registerCoreCommand(H.CursorUp, { registerCoreCommand(H.CursorUpSelect, { primary: KeyMod.Shift | KeyCode.UpArrow, secondary: [getWordNavigationKB(true, KeyCode.UpArrow)], - mac: { primary: KeyMod.Shift | KeyCode.UpArrow } + mac: { primary: KeyMod.Shift | KeyCode.UpArrow }, + linux: { primary: KeyMod.Shift | KeyCode.UpArrow } }); registerCoreCommand(H.CursorDown, { primary: KeyCode.DownArrow, @@ -164,7 +165,8 @@ registerCoreCommand(H.CursorDown, { registerCoreCommand(H.CursorDownSelect, { primary: KeyMod.Shift | KeyCode.DownArrow, secondary: [getWordNavigationKB(true, KeyCode.DownArrow)], - mac: { primary: KeyMod.Shift | KeyCode.DownArrow } + mac: { primary: KeyMod.Shift | KeyCode.DownArrow }, + linux: { primary: KeyMod.Shift | KeyCode.DownArrow } }); registerCoreCommand(H.CursorPageUp, { primary: KeyCode.PageUp diff --git a/src/vs/editor/contrib/linesOperations/common/linesOperations.ts b/src/vs/editor/contrib/linesOperations/common/linesOperations.ts index e68ea47b55d..a451fd9df4c 100644 --- a/src/vs/editor/contrib/linesOperations/common/linesOperations.ts +++ b/src/vs/editor/contrib/linesOperations/common/linesOperations.ts @@ -242,12 +242,12 @@ CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(TrimTrailin CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(MoveLinesDownAction, MoveLinesDownAction.ID, nls.localize('lines.moveDown', "Move Line Down"), { context: ContextKey.EditorTextFocus, primary: KeyMod.Alt | KeyCode.DownArrow, - linux: { primary: KeyMod.CtrlCmd | KeyCode.DownArrow } + linux: { primary: KeyMod.Alt | KeyCode.DownArrow } })); CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(MoveLinesUpAction, MoveLinesUpAction.ID, nls.localize('lines.moveUp', "Move Line Up"), { context: ContextKey.EditorTextFocus, primary: KeyMod.Alt | KeyCode.UpArrow, - linux: { primary: KeyMod.CtrlCmd | KeyCode.UpArrow } + linux: { primary: KeyMod.Alt | KeyCode.UpArrow } })); CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(CopyLinesDownAction, CopyLinesDownAction.ID, nls.localize('lines.copyDown', "Copy Line Down"), { context: ContextKey.EditorTextFocus, diff --git a/src/vs/editor/contrib/multicursor/common/multicursor.ts b/src/vs/editor/contrib/multicursor/common/multicursor.ts index e9e173fd690..0efb91e4821 100644 --- a/src/vs/editor/contrib/multicursor/common/multicursor.ts +++ b/src/vs/editor/contrib/multicursor/common/multicursor.ts @@ -32,10 +32,16 @@ class InsertCursorBelow extends HandlerEditorAction { CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(InsertCursorAbove, InsertCursorAbove.ID, nls.localize('mutlicursor.insertAbove', "Insert Cursor Above"), { context: ContextKey.EditorTextFocus, primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.UpArrow, - linux: { primary: KeyMod.CtrlCmd| KeyMod.WinCtrl | KeyCode.UpArrow } + linux: { + primary: KeyMod.Shift | KeyMod.Alt | KeyCode.UpArrow, + secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.UpArrow] + } })); CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(InsertCursorBelow, InsertCursorBelow.ID, nls.localize('mutlicursor.insertBelow', "Insert Cursor Below"), { context: ContextKey.EditorTextFocus, primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.DownArrow, - linux: { primary: KeyMod.CtrlCmd| KeyMod.WinCtrl | KeyCode.DownArrow } + linux: { + primary: KeyMod.Shift | KeyMod.Alt | KeyCode.DownArrow, + secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.DownArrow] + } })); diff --git a/src/vs/platform/keybinding/common/keybindingsRegistry.ts b/src/vs/platform/keybinding/common/keybindingsRegistry.ts index b391a7daea9..65ac634a595 100644 --- a/src/vs/platform/keybinding/common/keybindingsRegistry.ts +++ b/src/vs/platform/keybinding/common/keybindingsRegistry.ts @@ -103,11 +103,6 @@ class KeybindingsRegistryImpl implements IKeybindingsRegistry { } } } - if (Platform.isLinux) { - if (!BinaryKeybindings.hasCtrlCmd(keybinding) && !BinaryKeybindings.hasShift(keybinding) && BinaryKeybindings.hasAlt(keybinding) && !BinaryKeybindings.hasWinCtrl(keybinding)) { - console.warn('Alt+ keybindings should not be used by default under Linux. Offender: ', keybinding, ' for ', commandId); - } - } this._keybindings.push({ keybinding: keybinding, command: commandId, From c37cb211f1f2d6a9c53a96501ed3849ab4c2c1e3 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 27 Nov 2015 11:52:45 +0100 Subject: [PATCH 172/588] Make colors in dark and light theme more consistent, fix xml (#23), jade (#277) --- src/vs/editor/browser/widget/media/tokens.css | 101 ++-- src/vs/languages/css/common/css.ts | 71 +-- src/vs/languages/css/common/cssTokenTypes.ts | 11 + src/vs/languages/css/test/common/css.test.ts | 167 +++--- .../json/common/features/jsonTokenTypes.ts | 8 +- src/vs/languages/less/common/less.ts | 29 +- .../less/test/common/colorizer.test.ts | 305 +++++------ src/vs/languages/markdown/common/tokens.css | 137 +++-- .../markdown/test/common/markdown.test.ts | 7 +- src/vs/languages/php/test/common/php.test.ts | 13 +- src/vs/languages/sass/common/sass.ts | 41 +- .../languages/sass/test/common/sass.test.ts | 485 +++++++++--------- .../languages/vsxml/common/vsxmlTokenTypes.ts | 2 +- 13 files changed, 730 insertions(+), 647 deletions(-) create mode 100644 src/vs/languages/css/common/cssTokenTypes.ts diff --git a/src/vs/editor/browser/widget/media/tokens.css b/src/vs/editor/browser/widget/media/tokens.css index aea5e863061..b4af3c7731a 100644 --- a/src/vs/editor/browser/widget/media/tokens.css +++ b/src/vs/editor/browser/widget/media/tokens.css @@ -70,7 +70,6 @@ .monaco-editor.vs .token.delimiter.html { color: #383838; } .monaco-editor.vs .token.metatag.content.html { color: red; } .monaco-editor.vs .token.metatag.html { color: gray; } -.monaco-editor.vs .token.tag.html { color: #800000; } .monaco-editor.vs .token.attribute.name.html { color: red; } .monaco-editor.vs .token.attribute.value.html { color: blue; } @@ -80,7 +79,6 @@ .monaco-editor.vs .token.delimiter.xml { color: blue; } .monaco-editor.vs .token.metatag.content.xml { color: red; } .monaco-editor.vs .token.metatag.xml { color: gray; } -.monaco-editor.vs .token.tag.xml { color: #800000; } .monaco-editor.vs .token.attribute.name.xml { color: red; } .monaco-editor.vs .token.attribute.value.xml { color: blue; } @@ -96,7 +94,6 @@ .monaco-editor.vs .token.delimiter.vs { color: #708870; } /* Jade */ -.monaco-editor.vs .token.tag.jade { color: #800000; } .monaco-editor.vs .token.tag.id.jade, .monaco-editor.vs .token.tag.class.jade { color: #4F76AC; } .monaco-editor.vs .token.interpolation.jade { color: magenta; } @@ -127,7 +124,7 @@ .monaco-editor.vs-dark .token.number.octal { color: #204070; } .monaco-editor.vs-dark .token.regexp { color: #B46695; } .monaco-editor.vs-dark .token.delimiter { color: #DCDCDC; } -.monaco-editor.vs-dark .token.tag { color: #D7BA7D; } +.monaco-editor.vs-dark .token.tag { color: #569CD6; } .monaco-editor.vs-dark .token.metatag { color: #DD6A6F; } .monaco-editor.vs-dark .token.annotation { color: #cc6666; } .monaco-editor.vs-dark .token.key { color: #9CDCFE; } @@ -173,7 +170,6 @@ /* HTML */ -.monaco-editor.vs-dark .token.tag.html { color: #569CD6; } .monaco-editor.vs-dark .token.delimiter.html { color: #808080; } .monaco-editor.vs-dark .token.metatag.content.html { color: #9CDCFE; } .monaco-editor.vs-dark .token.metatag.html { color: #569CD6; } @@ -181,7 +177,6 @@ .monaco-editor.vs-dark .token.string.html { color: #CE9178; } /* XML */ -.monaco-editor.vs-dark .token.tag.xml { color: #569CD6; } .monaco-editor.vs-dark .token.delimiter.xml { color: #808080; } .monaco-editor.vs-dark .token.metatag.content.xml { color: #9CDCFE; } .monaco-editor.vs-dark .token.metatag.xml { color: #569CD6; } @@ -199,7 +194,6 @@ .monaco-editor.vs-dark .token.attribute.value.vs { color: #C4C4C4; } /* Jade */ -.monaco-editor.vs-dark .token.tag.jade { color: #569CD6; } .monaco-editor.vs-dark .token.tag.id.jade, .monaco-editor.vs-dark .token.tag.class.jade { color: #4F76AC; } .monaco-editor.vs-dark .token.interpolation.jade { color: magenta; } @@ -311,8 +305,8 @@ .monaco-editor.hc-black .token.variable { color: #1AEBFF; } .monaco-editor.hc-black .token.variable.predefined { color: #1AEBFF; } .monaco-editor.hc-black .token.constant { color: #dd0000; } -.monaco-editor.hc-black .token.string { color: #C0C0C0; } -.monaco-editor.hc-black .token.string.escape { color: #C0C0C0; } +.monaco-editor.hc-black .token.string { color: #CE9178; } +.monaco-editor.hc-black .token.string.escape { color: #CE9178; } .monaco-editor.hc-black .token.comment { color: #008000; } .monaco-editor.hc-black .token.comment.shebang { color: #929292; } .monaco-editor.hc-black .token.comment.doc { color: #608B4E; } @@ -325,7 +319,7 @@ .monaco-editor.hc-black .token.number.binary { color: #FFFFFF; } .monaco-editor.hc-black .token.regexp { color: #C0C0C0; } .monaco-editor.hc-black .token.delimiter { color: #FFFF00; } -.monaco-editor.hc-black .token.tag { color: #FFA500; } +.monaco-editor.hc-black .token.tag { color: #569CD6; } .monaco-editor.hc-black .token.metatag { color: #569CD6; } .monaco-editor.hc-black .token.annotation { color: #569CD6; } .monaco-editor.hc-black .token.key { color: #9CDCFE; } @@ -371,7 +365,6 @@ /* HTML */ -.monaco-editor.hc-black .token.tag.html { color: #1AEBFF; } .monaco-editor.hc-black .token.delimiter.html { color: #FFFF00; } .monaco-editor.hc-black .token.metatag.content.html { color: #1AEBFF; } .monaco-editor.hc-black .token.metatag.html { color: #569CD6; } @@ -379,7 +372,6 @@ .monaco-editor.hc-black .token.string.html { color: #CE9178; } /* XML */ -.monaco-editor.hc-black .token.tag.xml { color: #1AEBFF; } .monaco-editor.hc-black .token.delimiter.xml { color: #FFFF00; } .monaco-editor.hc-black .token.metatag.content.xml { color: #1AEBFF; } .monaco-editor.hc-black .token.metatag.xml { color: #569CD6; } @@ -397,7 +389,7 @@ .monaco-editor.hc-black .token.attribute.value.vs { color: #C4C4C4; } /* Jade */ -.monaco-editor.hc-black .token.tag.jade { color: #569CD6; } +.monaco-editor.hc-black .token.tag.string.jade { color: #CE9178; } .monaco-editor.hc-black .token.tag.id.jade, .monaco-editor.hc-black .token.tag.class.jade { color: #4F76AC; } .monaco-editor.hc-black .token.interpolation.jade { color: magenta; } @@ -437,6 +429,8 @@ .monaco-editor.vs .token.constant.numeric.octal { color: #204070; } .monaco-editor.vs .token.constant.numeric.binary { color: #e07070; } .monaco-editor.vs .token.constant.regexp { color: #811f3f; } +.monaco-editor.vs .token.constant.rgb-value { color: #0451A5; } + /*.monaco-editor.vs .token.constant.character .monaco-editor.vs .token.constant.character.escape .monaco-editor.vs .token.constant.language.boolean @@ -450,9 +444,13 @@ .monaco-editor.vs .token.entity { color: #A31515; } .monaco-editor.vs .token.entity.name { color: #800000; } +.monaco-editor.vs .token.entity.name.tag { color: #800000; } .monaco-editor.vs .token.entity.name.function { color: #444444; } -.monaco-editor.vs .token.entity.name.punctuation { color: #000000; } .monaco-editor.vs .token.entity.name.class { color: #2B91AF; } +.monaco-editor.vs .token.entity.name.selector { color: #800000; } +.monaco-editor.vs .token.entity.other.selector { color: #800000; } +.monaco-editor.vs .token.entity.other.attribute-name { color: red; } +.monaco-editor.vs .token.entity.other.attribute-name.css { color: #800000; } /*.monaco-editor.vs .token.entity.name.type .monaco-editor.vs .token.entity.name.tag @@ -481,14 +479,8 @@ .monaco-editor.vs .token.markup.other*/ .monaco-editor.vs .token.meta { color: #000000; } - -.monaco-editor.vs .token.entity.meta.other.selector { color: #800000; } -.monaco-editor.vs .token.entity.meta.name.selector { color: #800000; } -.monaco-editor.vs .token.entity.other.attribute-name { color: #800000; } - -.monaco-editor.vs .token.entity.other.attribute-name.html { color: red; } -.monaco-editor.vs .token.property-name { color: darkred; } -.monaco-editor.vs .token.property-value { color: #0451A5; } +.monaco-editor.vs .token.meta.selector { color: #800000; } +.monaco-editor.vs .token.meta.tag { color: #800000; } .monaco-editor.vs .token.storage { color: gray }; .monaco-editor.vs .token.storage.content { color: red }; @@ -500,6 +492,7 @@ .monaco-editor.vs .token.var.annotation.storage.type { color: #2B91AF; } .monaco-editor.vs .token.string { color: #A31515; } +.monaco-editor.vs .token.string.tag { color: blue; } /*.monaco-editor.vs .token.string.quoted .monaco-editor.vs .token.string.quoted.single .monaco-editor.vs .token.string.quoted.double @@ -514,6 +507,7 @@ .monaco-editor.vs .token.support { color: #800000; } .monaco-editor.vs .token.support.type { color: red; } .monaco-editor.vs .token.support.type.json { color: #A31515; } +.monaco-editor.vs .token.support.property-value { color: #0451A5; } /*.monaco-editor.vs .token.support.function .monaco-editor.vs .token.support.class .monaco-editor.vs .token.support.type @@ -528,9 +522,10 @@ /* Keywords should come at the end in order to match cases like token.keyword.string */ .monaco-editor.vs .token.keyword { color: #0000FF; } -.monaco-editor.vs .token.keyword.control { color: #AF00DB; } +.monaco-editor.vs .token.keyword.control { color: #0000FF; } .monaco-editor.vs .token.keyword.operator { color: #666666; } .monaco-editor.vs .token.keyword.operator.new { color: #0000FF; } +.monaco-editor.vs .token.keyword.other.unit { color: #09885A; } /*.monaco-editor.vs .token.keyword.operator .monaco-editor.vs .token.keyword.other*/ @@ -538,6 +533,8 @@ .monaco-editor.vs .token.punctuation.string { color: #A31515; } .monaco-editor.vs .token.punctuation.string.quoted.variable { color: #001188; } .monaco-editor.vs .token.punctuation.string.regexp { color: #811f3f; } +.monaco-editor.vs .token.punctuation.tag { color: #800000; } +.monaco-editor.vs .token.punctuation.string.tag { color: blue; } /* -------------------------------- Begin vs-dark tokens -------------------------------- */ .monaco-editor.vs-dark .token { color: #D4D4D4; } @@ -561,7 +558,8 @@ .monaco-editor.vs-dark .token.constant.numeric.hex { color: #5BB498; } .monaco-editor.vs-dark .token.constant.numeric.octal { color: #204070; } .monaco-editor.vs-dark .token.constant.numeric.binary { color: #e07070; } -.monaco-editor.vs-dark .token.constant.regexp { color: #B46695; } +.monaco-editor.vs-dark .token.constant.regexp { color: #646695; } +.monaco-editor.vs-dark .token.constant.rgb-value { color: #D4D4D4; } /*.monaco-editor.vs-dark .token.constant.character .monaco-editor.vs-dark .token.constant.character.escape .monaco-editor.vs-dark .token.constant.language.boolean @@ -575,9 +573,14 @@ .monaco-editor.vs-dark .token.entity { color: #9CDCFE; } .monaco-editor.vs-dark .token.entity.name { color: #569CD6; } +.monaco-editor.vs-dark .token.entity.name.tag { color: #569CD6; } .monaco-editor.vs-dark .token.entity.name.function { color: #DCDCAA; } -.monaco-editor.vs-dark .token.entity.name.punctuation { color: #DCDCAA; } .monaco-editor.vs-dark .token.entity.name.class { color: #4EC9B0; } +.monaco-editor.vs-dark .token.entity.name.selector { color: #569CD6; } + +.monaco-editor.vs-dark .token.entity.other.selector { color: #569CD6; } +.monaco-editor.vs-dark .token.entity.other.attribute-name { color: #9CDCFE; } +.monaco-editor.vs-dark .token.entity.other.attribute-name.css { color: #569CD6; } /* .monaco-editor.vs-dark .token.entity.name.type .monaco-editor.vs-dark .token.entity.name.tag @@ -604,14 +607,8 @@ .monaco-editor.vs-dark .token.markup.other*/ .monaco-editor.vs-dark .token.meta { color: #D4D4D4; } - -.monaco-editor.vs-dark .token.entity.meta.other.selector { color: #569CD6; } -.monaco-editor.vs-dark .token.entity.meta.name.selector { color: #569CD6; } -.monaco-editor.vs-dark .token.entity.other.attribute-name { color: #569CD6; } - -.monaco-editor.vs-dark .token.token.entity.other.attribute-name.html { color: #9CDCFE; } -.monaco-editor.vs-dark .token.property-name { color: #9CDCFE; } -.monaco-editor.vs-dark .token.property-value { color: #CE9178; } +.monaco-editor.vs-dark .token.meta.selector { color: #569CD6; } +.monaco-editor.vs-dark .token.meta.tag { color: #CE9178; } .monaco-editor.vs-dark .token.storage { color: #569CD6 }; .monaco-editor.vs-dark .token.storage.content { color: #9CDCFE }; @@ -625,6 +622,7 @@ .monaco-editor.vs-dark .token.var.annotation.storage.type { color: #4EC9B0; } .monaco-editor.vs-dark .token.string { color: #CE9178; } +.monaco-editor.vs-dark .token.string.tag { color: #CE9178; } /*.monaco-editor.vs-dark .token.string.quoted .monaco-editor.vs-dark .token.string.quoted.single .monaco-editor.vs-dark .token.string.quoted.double @@ -636,8 +634,9 @@ .monaco-editor.vs-dark .token.string.regexp { color: #D16969; } /*.monaco-editor.vs-dark .token.string.other*/ -.monaco-editor.vs-dark .token.support { color: #D7BA7D; } +.monaco-editor.vs-dark .token.support { color: #A79873; } .monaco-editor.vs-dark .token.support.type { color: #9CDCFE; } +.monaco-editor.vs-dark .token.support.property-value { color: #CE9178; } /*.monaco-editor.vs-dark .token.support.function .monaco-editor.vs-dark .token.support.class .monaco-editor.vs-dark .token.support.constant @@ -651,16 +650,20 @@ /* Keywords should come at the end in order to match cases like token.keyword.string */ .monaco-editor.vs-dark .token.keyword { color: #569CD6; } -.monaco-editor.vs-dark .token.keyword.control { color: #C586C0; } +.monaco-editor.vs-dark .token.keyword.control { color: #569CD6; } .monaco-editor.vs-dark .token.keyword.operator { color: #909090; } .monaco-editor.vs-dark .token.keyword.operator.new { color: #569CD6; } +.monaco-editor.vs-dark .token.keyword.other.unit { color: #B5CEA8; } /*.monaco-editor.vs-dark .token.keyword.operator .monaco-editor.vs-dark .token.keyword.other*/ -.monaco-editor.vs-dark .token.punctuation { color: #DCDCDC; } +.monaco-editor.vs-dark .token.punctuation { color: #DCDCDC; } .monaco-editor.vs-dark .token.punctuation.string { color: #CE9178; } .monaco-editor.vs-dark .token.punctuation.string.quoted.variable { color: #74B0DF; } .monaco-editor.vs-dark .token.punctuation.string.regexp { color: #D16969; } +.monaco-editor.vs-dark .token.punctuation.tag { color: #569CD6; } +.monaco-editor.vs-dark .token.punctuation.string.tag { color: #CE9178; } + /* -------------------------------- End vs-dark tokens -------------------------------- */ @@ -688,6 +691,7 @@ .monaco-editor.hc-black .token.constant.numeric.octal { color: #204070; } .monaco-editor.hc-black .token.constant.numeric.binary { color: #e07070; } .monaco-editor.hc-black .token.constant.regexp { color: #B46695; } +.monaco-editor.hc-black .token.constant.rgb-value { color: #D4D4D4; } /*.monaco-editor.hc-black .token.constant.character .monaco-editor.hc-black .token.constant.character.escape .monaco-editor.hc-black .token.constant.language.boolean @@ -701,9 +705,13 @@ .monaco-editor.hc-black .token.entity { color: #9CDCFE; } .monaco-editor.hc-black .token.entity.name { color: #569CD6; } +.monaco-editor.hc-black .token.entity.name.tag { color: #569CD6; } .monaco-editor.hc-black .token.entity.name.function { color: #DCDCAA; } -.monaco-editor.hc-black .token.entity.name.punctuation { color: #DCDCAA; } .monaco-editor.hc-black .token.entity.name.class { color: #4EC9B0; } +.monaco-editor.hc-black .token.entity.name.selector { color: #569CD6; } +.monaco-editor.hc-black .token.entity.other.selector { color: #569CD6; } +.monaco-editor.hc-black .token.entity.other.attribute-name { color: #9CDCFE; } +.monaco-editor.hc-black .token.entity.other.attribute-name.css { color: #569CD6; } /* .monaco-editor.hc-black .token.entity.name.type .monaco-editor.hc-black .token.entity.name.tag @@ -730,14 +738,8 @@ .monaco-editor.hc-black .token.markup.other*/ .monaco-editor.hc-black .token.meta { color: #D4D4D4; } - -.monaco-editor.hc-black .token.entity.meta.other.selector { color: #569CD6; } -.monaco-editor.hc-black .token.entity.meta.name.selector { color: #569CD6; } -.monaco-editor.hc-black .token.entity.other.attribute-name { color: #569CD6; } -.monaco-editor.hc-black .token.entity.other.attribute-name.html { color: #9CDCFE; } - -.monaco-editor.hc-black .token.property-name { color: #9CDCFE; } -.monaco-editor.hc-black .token.property-value { color: #CE9178; } +.monaco-editor.hc-black .token.meta.selector { color: #569CD6; } +.monaco-editor.hc-black .token.meta.tag { color: #CE9178; } .monaco-editor.hc-black .token.storage { color: #569CD6 }; .monaco-editor.hc-black .token.storage.content { color: #9CDCFE }; @@ -751,6 +753,7 @@ .monaco-editor.hc-black .token.var.annotation.storage.type { color: #4EC9B0; } .monaco-editor.hc-black .token.string { color: #CE9178; } +.monaco-editor.hc-black .token.string.tag { color: #CE9178; } /*.monaco-editor.hc-black .token.string.quoted .monaco-editor.hc-black .token.string.quoted.single .monaco-editor.hc-black .token.string.quoted.double @@ -763,7 +766,8 @@ /*.monaco-editor.hc-black .token.string.other*/ .monaco-editor.hc-black .token.support { color: #800000; } -.monaco-editor.vs-dark .token.support.type { color: #9CDCFE; } +.monaco-editor.hc-black .token.support.type { color: #9CDCFE; } +.monaco-editor.hc-black .token.support.property-value { color: #CE9178; } /*.monaco-editor.hc-black .token.support.function .monaco-editor.hc-black .token.support.class .monaco-editor.hc-black .token.support.constant @@ -778,9 +782,10 @@ /* Keywords should come at the end in order to match cases like token.keyword.string */ .monaco-editor.hc-black .token.keyword { color: #569CD6; } -.monaco-editor.hc-black .token.keyword.control { color: #C586C0; } +.monaco-editor.hc-black .token.keyword.control { color: #569CD6; } .monaco-editor.hc-black .token.keyword.operator { color: #909090; } .monaco-editor.hc-black .token.keyword.operator.new { color: #569CD6; } +.monaco-editor.hc-black .token.keyword.other.unit { color: #B5CEA8; } /*.monaco-editor.hc-black .token.keyword.operator .monaco-editor.hc-black .token.keyword.other*/ @@ -788,5 +793,7 @@ .monaco-editor.hc-black .token.punctuation.string { color: #CE9178; } .monaco-editor.hc-black .token.punctuation.string.quoted.variable { color: #74B0DF; } .monaco-editor.hc-black .token.punctuation.string.regexp { color: #D16969; } +.monaco-editor.hc-black .token.punctuation.tag { color: #569CD6; } +.monaco-editor.hc-black .token.punctuation.string.tag { color: #CE9178; } /* -------------------------------- End hc-black tokens ----------------------------- */ \ No newline at end of file diff --git a/src/vs/languages/css/common/css.ts b/src/vs/languages/css/common/css.ts index 1038124112e..d002e074678 100644 --- a/src/vs/languages/css/common/css.ts +++ b/src/vs/languages/css/common/css.ts @@ -12,6 +12,7 @@ import EditorCommon = require('vs/editor/common/editorCommon'); import Modes = require('vs/editor/common/modes'); import {OneWorkerAttr} from 'vs/platform/thread/common/threadService'; import cssWorker = require('vs/languages/css/common/cssWorker'); +import cssTokenTypes = require('vs/languages/css/common/cssTokenTypes'); import {AbstractMode} from 'vs/editor/common/modes/abstractMode'; import {AbstractState} from 'vs/editor/common/modes/abstractState'; import {AsyncDescriptor2, createAsyncDescriptor2} from 'vs/platform/instantiation/common/descriptors'; @@ -32,6 +33,8 @@ export enum States { MetaInUrlFunction, } +export { cssTokenTypes }; + var identRegEx = /^-?-?([a-zA-Z]|(\\(([0-9a-fA-F]{1,6}\s?)|[^[0-9a-fA-F])))([\w\-]|(\\(([0-9a-fA-F]{1,6}\s?)|[^[0-9a-fA-F])))*/; export class State extends AbstractState { @@ -131,13 +134,13 @@ export class State extends AbstractState { switch (this.kind) { case States.ValuePostUrl: if (ch === '(') { - return this.nextState(States.ValueInUrlFunction, { type:'punctuation.parenthesis.css', bracket: Modes.Bracket.Open }); + return this.nextState(States.ValueInUrlFunction, { type: 'punctuation.parenthesis.css', bracket: Modes.Bracket.Open }); } this.kind = States.Value; break; case States.MetaPostUrl: if (ch === '(') { - return this.nextState(States.MetaInUrlFunction, { type:'punctuation.parenthesis.css', bracket: Modes.Bracket.Open }); + return this.nextState(States.MetaInUrlFunction, { type: 'punctuation.parenthesis.css', bracket: Modes.Bracket.Open }); } this.kind = States.Meta; break; @@ -155,32 +158,32 @@ export class State extends AbstractState { switch (this.kind) { case States.Selector: if (ch === '{') { - return this.nextState(States.Rule, { type:'punctuation.bracket.css', bracket: Modes.Bracket.Open }); + return this.nextState(States.Rule, { type: 'punctuation.bracket.css', bracket: Modes.Bracket.Open }); } if (ch === '(' || ch === ')') { - return { type:'punctuation.parenthesis.css', bracket: ch === '(' ? Modes.Bracket.Open : Modes.Bracket.Close }; + return { type: 'punctuation.parenthesis.css', bracket: ch === '(' ? Modes.Bracket.Open : Modes.Bracket.Close }; } if (ch === '@' && !this.inMeta) { //@import, @media, @key-word-animation stream.advanceIfRegExp2(identRegEx); - return this.nextState(States.Meta, { type:'keyword.css' }); + return this.nextState(States.Meta, { type: cssTokenTypes.TOKEN_AT_KEYWORD + '.css' }); } if (ch === '}' && this.inMeta) { //@import, @media, @key-word-animation this.inMeta = false; - return this.nextState(States.Selector, { type:'punctuation.bracket.css', bracket: Modes.Bracket.Close }); + return this.nextState(States.Selector, { type: 'punctuation.bracket.css', bracket: Modes.Bracket.Close }); } if (/[\*\(\)\[\]\+>=\~\|;]/.test(ch)) { - return { type:'punctuation.css' }; + return { type: 'punctuation.css' }; } if (ch === '#') { stream.advanceIfRegExp2(identRegEx); - return { type:'entity.other.attribute-name.id.css' }; + return { type: cssTokenTypes.TOKEN_SELECTOR + '.id.css' }; } if (ch === '.') { stream.advanceIfRegExp2(identRegEx); - return { type:'entity.other.attribute-name.class.css' }; + return { type: cssTokenTypes.TOKEN_SELECTOR + '.class.css' }; } this.consumeIdent(stream); - return { type:'entity.name.tag.css' }; + return { type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.css' }; case States.Meta: if (ch === '{') { @@ -188,74 +191,74 @@ export class State extends AbstractState { if (this.inMeta) { nextState = States.Selector; } - return this.nextState(nextState, { type:'punctuation.bracket.css', bracket: Modes.Bracket.Open }); + return this.nextState(nextState, { type: 'punctuation.bracket.css', bracket: Modes.Bracket.Open }); } if (ch === '(' || ch === ')') { - return { type:'punctuation.parenthesis.css', bracket: ch === '(' ? Modes.Bracket.Open : Modes.Bracket.Close }; + return { type: 'punctuation.parenthesis.css', bracket: ch === '(' ? Modes.Bracket.Open : Modes.Bracket.Close }; } if (ch === ';') { if (this.metaBraceCount === 0) { this.inMeta = false; } - return this.nextState(States.Selector, { type:'punctuation.css' }); + return this.nextState(States.Selector, { type: 'punctuation.css' }); } if ((ch === 'u' || ch === 'U') && stream.advanceIfStringCaseInsensitive2('rl')) { stream.advanceIfStringCaseInsensitive2('-prefix'); // support 'url-prefix' (part of @-mox-document) - return this.nextState(States.MetaPostUrl, { type:'meta.property-value.css' }); + return this.nextState(States.MetaPostUrl, { type: cssTokenTypes.TOKEN_VALUE + '.css' }); } if (/[\*\(\)\[\]\+>=\~\|]/.test(ch)) { - return { type:'punctuation.css' }; + return { type: 'punctuation.css' }; } this.inMeta = true; this.consumeIdent(stream); - return { type:'meta.property-value.css' }; + return { type: cssTokenTypes.TOKEN_VALUE + '.css' }; case States.Rule: if (ch === '}') { - return this.nextState(States.Selector, { type:'punctuation.bracket.css', bracket: Modes.Bracket.Close }); + return this.nextState(States.Selector, { type: 'punctuation.bracket.css', bracket: Modes.Bracket.Close }); } if (ch === ':') { - return this.nextState(States.Value, { type:'punctuation.css' }); + return this.nextState(States.Value, { type: 'punctuation.css' }); } if (ch === '(' || ch === ')') { - return { type:'punctuation.parenthesis.css', bracket: ch === '(' ? Modes.Bracket.Open : Modes.Bracket.Close }; + return { type: 'punctuation.parenthesis.css', bracket: ch === '(' ? Modes.Bracket.Open : Modes.Bracket.Close }; } this.consumeIdent(stream); - return { type:'support.type.property-name.css' }; + return { type: cssTokenTypes.TOKEN_PROPERTY + '.css' }; case States.Value: if (ch === '}') { - return this.nextState(States.Selector, { type:'punctuation.bracket.css', bracket: Modes.Bracket.Close }); + return this.nextState(States.Selector, { type: 'punctuation.bracket.css', bracket: Modes.Bracket.Close }); } if (ch === ';') { - return this.nextState(States.Rule, { type:'punctuation.css' }); + return this.nextState(States.Rule, { type: 'punctuation.css' }); } if ((ch === 'u' || ch === 'U') && stream.advanceIfStringCaseInsensitive2('rl')) { - return this.nextState(States.ValuePostUrl, { type:'meta.property-value.css' }); + return this.nextState(States.ValuePostUrl, { type: cssTokenTypes.TOKEN_VALUE + '.css' }); } if (ch === '(' || ch === ')') { - return { type:'punctuation.parenthesis.css', bracket: ch === '(' ? Modes.Bracket.Open : Modes.Bracket.Close }; + return { type: 'punctuation.parenthesis.css', bracket: ch === '(' ? Modes.Bracket.Open : Modes.Bracket.Close }; } if (ch === ',') { - return { type:'punctuation.css' }; + return { type: 'punctuation.css' }; } if (ch === '#') { stream.advanceIfRegExp2(/^[\w]*/); - return { type:'meta.property-value.hex.css' }; + return { type: cssTokenTypes.TOKEN_VALUE + '.hex.css' }; } if (/\d/.test(ch) || (/-|\+/.test(ch) && !stream.eos() && /\d/.test(stream.peek()))) { stream.advanceIfRegExp2(/^[\d\.]*/); - return this.nextState(States.Unit, { type:'meta.property-value.numeric.css' }); + return this.nextState(States.Unit, { type: cssTokenTypes.TOKEN_VALUE + '.numeric.css' }); } if (ch === '!') { - return { type:'meta.property-value.keyword.css' }; // ! + return { type: cssTokenTypes.TOKEN_VALUE + '.keyword.css' }; // ! } if ((ch === 'i' || ch === 'I') && stream.advanceIfStringCaseInsensitive2('mportant')) { - return { type:'meta.property-value.keyword.css' }; // important + return { type: cssTokenTypes.TOKEN_VALUE + '.keyword.css' }; // important } if (this.consumeIdent(stream)) { - return { type:'meta.property-value.css' }; + return { type: cssTokenTypes.TOKEN_VALUE + '.css' }; } break; @@ -263,7 +266,7 @@ export class State extends AbstractState { // css units - see: http://www.w3.org/TR/css3-values/#font-relative-lengths stream.goBack(1); if(stream.advanceIfRegExp2(/^(em|ex|ch|rem|vw|vh|vm|cm|mm|in|px|pt|pc|deg|grad|rad|turn|s|ms|Hz|kHz|%)/)) { - return { type:'meta.property-value.unit.css' }; + return { type: cssTokenTypes.TOKEN_VALUE + '.unit.css' }; } // no unit, back to value state this.nextState(States.Value, null); @@ -299,17 +302,17 @@ export class CSSMode extends AbstractMode { getInitialState: () => new State(this, States.Selector, false, null, false, 0) }, false, false); this.electricCharacterSupport = new supports.BracketElectricCharacterSupport(this, { brackets: [ - { tokenType:'punctuation.bracket.css', open: '{', close: '}', isElectric: true } + { tokenType: 'punctuation.bracket.css', open: '{', close: '}', isElectric: true } ] }); this.extraInfoSupport = this; this.referenceSupport = new supports.ReferenceSupport(this, { - tokens: ['support.type.property-name.css', 'meta.property-value.css', 'entity.name.tag.css'], + tokens: [cssTokenTypes.TOKEN_PROPERTY + '.css', cssTokenTypes.TOKEN_VALUE + '.css', cssTokenTypes.TOKEN_SELECTOR_TAG + '.css'], findReferences: (resource, position, /*unused*/includeDeclaration) => this.findReferences(resource, position)}); this.logicalSelectionSupport = this; this.outlineSupport = this; this.declarationSupport = new supports.DeclarationSupport(this, { - tokens: ['meta.property-value.css'], + tokens: [cssTokenTypes.TOKEN_VALUE + '.css'], findDeclaration: (resource, position) => this.findDeclaration(resource, position)}); this.characterPairSupport = new supports.CharacterPairSupport(this, { diff --git a/src/vs/languages/css/common/cssTokenTypes.ts b/src/vs/languages/css/common/cssTokenTypes.ts new file mode 100644 index 00000000000..8fdd3436714 --- /dev/null +++ b/src/vs/languages/css/common/cssTokenTypes.ts @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +export const TOKEN_SELECTOR = 'entity.name.selector'; +export const TOKEN_SELECTOR_TAG = 'entity.name.tag'; +export const TOKEN_PROPERTY = 'support.type.property-name'; +export const TOKEN_VALUE = 'support.property-value'; +export const TOKEN_AT_KEYWORD = 'keyword.control.at-rule'; diff --git a/src/vs/languages/css/test/common/css.test.ts b/src/vs/languages/css/test/common/css.test.ts index 529a0e8f182..9d737d39f0b 100644 --- a/src/vs/languages/css/test/common/css.test.ts +++ b/src/vs/languages/css/test/common/css.test.ts @@ -9,6 +9,7 @@ import cssMode = require('vs/languages/css/common/css'); import EditorCommon = require('vs/editor/common/editorCommon'); import Modes = require('vs/editor/common/modes'); import modesUtil = require('vs/editor/test/common/modesUtil'); +import {cssTokenTypes} from 'vs/languages/css/common/css'; suite('CSS Colorizing', () => { @@ -31,7 +32,7 @@ suite('CSS Colorizing', () => { line: ' body ', tokens: [ { startIndex:0, type: '' }, - { startIndex:6, type: 'entity.name.tag.css' }, + { startIndex:6, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.css' }, { startIndex:10, type: '' } ]} ]); @@ -49,65 +50,65 @@ suite('CSS Colorizing', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: 'body {', tokens: [ - { startIndex:0, type: 'entity.name.tag.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.css' }, { startIndex:4, type: '' }, { startIndex:5, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Open } ]}, { line: ' margin: 0;', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.css' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:8, type: 'punctuation.css' }, { startIndex:9, type: '' }, - { startIndex:10, type: 'meta.property-value.numeric.css' }, + { startIndex:10, type: cssTokenTypes.TOKEN_VALUE + '.numeric.css' }, { startIndex:11, type: 'punctuation.css' } ]}, { line: ' padding: 3em 6em;', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.css' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:9, type: 'punctuation.css' }, { startIndex:10, type: '' }, - { startIndex:11, type: 'meta.property-value.numeric.css' }, - { startIndex:12, type: 'meta.property-value.unit.css' }, + { startIndex:11, type: cssTokenTypes.TOKEN_VALUE + '.numeric.css' }, + { startIndex:12, type: cssTokenTypes.TOKEN_VALUE + '.unit.css' }, { startIndex:14, type: '' }, - { startIndex:15, type: 'meta.property-value.numeric.css' }, - { startIndex:16, type: 'meta.property-value.unit.css' }, + { startIndex:15, type: cssTokenTypes.TOKEN_VALUE + '.numeric.css' }, + { startIndex:16, type: cssTokenTypes.TOKEN_VALUE + '.unit.css' }, { startIndex:18, type: 'punctuation.css' } ]}, { line: ' font-family: tahoma, arial, sans-serif;', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.css' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:13, type: 'punctuation.css' }, { startIndex:14, type: '' }, - { startIndex:15, type: 'meta.property-value.css' }, + { startIndex:15, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:21, type: 'punctuation.css' }, { startIndex:22, type: '' }, - { startIndex:23, type: 'meta.property-value.css' }, + { startIndex:23, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:28, type: 'punctuation.css' }, { startIndex:29, type: '' }, - { startIndex:30, type: 'meta.property-value.css' }, + { startIndex:30, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:40, type: 'punctuation.css' } ]}, { line: ' text-decoration: none !important;', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.css' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:17, type: 'punctuation.css' }, { startIndex:18, type: '' }, - { startIndex:19, type: 'meta.property-value.css' }, + { startIndex:19, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:23, type: '' }, - { startIndex:24, type: 'meta.property-value.keyword.css' }, + { startIndex:24, type: cssTokenTypes.TOKEN_VALUE + '.keyword.css' }, { startIndex:34, type: 'punctuation.css' } ]}, { line: ' color: #000', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.css' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:7, type: 'punctuation.css' }, { startIndex:8, type: '' }, - { startIndex:9, type: 'meta.property-value.hex.css' } + { startIndex:9, type: cssTokenTypes.TOKEN_VALUE + '.hex.css' } ]}, { line: ' }', tokens: [ @@ -125,17 +126,17 @@ suite('CSS Colorizing', () => { { startIndex:1, type: '' }, { startIndex:2, type: 'punctuation.bracket.css' }, { startIndex:3, type: '' }, - { startIndex:4, type: 'support.type.property-name.css' }, + { startIndex:4, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:11, type: 'punctuation.css' }, { startIndex:12, type: '' }, - { startIndex:13, type: 'meta.property-value.numeric.css' }, - { startIndex:14, type: 'meta.property-value.unit.css' }, + { startIndex:13, type: cssTokenTypes.TOKEN_VALUE + '.numeric.css' }, + { startIndex:14, type: cssTokenTypes.TOKEN_VALUE + '.unit.css' }, { startIndex:16, type: '' }, - { startIndex:17, type: 'meta.property-value.numeric.css' }, - { startIndex:19, type: 'meta.property-value.unit.css' }, + { startIndex:17, type: cssTokenTypes.TOKEN_VALUE + '.numeric.css' }, + { startIndex:19, type: cssTokenTypes.TOKEN_VALUE + '.unit.css' }, { startIndex:21, type: '' }, - { startIndex:22, type: 'meta.property-value.numeric.css' }, - { startIndex:26, type: 'meta.property-value.unit.css' }, + { startIndex:22, type: cssTokenTypes.TOKEN_VALUE + '.numeric.css' }, + { startIndex:26, type: cssTokenTypes.TOKEN_VALUE + '.unit.css' }, { startIndex:28, type: 'punctuation.css' }, { startIndex:29, type: '' }, { startIndex:30, type: 'punctuation.bracket.css' } @@ -151,7 +152,7 @@ suite('CSS Colorizing', () => { { startIndex:1, type: '' }, { startIndex:2, type: 'punctuation.bracket.css' }, { startIndex:3, type: '' }, - { startIndex:4, type: 'support.type.property-name.css' }, + { startIndex:4, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:11, type: 'punctuation.css' }, { startIndex:12, type: '' } ]} @@ -162,11 +163,11 @@ suite('CSS Colorizing', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: 'h1 /*comment*/ p {', tokens: [ - { startIndex:0, type: 'entity.name.tag.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.css' }, { startIndex:2, type: '' }, { startIndex:3, type: 'comment.css' }, { startIndex:14, type: '' }, - { startIndex:15, type: 'entity.name.tag.css' }, + { startIndex:15, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.css' }, { startIndex:16, type: '' }, { startIndex:17, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Open } ]} @@ -177,7 +178,7 @@ suite('CSS Colorizing', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: 'h1 /*com', tokens: [ - { startIndex:0, type: 'entity.name.tag.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.css' }, { startIndex:2, type: '' }, { startIndex:3, type: 'comment.css' } ]}, { @@ -185,7 +186,7 @@ suite('CSS Colorizing', () => { tokens: [ { startIndex:0, type: 'comment.css' }, { startIndex:6, type: '' }, - { startIndex:7, type: 'entity.name.tag.css' } + { startIndex:7, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.css' } ]} ]); }); @@ -194,7 +195,7 @@ suite('CSS Colorizing', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '#myID {', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.id.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.id.css' }, { startIndex:5, type: '' }, { startIndex:6, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Open } ]} @@ -205,7 +206,7 @@ suite('CSS Colorizing', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '.myID {', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.css' }, { startIndex:5, type: '' }, { startIndex:6, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Open } ]} @@ -216,9 +217,9 @@ suite('CSS Colorizing', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '@import url("something.css");', tokens: [ - { startIndex:0, type: 'keyword.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.css' }, { startIndex:7, type: '' }, - { startIndex:8, type: 'meta.property-value.css' }, + { startIndex:8, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:11, type: 'punctuation.parenthesis.css', bracket: Modes.Bracket.Open }, { startIndex:12, type: 'string.css' }, { startIndex:27, type: 'punctuation.parenthesis.css', bracket: Modes.Bracket.Close }, @@ -234,7 +235,7 @@ suite('CSS Colorizing', () => { line: ' content: "";', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.css' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:9, type: 'punctuation.css' }, { startIndex:10, type: '' }, { startIndex:11, type: 'string.css' }, @@ -247,14 +248,14 @@ suite('CSS Colorizing', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '@font-face {', tokens: [ - { startIndex:0, type: 'keyword.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.css' }, { startIndex:10, type: '' }, { startIndex:11, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Open } ]}, { line: ' font-family: "Opificio";', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.css' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:13, type: 'punctuation.css' }, { startIndex:14, type: '' }, { startIndex:15, type: 'string.css' }, @@ -277,29 +278,29 @@ suite('CSS Colorizing', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '@-webkit-keyframes infinite-spinning {', tokens: [ - { startIndex:0, type: 'keyword.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.css' }, { startIndex:18, type: '' }, - { startIndex:19, type: 'meta.property-value.css' }, + { startIndex:19, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:36, type: '' }, { startIndex:37, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Open } ]}, { line: ' from {', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'entity.name.tag.css' }, + { startIndex:2, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.css' }, { startIndex:6, type: '' }, { startIndex:7, type: 'punctuation.bracket.css' } ]}, { line: ' -webkit-transform: rotate(0deg);', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.css' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:19, type: 'punctuation.css' }, { startIndex:20, type: '' }, - { startIndex:21, type: 'meta.property-value.css' }, + { startIndex:21, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:27, type: 'punctuation.parenthesis.css' }, - { startIndex:28, type: 'meta.property-value.numeric.css' }, - { startIndex:29, type: 'meta.property-value.unit.css' }, + { startIndex:28, type: cssTokenTypes.TOKEN_VALUE + '.numeric.css' }, + { startIndex:29, type: cssTokenTypes.TOKEN_VALUE + '.unit.css' }, { startIndex:32, type: 'punctuation.parenthesis.css' }, { startIndex:33, type: 'punctuation.css' } ]}, { @@ -311,20 +312,20 @@ suite('CSS Colorizing', () => { line: ' to {', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'entity.name.tag.css' }, + { startIndex:2, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.css' }, { startIndex:4, type: '' }, { startIndex:5, type: 'punctuation.bracket.css' } ]}, { line: ' -webkit-transform: rotate(360deg);', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.css' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:19, type: 'punctuation.css' }, { startIndex:20, type: '' }, - { startIndex:21, type: 'meta.property-value.css' }, + { startIndex:21, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:27, type: 'punctuation.parenthesis.css' }, - { startIndex:28, type: 'meta.property-value.numeric.css' }, - { startIndex:31, type: 'meta.property-value.unit.css' }, + { startIndex:28, type: cssTokenTypes.TOKEN_VALUE + '.numeric.css' }, + { startIndex:31, type: cssTokenTypes.TOKEN_VALUE + '.unit.css' }, { startIndex:34, type: 'punctuation.parenthesis.css' }, { startIndex:35, type: 'punctuation.css' } ]}, { @@ -344,9 +345,9 @@ suite('CSS Colorizing', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '@import url("something.css");', tokens: [ - { startIndex:0, type: 'keyword.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.css' }, { startIndex:7, type: '' }, - { startIndex:8, type: 'meta.property-value.css' }, + { startIndex:8, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:11, type: 'punctuation.parenthesis.css', bracket: Modes.Bracket.Open }, { startIndex:12, type: 'string.css' }, { startIndex:27, type: 'punctuation.parenthesis.css', bracket: Modes.Bracket.Close }, @@ -354,13 +355,13 @@ suite('CSS Colorizing', () => { ]}, { line: '.rule1{}', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.css' }, { startIndex:6, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Open }, { startIndex:7, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Close } ]}, { line: '.rule2{}', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.css' }, { startIndex:6, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Open }, { startIndex:7, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Close } ]} @@ -393,16 +394,16 @@ suite('CSS Colorizing', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '@import url("something.css");@import url("something.css");', tokens: [ - { startIndex:0, type: 'keyword.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.css' }, { startIndex:7, type: '' }, - { startIndex:8, type: 'meta.property-value.css' }, + { startIndex:8, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:11, type: 'punctuation.parenthesis.css', bracket: Modes.Bracket.Open }, { startIndex:12, type: 'string.css' }, { startIndex:27, type: 'punctuation.parenthesis.css', bracket: Modes.Bracket.Close }, { startIndex:28, type: 'punctuation.css' }, - { startIndex:29, type: 'keyword.css' }, + { startIndex:29, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.css' }, { startIndex:36, type: '' }, - { startIndex:37, type: 'meta.property-value.css' }, + { startIndex:37, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:40, type: 'punctuation.parenthesis.css', bracket: Modes.Bracket.Open }, { startIndex:41, type: 'string.css' }, { startIndex:56, type: 'punctuation.parenthesis.css', bracket: Modes.Bracket.Close }, @@ -416,27 +417,27 @@ suite('CSS Colorizing', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '.a{background:#f5f9fc !important}.b{font-family:"Helvetica Neue", Helvetica;height:31px;}', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.css' }, { startIndex:2, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Open }, - { startIndex:3, type: 'support.type.property-name.css' }, + { startIndex:3, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:13, type: 'punctuation.css' }, - { startIndex:14, type: 'meta.property-value.hex.css' }, + { startIndex:14, type: cssTokenTypes.TOKEN_VALUE + '.hex.css' }, { startIndex:21, type: '' }, - { startIndex:22, type: 'meta.property-value.keyword.css' }, + { startIndex:22, type: cssTokenTypes.TOKEN_VALUE + '.keyword.css' }, { startIndex:32, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Close }, - { startIndex:33, type: 'entity.other.attribute-name.class.css' }, + { startIndex:33, type: cssTokenTypes.TOKEN_SELECTOR + '.class.css' }, { startIndex:35, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Open }, - { startIndex:36, type: 'support.type.property-name.css' }, + { startIndex:36, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:47, type: 'punctuation.css' }, { startIndex:48, type: 'string.css' }, { startIndex:64, type: 'punctuation.css' }, { startIndex:65, type: '' }, - { startIndex:66, type: 'meta.property-value.css' }, + { startIndex:66, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:75, type: 'punctuation.css' }, - { startIndex:76, type: 'support.type.property-name.css' }, + { startIndex:76, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:82, type: 'punctuation.css' }, - { startIndex:83, type: 'meta.property-value.numeric.css' }, - { startIndex:85, type: 'meta.property-value.unit.css' }, + { startIndex:83, type: cssTokenTypes.TOKEN_VALUE + '.numeric.css' }, + { startIndex:85, type: cssTokenTypes.TOKEN_VALUE + '.unit.css' }, { startIndex:87, type: 'punctuation.css' }, { startIndex:88, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Close } ]} @@ -448,23 +449,23 @@ suite('CSS Colorizing', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '.even { background: #fff url(data:image/gif;base64,R0lGODlhBgASALMAAOfn5+rq6uvr6+zs7O7u7vHx8fPz8/b29vj4+P39/f///wAAAAAAAAAAAAAAAAAAACwAAAAABgASAAAIMAAVCBxIsKDBgwgTDkzAsKGAhxARSJx4oKJFAxgzFtjIkYDHjwNCigxAsiSAkygDAgA7) repeat-x bottom}', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.css' }, { startIndex:5, type: '' }, { startIndex:6, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Open }, { startIndex:7, type: '' }, - { startIndex:8, type: 'support.type.property-name.css' }, + { startIndex:8, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:18, type: 'punctuation.css' }, { startIndex:19, type: '' }, - { startIndex:20, type: 'meta.property-value.hex.css' }, + { startIndex:20, type: cssTokenTypes.TOKEN_VALUE + '.hex.css' }, { startIndex:24, type: '' }, - { startIndex:25, type: 'meta.property-value.css' }, + { startIndex:25, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:28, type: 'punctuation.parenthesis.css', bracket: Modes.Bracket.Open }, { startIndex:29, type: 'string.css' }, { startIndex:215, type: 'punctuation.parenthesis.css', bracket: Modes.Bracket.Close }, { startIndex:216, type: '' }, - { startIndex:217, type: 'meta.property-value.css' }, + { startIndex:217, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:225, type: '' }, - { startIndex:226, type: 'meta.property-value.css' }, + { startIndex:226, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:232, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Close } ]} ]); @@ -475,11 +476,11 @@ suite('CSS Colorizing', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '.a{background:url(/a.jpg)}', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.css' }, { startIndex:2, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Open }, - { startIndex:3, type: 'support.type.property-name.css' }, + { startIndex:3, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:13, type: 'punctuation.css' }, - { startIndex:14, type: 'meta.property-value.css' }, + { startIndex:14, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:17, type: 'punctuation.parenthesis.css', bracket: Modes.Bracket.Open }, { startIndex:18, type: 'string.css' }, { startIndex:24, type: 'punctuation.parenthesis.css', bracket: Modes.Bracket.Close }, @@ -492,7 +493,7 @@ suite('CSS Colorizing', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: 'p{}', tokens: [ - { startIndex:0, type: 'entity.name.tag.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.css' }, { startIndex:1, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Open }, { startIndex:2, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Close } ]} @@ -503,7 +504,7 @@ suite('CSS Colorizing', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: 'p:nth() {}', tokens: [ - { startIndex:0, type: 'entity.name.tag.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.css' }, { startIndex:5, type: 'punctuation.parenthesis.css', bracket: Modes.Bracket.Open }, { startIndex:6, type: 'punctuation.parenthesis.css', bracket: Modes.Bracket.Close }, { startIndex:7, type: '' }, @@ -538,12 +539,12 @@ suite('CSS Colorizing', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: 'input[type= \\"submit\\"', tokens: [ - { startIndex:0, type: 'entity.name.tag.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.css' }, { startIndex:5, type: 'punctuation.css'}, - { startIndex:6, type: 'entity.name.tag.css' }, + { startIndex:6, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.css' }, { startIndex:10, type: 'punctuation.css'}, { startIndex:11, type: ''}, - { startIndex:12, type: 'entity.name.tag.css'} + { startIndex:12, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.css'} ]} ]); }); @@ -552,10 +553,10 @@ suite('CSS Colorizing', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '.rule {\\', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.css' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.css' }, { startIndex:5, type: ''}, { startIndex:6, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Open }, - { startIndex:7, type: 'support.type.property-name.css'} + { startIndex:7, type: cssTokenTypes.TOKEN_PROPERTY + '.css'} ]} ]); }); diff --git a/src/vs/languages/json/common/features/jsonTokenTypes.ts b/src/vs/languages/json/common/features/jsonTokenTypes.ts index 199220f992a..9213ebf7509 100644 --- a/src/vs/languages/json/common/features/jsonTokenTypes.ts +++ b/src/vs/languages/json/common/features/jsonTokenTypes.ts @@ -8,10 +8,10 @@ export const TOKEN_DELIM_OBJECT = 'punctuation.bracket.json'; export const TOKEN_DELIM_ARRAY = 'punctuation.array.json'; export const TOKEN_DELIM_COLON = 'punctuation.colon.json'; export const TOKEN_DELIM_COMMA = 'punctuation.comma.json'; -export const TOKEN_VALUE_BOOLEAN= 'meta.property-value.keyword.json'; -export const TOKEN_VALUE_NULL= 'meta.property-value.constant.other.json'; -export const TOKEN_VALUE_STRING = 'meta.property-value.string.value.json'; -export const TOKEN_VALUE_NUMBER = 'meta.property-value.constant.numeric.json'; +export const TOKEN_VALUE_BOOLEAN= 'support.property-value.keyword.json'; +export const TOKEN_VALUE_NULL= 'support.property-value.constant.other.json'; +export const TOKEN_VALUE_STRING = 'support.property-value.string.value.json'; +export const TOKEN_VALUE_NUMBER = 'support.property-value.constant.numeric.json'; export const TOKEN_PROPERTY_NAME = 'support.type.property-name.json'; export const TOKEN_COMMENT_BLOCK = 'comment.block.json'; export const TOKEN_COMMENT_LINE = 'comment.line.json'; \ No newline at end of file diff --git a/src/vs/languages/less/common/less.ts b/src/vs/languages/less/common/less.ts index e1ac0ca30ff..e178f745c54 100644 --- a/src/vs/languages/less/common/less.ts +++ b/src/vs/languages/less/common/less.ts @@ -12,6 +12,7 @@ import Monarch = require('vs/editor/common/modes/monarch/monarch'); import Types = require('vs/editor/common/modes/monarch/monarchTypes'); import Compile = require('vs/editor/common/modes/monarch/monarchCompile'); import lessWorker = require('vs/languages/less/common/lessWorker'); +import {cssTokenTypes} from 'vs/languages/css/common/css'; import supports = require('vs/editor/common/modes/supports'); import {AbstractMode} from 'vs/editor/common/modes/abstractMode'; import {OneWorkerAttr} from 'vs/platform/thread/common/threadService'; @@ -54,20 +55,20 @@ export var language: Types.ILanguage = { { include: '@keyword' }, { include: '@strings' }, { include: '@numbers' }, - ['[*_]?[a-zA-Z\\-\\s]+(?=:.*(;|(\\\\$)))', 'support.type.property-name', '@attribute'], + ['[*_]?[a-zA-Z\\-\\s]+(?=:.*(;|(\\\\$)))', cssTokenTypes.TOKEN_PROPERTY, '@attribute'], ['url(\\-prefix)?\\(', { token: 'function', bracket: '@open', next: '@urldeclaration'}], ['[{}()\\[\\]]', '@brackets'], ['[,:;]', 'punctuation'], - ['#@identifierPlus', 'entity.other.attribute-name.id'], - ['&', 'entity.other.attribute-name.placeholder-selector'], + ['#@identifierPlus', cssTokenTypes.TOKEN_SELECTOR + '.id'], + ['&', cssTokenTypes.TOKEN_SELECTOR_TAG], - ['\\.@identifierPlus(?=\\()', 'entity.other.attribute-name.class', '@attribute'], - ['\\.@identifierPlus', 'entity.other.attribute-name.class'], + ['\\.@identifierPlus(?=\\()', cssTokenTypes.TOKEN_SELECTOR + '.class', '@attribute'], + ['\\.@identifierPlus', cssTokenTypes.TOKEN_SELECTOR + '.class'], - ['@identifierPlus', 'entity.name.tag'], + ['@identifierPlus', cssTokenTypes.TOKEN_SELECTOR_TAG], { include: '@operators' }, ['@(@identifier(?=[:,\\)]))', 'variable', '@attribute'], @@ -111,9 +112,9 @@ export var language: Types.ILanguage = { { include: '@keyword' }, - ['[a-zA-Z\\-]+(?=\\()', 'meta.property-value', '@attribute'], + ['[a-zA-Z\\-]+(?=\\()', cssTokenTypes.TOKEN_VALUE, '@attribute'], ['>', 'operator', '@pop'], - ['@identifier', 'meta.property-value'], + ['@identifier', cssTokenTypes.TOKEN_VALUE], { include: '@operators' }, ['@(@identifier)', 'variable'], @@ -124,7 +125,7 @@ export var language: Types.ILanguage = { ['[,=:]', 'punctuation'], ['\\s', ''], - ['.', 'meta.property-value'] + ['.', cssTokenTypes.TOKEN_VALUE] ], comments: [ @@ -138,12 +139,12 @@ export var language: Types.ILanguage = { ], numbers: [ - ['(\\d*\\.)?\\d+([eE][\\-+]?\\d+)?', { token: 'meta.property-value.numeric', next: '@units' }], - ['#[0-9a-fA-F_]+(?!\\w)', 'meta.property-value.rgb-value'] + ['(\\d*\\.)?\\d+([eE][\\-+]?\\d+)?', { token: cssTokenTypes.TOKEN_VALUE + '.numeric', next: '@units' }], + ['#[0-9a-fA-F_]+(?!\\w)', cssTokenTypes.TOKEN_VALUE + '.rgb-value'] ], units: [ - ['((em|ex|ch|rem|vw|vh|vm|cm|mm|in|px|pt|pc|deg|grad|rad|turn|s|ms|Hz|kHz|%)\\b)?', 'meta.property-value.unit', '@pop'] + ['((em|ex|ch|rem|vw|vh|vm|cm|mm|in|px|pt|pc|deg|grad|rad|turn|s|ms|Hz|kHz|%)\\b)?', cssTokenTypes.TOKEN_VALUE + '.unit', '@pop'] ], strings: [ @@ -197,11 +198,11 @@ export class LESSMode extends Monarch.MonarchMode impleme this.extraInfoSupport = this; this.referenceSupport = new supports.ReferenceSupport(this, { - tokens: ['support.type.property-name.less', 'meta.property-value.less', 'variable.less', 'entity.other.attribute-name.class.less', 'entity.other.attribute-name.id.less', 'selector.less'], + tokens: [cssTokenTypes.TOKEN_PROPERTY + '.less', cssTokenTypes.TOKEN_VALUE + '.less', 'variable.less', cssTokenTypes.TOKEN_SELECTOR + '.class.less', cssTokenTypes.TOKEN_SELECTOR + '.id.less', 'selector.less'], findReferences: (resource, position, /*unused*/includeDeclaration) => this.findReferences(resource, position)}); this.logicalSelectionSupport = this; this.declarationSupport = new supports.DeclarationSupport(this, { - tokens: ['variable.less', 'entity.other.attribute-name.class.less', 'entity.other.attribute-name.id.less', 'selector.less'], + tokens: ['variable.less', cssTokenTypes.TOKEN_SELECTOR + '.class.less', cssTokenTypes.TOKEN_SELECTOR + '.id.less', 'selector.less'], findDeclaration: (resource, position) => this.findDeclaration(resource, position)}); this.outlineSupport = this; diff --git a/src/vs/languages/less/test/common/colorizer.test.ts b/src/vs/languages/less/test/common/colorizer.test.ts index 97d2e60e197..f451f209919 100644 --- a/src/vs/languages/less/test/common/colorizer.test.ts +++ b/src/vs/languages/less/test/common/colorizer.test.ts @@ -11,6 +11,7 @@ import EditorCommon = require('vs/editor/common/editorCommon'); import Modes = require('vs/editor/common/modes'); import LESS = require('vs/languages/less/common/less'); import modesUtil = require('vs/editor/test/common/modesUtil'); +import {cssTokenTypes} from 'vs/languages/css/common/css'; suite('LESS-tokenization', () => { @@ -33,7 +34,7 @@ suite('LESS-tokenization', () => { tokens: [ { startIndex: 0, type: 'keyword.less' }, { startIndex: 8, type: 'punctuation.parenthesis.less' }, - { startIndex: 9, type: 'meta.property-value.numeric.less' }, + { startIndex: 9, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex: 11, type: 'punctuation.parenthesis.less' }, { startIndex: 12, type: 'punctuation.less' } ]}], @@ -52,7 +53,7 @@ suite('LESS-tokenization', () => { [{ line: 'whenn', tokens: [ - { startIndex: 0, type: 'entity.name.tag.less' } + { startIndex: 0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' } ]}], [{ @@ -69,8 +70,8 @@ suite('LESS-tokenization', () => { tokens: [ { startIndex: 0, type: 'keyword.less' }, { startIndex: 8, type: 'punctuation.parenthesis.less' }, - { startIndex: 9, type: 'meta.property-value.numeric.less' }, - { startIndex: 11, type: 'meta.property-value.unit.less' }, + { startIndex: 9, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, + { startIndex: 11, type: cssTokenTypes.TOKEN_VALUE + '.unit.less' }, { startIndex: 13, type: 'punctuation.parenthesis.less' }, { startIndex: 14, type: 'punctuation.less' } ]}], @@ -78,7 +79,7 @@ suite('LESS-tokenization', () => { [{ line: 'pxx', tokens: [ - { startIndex: 0, type: 'entity.name.tag.less' } + { startIndex: 0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' } ]}], // single line Strings @@ -164,7 +165,7 @@ suite('LESS-tokenization', () => { tokens: [ { startIndex:0, type: 'comment.less' }, { startIndex:13, type: '' }, - { startIndex:14, type: 'meta.property-value.numeric.less' }, + { startIndex:14, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:15, type: 'punctuation.less' } ]}], @@ -172,28 +173,28 @@ suite('LESS-tokenization', () => { [{ line: '0', tokens: [ - { startIndex:0, type: 'meta.property-value.numeric.less' } + { startIndex:0, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' } ]}], [{ line: ' 0', tokens: [ { startIndex:0, type: '' }, - { startIndex:1, type: 'meta.property-value.numeric.less' } + { startIndex:1, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' } ]}], [{ line: ' 0 ', tokens: [ { startIndex:0, type: '' }, - { startIndex:1, type: 'meta.property-value.numeric.less' }, + { startIndex:1, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:2, type: '' } ]}], [{ line: '0 ', tokens: [ - { startIndex:0, type: 'meta.property-value.numeric.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:1, type: '' } ]}], @@ -203,9 +204,9 @@ suite('LESS-tokenization', () => { { startIndex:0, type: 'variable.less' }, { startIndex:5, type: 'punctuation.less' }, { startIndex:6, type: '' }, - { startIndex:7, type: 'meta.property-value.numeric.less' }, + { startIndex:7, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:8, type: 'operator.less' }, - { startIndex:9, type: 'meta.property-value.numeric.less' } + { startIndex:9, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' } ]}], [{ @@ -214,9 +215,9 @@ suite('LESS-tokenization', () => { { startIndex:0, type: 'variable.less' }, { startIndex:5, type: 'punctuation.less' }, { startIndex:6, type: '' }, - { startIndex:7, type: 'meta.property-value.numeric.less' }, + { startIndex:7, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:10, type: 'operator.less' }, - { startIndex:11, type: 'meta.property-value.numeric.less' } + { startIndex:11, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' } ]}], [{ @@ -225,23 +226,23 @@ suite('LESS-tokenization', () => { { startIndex:0, type: 'variable.less' }, { startIndex:5, type: 'punctuation.less' }, { startIndex:6, type: '' }, - { startIndex:7, type: 'meta.property-value.numeric.less' }, + { startIndex:7, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:8, type: '' }, { startIndex:9, type: 'operator.less' }, { startIndex:10, type: '' }, - { startIndex:11, type: 'meta.property-value.numeric.less' } + { startIndex:11, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' } ]}], [{ line: '0123', tokens: [ - { startIndex:0, type: 'meta.property-value.numeric.less' } + { startIndex:0, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' } ]}], [{ line: '#012343', tokens: [ - { startIndex:0, type: 'meta.property-value.rgb-value.less' } + { startIndex:0, type: cssTokenTypes.TOKEN_VALUE + '.rgb-value.less' } ]}], // Bracket Matching @@ -249,20 +250,20 @@ suite('LESS-tokenization', () => { line: '[1,2,3]', tokens: [ { startIndex:0, type: 'punctuation.bracket.less', bracket: Modes.Bracket.Open }, - { startIndex:1, type: 'meta.property-value.numeric.less' }, + { startIndex:1, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:2, type: 'punctuation.less' }, - { startIndex:3, type: 'meta.property-value.numeric.less' }, + { startIndex:3, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:4, type: 'punctuation.less' }, - { startIndex:5, type: 'meta.property-value.numeric.less' }, + { startIndex:5, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:6, type: 'punctuation.bracket.less', bracket: Modes.Bracket.Close } ]}], [{ line: 'foo(123);', tokens: [ - { startIndex:0, type: 'entity.name.tag.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:3, type: 'punctuation.parenthesis.less', bracket: Modes.Bracket.Open }, - { startIndex:4, type: 'meta.property-value.numeric.less' }, + { startIndex:4, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:7, type: 'punctuation.parenthesis.less', bracket: Modes.Bracket.Close }, { startIndex:8, type: 'punctuation.less' } ]}], @@ -312,7 +313,7 @@ suite('LESS-tokenization', () => { { startIndex:10, type: '' }, { startIndex:11, type: 'punctuation.less' }, { startIndex:12, type: '' }, - { startIndex:13, type: 'meta.property-value.numeric.less' }, + { startIndex:13, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:14, type: 'punctuation.less' }, { startIndex:15, type: '' }, { startIndex:16, type: 'comment.less' } @@ -321,7 +322,7 @@ suite('LESS-tokenization', () => { [{ line: '.something(@some, @other) when (iscolor(@other)) { aname// my commen', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.less' }, { startIndex:10, type: 'punctuation.parenthesis.less' }, { startIndex:11, type: 'variable.less' }, { startIndex:16, type: 'punctuation.less' }, @@ -340,14 +341,14 @@ suite('LESS-tokenization', () => { { startIndex:48, type: '' }, { startIndex:49, type: 'punctuation.curly.less' }, { startIndex:50, type: '' }, - { startIndex:51, type: 'entity.name.tag.less' }, + { startIndex:51, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:56, type: 'comment.less' } ]}], [{ line: '.something(@some//mycomment', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.less' }, { startIndex:10, type: 'punctuation.parenthesis.less' }, { startIndex:11, type: 'variable.less' }, { startIndex:16, type: 'comment.less' } @@ -360,7 +361,7 @@ suite('LESS-tokenization', () => { { startIndex:10, type: '' }, { startIndex:11, type: 'punctuation.less' }, { startIndex:12, type: '' }, - { startIndex:13, type: 'meta.property-value.rgb-value.less' }, + { startIndex:13, type: cssTokenTypes.TOKEN_VALUE + '.rgb-value.less' }, { startIndex:15, type: 'punctuation.less' } ]}], @@ -396,7 +397,7 @@ suite('LESS-tokenization', () => { { startIndex:10, type: 'punctuation.less' }, { startIndex:11, type: '' }, { startIndex:12, type: 'comment.less' }, - { startIndex:29, type: 'meta.property-value.numeric.less' }, + { startIndex:29, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:30, type: 'punctuation.less' } ]}], @@ -408,7 +409,7 @@ suite('LESS-tokenization', () => { { startIndex:11, type: '' }, { startIndex:12, type: 'comment.less' }, { startIndex:23, type: '' }, - { startIndex:24, type: 'meta.property-value.numeric.less' }, + { startIndex:24, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:25, type: 'punctuation.less' } ]}], @@ -444,7 +445,7 @@ suite('LESS-tokenization', () => { { startIndex:15, type: '' }, { startIndex:16, type: 'punctuation.less' }, { startIndex:17, type: '' }, - { startIndex:18, type: 'meta.property-value.numeric.less' }, + { startIndex:18, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:19, type: 'punctuation.less' } ]}], @@ -452,11 +453,11 @@ suite('LESS-tokenization', () => { [{ line: '.class { filter: ~"ms:alwaysHasItsOwnSyntax.For.Stuff()";', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.less' }, { startIndex:6, type: '' }, { startIndex:7, type: 'punctuation.curly.less' }, { startIndex:8, type: '' }, - { startIndex:9, type: 'support.type.property-name.less' }, + { startIndex:9, type: cssTokenTypes.TOKEN_PROPERTY + '.less' }, { startIndex:15, type: 'punctuation.less' }, { startIndex:16, type: '' }, { startIndex:17, type: 'string.punctuation.less' }, @@ -469,10 +470,10 @@ suite('LESS-tokenization', () => { [{ line: '.class {.mixin (@a) when (@a > 10), (@a < -10) { }', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.less' }, { startIndex:6, type: '' }, { startIndex:7, type: 'punctuation.curly.less' }, - { startIndex:8, type: 'entity.other.attribute-name.class.less' }, + { startIndex:8, type: cssTokenTypes.TOKEN_SELECTOR + '.class.less' }, { startIndex:14, type: '' }, { startIndex:15, type: 'punctuation.parenthesis.less' }, { startIndex:16, type: 'variable.less' }, @@ -485,7 +486,7 @@ suite('LESS-tokenization', () => { { startIndex:28, type: '' }, { startIndex:29, type: 'operator.less' }, { startIndex:30, type: '' }, - { startIndex:31, type: 'meta.property-value.numeric.less' }, + { startIndex:31, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:33, type: 'punctuation.parenthesis.less' }, { startIndex:34, type: 'punctuation.less' }, { startIndex:35, type: '' }, @@ -495,7 +496,7 @@ suite('LESS-tokenization', () => { { startIndex:40, type: 'operator.less' }, { startIndex:41, type: '' }, { startIndex:42, type: 'operator.less' }, - { startIndex:43, type: 'meta.property-value.numeric.less' }, + { startIndex:43, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:45, type: 'punctuation.parenthesis.less' }, { startIndex:46, type: '' }, { startIndex:47, type: 'punctuation.curly.less' }, @@ -506,7 +507,7 @@ suite('LESS-tokenization', () => { [{ line: '.truth (@a) when (@a = true) { }', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.less' }, { startIndex:6, type: '' }, { startIndex:7, type: 'punctuation.parenthesis.less' }, { startIndex:8, type: 'variable.less' }, @@ -530,7 +531,7 @@ suite('LESS-tokenization', () => { [{ line: '.max (@a, @b) when (@a > @b) { width: @a; }', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.less' }, { startIndex:4, type: '' }, { startIndex:5, type: 'punctuation.parenthesis.less' }, { startIndex:6, type: 'variable.less' }, @@ -551,7 +552,7 @@ suite('LESS-tokenization', () => { { startIndex:28, type: '' }, { startIndex:29, type: 'punctuation.curly.less' }, { startIndex:30, type: '' }, - { startIndex:31, type: 'support.type.property-name.less' }, + { startIndex:31, type: cssTokenTypes.TOKEN_PROPERTY + '.less' }, { startIndex:36, type: 'punctuation.less' }, { startIndex:37, type: '' }, { startIndex:38, type: 'variable.less' }, @@ -563,7 +564,7 @@ suite('LESS-tokenization', () => { [{ line: '.mixin (@a, @b: 0) when (isnumber(@b)) { }', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.less' }, { startIndex:6, type: '' }, { startIndex:7, type: 'punctuation.parenthesis.less' }, { startIndex:8, type: 'variable.less' }, @@ -572,7 +573,7 @@ suite('LESS-tokenization', () => { { startIndex:12, type: 'variable.less' }, { startIndex:14, type: 'punctuation.less' }, { startIndex:15, type: '' }, - { startIndex:16, type: 'meta.property-value.numeric.less' }, + { startIndex:16, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:17, type: 'punctuation.parenthesis.less' }, { startIndex:18, type: '' }, { startIndex:19, type: 'keyword.less' }, @@ -592,7 +593,7 @@ suite('LESS-tokenization', () => { [{ line: '.mixin (@a, @b: black) when (iscolor(@b)) { }', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.less' }, { startIndex:6, type: '' }, { startIndex:7, type: 'punctuation.parenthesis.less' }, { startIndex:8, type: 'variable.less' }, @@ -601,7 +602,7 @@ suite('LESS-tokenization', () => { { startIndex:12, type: 'variable.less' }, { startIndex:14, type: 'punctuation.less' }, { startIndex:15, type: '' }, - { startIndex:16, type: 'meta.property-value.less' }, + { startIndex:16, type: cssTokenTypes.TOKEN_VALUE + '.less' }, { startIndex:21, type: 'punctuation.parenthesis.less' }, { startIndex:22, type: '' }, { startIndex:23, type: 'keyword.less' }, @@ -640,46 +641,46 @@ suite('LESS-tokenization', () => { [{ line: '.box-shadow(inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6));', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.less' }, { startIndex:11, type: 'punctuation.parenthesis.less' }, - { startIndex:12, type: 'meta.property-value.less' }, + { startIndex:12, type: cssTokenTypes.TOKEN_VALUE + '.less' }, { startIndex:17, type: '' }, - { startIndex:18, type: 'meta.property-value.numeric.less' }, + { startIndex:18, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:19, type: '' }, - { startIndex:20, type: 'meta.property-value.numeric.less' }, - { startIndex:21, type: 'meta.property-value.unit.less' }, + { startIndex:20, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, + { startIndex:21, type: cssTokenTypes.TOKEN_VALUE + '.unit.less' }, { startIndex:23, type: '' }, - { startIndex:24, type: 'meta.property-value.numeric.less' }, - { startIndex:25, type: 'meta.property-value.unit.less' }, + { startIndex:24, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, + { startIndex:25, type: cssTokenTypes.TOKEN_VALUE + '.unit.less' }, { startIndex:27, type: '' }, - { startIndex:28, type: 'meta.property-value.less' }, + { startIndex:28, type: cssTokenTypes.TOKEN_VALUE + '.less' }, { startIndex:32, type: 'punctuation.parenthesis.less' }, - { startIndex:33, type: 'meta.property-value.numeric.less' }, + { startIndex:33, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:34, type: 'punctuation.less' }, - { startIndex:35, type: 'meta.property-value.numeric.less' }, + { startIndex:35, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:36, type: 'punctuation.less' }, - { startIndex:37, type: 'meta.property-value.numeric.less' }, + { startIndex:37, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:38, type: 'punctuation.less' }, - { startIndex:39, type: 'meta.property-value.numeric.less' }, + { startIndex:39, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:43, type: 'punctuation.parenthesis.less' }, { startIndex:44, type: 'punctuation.less' }, { startIndex:45, type: '' }, - { startIndex:46, type: 'meta.property-value.numeric.less' }, + { startIndex:46, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:47, type: '' }, - { startIndex:48, type: 'meta.property-value.numeric.less' }, + { startIndex:48, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:49, type: '' }, - { startIndex:50, type: 'meta.property-value.numeric.less' }, - { startIndex:51, type: 'meta.property-value.unit.less' }, + { startIndex:50, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, + { startIndex:51, type: cssTokenTypes.TOKEN_VALUE + '.unit.less' }, { startIndex:53, type: '' }, - { startIndex:54, type: 'meta.property-value.less' }, + { startIndex:54, type: cssTokenTypes.TOKEN_VALUE + '.less' }, { startIndex:58, type: 'punctuation.parenthesis.less' }, - { startIndex:59, type: 'meta.property-value.numeric.less' }, + { startIndex:59, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:61, type: 'punctuation.less' }, - { startIndex:62, type: 'meta.property-value.numeric.less' }, + { startIndex:62, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:65, type: 'punctuation.less' }, - { startIndex:66, type: 'meta.property-value.numeric.less' }, + { startIndex:66, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:69, type: 'punctuation.less' }, - { startIndex:70, type: 'meta.property-value.numeric.less' }, + { startIndex:70, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:72, type: 'punctuation.parenthesis.less' }, { startIndex:73, type: 'punctuation.parenthesis.less' }, { startIndex:74, type: 'punctuation.less' } @@ -689,9 +690,9 @@ suite('LESS-tokenization', () => { [{ line: 'input[type="radio"]', tokens: [ - { startIndex:0, type: 'entity.name.tag.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:5, type: 'punctuation.bracket.less' }, - { startIndex:6, type: 'entity.name.tag.less' }, + { startIndex:6, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:10, type: 'operator.less' }, { startIndex:11, type: 'string.punctuation.less' }, { startIndex:12, type: 'string.less' }, @@ -711,7 +712,7 @@ suite('LESS-tokenization', () => { [{ line: 'some("\\42");', tokens: [ - { startIndex:0, type: 'entity.name.tag.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:4, type: 'punctuation.parenthesis.less' }, { startIndex:5, type: 'string.punctuation.less' }, { startIndex:6, type: 'string.less' }, @@ -735,7 +736,7 @@ suite('LESS-tokenization', () => { [{ line: 'class^="icon-"', tokens: [ - { startIndex:0, type: 'entity.name.tag.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:5, type: 'operator.less' }, { startIndex:7, type: 'string.punctuation.less' }, { startIndex:8, type: 'string.less' }, @@ -745,7 +746,7 @@ suite('LESS-tokenization', () => { [{ line: 'class*="icon-"', tokens: [ - { startIndex:0, type: 'entity.name.tag.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:5, type: 'operator.less' }, { startIndex:7, type: 'string.punctuation.less' }, { startIndex:8, type: 'string.less' }, @@ -755,7 +756,7 @@ suite('LESS-tokenization', () => { [{ line: 'class~="icon-"', tokens: [ - { startIndex:0, type: 'entity.name.tag.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:5, type: 'operator.less' }, { startIndex:7, type: 'string.punctuation.less' }, { startIndex:8, type: 'string.less' }, @@ -765,7 +766,7 @@ suite('LESS-tokenization', () => { [{ line: 'class ~ = "icon-"', tokens: [ - { startIndex:0, type: 'entity.name.tag.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:5, type: '' }, { startIndex:6, type: 'operator.less' }, { startIndex:7, type: '' }, @@ -779,7 +780,7 @@ suite('LESS-tokenization', () => { [{ line: 'class|="icon-"', tokens: [ - { startIndex:0, type: 'entity.name.tag.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:5, type: 'operator.less' }, { startIndex:7, type: 'string.punctuation.less' }, { startIndex:8, type: 'string.less' }, @@ -789,18 +790,18 @@ suite('LESS-tokenization', () => { [{ line: '.hide-text { font: 0/0 a; }', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.less' }, { startIndex:10, type: '' }, { startIndex:11, type: 'punctuation.curly.less' }, { startIndex:12, type: '' }, - { startIndex:13, type: 'support.type.property-name.less' }, + { startIndex:13, type: cssTokenTypes.TOKEN_PROPERTY + '.less' }, { startIndex:17, type: 'punctuation.less' }, { startIndex:18, type: '' }, - { startIndex:19, type: 'meta.property-value.numeric.less' }, + { startIndex:19, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:20, type: 'operator.less' }, - { startIndex:21, type: 'meta.property-value.numeric.less' }, + { startIndex:21, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:22, type: '' }, - { startIndex:23, type: 'meta.property-value.less' }, + { startIndex:23, type: cssTokenTypes.TOKEN_VALUE + '.less' }, { startIndex:24, type: 'punctuation.less' }, { startIndex:25, type: '' }, { startIndex:26, type: 'punctuation.curly.less' } @@ -810,7 +811,7 @@ suite('LESS-tokenization', () => { [{ line: '.translate3d(@x, @y, @z) { -webkit-transform: translate3d(@x, @y, @z); }', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.less' }, { startIndex:12, type: 'punctuation.parenthesis.less' }, { startIndex:13, type: 'variable.less' }, { startIndex:15, type: 'punctuation.less' }, @@ -823,10 +824,10 @@ suite('LESS-tokenization', () => { { startIndex:24, type: '' }, { startIndex:25, type: 'punctuation.curly.less' }, { startIndex:26, type: '' }, - { startIndex:27, type: 'support.type.property-name.less' }, + { startIndex:27, type: cssTokenTypes.TOKEN_PROPERTY + '.less' }, { startIndex:44, type: 'punctuation.less' }, { startIndex:45, type: '' }, - { startIndex:46, type: 'meta.property-value.less' }, + { startIndex:46, type: cssTokenTypes.TOKEN_VALUE + '.less' }, { startIndex:57, type: 'punctuation.parenthesis.less' }, { startIndex:58, type: 'variable.less' }, { startIndex:60, type: 'punctuation.less' }, @@ -845,20 +846,20 @@ suite('LESS-tokenization', () => { [{ line: '.dropdown-menu > li > a:hover > [class=" icon-"]', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.less' }, { startIndex:14, type: '' }, { startIndex:15, type: 'operator.less' }, { startIndex:16, type: '' }, - { startIndex:17, type: 'entity.name.tag.less' }, + { startIndex:17, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:19, type: '' }, { startIndex:20, type: 'operator.less' }, { startIndex:21, type: '' }, - { startIndex:22, type: 'entity.name.tag.less' }, + { startIndex:22, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:29, type: '' }, { startIndex:30, type: 'operator.less' }, { startIndex:31, type: '' }, { startIndex:32, type: 'punctuation.bracket.less' }, - { startIndex:33, type: 'entity.name.tag.less' }, + { startIndex:33, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:38, type: 'operator.less' }, { startIndex:39, type: 'string.punctuation.less' }, { startIndex:40, type: 'string.less' }, @@ -869,39 +870,39 @@ suite('LESS-tokenization', () => { [{ line: '.bw-gradient(@color: #F5F5F5, @start: 0, @stop: 255) { background: -webkit-gradient(color-stop(0, rgb(@start,@start,@start)), color-stop(1, rgb(@stop,@stop,@stop))); }', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.less' }, { startIndex:12, type: 'punctuation.parenthesis.less' }, { startIndex:13, type: 'variable.less' }, { startIndex:19, type: 'punctuation.less' }, { startIndex:20, type: '' }, - { startIndex:21, type: 'meta.property-value.rgb-value.less' }, + { startIndex:21, type: cssTokenTypes.TOKEN_VALUE + '.rgb-value.less' }, { startIndex:28, type: 'punctuation.less' }, { startIndex:29, type: '' }, { startIndex:30, type: 'variable.less' }, { startIndex:36, type: 'punctuation.less' }, { startIndex:37, type: '' }, - { startIndex:38, type: 'meta.property-value.numeric.less' }, + { startIndex:38, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:39, type: 'punctuation.less' }, { startIndex:40, type: '' }, { startIndex:41, type: 'variable.less' }, { startIndex:46, type: 'punctuation.less' }, { startIndex:47, type: '' }, - { startIndex:48, type: 'meta.property-value.numeric.less' }, + { startIndex:48, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:51, type: 'punctuation.parenthesis.less' }, { startIndex:52, type: '' }, { startIndex:53, type: 'punctuation.curly.less' }, { startIndex:54, type: '' }, - { startIndex:55, type: 'support.type.property-name.less' }, + { startIndex:55, type: cssTokenTypes.TOKEN_PROPERTY + '.less' }, { startIndex:65, type: 'punctuation.less' }, { startIndex:66, type: '' }, - { startIndex:67, type: 'meta.property-value.less' }, + { startIndex:67, type: cssTokenTypes.TOKEN_VALUE + '.less' }, { startIndex:83, type: 'punctuation.parenthesis.less' }, - { startIndex:84, type: 'meta.property-value.less' }, + { startIndex:84, type: cssTokenTypes.TOKEN_VALUE + '.less' }, { startIndex:94, type: 'punctuation.parenthesis.less' }, - { startIndex:95, type: 'meta.property-value.numeric.less' }, + { startIndex:95, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:96, type: 'punctuation.less' }, { startIndex:97, type: '' }, - { startIndex:98, type: 'meta.property-value.less' }, + { startIndex:98, type: cssTokenTypes.TOKEN_VALUE + '.less' }, { startIndex:101, type: 'punctuation.parenthesis.less' }, { startIndex:102, type: 'variable.less' }, { startIndex:108, type: 'punctuation.less' }, @@ -912,12 +913,12 @@ suite('LESS-tokenization', () => { { startIndex:123, type: 'punctuation.parenthesis.less' }, { startIndex:124, type: 'punctuation.less' }, { startIndex:125, type: '' }, - { startIndex:126, type: 'meta.property-value.less' }, + { startIndex:126, type: cssTokenTypes.TOKEN_VALUE + '.less' }, { startIndex:136, type: 'punctuation.parenthesis.less' }, - { startIndex:137, type: 'meta.property-value.numeric.less' }, + { startIndex:137, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:138, type: 'punctuation.less' }, { startIndex:139, type: '' }, - { startIndex:140, type: 'meta.property-value.less' }, + { startIndex:140, type: cssTokenTypes.TOKEN_VALUE + '.less' }, { startIndex:143, type: 'punctuation.parenthesis.less' }, { startIndex:144, type: 'variable.less' }, { startIndex:149, type: 'punctuation.less' }, @@ -937,7 +938,7 @@ suite('LESS-tokenization', () => { line: ' body ', tokens: [ { startIndex:0, type: '' }, - { startIndex:6, type: 'entity.name.tag.less' }, + { startIndex:6, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:10, type: '' } ]}], @@ -952,54 +953,54 @@ suite('LESS-tokenization', () => { [{ line: 'body {', tokens: [ - { startIndex:0, type: 'entity.name.tag.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:4, type: '' }, { startIndex:5, type: 'punctuation.curly.less', bracket: Modes.Bracket.Open } ]}, { line: ' margin: 0;', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.less' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.less' }, { startIndex:8, type: 'punctuation.less' }, { startIndex:9, type: '' }, - { startIndex:10, type: 'meta.property-value.numeric.less' }, + { startIndex:10, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, { startIndex:11, type: 'punctuation.less' } ]}, { line: ' padding: 3em 6em;', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.less' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.less' }, { startIndex:9, type: 'punctuation.less' }, { startIndex:10, type: '' }, - { startIndex:11, type: 'meta.property-value.numeric.less' }, - { startIndex:12, type: 'meta.property-value.unit.less' }, + { startIndex:11, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, + { startIndex:12, type: cssTokenTypes.TOKEN_VALUE + '.unit.less' }, { startIndex:14, type: '' }, - { startIndex:15, type: 'meta.property-value.numeric.less' }, - { startIndex:16, type: 'meta.property-value.unit.less' }, + { startIndex:15, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, + { startIndex:16, type: cssTokenTypes.TOKEN_VALUE + '.unit.less' }, { startIndex:18, type: 'punctuation.less' } ]}, { line: ' font-family: tahoma, arial, sans-serif;', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.less' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.less' }, { startIndex:13, type: 'punctuation.less' }, { startIndex:14, type: '' }, - { startIndex:15, type: 'meta.property-value.less' }, + { startIndex:15, type: cssTokenTypes.TOKEN_VALUE + '.less' }, { startIndex:21, type: 'punctuation.less' }, { startIndex:22, type: '' }, - { startIndex:23, type: 'meta.property-value.less' }, + { startIndex:23, type: cssTokenTypes.TOKEN_VALUE + '.less' }, { startIndex:28, type: 'punctuation.less' }, { startIndex:29, type: '' }, - { startIndex:30, type: 'meta.property-value.less' }, + { startIndex:30, type: cssTokenTypes.TOKEN_VALUE + '.less' }, { startIndex:40, type: 'punctuation.less' } ]}, { line: ' text-decoration: none !important;', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.less' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.less' }, { startIndex:17, type: 'punctuation.less' }, { startIndex:18, type: '' }, - { startIndex:19, type: 'meta.property-value.less' }, + { startIndex:19, type: cssTokenTypes.TOKEN_VALUE + '.less' }, { startIndex:23, type: '' }, { startIndex:24, type: 'keyword.less' }, { startIndex:34, type: 'punctuation.less' } @@ -1007,10 +1008,10 @@ suite('LESS-tokenization', () => { line: ' color: #000;', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.less' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.less' }, { startIndex:7, type: 'punctuation.less' }, { startIndex:8, type: '' }, - { startIndex:9, type: 'meta.property-value.rgb-value.less' }, + { startIndex:9, type: cssTokenTypes.TOKEN_VALUE + '.rgb-value.less' }, { startIndex:13, type: 'punctuation.less' } ]}, { line: ' }', @@ -1027,19 +1028,19 @@ suite('LESS-tokenization', () => { { startIndex:1, type: '' }, { startIndex:2, type: 'punctuation.curly.less' }, { startIndex:3, type: '' }, - { startIndex:4, type: 'support.type.property-name.less' }, + { startIndex:4, type: cssTokenTypes.TOKEN_PROPERTY + '.less' }, { startIndex:11, type: 'punctuation.less' }, { startIndex:12, type: '' }, - { startIndex:13, type: 'meta.property-value.numeric.less' }, - { startIndex:14, type: 'meta.property-value.unit.less' }, + { startIndex:13, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, + { startIndex:14, type: cssTokenTypes.TOKEN_VALUE + '.unit.less' }, { startIndex:16, type: '' }, { startIndex:17, type: 'operator.less' }, - { startIndex:18, type: 'meta.property-value.numeric.less' }, - { startIndex:19, type: 'meta.property-value.unit.less' }, + { startIndex:18, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, + { startIndex:19, type: cssTokenTypes.TOKEN_VALUE + '.unit.less' }, { startIndex:21, type: '' }, { startIndex:22, type: 'operator.less' }, - { startIndex:23, type: 'meta.property-value.numeric.less' }, - { startIndex:26, type: 'meta.property-value.unit.less' }, + { startIndex:23, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, + { startIndex:26, type: cssTokenTypes.TOKEN_VALUE + '.unit.less' }, { startIndex:28, type: 'punctuation.less' }, { startIndex:29, type: '' }, { startIndex:30, type: 'punctuation.curly.less' } @@ -1050,11 +1051,11 @@ suite('LESS-tokenization', () => { [{ line: 'h1 /*comment*/ p {', tokens: [ - { startIndex:0, type: 'entity.name.tag.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:2, type: '' }, { startIndex:3, type: 'comment.less' }, { startIndex:14, type: '' }, - { startIndex:15, type: 'entity.name.tag.less' }, + { startIndex:15, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:16, type: '' }, { startIndex:17, type: 'punctuation.curly.less', bracket: Modes.Bracket.Open } ]}], @@ -1065,7 +1066,7 @@ suite('LESS-tokenization', () => { [{ line: 'h1 /*com', tokens: [ - { startIndex:0, type: 'entity.name.tag.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:2, type: '' }, { startIndex:3, type: 'comment.less' } ]}, { @@ -1073,7 +1074,7 @@ suite('LESS-tokenization', () => { tokens: [ { startIndex:0, type: 'comment.less' }, { startIndex:6, type: '' }, - { startIndex:7, type: 'entity.name.tag.less' } + { startIndex:7, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' } ]}], // CSS ID rule @@ -1084,7 +1085,7 @@ suite('LESS-tokenization', () => { [{ line: '#myID {', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.id.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.id.less' }, { startIndex:5, type: '' }, { startIndex:6, type: 'punctuation.curly.less', bracket: Modes.Bracket.Open } ]}], @@ -1095,7 +1096,7 @@ suite('LESS-tokenization', () => { [{ line: '.myID {', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.less' }, { startIndex:5, type: '' }, { startIndex:6, type: 'punctuation.curly.less', bracket: Modes.Bracket.Open } ]}], @@ -1125,7 +1126,7 @@ suite('LESS-tokenization', () => { line: ' content: "con\\', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.less' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.less' }, { startIndex:9, type: 'punctuation.less' }, { startIndex:10, type: '' }, { startIndex:11, type: 'string.punctuation.less', bracket: Modes.Bracket.Open }, @@ -1147,7 +1148,7 @@ suite('LESS-tokenization', () => { line: ' content: "";', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.less' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.less' }, { startIndex:9, type: 'punctuation.less' }, { startIndex:10, type: '' }, { startIndex:11, type: 'string.punctuation.less', bracket: Modes.Bracket.Open }, @@ -1162,7 +1163,7 @@ suite('LESS-tokenization', () => { line: ' _content: "";', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.less' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.less' }, { startIndex:10, type: 'punctuation.less' }, { startIndex:11, type: '' }, { startIndex:12, type: 'string.punctuation.less', bracket: Modes.Bracket.Open }, @@ -1184,7 +1185,7 @@ suite('LESS-tokenization', () => { line: ' font-family: "Opificio";', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.less' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.less' }, { startIndex:13, type: 'punctuation.less' }, { startIndex:14, type: '' }, { startIndex:15, type: 'string.punctuation.less', bracket: Modes.Bracket.Open }, @@ -1206,7 +1207,7 @@ suite('LESS-tokenization', () => { [{ line: 'p{}', tokens: [ - { startIndex:0, type: 'entity.name.tag.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:1, type: 'punctuation.curly.less', bracket: Modes.Bracket.Open }, { startIndex:2, type: 'punctuation.curly.less', bracket: Modes.Bracket.Close } ]}], @@ -1214,7 +1215,7 @@ suite('LESS-tokenization', () => { [{ line: 'p:nth() {}', tokens: [ - { startIndex:0, type: 'entity.name.tag.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:5, type: 'punctuation.parenthesis.less', bracket: Modes.Bracket.Open }, { startIndex:6, type: 'punctuation.parenthesis.less', bracket: Modes.Bracket.Close }, { startIndex:7, type: '' }, @@ -1270,13 +1271,13 @@ suite('LESS-tokenization', () => { ]}, { line: '.rule1{}', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.less' }, { startIndex:6, type: 'punctuation.curly.less', bracket: Modes.Bracket.Open }, { startIndex:7, type: 'punctuation.curly.less', bracket: Modes.Bracket.Close } ]}, { line: '.rule2{}', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.less' }, { startIndex:6, type: 'punctuation.curly.less', bracket: Modes.Bracket.Open }, { startIndex:7, type: 'punctuation.curly.less', bracket: Modes.Bracket.Close } ]}], @@ -1287,27 +1288,27 @@ suite('LESS-tokenization', () => { tokens: [ { startIndex:0, type: 'variable.less' }, { startIndex:18, type: '' }, - { startIndex:19, type: 'entity.name.tag.less' }, + { startIndex:19, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:36, type: '' }, { startIndex:37, type: 'punctuation.curly.less', bracket: Modes.Bracket.Open } ]}, { line: ' from {', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'entity.name.tag.less' }, + { startIndex:2, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:6, type: '' }, { startIndex:7, type: 'punctuation.curly.less' } ]}, { line: ' -webkit-transform: rotate(0deg);', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.less' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.less' }, { startIndex:19, type: 'punctuation.less' }, { startIndex:20, type: '' }, - { startIndex:21, type: 'meta.property-value.less' }, + { startIndex:21, type: cssTokenTypes.TOKEN_VALUE + '.less' }, { startIndex:27, type: 'punctuation.parenthesis.less' }, - { startIndex:28, type: 'meta.property-value.numeric.less' }, - { startIndex:29, type: 'meta.property-value.unit.less' }, + { startIndex:28, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, + { startIndex:29, type: cssTokenTypes.TOKEN_VALUE + '.unit.less' }, { startIndex:32, type: 'punctuation.parenthesis.less' }, { startIndex:33, type: 'punctuation.less' } ]}, { @@ -1319,20 +1320,20 @@ suite('LESS-tokenization', () => { line: ' to {', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'entity.name.tag.less' }, + { startIndex:2, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:4, type: '' }, { startIndex:5, type: 'punctuation.curly.less' } ]}, { line: ' -webkit-transform: rotate(360deg);', tokens: [ { startIndex:0, type: '' }, - { startIndex:2, type: 'support.type.property-name.less' }, + { startIndex:2, type: cssTokenTypes.TOKEN_PROPERTY + '.less' }, { startIndex:19, type: 'punctuation.less' }, { startIndex:20, type: '' }, - { startIndex:21, type: 'meta.property-value.less' }, + { startIndex:21, type: cssTokenTypes.TOKEN_VALUE + '.less' }, { startIndex:27, type: 'punctuation.parenthesis.less' }, - { startIndex:28, type: 'meta.property-value.numeric.less' }, - { startIndex:31, type: 'meta.property-value.unit.less' }, + { startIndex:28, type: cssTokenTypes.TOKEN_VALUE + '.numeric.less' }, + { startIndex:31, type: cssTokenTypes.TOKEN_VALUE + '.unit.less' }, { startIndex:34, type: 'punctuation.parenthesis.less' }, { startIndex:35, type: 'punctuation.less' } ]}, { @@ -1352,12 +1353,12 @@ suite('LESS-tokenization', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: 'input[type= \\"submit\\"', tokens: [ - { startIndex:0, type: 'entity.name.tag.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:5, type: 'punctuation.bracket.less'}, - { startIndex:6, type: 'entity.name.tag.less' }, + { startIndex:6, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less' }, { startIndex:10, type: 'operator.less'}, { startIndex:11, type: ''}, - { startIndex:12, type: 'entity.name.tag.less'} + { startIndex:12, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less'} ]} ]); }); @@ -1366,13 +1367,13 @@ suite('LESS-tokenization', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '.\\34 hello { -moz-foo: --myvar }', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.class.less' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.class.less' }, { startIndex:10, type: ''}, { startIndex:11, type: 'punctuation.curly.less'}, { startIndex:12, type: ''}, - { startIndex:13, type: 'entity.name.tag.less'}, + { startIndex:13, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less'}, { startIndex:22, type: ''}, - { startIndex:23, type: 'entity.name.tag.less'}, + { startIndex:23, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.less'}, { startIndex:30, type: ''}, { startIndex:31, type: 'punctuation.curly.less'}, ]} diff --git a/src/vs/languages/markdown/common/tokens.css b/src/vs/languages/markdown/common/tokens.css index 41acddee165..7aa3fef41fe 100644 --- a/src/vs/languages/markdown/common/tokens.css +++ b/src/vs/languages/markdown/common/tokens.css @@ -41,9 +41,6 @@ /* PHP */ .monaco-editor.vs .token.metatag.php { font-weight: bold; } -.monaco-editor.vs .token.constant.php { color: #dd0000; } -.monaco-editor.vs .token.block.php { color: green; } -.monaco-editor.vs .token.variable.predefined.php { color: #ff8888; } /* Ruby */ .monaco-editor.vs .token.predefined.ruby { color: #0000FF; } @@ -73,15 +70,15 @@ .monaco-editor.vs .token.delimiter.html { color: #383838; } .monaco-editor.vs .token.metatag.content.html { color: red; } .monaco-editor.vs .token.metatag.html { color: gray; } -.monaco-editor.vs .token.tag.html { color: #800000; } .monaco-editor.vs .token.attribute.name.html { color: red; } .monaco-editor.vs .token.attribute.value.html { color: blue; } +.monaco-editor.vs .token.string.html { color: blue; } + /* XML */ .monaco-editor.vs .token.delimiter.xml { color: blue; } .monaco-editor.vs .token.metatag.content.xml { color: red; } .monaco-editor.vs .token.metatag.xml { color: gray; } -.monaco-editor.vs .token.tag.xml { color: #800000; } .monaco-editor.vs .token.attribute.name.xml { color: red; } .monaco-editor.vs .token.attribute.value.xml { color: blue; } @@ -97,7 +94,6 @@ .monaco-editor.vs .token.delimiter.vs { color: #708870; } /* Jade */ -.monaco-editor.vs .token.tag.jade { color: #800000; } .monaco-editor.vs .token.tag.id.jade, .monaco-editor.vs .token.tag.class.jade { color: #4F76AC; } .monaco-editor.vs .token.interpolation.jade { color: magenta; } @@ -128,7 +124,7 @@ .monaco-editor.vs-dark .token.number.octal { color: #204070; } .monaco-editor.vs-dark .token.regexp { color: #B46695; } .monaco-editor.vs-dark .token.delimiter { color: #DCDCDC; } -.monaco-editor.vs-dark .token.tag { color: #D7BA7D; } +.monaco-editor.vs-dark .token.tag { color: #569CD6; } .monaco-editor.vs-dark .token.metatag { color: #DD6A6F; } .monaco-editor.vs-dark .token.annotation { color: #cc6666; } .monaco-editor.vs-dark .token.key { color: #9CDCFE; } @@ -174,13 +170,13 @@ /* HTML */ -.monaco-editor.vs-dark .token.tag.html { color: #569CD6; } .monaco-editor.vs-dark .token.delimiter.html { color: #808080; } .monaco-editor.vs-dark .token.metatag.content.html { color: #9CDCFE; } .monaco-editor.vs-dark .token.metatag.html { color: #569CD6; } +.monaco-editor.vs-dark .token.string.html { color: #CE9178; } + /* XML */ -.monaco-editor.vs-dark .token.tag.xml { color: #569CD6; } .monaco-editor.vs-dark .token.delimiter.xml { color: #808080; } .monaco-editor.vs-dark .token.metatag.content.xml { color: #9CDCFE; } .monaco-editor.vs-dark .token.metatag.xml { color: #569CD6; } @@ -198,7 +194,6 @@ .monaco-editor.vs-dark .token.attribute.value.vs { color: #C4C4C4; } /* Jade */ -.monaco-editor.vs-dark .token.tag.jade { color: #569CD6; } .monaco-editor.vs-dark .token.tag.id.jade, .monaco-editor.vs-dark .token.tag.class.jade { color: #4F76AC; } .monaco-editor.vs-dark .token.interpolation.jade { color: magenta; } @@ -279,6 +274,9 @@ .monaco-editor.hc-white .token.metatag.content.html { color: #FF0000; } .monaco-editor.hc-white .token.metatag.html { color: #569CD6; } +.monaco-editor.hc-white .token.string.html { color: blue; } + + /* XML */ .monaco-editor.hc-white .token.tag.xml { color: #800000; } .monaco-editor.hc-white .token.delimiter.xml { color: #0000FF; } @@ -307,8 +305,8 @@ .monaco-editor.hc-black .token.variable { color: #1AEBFF; } .monaco-editor.hc-black .token.variable.predefined { color: #1AEBFF; } .monaco-editor.hc-black .token.constant { color: #dd0000; } -.monaco-editor.hc-black .token.string { color: #C0C0C0; } -.monaco-editor.hc-black .token.string.escape { color: #C0C0C0; } +.monaco-editor.hc-black .token.string { color: #CE9178; } +.monaco-editor.hc-black .token.string.escape { color: #CE9178; } .monaco-editor.hc-black .token.comment { color: #008000; } .monaco-editor.hc-black .token.comment.shebang { color: #929292; } .monaco-editor.hc-black .token.comment.doc { color: #608B4E; } @@ -321,7 +319,7 @@ .monaco-editor.hc-black .token.number.binary { color: #FFFFFF; } .monaco-editor.hc-black .token.regexp { color: #C0C0C0; } .monaco-editor.hc-black .token.delimiter { color: #FFFF00; } -.monaco-editor.hc-black .token.tag { color: #FFA500; } +.monaco-editor.hc-black .token.tag { color: #569CD6; } .monaco-editor.hc-black .token.metatag { color: #569CD6; } .monaco-editor.hc-black .token.annotation { color: #569CD6; } .monaco-editor.hc-black .token.key { color: #9CDCFE; } @@ -367,13 +365,13 @@ /* HTML */ -.monaco-editor.hc-black .token.tag.html { color: #1AEBFF; } .monaco-editor.hc-black .token.delimiter.html { color: #FFFF00; } .monaco-editor.hc-black .token.metatag.content.html { color: #1AEBFF; } .monaco-editor.hc-black .token.metatag.html { color: #569CD6; } +.monaco-editor.hc-black .token.string.html { color: #CE9178; } + /* XML */ -.monaco-editor.hc-black .token.tag.xml { color: #1AEBFF; } .monaco-editor.hc-black .token.delimiter.xml { color: #FFFF00; } .monaco-editor.hc-black .token.metatag.content.xml { color: #1AEBFF; } .monaco-editor.hc-black .token.metatag.xml { color: #569CD6; } @@ -391,7 +389,7 @@ .monaco-editor.hc-black .token.attribute.value.vs { color: #C4C4C4; } /* Jade */ -.monaco-editor.hc-black .token.tag.jade { color: #569CD6; } +.monaco-editor.hc-black .token.tag.string.jade { color: #CE9178; } .monaco-editor.hc-black .token.tag.id.jade, .monaco-editor.hc-black .token.tag.class.jade { color: #4F76AC; } .monaco-editor.hc-black .token.interpolation.jade { color: magenta; } @@ -431,6 +429,8 @@ .monaco-editor.vs .token.constant.numeric.octal { color: #204070; } .monaco-editor.vs .token.constant.numeric.binary { color: #e07070; } .monaco-editor.vs .token.constant.regexp { color: #811f3f; } +.monaco-editor.vs .token.constant.rgb-value { color: #0451A5; } + /*.monaco-editor.vs .token.constant.character .monaco-editor.vs .token.constant.character.escape .monaco-editor.vs .token.constant.language.boolean @@ -443,10 +443,14 @@ .monaco-editor.vs .token.brace.curly*/ .monaco-editor.vs .token.entity { color: #A31515; } -.monaco-editor.vs .token.entity.name { color: #A31515; } -.monaco-editor.vs .token.entity.name.function { color: #000000; } -.monaco-editor.vs .token.entity.name.punctuation { color: #000000; } +.monaco-editor.vs .token.entity.name { color: #800000; } +.monaco-editor.vs .token.entity.name.tag { color: #800000; } +.monaco-editor.vs .token.entity.name.function { color: #444444; } .monaco-editor.vs .token.entity.name.class { color: #2B91AF; } +.monaco-editor.vs .token.entity.name.selector { color: #800000; } +.monaco-editor.vs .token.entity.other.selector { color: #800000; } +.monaco-editor.vs .token.entity.other.attribute-name { color: red; } +.monaco-editor.vs .token.entity.other.attribute-name.css { color: #800000; } /*.monaco-editor.vs .token.entity.name.type .monaco-editor.vs .token.entity.name.tag @@ -475,8 +479,11 @@ .monaco-editor.vs .token.markup.other*/ .monaco-editor.vs .token.meta { color: #000000; } +.monaco-editor.vs .token.meta.selector { color: #800000; } +.monaco-editor.vs .token.meta.tag { color: #800000; } -/*.monaco-editor.vs .token.storage*/ +.monaco-editor.vs .token.storage { color: gray }; +.monaco-editor.vs .token.storage.content { color: red }; .monaco-editor.vs .token.storage.type { color: #0000FF; } .monaco-editor.vs .token.storage.modifier { color: #0000FF; } .monaco-editor.vs .token.cast.storage.type, @@ -485,6 +492,7 @@ .monaco-editor.vs .token.var.annotation.storage.type { color: #2B91AF; } .monaco-editor.vs .token.string { color: #A31515; } +.monaco-editor.vs .token.string.tag { color: blue; } /*.monaco-editor.vs .token.string.quoted .monaco-editor.vs .token.string.quoted.single .monaco-editor.vs .token.string.quoted.double @@ -496,8 +504,11 @@ .monaco-editor.vs .token.string.regexp { color: #811f3f; } /*.monaco-editor.vs .token.string.other*/ -/*.monaco-editor.vs .token.support -.monaco-editor.vs .token.support.function +.monaco-editor.vs .token.support { color: #800000; } +.monaco-editor.vs .token.support.type { color: red; } +.monaco-editor.vs .token.support.type.json { color: #A31515; } +.monaco-editor.vs .token.support.property-value { color: #0451A5; } +/*.monaco-editor.vs .token.support.function .monaco-editor.vs .token.support.class .monaco-editor.vs .token.support.type .monaco-editor.vs .token.support.constant @@ -511,12 +522,19 @@ /* Keywords should come at the end in order to match cases like token.keyword.string */ .monaco-editor.vs .token.keyword { color: #0000FF; } -.monaco-editor.vs .token.keyword.control { color: #AF00DB; } +.monaco-editor.vs .token.keyword.control { color: #0000FF; } .monaco-editor.vs .token.keyword.operator { color: #666666; } .monaco-editor.vs .token.keyword.operator.new { color: #0000FF; } +.monaco-editor.vs .token.keyword.other.unit { color: #09885A; } /*.monaco-editor.vs .token.keyword.operator .monaco-editor.vs .token.keyword.other*/ +.monaco-editor.vs .token.punctuation { color: #000000; } +.monaco-editor.vs .token.punctuation.string { color: #A31515; } +.monaco-editor.vs .token.punctuation.string.quoted.variable { color: #001188; } +.monaco-editor.vs .token.punctuation.string.regexp { color: #811f3f; } +.monaco-editor.vs .token.punctuation.tag { color: #800000; } +.monaco-editor.vs .token.punctuation.string.tag { color: blue; } /* -------------------------------- Begin vs-dark tokens -------------------------------- */ .monaco-editor.vs-dark .token { color: #D4D4D4; } @@ -540,7 +558,8 @@ .monaco-editor.vs-dark .token.constant.numeric.hex { color: #5BB498; } .monaco-editor.vs-dark .token.constant.numeric.octal { color: #204070; } .monaco-editor.vs-dark .token.constant.numeric.binary { color: #e07070; } -.monaco-editor.vs-dark .token.constant.regexp { color: #B46695; } +.monaco-editor.vs-dark .token.constant.regexp { color: #646695; } +.monaco-editor.vs-dark .token.constant.rgb-value { color: #D4D4D4; } /*.monaco-editor.vs-dark .token.constant.character .monaco-editor.vs-dark .token.constant.character.escape .monaco-editor.vs-dark .token.constant.language.boolean @@ -553,10 +572,15 @@ .monaco-editor.vs-dark .token.brace.curly*/ .monaco-editor.vs-dark .token.entity { color: #9CDCFE; } -.monaco-editor.vs-dark .token.entity.name { color: #9CDCFE; } -.monaco-editor.vs-dark .token.entity.name.function { color: #DCDCDC; } -.monaco-editor.vs-dark .token.entity.name.punctuation { color: #DCDCDC; } +.monaco-editor.vs-dark .token.entity.name { color: #569CD6; } +.monaco-editor.vs-dark .token.entity.name.tag { color: #569CD6; } +.monaco-editor.vs-dark .token.entity.name.function { color: #DCDCAA; } .monaco-editor.vs-dark .token.entity.name.class { color: #4EC9B0; } +.monaco-editor.vs-dark .token.entity.name.selector { color: #569CD6; } + +.monaco-editor.vs-dark .token.entity.other.selector { color: #569CD6; } +.monaco-editor.vs-dark .token.entity.other.attribute-name { color: #9CDCFE; } +.monaco-editor.vs-dark .token.entity.other.attribute-name.css { color: #569CD6; } /* .monaco-editor.vs-dark .token.entity.name.type .monaco-editor.vs-dark .token.entity.name.tag @@ -583,8 +607,11 @@ .monaco-editor.vs-dark .token.markup.other*/ .monaco-editor.vs-dark .token.meta { color: #D4D4D4; } +.monaco-editor.vs-dark .token.meta.selector { color: #569CD6; } +.monaco-editor.vs-dark .token.meta.tag { color: #CE9178; } -/*.monaco-editor.vs-dark .token.storage*/ +.monaco-editor.vs-dark .token.storage { color: #569CD6 }; +.monaco-editor.vs-dark .token.storage.content { color: #9CDCFE }; .monaco-editor.vs-dark .token.storage.type { color: #569CD6; } .monaco-editor.vs-dark .token.storage.modifier { color: #569CD6; } .monaco-editor.vs-dark .token.annotation.storage.type, @@ -595,6 +622,7 @@ .monaco-editor.vs-dark .token.var.annotation.storage.type { color: #4EC9B0; } .monaco-editor.vs-dark .token.string { color: #CE9178; } +.monaco-editor.vs-dark .token.string.tag { color: #CE9178; } /*.monaco-editor.vs-dark .token.string.quoted .monaco-editor.vs-dark .token.string.quoted.single .monaco-editor.vs-dark .token.string.quoted.double @@ -606,10 +634,11 @@ .monaco-editor.vs-dark .token.string.regexp { color: #D16969; } /*.monaco-editor.vs-dark .token.string.other*/ -/*.monaco-editor.vs-dark .token.support -.monaco-editor.vs-dark .token.support.function +.monaco-editor.vs-dark .token.support { color: #A79873; } +.monaco-editor.vs-dark .token.support.type { color: #9CDCFE; } +.monaco-editor.vs-dark .token.support.property-value { color: #CE9178; } +/*.monaco-editor.vs-dark .token.support.function .monaco-editor.vs-dark .token.support.class -.monaco-editor.vs-dark .token.support.type .monaco-editor.vs-dark .token.support.constant .monaco-editor.vs-dark .token.support.variable .monaco-editor.vs-dark .token.support.other*/ @@ -621,12 +650,20 @@ /* Keywords should come at the end in order to match cases like token.keyword.string */ .monaco-editor.vs-dark .token.keyword { color: #569CD6; } -.monaco-editor.vs-dark .token.keyword.control { color: #C586C0; } +.monaco-editor.vs-dark .token.keyword.control { color: #569CD6; } .monaco-editor.vs-dark .token.keyword.operator { color: #909090; } .monaco-editor.vs-dark .token.keyword.operator.new { color: #569CD6; } +.monaco-editor.vs-dark .token.keyword.other.unit { color: #B5CEA8; } /*.monaco-editor.vs-dark .token.keyword.operator .monaco-editor.vs-dark .token.keyword.other*/ +.monaco-editor.vs-dark .token.punctuation { color: #DCDCDC; } +.monaco-editor.vs-dark .token.punctuation.string { color: #CE9178; } +.monaco-editor.vs-dark .token.punctuation.string.quoted.variable { color: #74B0DF; } +.monaco-editor.vs-dark .token.punctuation.string.regexp { color: #D16969; } +.monaco-editor.vs-dark .token.punctuation.tag { color: #569CD6; } +.monaco-editor.vs-dark .token.punctuation.string.tag { color: #CE9178; } + /* -------------------------------- End vs-dark tokens -------------------------------- */ @@ -654,6 +691,7 @@ .monaco-editor.hc-black .token.constant.numeric.octal { color: #204070; } .monaco-editor.hc-black .token.constant.numeric.binary { color: #e07070; } .monaco-editor.hc-black .token.constant.regexp { color: #B46695; } +.monaco-editor.hc-black .token.constant.rgb-value { color: #D4D4D4; } /*.monaco-editor.hc-black .token.constant.character .monaco-editor.hc-black .token.constant.character.escape .monaco-editor.hc-black .token.constant.language.boolean @@ -666,10 +704,14 @@ .monaco-editor.hc-black .token.brace.curly*/ .monaco-editor.hc-black .token.entity { color: #9CDCFE; } -.monaco-editor.hc-black .token.entity.name { color: #9CDCFE; } -.monaco-editor.hc-black .token.entity.name.function { color: #DCDCDC; } -.monaco-editor.hc-black .token.entity.name.punctuation { color: #DCDCDC; } +.monaco-editor.hc-black .token.entity.name { color: #569CD6; } +.monaco-editor.hc-black .token.entity.name.tag { color: #569CD6; } +.monaco-editor.hc-black .token.entity.name.function { color: #DCDCAA; } .monaco-editor.hc-black .token.entity.name.class { color: #4EC9B0; } +.monaco-editor.hc-black .token.entity.name.selector { color: #569CD6; } +.monaco-editor.hc-black .token.entity.other.selector { color: #569CD6; } +.monaco-editor.hc-black .token.entity.other.attribute-name { color: #9CDCFE; } +.monaco-editor.hc-black .token.entity.other.attribute-name.css { color: #569CD6; } /* .monaco-editor.hc-black .token.entity.name.type .monaco-editor.hc-black .token.entity.name.tag @@ -696,8 +738,11 @@ .monaco-editor.hc-black .token.markup.other*/ .monaco-editor.hc-black .token.meta { color: #D4D4D4; } +.monaco-editor.hc-black .token.meta.selector { color: #569CD6; } +.monaco-editor.hc-black .token.meta.tag { color: #CE9178; } -/*.monaco-editor.hc-black .token.storage*/ +.monaco-editor.hc-black .token.storage { color: #569CD6 }; +.monaco-editor.hc-black .token.storage.content { color: #9CDCFE }; .monaco-editor.hc-black .token.storage.type { color: #569CD6; } .monaco-editor.hc-black .token.storage.modifier { color: #569CD6; } .monaco-editor.hc-black .token.annotation.storage.type, @@ -708,6 +753,7 @@ .monaco-editor.hc-black .token.var.annotation.storage.type { color: #4EC9B0; } .monaco-editor.hc-black .token.string { color: #CE9178; } +.monaco-editor.hc-black .token.string.tag { color: #CE9178; } /*.monaco-editor.hc-black .token.string.quoted .monaco-editor.hc-black .token.string.quoted.single .monaco-editor.hc-black .token.string.quoted.double @@ -719,26 +765,35 @@ .monaco-editor.hc-black .token.string.regexp { color: #D16969; } /*.monaco-editor.hc-black .token.string.other*/ -/*.monaco-editor.hc-black .token.support -.monaco-editor.hc-black .token.support.function +.monaco-editor.hc-black .token.support { color: #800000; } +.monaco-editor.hc-black .token.support.type { color: #9CDCFE; } +.monaco-editor.hc-black .token.support.property-value { color: #CE9178; } +/*.monaco-editor.hc-black .token.support.function .monaco-editor.hc-black .token.support.class -.monaco-editor.hc-black .token.support.type .monaco-editor.hc-black .token.support.constant .monaco-editor.hc-black .token.support.variable .monaco-editor.hc-black .token.support.other*/ .monaco-editor.hc-black .token.variable.parameter { color: #9CDCFE; } /*.monaco-editor.hc-black .token.variable*/ -.monaco-editor.vs-dark .token.variable.language { color: #4864AA; } +.monaco-editor.hc-black .token.variable.language { color: #4864AA; } /*.monaco-editor.hc-black .token.variable.other*/ /* Keywords should come at the end in order to match cases like token.keyword.string */ .monaco-editor.hc-black .token.keyword { color: #569CD6; } -.monaco-editor.hc-black .token.keyword.control { color: #C586C0; } +.monaco-editor.hc-black .token.keyword.control { color: #569CD6; } .monaco-editor.hc-black .token.keyword.operator { color: #909090; } .monaco-editor.hc-black .token.keyword.operator.new { color: #569CD6; } +.monaco-editor.hc-black .token.keyword.other.unit { color: #B5CEA8; } /*.monaco-editor.hc-black .token.keyword.operator .monaco-editor.hc-black .token.keyword.other*/ +.monaco-editor.hc-black .token.punctuation { color: #DCDCDC; } +.monaco-editor.hc-black .token.punctuation.string { color: #CE9178; } +.monaco-editor.hc-black .token.punctuation.string.quoted.variable { color: #74B0DF; } +.monaco-editor.hc-black .token.punctuation.string.regexp { color: #D16969; } +.monaco-editor.hc-black .token.punctuation.tag { color: #569CD6; } +.monaco-editor.hc-black .token.punctuation.string.tag { color: #CE9178; } + /* -------------------------------- End hc-black tokens ----------------------------- */ \ No newline at end of file diff --git a/src/vs/languages/markdown/test/common/markdown.test.ts b/src/vs/languages/markdown/test/common/markdown.test.ts index 8590b5ba4e3..43c4e3eb00e 100644 --- a/src/vs/languages/markdown/test/common/markdown.test.ts +++ b/src/vs/languages/markdown/test/common/markdown.test.ts @@ -10,6 +10,7 @@ import markdownMode = require('vs/languages/markdown/common/markdown'); import EditorCommon = require('vs/editor/common/editorCommon'); import Modes = require('vs/editor/common/modes'); import {htmlTokenTypes} from 'vs/languages/html/common/html'; +import {cssTokenTypes} from 'vs/languages/css/common/css'; suite('Markdown - tokenization', () => { @@ -56,14 +57,14 @@ suite('Markdown - tokenization', () => { line: '*bar*', tokens: [ { startIndex:0, type: htmlTokenTypes.getTag('style.md'), bracket: Modes.Bracket.Open }, - { startIndex:7, type: 'entity.name.tag.css' }, + { startIndex:7, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.css' }, { startIndex:10, type: '' }, { startIndex:11, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Open }, { startIndex:12, type: '' }, - { startIndex:13, type: 'support.type.property-name.css' }, + { startIndex:13, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:23, type: 'punctuation.css' }, { startIndex:24, type: '' }, - { startIndex:25, type: 'meta.property-value.css' }, + { startIndex:25, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:28, type: '' }, { startIndex:29, type: 'punctuation.bracket.css', bracket: Modes.Bracket.Close }, { startIndex:30, type: htmlTokenTypes.getTag('style.md'), bracket: Modes.Bracket.Close }, diff --git a/src/vs/languages/php/test/common/php.test.ts b/src/vs/languages/php/test/common/php.test.ts index 2a78b5a1bd4..2376fb53c81 100644 --- a/src/vs/languages/php/test/common/php.test.ts +++ b/src/vs/languages/php/test/common/php.test.ts @@ -14,6 +14,7 @@ import EditorCommon = require('vs/editor/common/editorCommon'); import Modes = require('vs/editor/common/modes'); import modesUtil = require('vs/editor/test/common/modesUtil'); import {htmlTokenTypes} from 'vs/languages/html/common/html'; +import {cssTokenTypes} from 'vs/languages/css/common/css'; suite('Syntax Highlighting - PHP', () => { @@ -1767,9 +1768,9 @@ suite('Syntax Highlighting - PHP', () => { { startIndex:15, type: 'metatag.php' }, { startIndex:17, type: 'punctuation.bracket.css' }, { startIndex:18, type: '' }, - { startIndex:19, type: 'support.type.property-name.css' }, + { startIndex:19, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:24, type: 'punctuation.css' }, - { startIndex:25, type: 'meta.property-value.css' }, + { startIndex:25, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:29, type: 'punctuation.css' }, { startIndex:30, type: '' }, { startIndex:31, type: 'punctuation.bracket.css' }, @@ -1787,9 +1788,9 @@ suite('Syntax Highlighting - PHP', () => { { startIndex:15, type: 'metatag.php' }, { startIndex:17, type: 'punctuation.bracket.css' }, { startIndex:18, type: '' }, - { startIndex:19, type: 'support.type.property-name.css' }, + { startIndex:19, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:24, type: 'punctuation.css' }, - { startIndex:25, type: 'meta.property-value.css' }, + { startIndex:25, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:29, type: 'punctuation.css' }, { startIndex:30, type: '' }, { startIndex:31, type: 'punctuation.bracket.css' }, @@ -1814,9 +1815,9 @@ suite('Syntax Highlighting - PHP', () => { { startIndex:23, type: '' }, { startIndex:24, type: 'punctuation.bracket.css' }, { startIndex:25, type: '' }, - { startIndex:26, type: 'support.type.property-name.css' }, + { startIndex:26, type: cssTokenTypes.TOKEN_PROPERTY + '.css' }, { startIndex:31, type: 'punctuation.css' }, - { startIndex:32, type: 'meta.property-value.css' }, + { startIndex:32, type: cssTokenTypes.TOKEN_VALUE + '.css' }, { startIndex:36, type: 'punctuation.css' }, { startIndex:37, type: '' }, { startIndex:38, type: 'punctuation.bracket.css' }, diff --git a/src/vs/languages/sass/common/sass.ts b/src/vs/languages/sass/common/sass.ts index 1a23c29aca4..0a7537b481c 100644 --- a/src/vs/languages/sass/common/sass.ts +++ b/src/vs/languages/sass/common/sass.ts @@ -13,6 +13,7 @@ import EditorCommon = require('vs/editor/common/editorCommon'); import Modes = require('vs/editor/common/modes'); import sassWorker = require('vs/languages/sass/common/sassWorker'); import supports = require('vs/editor/common/modes/supports'); +import {cssTokenTypes} from 'vs/languages/css/common/css'; import {AbstractMode} from 'vs/editor/common/modes/abstractMode'; import {OneWorkerAttr} from 'vs/platform/thread/common/threadService'; import {AsyncDescriptor2, createAsyncDescriptor2} from 'vs/platform/instantiation/common/descriptors'; @@ -47,9 +48,9 @@ export var language = { tokenizer: { root: [ { include: '@selector' }, - ['[@](charset|namespace)', { token: 'keyword.control.at-rule', next: '@declarationbody'}], - ['[@](function)', { token: 'keyword.control.at-rule', next: '@functiondeclaration'}], - ['[@](mixin)', { token: 'keyword.control.at-rule', next: '@mixindeclaration'}], + ['[@](charset|namespace)', { token: cssTokenTypes.TOKEN_AT_KEYWORD, next: '@declarationbody'}], + ['[@](function)', { token: cssTokenTypes.TOKEN_AT_KEYWORD, next: '@functiondeclaration'}], + ['[@](mixin)', { token: cssTokenTypes.TOKEN_AT_KEYWORD, next: '@mixindeclaration'}], ], selector: [ @@ -57,29 +58,29 @@ export var language = { { include: '@import' }, { include: '@variabledeclaration' }, { include: '@warndebug' }, // sass: log statements - ['[@](include)', { token: 'keyword.control.at-rule', next: '@includedeclaration'}], // sass: include statement - ['[@](keyframes|-webkit-keyframes|-moz-keyframes|-o-keyframes)', { token: 'keyword.control.at-rule', next: '@keyframedeclaration'}], - ['[@](page|content|font-face|-moz-document)', { token: 'keyword.control.at-rule'}], // sass: placeholder for includes + ['[@](include)', { token: cssTokenTypes.TOKEN_AT_KEYWORD, next: '@includedeclaration'}], // sass: include statement + ['[@](keyframes|-webkit-keyframes|-moz-keyframes|-o-keyframes)', { token: cssTokenTypes.TOKEN_AT_KEYWORD, next: '@keyframedeclaration'}], + ['[@](page|content|font-face|-moz-document)', { token: cssTokenTypes.TOKEN_AT_KEYWORD}], // sass: placeholder for includes ['url(\\-prefix)?\\(', { token: 'support.function.name', bracket: '@open', next: '@urldeclaration'}], { include: '@controlstatement' }, // sass control statements { include: '@selectorname' }, - ['[&\\*]', 'entity.name.tag'], // selector symbols + ['[&\\*]', cssTokenTypes.TOKEN_SELECTOR_TAG], // selector symbols ['[>\\+,]', 'punctuation'], // selector operators ['\\[', { token: 'punctuation.bracket', bracket: '@open', next: '@selectorattribute' }], ['{', { token: 'punctuation.curly', bracket: '@open', next: '@selectorbody' }], ], selectorbody: [ - ['[*_]?@identifier@ws:(?=(\\s|\\d|[^{;}]*[;}]))', 'support.type.property-name', '@rulevalue'], // rule definition: to distinguish from a nested selector check for whitespace, number or a semicolon + ['[*_]?@identifier@ws:(?=(\\s|\\d|[^{;}]*[;}]))', cssTokenTypes.TOKEN_PROPERTY, '@rulevalue'], // rule definition: to distinguish from a nested selector check for whitespace, number or a semicolon { include: '@selector'}, // sass: nested selectors - ['[@](extend)', { token: 'keyword.control.at-rule', next: '@extendbody'}], // sass: extend other selectors - ['[@](return)', { token: 'keyword.control.at-rule', next: '@declarationbody'}], + ['[@](extend)', { token: cssTokenTypes.TOKEN_AT_KEYWORD, next: '@extendbody'}], // sass: extend other selectors + ['[@](return)', { token: cssTokenTypes.TOKEN_AT_KEYWORD, next: '@declarationbody'}], ['}', { token: 'punctuation.curly', bracket: '@close', next: '@pop'}], ], selectorname: [ ['#{', { token: 'support.function.interpolation', bracket: '@open', next: '@variableinterpolation' }], // sass: interpolation - ['(\\.|#(?=[^{])|%|(@identifier)|:)+', 'entity.other.attribute-name'], // selector (.foo, div, ...) + ['(\\.|#(?=[^{])|%|(@identifier)|:)+', cssTokenTypes.TOKEN_SELECTOR], // selector (.foo, div, ...) ], selectorattribute: [ @@ -111,17 +112,17 @@ export var language = { ], nestedproperty: [ - ['[*_]?@identifier@ws:', 'support.type.property-name', '@rulevalue'], + ['[*_]?@identifier@ws:', cssTokenTypes.TOKEN_PROPERTY, '@rulevalue'], { include: '@comments' }, ['}', { token: 'punctuation.curly', bracket: '@close', next: '@pop'}], ], warndebug: [ - ['[@](warn|debug)', { token: 'keyword.control.at-rule', next: '@declarationbody'}], + ['[@](warn|debug)', { token: cssTokenTypes.TOKEN_AT_KEYWORD, next: '@declarationbody'}], ], import: [ - ['[@](import)', { token: 'keyword.control.at-rule', next: '@declarationbody'}], + ['[@](import)', { token: cssTokenTypes.TOKEN_AT_KEYWORD, next: '@declarationbody'}], ], variabledeclaration: [ // sass variables @@ -174,7 +175,7 @@ export var language = { ], name: [ - ['@identifier', 'meta.property-value'], + ['@identifier', cssTokenTypes.TOKEN_VALUE], ], numbers: [ @@ -200,7 +201,7 @@ export var language = { ], parameterdeclaration: [ - ['\\$@identifier@ws:', 'support.type.property-name'], + ['\\$@identifier@ws:', cssTokenTypes.TOKEN_PROPERTY], ['\\.\\.\\.', 'keyword.operator'], // var args in declaration [',', 'punctuation'], { include: '@term' }, @@ -237,7 +238,7 @@ export var language = { ], functionbody: [ - ['[@](return)', { token: 'keyword.control.at-rule'}], + ['[@](return)', { token: cssTokenTypes.TOKEN_AT_KEYWORD}], { include: '@variabledeclaration' }, { include: '@term' }, { include: '@controlstatement' }, @@ -250,7 +251,7 @@ export var language = { ], functionarguments: [ - ['\\$@identifier@ws:', 'support.type.property-name'], + ['\\$@identifier@ws:', cssTokenTypes.TOKEN_PROPERTY], ['[,]', 'punctuation'], { include: '@term' }, ['\\)', { token: 'support.function.name', bracket: '@close', next: '@pop'}], @@ -299,11 +300,11 @@ export class SASSMode extends Monarch.MonarchMode impleme this.extraInfoSupport = this; this.referenceSupport = new supports.ReferenceSupport(this, { - tokens: ['support.type.property-name.sass', 'meta.property-value.sass', 'variable.decl.sass', 'variable.ref.sass', 'support.function.name.sass', 'support.type.property-name.sass', 'entity.other.attribute-name.sass'], + tokens: [cssTokenTypes.TOKEN_PROPERTY + '.sass', cssTokenTypes.TOKEN_VALUE + '.sass', 'variable.decl.sass', 'variable.ref.sass', 'support.function.name.sass', cssTokenTypes.TOKEN_PROPERTY + '.sass', cssTokenTypes.TOKEN_SELECTOR + '.sass'], findReferences: (resource, position, /*unused*/includeDeclaration) => this.findReferences(resource, position)}); this.logicalSelectionSupport = this; this.declarationSupport = new supports.DeclarationSupport(this, { - tokens: ['variable.decl.sass', 'variable.ref.sass', 'support.function.name.sass', 'support.type.property-name.sass', 'entity.other.attribute-name.sass'], + tokens: ['variable.decl.sass', 'variable.ref.sass', 'support.function.name.sass', cssTokenTypes.TOKEN_PROPERTY + '.sass', cssTokenTypes.TOKEN_SELECTOR + '.sass'], findDeclaration: (resource, position) => this.findDeclaration(resource, position)}); this.outlineSupport = this; diff --git a/src/vs/languages/sass/test/common/sass.test.ts b/src/vs/languages/sass/test/common/sass.test.ts index da9645d70c4..f0daeda289d 100644 --- a/src/vs/languages/sass/test/common/sass.test.ts +++ b/src/vs/languages/sass/test/common/sass.test.ts @@ -8,6 +8,7 @@ import 'vs/languages/sass/common/sass.contribution'; import SASS = require('vs/languages/sass/common/sass'); import modesUtil = require('vs/editor/test/common/modesUtil'); import Modes = require('vs/editor/common/modes'); +import {cssTokenTypes} from 'vs/languages/css/common/css'; suite('Sass Colorizer', () => { @@ -28,45 +29,45 @@ suite('Sass Colorizer', () => { [{ line: '#main {\n width: 97%;\n p, div {\n font-size: 2em;\n a { font-weight: bold; }\n }\n pre { font-size: 3em; }\n}', tokens: [ - { startIndex: 0, type: 'entity.other.attribute-name.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 5, type: '' }, { startIndex: 6, type: 'punctuation.curly.sass' }, { startIndex: 7, type: '' }, - { startIndex: 10, type: 'support.type.property-name.sass' }, + { startIndex: 10, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 16, type: '' }, { startIndex: 17, type: 'constant.numeric.sass' }, { startIndex: 20, type: 'punctuation.sass' }, { startIndex: 21, type: '' }, - { startIndex: 24, type: 'entity.other.attribute-name.sass' }, + { startIndex: 24, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 25, type: 'punctuation.sass' }, { startIndex: 26, type: '' }, - { startIndex: 27, type: 'entity.other.attribute-name.sass' }, + { startIndex: 27, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 30, type: '' }, { startIndex: 31, type: 'punctuation.curly.sass' }, { startIndex: 32, type: '' }, - { startIndex: 37, type: 'support.type.property-name.sass' }, + { startIndex: 37, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 47, type: '' }, { startIndex: 48, type: 'constant.numeric.sass' }, { startIndex: 51, type: 'punctuation.sass' }, { startIndex: 52, type: '' }, - { startIndex: 57, type: 'entity.other.attribute-name.sass' }, + { startIndex: 57, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 58, type: '' }, { startIndex: 59, type: 'punctuation.curly.sass' }, { startIndex: 60, type: '' }, - { startIndex: 61, type: 'support.type.property-name.sass' }, + { startIndex: 61, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 73, type: '' }, - { startIndex: 74, type: 'meta.property-value.sass' }, + { startIndex: 74, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 78, type: 'punctuation.sass' }, { startIndex: 79, type: '' }, { startIndex: 80, type: 'punctuation.curly.sass' }, { startIndex: 81, type: '' }, { startIndex: 84, type: 'punctuation.curly.sass' }, { startIndex: 85, type: '' }, - { startIndex: 88, type: 'entity.other.attribute-name.sass' }, + { startIndex: 88, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 91, type: '' }, { startIndex: 92, type: 'punctuation.curly.sass' }, { startIndex: 93, type: '' }, - { startIndex: 94, type: 'support.type.property-name.sass' }, + { startIndex: 94, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 104, type: '' }, { startIndex: 105, type: 'constant.numeric.sass' }, { startIndex: 108, type: 'punctuation.sass' }, @@ -80,32 +81,32 @@ suite('Sass Colorizer', () => { [{ line: '#main {\n color: black;\n a {\n font-weight: bold;\n &:hover { color: red; }\n }\n}', tokens: [ - { startIndex: 0, type: 'entity.other.attribute-name.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 5, type: '' }, { startIndex: 6, type: 'punctuation.curly.sass' }, { startIndex: 7, type: '' }, - { startIndex: 10, type: 'support.type.property-name.sass' }, + { startIndex: 10, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 16, type: '' }, - { startIndex: 17, type: 'meta.property-value.sass' }, + { startIndex: 17, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 22, type: 'punctuation.sass' }, { startIndex: 23, type: '' }, - { startIndex: 26, type: 'entity.other.attribute-name.sass' }, + { startIndex: 26, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 27, type: '' }, { startIndex: 28, type: 'punctuation.curly.sass' }, { startIndex: 29, type: '' }, - { startIndex: 34, type: 'support.type.property-name.sass' }, + { startIndex: 34, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 46, type: '' }, - { startIndex: 47, type: 'meta.property-value.sass' }, + { startIndex: 47, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 51, type: 'punctuation.sass' }, { startIndex: 52, type: '' }, - { startIndex: 57, type: 'entity.name.tag.sass' }, - { startIndex: 58, type: 'entity.other.attribute-name.sass' }, + { startIndex: 57, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.sass' }, + { startIndex: 58, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 64, type: '' }, { startIndex: 65, type: 'punctuation.curly.sass' }, { startIndex: 66, type: '' }, - { startIndex: 67, type: 'support.type.property-name.sass' }, + { startIndex: 67, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 73, type: '' }, - { startIndex: 74, type: 'meta.property-value.sass' }, + { startIndex: 74, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 77, type: 'punctuation.sass' }, { startIndex: 78, type: '' }, { startIndex: 79, type: 'punctuation.curly.sass' }, @@ -119,11 +120,11 @@ suite('Sass Colorizer', () => { [{ line: '.funky {\n font: 2px/3px {\n family: fantasy;\n size: 30em;\n weight: bold;\n }\n color: black;\n}', tokens: [ - { startIndex: 0, type: 'entity.other.attribute-name.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 6, type: '' }, { startIndex: 7, type: 'punctuation.curly.sass' }, { startIndex: 8, type: '' }, - { startIndex: 11, type: 'support.type.property-name.sass' }, + { startIndex: 11, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 16, type: '' }, { startIndex: 17, type: 'constant.numeric.sass' }, { startIndex: 20, type: 'keyword.operator.sass' }, @@ -131,26 +132,26 @@ suite('Sass Colorizer', () => { { startIndex: 24, type: '' }, { startIndex: 25, type: 'punctuation.curly.sass' }, { startIndex: 26, type: '' }, - { startIndex: 31, type: 'support.type.property-name.sass' }, + { startIndex: 31, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 38, type: '' }, - { startIndex: 39, type: 'meta.property-value.sass' }, + { startIndex: 39, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 46, type: 'punctuation.sass' }, { startIndex: 47, type: '' }, - { startIndex: 52, type: 'support.type.property-name.sass' }, + { startIndex: 52, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 57, type: '' }, { startIndex: 58, type: 'constant.numeric.sass' }, { startIndex: 62, type: 'punctuation.sass' }, { startIndex: 63, type: '' }, - { startIndex: 68, type: 'support.type.property-name.sass' }, + { startIndex: 68, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 75, type: '' }, - { startIndex: 76, type: 'meta.property-value.sass' }, + { startIndex: 76, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 80, type: 'punctuation.sass' }, { startIndex: 81, type: '' }, { startIndex: 84, type: 'punctuation.curly.sass' }, { startIndex: 85, type: '' }, - { startIndex: 88, type: 'support.type.property-name.sass' }, + { startIndex: 88, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 94, type: '' }, - { startIndex: 95, type: 'meta.property-value.sass' }, + { startIndex: 95, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 100, type: 'punctuation.sass' }, { startIndex: 101, type: '' }, { startIndex: 102, type: 'punctuation.curly.sass' } @@ -160,57 +161,57 @@ suite('Sass Colorizer', () => { [{ line: 'tr.default {\n foo: { // properties\n foo : 1;\n }\n foo: 1px; // rule\n foo.bar { // selector\n foo : 1;\n }\n foo:bar { // selector\n foo : 1;\n }\n foo: 1px; // rule\n}', tokens: [ - { startIndex: 0, type: 'entity.other.attribute-name.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 10, type: '' }, { startIndex: 11, type: 'punctuation.curly.sass' }, { startIndex: 12, type: '' }, - { startIndex: 15, type: 'support.type.property-name.sass' }, + { startIndex: 15, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 19, type: '' }, { startIndex: 20, type: 'punctuation.curly.sass' }, { startIndex: 21, type: '' }, { startIndex: 22, type: 'comment.sass' }, { startIndex: 35, type: '' }, - { startIndex: 40, type: 'support.type.property-name.sass' }, + { startIndex: 40, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 45, type: '' }, { startIndex: 46, type: 'constant.numeric.sass' }, { startIndex: 47, type: 'punctuation.sass' }, { startIndex: 48, type: '' }, { startIndex: 51, type: 'punctuation.curly.sass' }, { startIndex: 52, type: '' }, - { startIndex: 55, type: 'support.type.property-name.sass' }, + { startIndex: 55, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 59, type: '' }, { startIndex: 60, type: 'constant.numeric.sass' }, { startIndex: 63, type: 'punctuation.sass' }, { startIndex: 64, type: '' }, { startIndex: 65, type: 'comment.sass' }, { startIndex: 72, type: '' }, - { startIndex: 75, type: 'entity.other.attribute-name.sass' }, + { startIndex: 75, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 82, type: '' }, { startIndex: 83, type: 'punctuation.curly.sass' }, { startIndex: 84, type: '' }, { startIndex: 85, type: 'comment.sass' }, { startIndex: 96, type: '' }, - { startIndex: 101, type: 'support.type.property-name.sass' }, + { startIndex: 101, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 106, type: '' }, { startIndex: 107, type: 'constant.numeric.sass' }, { startIndex: 108, type: 'punctuation.sass' }, { startIndex: 109, type: '' }, { startIndex: 112, type: 'punctuation.curly.sass' }, { startIndex: 113, type: '' }, - { startIndex: 116, type: 'entity.other.attribute-name.sass' }, + { startIndex: 116, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 123, type: '' }, { startIndex: 124, type: 'punctuation.curly.sass' }, { startIndex: 125, type: '' }, { startIndex: 126, type: 'comment.sass' }, { startIndex: 137, type: '' }, - { startIndex: 142, type: 'support.type.property-name.sass' }, + { startIndex: 142, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 147, type: '' }, { startIndex: 148, type: 'constant.numeric.sass' }, { startIndex: 149, type: 'punctuation.sass' }, { startIndex: 150, type: '' }, { startIndex: 153, type: 'punctuation.curly.sass' }, { startIndex: 154, type: '' }, - { startIndex: 157, type: 'support.type.property-name.sass' }, + { startIndex: 157, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 161, type: '' }, { startIndex: 162, type: 'constant.numeric.sass' }, { startIndex: 165, type: 'punctuation.sass' }, @@ -224,11 +225,11 @@ suite('Sass Colorizer', () => { [{ line: 'tr.default {\n foo.bar {\n $foo: 1px\n }\n foo: {\n foo : white\n }\n foo.bar1 {\n @extend tr.default\n }\n foo.bar2 {\n @import "compass"\n }\n bar: black\n}', tokens: [ - { startIndex: 0, type: 'entity.other.attribute-name.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 10, type: '' }, { startIndex: 11, type: 'punctuation.curly.sass' }, { startIndex: 12, type: '' }, - { startIndex: 15, type: 'entity.other.attribute-name.sass' }, + { startIndex: 15, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 22, type: '' }, { startIndex: 23, type: 'punctuation.curly.sass' }, { startIndex: 24, type: '' }, @@ -238,31 +239,31 @@ suite('Sass Colorizer', () => { { startIndex: 38, type: '' }, { startIndex: 41, type: 'punctuation.curly.sass' }, { startIndex: 42, type: '' }, - { startIndex: 45, type: 'support.type.property-name.sass' }, + { startIndex: 45, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 49, type: '' }, { startIndex: 50, type: 'punctuation.curly.sass' }, { startIndex: 51, type: '' }, - { startIndex: 56, type: 'support.type.property-name.sass' }, + { startIndex: 56, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 61, type: '' }, - { startIndex: 62, type: 'meta.property-value.sass' }, + { startIndex: 62, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 67, type: '' }, { startIndex: 70, type: 'punctuation.curly.sass' }, { startIndex: 71, type: '' }, - { startIndex: 74, type: 'entity.other.attribute-name.sass' }, + { startIndex: 74, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 82, type: '' }, { startIndex: 83, type: 'punctuation.curly.sass' }, { startIndex: 84, type: '' }, - { startIndex: 89, type: 'keyword.control.at-rule.sass' }, + { startIndex: 89, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 96, type: '' }, - { startIndex: 97, type: 'entity.other.attribute-name.sass' }, + { startIndex: 97, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 107, type: '' }, { startIndex: 110, type: 'punctuation.curly.sass' }, { startIndex: 111, type: '' }, - { startIndex: 114, type: 'entity.other.attribute-name.sass' }, + { startIndex: 114, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 122, type: '' }, { startIndex: 123, type: 'punctuation.curly.sass' }, { startIndex: 124, type: '' }, - { startIndex: 129, type: 'keyword.control.at-rule.sass' }, + { startIndex: 129, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 136, type: '' }, { startIndex: 137, type: 'string.punctuation.sass' }, { startIndex: 138, type: 'string.sass' }, @@ -270,9 +271,9 @@ suite('Sass Colorizer', () => { { startIndex: 146, type: '' }, { startIndex: 149, type: 'punctuation.curly.sass' }, { startIndex: 150, type: '' }, - { startIndex: 153, type: 'support.type.property-name.sass' }, + { startIndex: 153, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 157, type: '' }, - { startIndex: 158, type: 'meta.property-value.sass' }, + { startIndex: 158, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 163, type: '' }, { startIndex: 164, type: 'punctuation.curly.sass' } ]}], @@ -281,21 +282,21 @@ suite('Sass Colorizer', () => { [{ line: 'legend {foo{a:s}margin-top:0;margin-bottom:#123;margin-top:s(1)}', tokens: [ - { startIndex: 0, type: 'entity.other.attribute-name.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 6, type: '' }, { startIndex: 7, type: 'punctuation.curly.sass' }, - { startIndex: 8, type: 'entity.other.attribute-name.sass' }, + { startIndex: 8, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 11, type: 'punctuation.curly.sass' }, - { startIndex: 12, type: 'support.type.property-name.sass' }, - { startIndex: 14, type: 'meta.property-value.sass' }, + { startIndex: 12, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, + { startIndex: 14, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 15, type: 'punctuation.curly.sass' }, - { startIndex: 16, type: 'support.type.property-name.sass' }, + { startIndex: 16, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 27, type: 'constant.numeric.sass' }, { startIndex: 28, type: 'punctuation.sass' }, - { startIndex: 29, type: 'support.type.property-name.sass' }, + { startIndex: 29, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 43, type: 'constant.rgb-value.sass' }, { startIndex: 47, type: 'punctuation.sass' }, - { startIndex: 48, type: 'support.type.property-name.sass' }, + { startIndex: 48, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 59, type: 'support.function.name.sass' }, { startIndex: 61, type: 'constant.numeric.sass' }, { startIndex: 62, type: 'support.function.name.sass' }, @@ -316,13 +317,13 @@ suite('Sass Colorizer', () => { { startIndex: 112, type: '' }, { startIndex: 113, type: 'comment.sass' }, { startIndex: 152, type: '' }, - { startIndex: 153, type: 'entity.other.attribute-name.sass' }, + { startIndex: 153, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 157, type: '' }, { startIndex: 158, type: 'punctuation.curly.sass' }, { startIndex: 159, type: '' }, - { startIndex: 160, type: 'support.type.property-name.sass' }, + { startIndex: 160, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 166, type: '' }, - { startIndex: 167, type: 'meta.property-value.sass' }, + { startIndex: 167, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 172, type: 'punctuation.sass' }, { startIndex: 173, type: '' }, { startIndex: 174, type: 'punctuation.curly.sass' }, @@ -333,13 +334,13 @@ suite('Sass Colorizer', () => { { startIndex: 263, type: '' }, { startIndex: 264, type: 'comment.sass' }, { startIndex: 313, type: '' }, - { startIndex: 314, type: 'entity.other.attribute-name.sass' }, + { startIndex: 314, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 315, type: '' }, { startIndex: 316, type: 'punctuation.curly.sass' }, { startIndex: 317, type: '' }, - { startIndex: 318, type: 'support.type.property-name.sass' }, + { startIndex: 318, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 324, type: '' }, - { startIndex: 325, type: 'meta.property-value.sass' }, + { startIndex: 325, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 330, type: 'punctuation.sass' }, { startIndex: 331, type: '' }, { startIndex: 332, type: 'punctuation.curly.sass' } @@ -363,7 +364,7 @@ suite('Sass Colorizer', () => { { startIndex: 37, type: 'literal.sass' }, { startIndex: 45, type: 'punctuation.sass' }, { startIndex: 46, type: '' }, - { startIndex: 47, type: 'entity.other.attribute-name.sass' }, + { startIndex: 47, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 52, type: '' }, { startIndex: 53, type: 'punctuation.curly.sass' }, { startIndex: 54, type: '' }, @@ -372,7 +373,7 @@ suite('Sass Colorizer', () => { { startIndex: 68, type: 'constant.numeric.sass' }, { startIndex: 71, type: 'punctuation.sass' }, { startIndex: 72, type: '' }, - { startIndex: 75, type: 'support.type.property-name.sass' }, + { startIndex: 75, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 81, type: '' }, { startIndex: 82, type: 'variable.ref.sass' }, { startIndex: 88, type: 'punctuation.sass' }, @@ -387,7 +388,7 @@ suite('Sass Colorizer', () => { { startIndex: 127, type: 'constant.numeric.sass' }, { startIndex: 131, type: 'punctuation.sass' }, { startIndex: 132, type: '' }, - { startIndex: 135, type: 'support.type.property-name.sass' }, + { startIndex: 135, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 140, type: '' }, { startIndex: 141, type: 'support.function.interpolation.sass' }, { startIndex: 143, type: 'variable.ref.sass' }, @@ -402,15 +403,15 @@ suite('Sass Colorizer', () => { { startIndex: 173, type: '' }, { startIndex: 174, type: 'variable.decl.sass' }, { startIndex: 180, type: '' }, - { startIndex: 181, type: 'meta.property-value.sass' }, + { startIndex: 181, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 184, type: 'punctuation.sass' }, { startIndex: 185, type: '' }, { startIndex: 186, type: 'variable.decl.sass' }, { startIndex: 192, type: '' }, - { startIndex: 193, type: 'meta.property-value.sass' }, + { startIndex: 193, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 199, type: 'punctuation.sass' }, { startIndex: 200, type: '' }, - { startIndex: 201, type: 'entity.other.attribute-name.sass' }, + { startIndex: 201, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 203, type: 'support.function.interpolation.sass' }, { startIndex: 205, type: 'variable.ref.sass' }, { startIndex: 210, type: 'support.function.interpolation.sass' }, @@ -420,9 +421,9 @@ suite('Sass Colorizer', () => { { startIndex: 216, type: 'support.function.interpolation.sass' }, { startIndex: 218, type: 'variable.ref.sass' }, { startIndex: 223, type: 'support.function.interpolation.sass' }, - { startIndex: 224, type: 'support.type.property-name.sass' }, + { startIndex: 224, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 231, type: '' }, - { startIndex: 232, type: 'meta.property-value.sass' }, + { startIndex: 232, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 236, type: 'punctuation.sass' }, { startIndex: 237, type: '' }, { startIndex: 238, type: 'punctuation.curly.sass' } @@ -457,11 +458,11 @@ suite('Sass Colorizer', () => { [{ line: 'p {\n width: (1em + 2em) * 3;\n color: #010203 + #040506;\n font-family: sans- + "serif";\n margin: 3px + 4px auto;\n content: "I ate #{5 + 10} pies!";\n color: hsl(0, 100%, 50%);\n color: hsl($hue: 0, $saturation: 100%, $lightness: 50%);\n}', tokens: [ - { startIndex: 0, type: 'entity.other.attribute-name.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 1, type: '' }, { startIndex: 2, type: 'punctuation.curly.sass' }, { startIndex: 3, type: '' }, - { startIndex: 6, type: 'support.type.property-name.sass' }, + { startIndex: 6, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 12, type: '' }, { startIndex: 13, type: 'punctuation.parenthesis.sass' }, { startIndex: 14, type: 'constant.numeric.sass' }, @@ -476,7 +477,7 @@ suite('Sass Colorizer', () => { { startIndex: 27, type: 'constant.numeric.sass' }, { startIndex: 28, type: 'punctuation.sass' }, { startIndex: 29, type: '' }, - { startIndex: 32, type: 'support.type.property-name.sass' }, + { startIndex: 32, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 38, type: '' }, { startIndex: 39, type: 'constant.rgb-value.sass' }, { startIndex: 46, type: '' }, @@ -485,9 +486,9 @@ suite('Sass Colorizer', () => { { startIndex: 49, type: 'constant.rgb-value.sass' }, { startIndex: 56, type: 'punctuation.sass' }, { startIndex: 57, type: '' }, - { startIndex: 60, type: 'support.type.property-name.sass' }, + { startIndex: 60, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 72, type: '' }, - { startIndex: 73, type: 'meta.property-value.sass' }, + { startIndex: 73, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 78, type: '' }, { startIndex: 79, type: 'keyword.operator.sass' }, { startIndex: 80, type: '' }, @@ -496,7 +497,7 @@ suite('Sass Colorizer', () => { { startIndex: 87, type: 'string.punctuation.sass' }, { startIndex: 88, type: 'punctuation.sass' }, { startIndex: 89, type: '' }, - { startIndex: 92, type: 'support.type.property-name.sass' }, + { startIndex: 92, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 99, type: '' }, { startIndex: 100, type: 'constant.numeric.sass' }, { startIndex: 103, type: '' }, @@ -504,17 +505,17 @@ suite('Sass Colorizer', () => { { startIndex: 105, type: '' }, { startIndex: 106, type: 'constant.numeric.sass' }, { startIndex: 109, type: '' }, - { startIndex: 110, type: 'meta.property-value.sass' }, + { startIndex: 110, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 114, type: 'punctuation.sass' }, { startIndex: 115, type: '' }, - { startIndex: 118, type: 'support.type.property-name.sass' }, + { startIndex: 118, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 126, type: '' }, { startIndex: 127, type: 'string.punctuation.sass' }, { startIndex: 128, type: 'string.sass' }, { startIndex: 149, type: 'string.punctuation.sass' }, { startIndex: 150, type: 'punctuation.sass' }, { startIndex: 151, type: '' }, - { startIndex: 154, type: 'support.type.property-name.sass' }, + { startIndex: 154, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 160, type: '' }, { startIndex: 161, type: 'support.function.name.sass' }, { startIndex: 165, type: 'constant.numeric.sass' }, @@ -527,20 +528,20 @@ suite('Sass Colorizer', () => { { startIndex: 177, type: 'support.function.name.sass' }, { startIndex: 178, type: 'punctuation.sass' }, { startIndex: 179, type: '' }, - { startIndex: 182, type: 'support.type.property-name.sass' }, + { startIndex: 182, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 188, type: '' }, { startIndex: 189, type: 'support.function.name.sass' }, - { startIndex: 193, type: 'support.type.property-name.sass' }, + { startIndex: 193, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 198, type: '' }, { startIndex: 199, type: 'constant.numeric.sass' }, { startIndex: 200, type: 'punctuation.sass' }, { startIndex: 201, type: '' }, - { startIndex: 202, type: 'support.type.property-name.sass' }, + { startIndex: 202, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 214, type: '' }, { startIndex: 215, type: 'constant.numeric.sass' }, { startIndex: 219, type: 'punctuation.sass' }, { startIndex: 220, type: '' }, - { startIndex: 221, type: 'support.type.property-name.sass' }, + { startIndex: 221, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 232, type: '' }, { startIndex: 233, type: 'constant.numeric.sass' }, { startIndex: 236, type: 'support.function.name.sass' }, @@ -563,7 +564,7 @@ suite('Sass Colorizer', () => { { startIndex: 34, type: 'constant.numeric.sass' }, { startIndex: 38, type: 'punctuation.sass' }, { startIndex: 39, type: '' }, - { startIndex: 40, type: 'keyword.control.at-rule.sass' }, + { startIndex: 40, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 49, type: '' }, { startIndex: 50, type: 'support.function.name.sass' }, { startIndex: 61, type: 'variable.ref.sass' }, @@ -571,7 +572,7 @@ suite('Sass Colorizer', () => { { startIndex: 64, type: '' }, { startIndex: 65, type: 'punctuation.curly.sass' }, { startIndex: 66, type: '' }, - { startIndex: 69, type: 'keyword.control.at-rule.sass' }, + { startIndex: 69, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 76, type: '' }, { startIndex: 77, type: 'variable.ref.sass' }, { startIndex: 79, type: '' }, @@ -596,11 +597,11 @@ suite('Sass Colorizer', () => { { startIndex: 121, type: '' }, { startIndex: 122, type: 'punctuation.curly.sass' }, { startIndex: 123, type: '' }, - { startIndex: 124, type: 'entity.other.attribute-name.sass' }, + { startIndex: 124, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 132, type: '' }, { startIndex: 133, type: 'punctuation.curly.sass' }, { startIndex: 134, type: '' }, - { startIndex: 135, type: 'support.type.property-name.sass' }, + { startIndex: 135, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 141, type: '' }, { startIndex: 142, type: 'support.function.name.sass' }, { startIndex: 153, type: 'constant.numeric.sass' }, @@ -614,7 +615,7 @@ suite('Sass Colorizer', () => { [{ line: '@import "foo.scss";\n$family: unquote("Droid+Sans");\n@import "rounded-corners" url("http://fonts.googleapis.com/css?family=#{$family}");\n#main {\n @import "example";\n}', tokens: [ - { startIndex: 0, type: 'keyword.control.at-rule.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 7, type: '' }, { startIndex: 8, type: 'string.punctuation.sass' }, { startIndex: 9, type: 'string.sass' }, @@ -630,7 +631,7 @@ suite('Sass Colorizer', () => { { startIndex: 49, type: 'support.function.name.sass' }, { startIndex: 50, type: 'punctuation.sass' }, { startIndex: 51, type: '' }, - { startIndex: 52, type: 'keyword.control.at-rule.sass' }, + { startIndex: 52, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 59, type: '' }, { startIndex: 60, type: 'string.punctuation.sass' }, { startIndex: 61, type: 'string.sass' }, @@ -643,11 +644,11 @@ suite('Sass Colorizer', () => { { startIndex: 133, type: 'support.function.name.sass' }, { startIndex: 134, type: 'punctuation.sass' }, { startIndex: 135, type: '' }, - { startIndex: 136, type: 'entity.other.attribute-name.sass' }, + { startIndex: 136, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 141, type: '' }, { startIndex: 142, type: 'punctuation.curly.sass' }, { startIndex: 143, type: '' }, - { startIndex: 146, type: 'keyword.control.at-rule.sass' }, + { startIndex: 146, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 153, type: '' }, { startIndex: 154, type: 'string.punctuation.sass' }, { startIndex: 155, type: 'string.sass' }, @@ -661,30 +662,30 @@ suite('Sass Colorizer', () => { [{ line: '.sidebar {\n width: 300px;\n @media screen and (orientation: landscape) {\n width: 500px;\n }\n}', tokens: [ - { startIndex: 0, type: 'entity.other.attribute-name.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 8, type: '' }, { startIndex: 9, type: 'punctuation.curly.sass' }, { startIndex: 10, type: '' }, - { startIndex: 13, type: 'support.type.property-name.sass' }, + { startIndex: 13, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 19, type: '' }, { startIndex: 20, type: 'constant.numeric.sass' }, { startIndex: 25, type: 'punctuation.sass' }, { startIndex: 26, type: '' }, { startIndex: 29, type: 'keyword.flow.control.at-rule.sass' }, { startIndex: 35, type: '' }, - { startIndex: 36, type: 'meta.property-value.sass' }, + { startIndex: 36, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 42, type: '' }, { startIndex: 43, type: 'keyword.operator.sass' }, { startIndex: 46, type: '' }, { startIndex: 47, type: 'punctuation.parenthesis.sass' }, - { startIndex: 48, type: 'meta.property-value.sass' }, + { startIndex: 48, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 59, type: '' }, - { startIndex: 61, type: 'meta.property-value.sass' }, + { startIndex: 61, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 70, type: 'punctuation.parenthesis.sass' }, { startIndex: 71, type: '' }, { startIndex: 72, type: 'punctuation.curly.sass' }, { startIndex: 73, type: '' }, - { startIndex: 78, type: 'support.type.property-name.sass' }, + { startIndex: 78, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 84, type: '' }, { startIndex: 85, type: 'constant.numeric.sass' }, { startIndex: 90, type: 'punctuation.sass' }, @@ -698,70 +699,70 @@ suite('Sass Colorizer', () => { [{ line: '.error {\n border: 1px #f00;\n background-color: #fdd;\n}\n.seriousError {\n @extend .error;\n border-width: 3px;\n}\n#context a%extreme {\n color: blue;\n font-weight: bold;\n font-size: 2em;\n}\n.notice {\n @extend %extreme !optional;\n}', tokens: [ - { startIndex: 0, type: 'entity.other.attribute-name.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 6, type: '' }, { startIndex: 7, type: 'punctuation.curly.sass' }, { startIndex: 8, type: '' }, - { startIndex: 11, type: 'support.type.property-name.sass' }, + { startIndex: 11, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 18, type: '' }, { startIndex: 19, type: 'constant.numeric.sass' }, { startIndex: 22, type: '' }, { startIndex: 23, type: 'constant.rgb-value.sass' }, { startIndex: 27, type: 'punctuation.sass' }, { startIndex: 28, type: '' }, - { startIndex: 31, type: 'support.type.property-name.sass' }, + { startIndex: 31, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 48, type: '' }, { startIndex: 49, type: 'constant.rgb-value.sass' }, { startIndex: 53, type: 'punctuation.sass' }, { startIndex: 54, type: '' }, { startIndex: 55, type: 'punctuation.curly.sass' }, { startIndex: 56, type: '' }, - { startIndex: 57, type: 'entity.other.attribute-name.sass' }, + { startIndex: 57, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 70, type: '' }, { startIndex: 71, type: 'punctuation.curly.sass' }, { startIndex: 72, type: '' }, - { startIndex: 75, type: 'keyword.control.at-rule.sass' }, + { startIndex: 75, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 82, type: '' }, - { startIndex: 83, type: 'entity.other.attribute-name.sass' }, + { startIndex: 83, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 89, type: 'punctuation.sass' }, { startIndex: 90, type: '' }, - { startIndex: 93, type: 'support.type.property-name.sass' }, + { startIndex: 93, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 106, type: '' }, { startIndex: 107, type: 'constant.numeric.sass' }, { startIndex: 110, type: 'punctuation.sass' }, { startIndex: 111, type: '' }, { startIndex: 112, type: 'punctuation.curly.sass' }, { startIndex: 113, type: '' }, - { startIndex: 114, type: 'entity.other.attribute-name.sass' }, + { startIndex: 114, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 122, type: '' }, - { startIndex: 123, type: 'entity.other.attribute-name.sass' }, + { startIndex: 123, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 132, type: '' }, { startIndex: 133, type: 'punctuation.curly.sass' }, { startIndex: 134, type: '' }, - { startIndex: 137, type: 'support.type.property-name.sass' }, + { startIndex: 137, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 143, type: '' }, - { startIndex: 144, type: 'meta.property-value.sass' }, + { startIndex: 144, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 148, type: 'punctuation.sass' }, { startIndex: 149, type: '' }, - { startIndex: 152, type: 'support.type.property-name.sass' }, + { startIndex: 152, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 164, type: '' }, - { startIndex: 165, type: 'meta.property-value.sass' }, + { startIndex: 165, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 169, type: 'punctuation.sass' }, { startIndex: 170, type: '' }, - { startIndex: 173, type: 'support.type.property-name.sass' }, + { startIndex: 173, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 183, type: '' }, { startIndex: 184, type: 'constant.numeric.sass' }, { startIndex: 187, type: 'punctuation.sass' }, { startIndex: 188, type: '' }, { startIndex: 189, type: 'punctuation.curly.sass' }, { startIndex: 190, type: '' }, - { startIndex: 191, type: 'entity.other.attribute-name.sass' }, + { startIndex: 191, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 198, type: '' }, { startIndex: 199, type: 'punctuation.curly.sass' }, { startIndex: 200, type: '' }, - { startIndex: 203, type: 'keyword.control.at-rule.sass' }, + { startIndex: 203, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 210, type: '' }, - { startIndex: 211, type: 'entity.other.attribute-name.sass' }, + { startIndex: 211, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 219, type: '' }, { startIndex: 220, type: 'literal.sass' }, { startIndex: 229, type: 'punctuation.sass' }, @@ -773,7 +774,7 @@ suite('Sass Colorizer', () => { [{ line: '@debug 10em + 12em;\n@mixin adjust-location($x, $y) {\n @if unitless($x) {\n @warn "Assuming #{$x} to be in pixels";\n $x: 1px * $x;\n }\n @if unitless($y) {\n @warn "Assuming #{$y} to be in pixels";\n $y: 1px * $y;\n }\n position: relative; left: $x; top: $y;\n}', tokens: [ - { startIndex: 0, type: 'keyword.control.at-rule.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 6, type: '' }, { startIndex: 7, type: 'constant.numeric.sass' }, { startIndex: 11, type: '' }, @@ -782,7 +783,7 @@ suite('Sass Colorizer', () => { { startIndex: 14, type: 'constant.numeric.sass' }, { startIndex: 18, type: 'punctuation.sass' }, { startIndex: 19, type: '' }, - { startIndex: 20, type: 'keyword.control.at-rule.sass' }, + { startIndex: 20, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 26, type: '' }, { startIndex: 27, type: 'support.function.name.sass' }, { startIndex: 43, type: 'variable.ref.sass' }, @@ -801,7 +802,7 @@ suite('Sass Colorizer', () => { { startIndex: 71, type: '' }, { startIndex: 72, type: 'punctuation.curly.sass' }, { startIndex: 73, type: '' }, - { startIndex: 78, type: 'keyword.control.at-rule.sass' }, + { startIndex: 78, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 83, type: '' }, { startIndex: 84, type: 'string.punctuation.sass' }, { startIndex: 85, type: 'string.sass' }, @@ -827,7 +828,7 @@ suite('Sass Colorizer', () => { { startIndex: 158, type: '' }, { startIndex: 159, type: 'punctuation.curly.sass' }, { startIndex: 160, type: '' }, - { startIndex: 165, type: 'keyword.control.at-rule.sass' }, + { startIndex: 165, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 170, type: '' }, { startIndex: 171, type: 'string.punctuation.sass' }, { startIndex: 172, type: 'string.sass' }, @@ -845,17 +846,17 @@ suite('Sass Colorizer', () => { { startIndex: 222, type: '' }, { startIndex: 225, type: 'punctuation.curly.sass' }, { startIndex: 226, type: '' }, - { startIndex: 229, type: 'support.type.property-name.sass' }, + { startIndex: 229, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 238, type: '' }, - { startIndex: 239, type: 'meta.property-value.sass' }, + { startIndex: 239, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 247, type: 'punctuation.sass' }, { startIndex: 248, type: '' }, - { startIndex: 249, type: 'support.type.property-name.sass' }, + { startIndex: 249, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 254, type: '' }, { startIndex: 255, type: 'variable.ref.sass' }, { startIndex: 257, type: 'punctuation.sass' }, { startIndex: 258, type: '' }, - { startIndex: 259, type: 'support.type.property-name.sass' }, + { startIndex: 259, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 263, type: '' }, { startIndex: 264, type: 'variable.ref.sass' }, { startIndex: 266, type: 'punctuation.sass' }, @@ -867,7 +868,7 @@ suite('Sass Colorizer', () => { [{ line: 'p {\n @if 1 + 1 == 2 { border: 1px solid; }\n @if 5 < 3 { border: 2px dotted; }\n @if null { border: 3px double; }\n}', tokens: [ - { startIndex: 0, type: 'entity.other.attribute-name.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 1, type: '' }, { startIndex: 2, type: 'punctuation.curly.sass' }, { startIndex: 3, type: '' }, @@ -885,11 +886,11 @@ suite('Sass Colorizer', () => { { startIndex: 20, type: '' }, { startIndex: 21, type: 'punctuation.curly.sass' }, { startIndex: 22, type: '' }, - { startIndex: 23, type: 'support.type.property-name.sass' }, + { startIndex: 23, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 30, type: '' }, { startIndex: 31, type: 'constant.numeric.sass' }, { startIndex: 34, type: '' }, - { startIndex: 35, type: 'meta.property-value.sass' }, + { startIndex: 35, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 40, type: 'punctuation.sass' }, { startIndex: 41, type: '' }, { startIndex: 43, type: 'punctuation.curly.sass' }, @@ -904,26 +905,26 @@ suite('Sass Colorizer', () => { { startIndex: 56, type: '' }, { startIndex: 62, type: 'punctuation.curly.sass' }, { startIndex: 63, type: '' }, - { startIndex: 64, type: 'support.type.property-name.sass' }, + { startIndex: 64, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 71, type: '' }, { startIndex: 72, type: 'constant.numeric.sass' }, { startIndex: 75, type: '' }, - { startIndex: 76, type: 'meta.property-value.sass' }, + { startIndex: 76, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 82, type: 'punctuation.sass' }, { startIndex: 83, type: '' }, { startIndex: 84, type: 'punctuation.curly.sass' }, { startIndex: 85, type: '' }, { startIndex: 88, type: 'keyword.flow.control.at-rule.sass' }, { startIndex: 91, type: '' }, - { startIndex: 92, type: 'meta.property-value.sass' }, + { startIndex: 92, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 96, type: '' }, { startIndex: 103, type: 'punctuation.curly.sass' }, { startIndex: 104, type: '' }, - { startIndex: 105, type: 'support.type.property-name.sass' }, + { startIndex: 105, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 112, type: '' }, { startIndex: 113, type: 'constant.numeric.sass' }, { startIndex: 116, type: '' }, - { startIndex: 117, type: 'meta.property-value.sass' }, + { startIndex: 117, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 123, type: 'punctuation.sass' }, { startIndex: 124, type: '' }, { startIndex: 125, type: 'punctuation.curly.sass' }, @@ -937,10 +938,10 @@ suite('Sass Colorizer', () => { tokens: [ { startIndex: 0, type: 'variable.decl.sass' }, { startIndex: 6, type: '' }, - { startIndex: 7, type: 'meta.property-value.sass' }, + { startIndex: 7, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 14, type: 'punctuation.sass' }, { startIndex: 15, type: '' }, - { startIndex: 16, type: 'entity.other.attribute-name.sass' }, + { startIndex: 16, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 17, type: '' }, { startIndex: 18, type: 'punctuation.curly.sass' }, { startIndex: 19, type: '' }, @@ -950,13 +951,13 @@ suite('Sass Colorizer', () => { { startIndex: 31, type: '' }, { startIndex: 32, type: 'keyword.operator.sass' }, { startIndex: 34, type: '' }, - { startIndex: 35, type: 'meta.property-value.sass' }, + { startIndex: 35, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 40, type: '' }, { startIndex: 41, type: 'punctuation.curly.sass' }, { startIndex: 42, type: '' }, - { startIndex: 47, type: 'support.type.property-name.sass' }, + { startIndex: 47, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 53, type: '' }, - { startIndex: 54, type: 'meta.property-value.sass' }, + { startIndex: 54, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 58, type: 'punctuation.sass' }, { startIndex: 59, type: '' }, { startIndex: 62, type: 'punctuation.curly.sass' }, @@ -969,13 +970,13 @@ suite('Sass Colorizer', () => { { startIndex: 78, type: '' }, { startIndex: 79, type: 'keyword.operator.sass' }, { startIndex: 81, type: '' }, - { startIndex: 82, type: 'meta.property-value.sass' }, + { startIndex: 82, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 89, type: '' }, { startIndex: 90, type: 'punctuation.curly.sass' }, { startIndex: 91, type: '' }, - { startIndex: 96, type: 'support.type.property-name.sass' }, + { startIndex: 96, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 102, type: '' }, - { startIndex: 103, type: 'meta.property-value.sass' }, + { startIndex: 103, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 106, type: 'punctuation.sass' }, { startIndex: 107, type: '' }, { startIndex: 110, type: 'punctuation.curly.sass' }, @@ -984,9 +985,9 @@ suite('Sass Colorizer', () => { { startIndex: 117, type: '' }, { startIndex: 118, type: 'punctuation.curly.sass' }, { startIndex: 119, type: '' }, - { startIndex: 124, type: 'support.type.property-name.sass' }, + { startIndex: 124, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 130, type: '' }, - { startIndex: 131, type: 'meta.property-value.sass' }, + { startIndex: 131, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 136, type: 'punctuation.sass' }, { startIndex: 137, type: '' }, { startIndex: 140, type: 'punctuation.curly.sass' }, @@ -1012,14 +1013,14 @@ suite('Sass Colorizer', () => { { startIndex: 24, type: '' }, { startIndex: 25, type: 'punctuation.curly.sass' }, { startIndex: 26, type: '' }, - { startIndex: 29, type: 'entity.other.attribute-name.sass' }, + { startIndex: 29, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 35, type: 'support.function.interpolation.sass' }, { startIndex: 37, type: 'variable.ref.sass' }, { startIndex: 39, type: 'support.function.interpolation.sass' }, { startIndex: 40, type: '' }, { startIndex: 41, type: 'punctuation.curly.sass' }, { startIndex: 42, type: '' }, - { startIndex: 43, type: 'support.type.property-name.sass' }, + { startIndex: 43, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 49, type: '' }, { startIndex: 50, type: 'constant.numeric.sass' }, { startIndex: 53, type: '' }, @@ -1043,28 +1044,28 @@ suite('Sass Colorizer', () => { { startIndex: 13, type: '' }, { startIndex: 14, type: 'keyword.flow.control.at-rule.sass' }, { startIndex: 16, type: '' }, - { startIndex: 17, type: 'meta.property-value.sass' }, + { startIndex: 17, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 21, type: 'keyword.operator.sass' }, { startIndex: 22, type: '' }, - { startIndex: 23, type: 'meta.property-value.sass' }, + { startIndex: 23, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 31, type: 'keyword.operator.sass' }, { startIndex: 32, type: '' }, - { startIndex: 33, type: 'meta.property-value.sass' }, + { startIndex: 33, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 38, type: 'keyword.operator.sass' }, { startIndex: 39, type: '' }, - { startIndex: 40, type: 'meta.property-value.sass' }, + { startIndex: 40, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 50, type: '' }, { startIndex: 51, type: 'punctuation.curly.sass' }, { startIndex: 52, type: '' }, - { startIndex: 55, type: 'entity.other.attribute-name.sass' }, + { startIndex: 55, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 56, type: 'support.function.interpolation.sass' }, { startIndex: 58, type: 'variable.ref.sass' }, { startIndex: 65, type: 'support.function.interpolation.sass' }, - { startIndex: 66, type: 'entity.other.attribute-name.sass' }, + { startIndex: 66, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 71, type: '' }, { startIndex: 72, type: 'punctuation.curly.sass' }, { startIndex: 73, type: '' }, - { startIndex: 78, type: 'support.type.property-name.sass' }, + { startIndex: 78, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 95, type: '' }, { startIndex: 96, type: 'support.function.name.sass' }, { startIndex: 100, type: 'string.punctuation.sass' }, @@ -1097,14 +1098,14 @@ suite('Sass Colorizer', () => { { startIndex: 20, type: '' }, { startIndex: 21, type: 'punctuation.curly.sass' }, { startIndex: 22, type: '' }, - { startIndex: 25, type: 'entity.other.attribute-name.sass' }, + { startIndex: 25, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 31, type: 'support.function.interpolation.sass' }, { startIndex: 33, type: 'variable.ref.sass' }, { startIndex: 35, type: 'support.function.interpolation.sass' }, { startIndex: 36, type: '' }, { startIndex: 37, type: 'punctuation.curly.sass' }, { startIndex: 38, type: '' }, - { startIndex: 39, type: 'support.type.property-name.sass' }, + { startIndex: 39, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 45, type: '' }, { startIndex: 46, type: 'constant.numeric.sass' }, { startIndex: 49, type: '' }, @@ -1131,7 +1132,7 @@ suite('Sass Colorizer', () => { [{ line: '@function foo($total, $a) {\n @for $i from 0 to $total {\n @if (unit($a) == "%") and ($i == ($total - 1)) {\n $z: 100%;\n @return \'1\';\n }\n }\n @return $grid;\n}', tokens: [ - { startIndex: 0, type: 'keyword.control.at-rule.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 9, type: '' }, { startIndex: 10, type: 'support.function.name.sass' }, { startIndex: 14, type: 'variable.ref.sass' }, @@ -1193,7 +1194,7 @@ suite('Sass Colorizer', () => { { startIndex: 120, type: 'constant.numeric.sass' }, { startIndex: 124, type: 'punctuation.sass' }, { startIndex: 125, type: '' }, - { startIndex: 132, type: 'keyword.control.at-rule.sass' }, + { startIndex: 132, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 139, type: '' }, { startIndex: 140, type: 'string.punctuation.sass' }, { startIndex: 141, type: 'string.sass' }, @@ -1204,7 +1205,7 @@ suite('Sass Colorizer', () => { { startIndex: 150, type: '' }, { startIndex: 153, type: 'punctuation.curly.sass' }, { startIndex: 154, type: '' }, - { startIndex: 157, type: 'keyword.control.at-rule.sass' }, + { startIndex: 157, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 164, type: '' }, { startIndex: 165, type: 'variable.ref.sass' }, { startIndex: 170, type: 'punctuation.sass' }, @@ -1216,50 +1217,50 @@ suite('Sass Colorizer', () => { [{ line: '@mixin large-text {\n font: {\n family: Arial;\n size: 20px;\n weight: bold;\n }\n color: #ff0000;\n}\n.page-title {\n @include large-text;\n padding: 4px;\n}', tokens: [ - { startIndex: 0, type: 'keyword.control.at-rule.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 6, type: '' }, { startIndex: 7, type: 'support.function.name.sass' }, { startIndex: 17, type: '' }, { startIndex: 18, type: 'punctuation.curly.sass' }, { startIndex: 19, type: '' }, - { startIndex: 22, type: 'support.type.property-name.sass' }, + { startIndex: 22, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 27, type: '' }, { startIndex: 28, type: 'punctuation.curly.sass' }, { startIndex: 29, type: '' }, - { startIndex: 34, type: 'support.type.property-name.sass' }, + { startIndex: 34, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 41, type: '' }, - { startIndex: 42, type: 'meta.property-value.sass' }, + { startIndex: 42, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 47, type: 'punctuation.sass' }, { startIndex: 48, type: '' }, - { startIndex: 53, type: 'support.type.property-name.sass' }, + { startIndex: 53, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 58, type: '' }, { startIndex: 59, type: 'constant.numeric.sass' }, { startIndex: 63, type: 'punctuation.sass' }, { startIndex: 64, type: '' }, - { startIndex: 69, type: 'support.type.property-name.sass' }, + { startIndex: 69, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 76, type: '' }, - { startIndex: 77, type: 'meta.property-value.sass' }, + { startIndex: 77, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 81, type: 'punctuation.sass' }, { startIndex: 82, type: '' }, { startIndex: 85, type: 'punctuation.curly.sass' }, { startIndex: 86, type: '' }, - { startIndex: 89, type: 'support.type.property-name.sass' }, + { startIndex: 89, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 95, type: '' }, { startIndex: 96, type: 'constant.rgb-value.sass' }, { startIndex: 103, type: 'punctuation.sass' }, { startIndex: 104, type: '' }, { startIndex: 105, type: 'punctuation.curly.sass' }, { startIndex: 106, type: '' }, - { startIndex: 107, type: 'entity.other.attribute-name.sass' }, + { startIndex: 107, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 118, type: '' }, { startIndex: 119, type: 'punctuation.curly.sass' }, { startIndex: 120, type: '' }, - { startIndex: 123, type: 'keyword.control.at-rule.sass' }, + { startIndex: 123, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 131, type: '' }, { startIndex: 132, type: 'support.function.name.sass' }, { startIndex: 142, type: 'punctuation.sass' }, { startIndex: 143, type: '' }, - { startIndex: 146, type: 'support.type.property-name.sass' }, + { startIndex: 146, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 154, type: '' }, { startIndex: 155, type: 'constant.numeric.sass' }, { startIndex: 158, type: 'punctuation.sass' }, @@ -1271,50 +1272,50 @@ suite('Sass Colorizer', () => { [{ line: '@mixin sexy-border($color, $width: 1in) {\n border: {\n color: $color;\n width: $width;\n style: dashed;\n }\n}\np { @include sexy-border(blue); }', tokens: [ - { startIndex: 0, type: 'keyword.control.at-rule.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 6, type: '' }, { startIndex: 7, type: 'support.function.name.sass' }, { startIndex: 19, type: 'variable.ref.sass' }, { startIndex: 25, type: 'punctuation.sass' }, { startIndex: 26, type: '' }, - { startIndex: 27, type: 'support.type.property-name.sass' }, + { startIndex: 27, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 34, type: '' }, { startIndex: 35, type: 'constant.numeric.sass' }, { startIndex: 38, type: 'support.function.name.sass' }, { startIndex: 39, type: '' }, { startIndex: 40, type: 'punctuation.curly.sass' }, { startIndex: 41, type: '' }, - { startIndex: 44, type: 'support.type.property-name.sass' }, + { startIndex: 44, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 51, type: '' }, { startIndex: 52, type: 'punctuation.curly.sass' }, { startIndex: 53, type: '' }, - { startIndex: 58, type: 'support.type.property-name.sass' }, + { startIndex: 58, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 64, type: '' }, { startIndex: 65, type: 'variable.ref.sass' }, { startIndex: 71, type: 'punctuation.sass' }, { startIndex: 72, type: '' }, - { startIndex: 77, type: 'support.type.property-name.sass' }, + { startIndex: 77, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 83, type: '' }, { startIndex: 84, type: 'variable.ref.sass' }, { startIndex: 90, type: 'punctuation.sass' }, { startIndex: 91, type: '' }, - { startIndex: 96, type: 'support.type.property-name.sass' }, + { startIndex: 96, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 102, type: '' }, - { startIndex: 103, type: 'meta.property-value.sass' }, + { startIndex: 103, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 109, type: 'punctuation.sass' }, { startIndex: 110, type: '' }, { startIndex: 113, type: 'punctuation.curly.sass' }, { startIndex: 114, type: '' }, { startIndex: 115, type: 'punctuation.curly.sass' }, { startIndex: 116, type: '' }, - { startIndex: 117, type: 'entity.other.attribute-name.sass' }, + { startIndex: 117, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 118, type: '' }, { startIndex: 119, type: 'punctuation.curly.sass' }, { startIndex: 120, type: '' }, - { startIndex: 121, type: 'keyword.control.at-rule.sass' }, + { startIndex: 121, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 129, type: '' }, { startIndex: 130, type: 'support.function.name.sass' }, - { startIndex: 142, type: 'meta.property-value.sass' }, + { startIndex: 142, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 146, type: 'support.function.name.sass' }, { startIndex: 147, type: 'punctuation.sass' }, { startIndex: 148, type: '' }, @@ -1325,7 +1326,7 @@ suite('Sass Colorizer', () => { [{ line: '@mixin box-shadow($shadows...) {\n -moz-box-shadow: $shadows;\n -webkit-box-shadow: $shadows;\n box-shadow: $shadows;\n}\n.shadows {\n @include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);\n}', tokens: [ - { startIndex: 0, type: 'keyword.control.at-rule.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 6, type: '' }, { startIndex: 7, type: 'support.function.name.sass' }, { startIndex: 18, type: 'variable.ref.sass' }, @@ -1334,28 +1335,28 @@ suite('Sass Colorizer', () => { { startIndex: 30, type: '' }, { startIndex: 31, type: 'punctuation.curly.sass' }, { startIndex: 32, type: '' }, - { startIndex: 35, type: 'support.type.property-name.sass' }, + { startIndex: 35, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 51, type: '' }, { startIndex: 52, type: 'variable.ref.sass' }, { startIndex: 60, type: 'punctuation.sass' }, { startIndex: 61, type: '' }, - { startIndex: 64, type: 'support.type.property-name.sass' }, + { startIndex: 64, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 83, type: '' }, { startIndex: 84, type: 'variable.ref.sass' }, { startIndex: 92, type: 'punctuation.sass' }, { startIndex: 93, type: '' }, - { startIndex: 96, type: 'support.type.property-name.sass' }, + { startIndex: 96, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 107, type: '' }, { startIndex: 108, type: 'variable.ref.sass' }, { startIndex: 116, type: 'punctuation.sass' }, { startIndex: 117, type: '' }, { startIndex: 118, type: 'punctuation.curly.sass' }, { startIndex: 119, type: '' }, - { startIndex: 120, type: 'entity.other.attribute-name.sass' }, + { startIndex: 120, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 128, type: '' }, { startIndex: 129, type: 'punctuation.curly.sass' }, { startIndex: 130, type: '' }, - { startIndex: 133, type: 'keyword.control.at-rule.sass' }, + { startIndex: 133, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 141, type: '' }, { startIndex: 142, type: 'support.function.name.sass' }, { startIndex: 153, type: 'constant.numeric.sass' }, @@ -1384,7 +1385,7 @@ suite('Sass Colorizer', () => { [{ line: '@mixin colors($text, $background, $border) {\n color: $text;\n background-color: $background;\n border-color: $border;\n}\n$values: #ff0000, #00ff00, #0000ff;\n.primary {\n @include colors($values...);\n}', tokens: [ - { startIndex: 0, type: 'keyword.control.at-rule.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 6, type: '' }, { startIndex: 7, type: 'support.function.name.sass' }, { startIndex: 14, type: 'variable.ref.sass' }, @@ -1398,17 +1399,17 @@ suite('Sass Colorizer', () => { { startIndex: 42, type: '' }, { startIndex: 43, type: 'punctuation.curly.sass' }, { startIndex: 44, type: '' }, - { startIndex: 47, type: 'support.type.property-name.sass' }, + { startIndex: 47, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 53, type: '' }, { startIndex: 54, type: 'variable.ref.sass' }, { startIndex: 59, type: 'punctuation.sass' }, { startIndex: 60, type: '' }, - { startIndex: 63, type: 'support.type.property-name.sass' }, + { startIndex: 63, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 80, type: '' }, { startIndex: 81, type: 'variable.ref.sass' }, { startIndex: 92, type: 'punctuation.sass' }, { startIndex: 93, type: '' }, - { startIndex: 96, type: 'support.type.property-name.sass' }, + { startIndex: 96, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 109, type: '' }, { startIndex: 110, type: 'variable.ref.sass' }, { startIndex: 117, type: 'punctuation.sass' }, @@ -1426,11 +1427,11 @@ suite('Sass Colorizer', () => { { startIndex: 148, type: 'constant.rgb-value.sass' }, { startIndex: 155, type: 'punctuation.sass' }, { startIndex: 156, type: '' }, - { startIndex: 157, type: 'entity.other.attribute-name.sass' }, + { startIndex: 157, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 165, type: '' }, { startIndex: 166, type: 'punctuation.curly.sass' }, { startIndex: 167, type: '' }, - { startIndex: 170, type: 'keyword.control.at-rule.sass' }, + { startIndex: 170, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 178, type: '' }, { startIndex: 179, type: 'support.function.name.sass' }, { startIndex: 186, type: 'variable.ref.sass' }, @@ -1445,35 +1446,35 @@ suite('Sass Colorizer', () => { [{ line: '@mixin apply-to-ie6-only {\n * html {\n @content;\n }\n}\n@include apply-to-ie6-only {\n #logo {\n background-image: url(/logo.gif);\n }\n}', tokens: [ - { startIndex: 0, type: 'keyword.control.at-rule.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 6, type: '' }, { startIndex: 7, type: 'support.function.name.sass' }, { startIndex: 24, type: '' }, { startIndex: 25, type: 'punctuation.curly.sass' }, { startIndex: 26, type: '' }, - { startIndex: 29, type: 'entity.name.tag.sass' }, + { startIndex: 29, type: cssTokenTypes.TOKEN_SELECTOR_TAG + '.sass' }, { startIndex: 30, type: '' }, - { startIndex: 31, type: 'entity.other.attribute-name.sass' }, + { startIndex: 31, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 35, type: '' }, { startIndex: 36, type: 'punctuation.curly.sass' }, { startIndex: 37, type: '' }, - { startIndex: 42, type: 'keyword.control.at-rule.sass' }, + { startIndex: 42, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 50, type: '' }, { startIndex: 54, type: 'punctuation.curly.sass' }, { startIndex: 55, type: '' }, { startIndex: 56, type: 'punctuation.curly.sass' }, { startIndex: 57, type: '' }, - { startIndex: 58, type: 'keyword.control.at-rule.sass' }, + { startIndex: 58, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 66, type: '' }, { startIndex: 67, type: 'support.function.name.sass' }, { startIndex: 84, type: '' }, { startIndex: 85, type: 'punctuation.curly.sass' }, { startIndex: 86, type: '' }, - { startIndex: 89, type: 'entity.other.attribute-name.sass' }, + { startIndex: 89, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 94, type: '' }, { startIndex: 95, type: 'punctuation.curly.sass' }, { startIndex: 96, type: '' }, - { startIndex: 101, type: 'support.type.property-name.sass' }, + { startIndex: 101, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 118, type: '' }, { startIndex: 119, type: 'support.function.name.sass' }, { startIndex: 123, type: 'string.sass' }, @@ -1489,7 +1490,7 @@ suite('Sass Colorizer', () => { [{ line: '@charset "UTF-8";', tokens: [ - { startIndex: 0, type: 'keyword.control.at-rule.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 8, type: '' }, { startIndex: 9, type: 'string.punctuation.sass' }, { startIndex: 10, type: 'string.sass' }, @@ -1502,17 +1503,17 @@ suite('Sass Colorizer', () => { line: '[rel="external"]::after {\n content: \'s\';\n}', tokens: [ { startIndex: 0, type: 'punctuation.bracket.sass' }, - { startIndex: 1, type: 'meta.property-value.sass' }, + { startIndex: 1, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 4, type: 'keyword.operator.sass' }, { startIndex: 5, type: 'string.punctuation.sass' }, { startIndex: 6, type: 'string.sass' }, { startIndex: 14, type: 'string.punctuation.sass' }, { startIndex: 15, type: 'punctuation.bracket.sass' }, - { startIndex: 16, type: 'entity.other.attribute-name.sass' }, + { startIndex: 16, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 23, type: '' }, { startIndex: 24, type: 'punctuation.curly.sass' }, { startIndex: 25, type: '' }, - { startIndex: 30, type: 'support.type.property-name.sass' }, + { startIndex: 30, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 38, type: '' }, { startIndex: 39, type: 'string.punctuation.sass' }, { startIndex: 40, type: 'string.sass' }, @@ -1526,18 +1527,18 @@ suite('Sass Colorizer', () => { [{ line: '@page :left {\n margin-left: 4cm;\n margin-right: 3cm;\n}', tokens: [ - { startIndex: 0, type: 'keyword.control.at-rule.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 5, type: '' }, - { startIndex: 6, type: 'entity.other.attribute-name.sass' }, + { startIndex: 6, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 11, type: '' }, { startIndex: 12, type: 'punctuation.curly.sass' }, { startIndex: 13, type: '' }, - { startIndex: 16, type: 'support.type.property-name.sass' }, + { startIndex: 16, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 28, type: '' }, { startIndex: 29, type: 'constant.numeric.sass' }, { startIndex: 32, type: 'punctuation.sass' }, { startIndex: 33, type: '' }, - { startIndex: 36, type: 'support.type.property-name.sass' }, + { startIndex: 36, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 49, type: '' }, { startIndex: 50, type: 'constant.numeric.sass' }, { startIndex: 53, type: 'punctuation.sass' }, @@ -1549,27 +1550,27 @@ suite('Sass Colorizer', () => { [{ line: '@mixin error($a: false) {\n @extend .#{$a};\n @extend ##{$a};\n}\n#bar {a: 1px;}\n.bar {b: 1px;}\nfoo {\n @include error(\'bar\'); \n}', tokens: [ - { startIndex: 0, type: 'keyword.control.at-rule.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 6, type: '' }, { startIndex: 7, type: 'support.function.name.sass' }, - { startIndex: 13, type: 'support.type.property-name.sass' }, + { startIndex: 13, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 16, type: '' }, - { startIndex: 17, type: 'meta.property-value.sass' }, + { startIndex: 17, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 22, type: 'support.function.name.sass' }, { startIndex: 23, type: '' }, { startIndex: 24, type: 'punctuation.curly.sass' }, { startIndex: 25, type: '' }, - { startIndex: 28, type: 'keyword.control.at-rule.sass' }, + { startIndex: 28, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 35, type: '' }, - { startIndex: 36, type: 'entity.other.attribute-name.sass' }, + { startIndex: 36, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 37, type: 'support.function.interpolation.sass' }, { startIndex: 39, type: 'variable.ref.sass' }, { startIndex: 41, type: 'support.function.interpolation.sass' }, { startIndex: 42, type: 'punctuation.sass' }, { startIndex: 43, type: '' }, - { startIndex: 46, type: 'keyword.control.at-rule.sass' }, + { startIndex: 46, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 53, type: '' }, - { startIndex: 54, type: 'entity.other.attribute-name.sass' }, + { startIndex: 54, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 55, type: 'support.function.interpolation.sass' }, { startIndex: 57, type: 'variable.ref.sass' }, { startIndex: 59, type: 'support.function.interpolation.sass' }, @@ -1577,29 +1578,29 @@ suite('Sass Colorizer', () => { { startIndex: 61, type: '' }, { startIndex: 62, type: 'punctuation.curly.sass' }, { startIndex: 63, type: '' }, - { startIndex: 64, type: 'entity.other.attribute-name.sass' }, + { startIndex: 64, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 68, type: '' }, { startIndex: 69, type: 'punctuation.curly.sass' }, - { startIndex: 70, type: 'support.type.property-name.sass' }, + { startIndex: 70, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 72, type: '' }, { startIndex: 73, type: 'constant.numeric.sass' }, { startIndex: 76, type: 'punctuation.sass' }, { startIndex: 77, type: 'punctuation.curly.sass' }, { startIndex: 78, type: '' }, - { startIndex: 79, type: 'entity.other.attribute-name.sass' }, + { startIndex: 79, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 83, type: '' }, { startIndex: 84, type: 'punctuation.curly.sass' }, - { startIndex: 85, type: 'support.type.property-name.sass' }, + { startIndex: 85, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 87, type: '' }, { startIndex: 88, type: 'constant.numeric.sass' }, { startIndex: 91, type: 'punctuation.sass' }, { startIndex: 92, type: 'punctuation.curly.sass' }, { startIndex: 93, type: '' }, - { startIndex: 94, type: 'entity.other.attribute-name.sass' }, + { startIndex: 94, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 97, type: '' }, { startIndex: 98, type: 'punctuation.curly.sass' }, { startIndex: 99, type: '' }, - { startIndex: 102, type: 'keyword.control.at-rule.sass' }, + { startIndex: 102, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 110, type: '' }, { startIndex: 111, type: 'support.function.name.sass' }, { startIndex: 117, type: 'string.punctuation.sass' }, @@ -1615,16 +1616,16 @@ suite('Sass Colorizer', () => { [{ line: '@font-face { font-family: Delicious; src: url(\'Delicious-Roman.otf\'); } ', tokens: [ - { startIndex: 0, type: 'keyword.control.at-rule.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 10, type: '' }, { startIndex: 11, type: 'punctuation.curly.sass' }, { startIndex: 12, type: '' }, - { startIndex: 13, type: 'support.type.property-name.sass' }, + { startIndex: 13, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 25, type: '' }, - { startIndex: 26, type: 'meta.property-value.sass' }, + { startIndex: 26, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 35, type: 'punctuation.sass' }, { startIndex: 36, type: '' }, - { startIndex: 37, type: 'support.type.property-name.sass' }, + { startIndex: 37, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 41, type: '' }, { startIndex: 42, type: 'support.function.name.sass' }, { startIndex: 46, type: 'string.punctuation.sass' }, @@ -1641,7 +1642,7 @@ suite('Sass Colorizer', () => { [{ line: '@-webkit-keyframes NAME-YOUR-ANIMATION {\n 0% { opacity: 0; }\n 100% { opacity: 1; }\n}\n@-moz-keyframes NAME-YOUR-ANIMATION {\n 0% { opacity: 0; }\n 100% { opacity: 1; }\n}\n@-o-keyframes NAME-YOUR-ANIMATION {\n 0% { opacity: 0; }\n 100% { opacity: 1; }\n}\n@keyframes NAME-YOUR-ANIMATION {\n 0% { opacity: 0; }\n 100% { opacity: 1; }\n}', tokens: [ - { startIndex: 0, type: 'keyword.control.at-rule.sass' }, + { startIndex: 0, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 18, type: '' }, { startIndex: 19, type: 'support.function.name.sass' }, { startIndex: 38, type: '' }, @@ -1651,7 +1652,7 @@ suite('Sass Colorizer', () => { { startIndex: 45, type: '' }, { startIndex: 48, type: 'punctuation.curly.sass' }, { startIndex: 49, type: '' }, - { startIndex: 50, type: 'support.type.property-name.sass' }, + { startIndex: 50, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 58, type: '' }, { startIndex: 59, type: 'constant.numeric.sass' }, { startIndex: 60, type: 'punctuation.sass' }, @@ -1662,7 +1663,7 @@ suite('Sass Colorizer', () => { { startIndex: 70, type: '' }, { startIndex: 71, type: 'punctuation.curly.sass' }, { startIndex: 72, type: '' }, - { startIndex: 73, type: 'support.type.property-name.sass' }, + { startIndex: 73, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 81, type: '' }, { startIndex: 82, type: 'constant.numeric.sass' }, { startIndex: 83, type: 'punctuation.sass' }, @@ -1671,7 +1672,7 @@ suite('Sass Colorizer', () => { { startIndex: 86, type: '' }, { startIndex: 87, type: 'punctuation.curly.sass' }, { startIndex: 88, type: '' }, - { startIndex: 89, type: 'keyword.control.at-rule.sass' }, + { startIndex: 89, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 104, type: '' }, { startIndex: 105, type: 'support.function.name.sass' }, { startIndex: 124, type: '' }, @@ -1681,7 +1682,7 @@ suite('Sass Colorizer', () => { { startIndex: 131, type: '' }, { startIndex: 134, type: 'punctuation.curly.sass' }, { startIndex: 135, type: '' }, - { startIndex: 136, type: 'support.type.property-name.sass' }, + { startIndex: 136, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 144, type: '' }, { startIndex: 145, type: 'constant.numeric.sass' }, { startIndex: 146, type: 'punctuation.sass' }, @@ -1692,7 +1693,7 @@ suite('Sass Colorizer', () => { { startIndex: 156, type: '' }, { startIndex: 157, type: 'punctuation.curly.sass' }, { startIndex: 158, type: '' }, - { startIndex: 159, type: 'support.type.property-name.sass' }, + { startIndex: 159, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 167, type: '' }, { startIndex: 168, type: 'constant.numeric.sass' }, { startIndex: 169, type: 'punctuation.sass' }, @@ -1701,7 +1702,7 @@ suite('Sass Colorizer', () => { { startIndex: 172, type: '' }, { startIndex: 173, type: 'punctuation.curly.sass' }, { startIndex: 174, type: '' }, - { startIndex: 175, type: 'keyword.control.at-rule.sass' }, + { startIndex: 175, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 188, type: '' }, { startIndex: 189, type: 'support.function.name.sass' }, { startIndex: 208, type: '' }, @@ -1711,7 +1712,7 @@ suite('Sass Colorizer', () => { { startIndex: 215, type: '' }, { startIndex: 218, type: 'punctuation.curly.sass' }, { startIndex: 219, type: '' }, - { startIndex: 220, type: 'support.type.property-name.sass' }, + { startIndex: 220, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 228, type: '' }, { startIndex: 229, type: 'constant.numeric.sass' }, { startIndex: 230, type: 'punctuation.sass' }, @@ -1722,7 +1723,7 @@ suite('Sass Colorizer', () => { { startIndex: 240, type: '' }, { startIndex: 241, type: 'punctuation.curly.sass' }, { startIndex: 242, type: '' }, - { startIndex: 243, type: 'support.type.property-name.sass' }, + { startIndex: 243, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 251, type: '' }, { startIndex: 252, type: 'constant.numeric.sass' }, { startIndex: 253, type: 'punctuation.sass' }, @@ -1731,7 +1732,7 @@ suite('Sass Colorizer', () => { { startIndex: 256, type: '' }, { startIndex: 257, type: 'punctuation.curly.sass' }, { startIndex: 258, type: '' }, - { startIndex: 259, type: 'keyword.control.at-rule.sass' }, + { startIndex: 259, type: cssTokenTypes.TOKEN_AT_KEYWORD + '.sass' }, { startIndex: 269, type: '' }, { startIndex: 270, type: 'support.function.name.sass' }, { startIndex: 289, type: '' }, @@ -1741,7 +1742,7 @@ suite('Sass Colorizer', () => { { startIndex: 296, type: '' }, { startIndex: 299, type: 'punctuation.curly.sass' }, { startIndex: 300, type: '' }, - { startIndex: 301, type: 'support.type.property-name.sass' }, + { startIndex: 301, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 309, type: '' }, { startIndex: 310, type: 'constant.numeric.sass' }, { startIndex: 311, type: 'punctuation.sass' }, @@ -1752,7 +1753,7 @@ suite('Sass Colorizer', () => { { startIndex: 321, type: '' }, { startIndex: 322, type: 'punctuation.curly.sass' }, { startIndex: 323, type: '' }, - { startIndex: 324, type: 'support.type.property-name.sass' }, + { startIndex: 324, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 332, type: '' }, { startIndex: 333, type: 'constant.numeric.sass' }, { startIndex: 334, type: 'punctuation.sass' }, @@ -1767,17 +1768,17 @@ suite('Sass Colorizer', () => { line: '[data-icon=\'test-1\']:before {\n content:\'\\\\\';\n}\n/* a comment */\n$var1: \'\\\'\';\n$var2: "\\"";\n/* another comment */', tokens: [ { startIndex: 0, type: 'punctuation.bracket.sass' }, - { startIndex: 1, type: 'meta.property-value.sass' }, + { startIndex: 1, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex: 10, type: 'keyword.operator.sass' }, { startIndex: 11, type: 'string.punctuation.sass' }, { startIndex: 12, type: 'string.sass' }, { startIndex: 18, type: 'string.punctuation.sass' }, { startIndex: 19, type: 'punctuation.bracket.sass' }, - { startIndex: 20, type: 'entity.other.attribute-name.sass' }, + { startIndex: 20, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex: 27, type: '' }, { startIndex: 28, type: 'punctuation.curly.sass' }, { startIndex: 29, type: '' }, - { startIndex: 32, type: 'support.type.property-name.sass' }, + { startIndex: 32, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 40, type: 'string.punctuation.sass' }, { startIndex: 41, type: 'string.sass' }, { startIndex: 43, type: 'string.punctuation.sass' }, @@ -1813,7 +1814,7 @@ suite('Sass Colorizer', () => { line: ' _content: "";', tokens: [ { startIndex: 0, type: '' }, - { startIndex: 2, type: 'support.type.property-name.sass' }, + { startIndex: 2, type: cssTokenTypes.TOKEN_PROPERTY + '.sass' }, { startIndex: 11, type: '' }, { startIndex: 12, type: 'string.punctuation.sass' }, { startIndex: 13, type: 'string.punctuation.sass' }, @@ -1826,12 +1827,12 @@ suite('Sass Colorizer', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: 'input[type= \\"submit\\"', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.sass' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex:5, type: 'punctuation.bracket.sass'}, - { startIndex:6, type: 'meta.property-value.sass' }, + { startIndex:6, type: cssTokenTypes.TOKEN_VALUE + '.sass' }, { startIndex:10, type: 'keyword.operator.sass'}, { startIndex:11, type: ''}, - { startIndex:12, type: 'meta.property-value.sass'} + { startIndex:12, type: cssTokenTypes.TOKEN_VALUE + '.sass'} ]} ]); }); @@ -1840,13 +1841,13 @@ suite('Sass Colorizer', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '.\\34 hello { -moz-foo: --myvar }', tokens: [ - { startIndex:0, type: 'entity.other.attribute-name.sass' }, + { startIndex:0, type: cssTokenTypes.TOKEN_SELECTOR + '.sass' }, { startIndex:10, type: ''}, { startIndex:11, type: 'punctuation.curly.sass'}, { startIndex:12, type: ''}, - { startIndex:13, type: 'support.type.property-name.sass'}, + { startIndex:13, type: cssTokenTypes.TOKEN_PROPERTY + '.sass'}, { startIndex:22, type: ''}, - { startIndex:23, type: 'meta.property-value.sass'}, + { startIndex:23, type: cssTokenTypes.TOKEN_VALUE + '.sass'}, { startIndex:30, type: ''}, { startIndex:31, type: 'punctuation.curly.sass'}, ]} diff --git a/src/vs/languages/vsxml/common/vsxmlTokenTypes.ts b/src/vs/languages/vsxml/common/vsxmlTokenTypes.ts index f0ddbcb916c..ee4602cdb9c 100644 --- a/src/vs/languages/vsxml/common/vsxmlTokenTypes.ts +++ b/src/vs/languages/vsxml/common/vsxmlTokenTypes.ts @@ -4,5 +4,5 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -export const TOKEN_VALUE = 'meta.property-value.constant.other.json'; +export const TOKEN_VALUE = 'support.property-value.constant.other.json'; export const TOKEN_KEY = 'support.type.property-name.json'; \ No newline at end of file From bce1beb7c2b19ba39127405c476987bd546204ce Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 27 Nov 2015 12:10:22 +0100 Subject: [PATCH 173/588] scoped git in git actions --- .../git/browser/gitActions.contribution.ts | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/parts/git/browser/gitActions.contribution.ts b/src/vs/workbench/parts/git/browser/gitActions.contribution.ts index 6442cf9abf5..6c238d363da 100644 --- a/src/vs/workbench/parts/git/browser/gitActions.contribution.ts +++ b/src/vs/workbench/parts/git/browser/gitActions.contribution.ts @@ -33,17 +33,17 @@ import wbar = require('vs/workbench/browser/actionRegistry'); import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { OpenChangeAction, SyncAction } from './gitActions'; import Severity from 'vs/base/common/severity'; +import paths = require('vs/base/common/paths'); +import URI from 'vs/base/common/uri'; function getStatus(gitService: IGitService, contextService: IWorkspaceContextService, input: WorkbenchEditorCommon.IFileEditorInput): IFileStatus { - var statusModel = gitService.getModel().getStatus(); + const model = gitService.getModel(); + const repositoryRoot = model.getRepositoryRoot(); + const statusModel = model.getStatus(); + const repositoryRelativePath = paths.normalize(paths.relative(repositoryRoot, input.getResource().fsPath)); - var workspaceRelativePath = contextService.toWorkspaceRelativePath(input.getResource()); - if (!workspaceRelativePath) { - return null; // out of workspace not yet supported - } - - return statusModel.getWorkingTreeStatus().find(workspaceRelativePath) || - statusModel.getIndexStatus().find(workspaceRelativePath); + return statusModel.getWorkingTreeStatus().find(repositoryRelativePath) || + statusModel.getIndexStatus().find(repositoryRelativePath); } class OpenInDiffAction extends baseeditor.EditorInputAction { @@ -78,6 +78,10 @@ class OpenInDiffAction extends baseeditor.EditorInputAction { return false; } + if (!(typeof this.gitService.getModel().getRepositoryRoot() === 'string')) { + return false; + } + var status = this.getStatus(); return status && ( @@ -164,6 +168,10 @@ class OpenInEditorAction extends baseeditor.EditorInputAction { return false; } + if (!(typeof this.gitService.getModel().getRepositoryRoot() === 'string')) { + return false; + } + var status:IFileStatus = (this.input).getFileStatus(); if (OpenInEditorAction.DELETED_STATES.indexOf(status.getStatus()) > -1) { return false; @@ -173,18 +181,19 @@ class OpenInEditorAction extends baseeditor.EditorInputAction { } public run(event?: any): Promise { - var sideBySide = !!(event && (event.ctrlKey || event.metaKey)); - var modifiedViewState = this.saveTextViewState(); - var path = this.getPath(); + const model = this.gitService.getModel(); + const resource = URI.file(paths.join(model.getRepositoryRoot(), this.getRepositoryRelativePath())); + const sideBySide = !!(event && (event.ctrlKey || event.metaKey)); + const modifiedViewState = this.saveTextViewState(); - return this.fileService.resolveFile(this.contextService.toResource(path)).then((stat: IFileStat) => { + return this.fileService.resolveFile(resource).then(stat => { return this.editorService.openEditor({ resource: stat.resource, mime: stat.mime, options: { forceOpen: true } - }, sideBySide).then((editor)=> { + }, sideBySide).then(editor => { this.restoreTextViewState(modifiedViewState); if (this.partService.isVisible(Parts.SIDEBAR_PART)) { @@ -222,7 +231,7 @@ class OpenInEditorAction extends baseeditor.EditorInputAction { return null; } - private getPath():string { + private getRepositoryRelativePath():string { var status: IFileStatus = ( this.input).getFileStatus(); if (status.getStatus() === Status.INDEX_RENAMED) { From 0199fc41573efdeb01eb17a44c87af05fb62a23f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 27 Nov 2015 12:29:10 +0100 Subject: [PATCH 174/588] update comments --- src/vs/workbench/browser/parts/editor/binaryEditorModel.ts | 2 +- src/vs/workbench/browser/parts/editor/stringEditorInput.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/binaryEditorModel.ts b/src/vs/workbench/browser/parts/editor/binaryEditorModel.ts index 58b3c6cdc98..92dd238c337 100644 --- a/src/vs/workbench/browser/parts/editor/binaryEditorModel.ts +++ b/src/vs/workbench/browser/parts/editor/binaryEditorModel.ts @@ -8,7 +8,7 @@ import {EditorModel} from 'vs/workbench/common/editor'; import URI from 'vs/base/common/uri'; /** - * An editor model that just represents a URL and mime for a resource that can be loaded. + * An editor model that just represents a resource and mime for a resource that can be loaded. */ export class BinaryEditorModel extends EditorModel { private name: string; diff --git a/src/vs/workbench/browser/parts/editor/stringEditorInput.ts b/src/vs/workbench/browser/parts/editor/stringEditorInput.ts index 3723e1c1b14..8eab1c9a13f 100644 --- a/src/vs/workbench/browser/parts/editor/stringEditorInput.ts +++ b/src/vs/workbench/browser/parts/editor/stringEditorInput.ts @@ -44,7 +44,7 @@ export class StringEditorInput extends EditorInput { } protected getResource(): URI { - // Subclasses can implement to associate a resource URL with the input + // Subclasses can implement to associate a resource with the input return null; } From 5235faf528a7b25f137522853b125a9266094fb8 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 27 Nov 2015 12:44:42 +0100 Subject: [PATCH 175/588] scoped git in dirty diff --- .../git/browser/gitWorkbenchContributions.ts | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/parts/git/browser/gitWorkbenchContributions.ts b/src/vs/workbench/parts/git/browser/gitWorkbenchContributions.ts index cdb3ebcf6d6..b05be24d7e3 100644 --- a/src/vs/workbench/parts/git/browser/gitWorkbenchContributions.ts +++ b/src/vs/workbench/parts/git/browser/gitWorkbenchContributions.ts @@ -9,6 +9,7 @@ import 'vs/css!./media/git.contribution'; import nls = require('vs/nls'); import async = require('vs/base/common/async'); import errors = require('vs/base/common/errors'); +import paths = require('vs/base/common/paths'); import actions = require('vs/base/common/actions'); import lifecycle = require('vs/base/common/lifecycle'); import Severity from 'vs/base/common/severity'; @@ -335,7 +336,19 @@ export class DirtyDiffDecorator implements ext.IWorkbenchContribution { // HACK: This is the best current way of figuring out whether to draw these decorations // or not. Needs context from the editor, to know whether it is a diff editor, in place editor // etc. - var models = this.editorService.getVisibleEditors() + + const repositoryRoot = this.gitService.getModel().getRepositoryRoot(); + + // If there is no repository root, just wait until that changes + if (typeof repositoryRoot !== 'string') { + this.gitService.addOneTimeListener(git.ServiceEvents.STATE_CHANGED, () => this.onEditorInputChange()); + + this.models.forEach(m => this.onModelInvisible(m)); + this.models = []; + return; + } + + const models = this.editorService.getVisibleEditors() // map to the editor controls .map(e => e.getControl()) @@ -354,12 +367,12 @@ export class DirtyDiffDecorator implements ext.IWorkbenchContribution { // remove nulls .filter(p => !!p.resource && - // and ivalid resources - (p.resource.scheme === 'file' && !!this.contextService.isInsideWorkspace(p.resource)) + // and invalid resources + (p.resource.scheme === 'file' && paths.isEqualOrParent(p.resource.fsPath, repositoryRoot)) ) // get paths - .map(p => ({ model: p.model, path: this.contextService.toWorkspaceRelativePath(p.resource) })) + .map(p => ({ model: p.model, path: paths.normalize(paths.relative(repositoryRoot, p.resource.fsPath)) })) // remove nulls and inside .git files .filter(p => !!p.path && p.path.indexOf('.git/') === -1); From e9f4f8df430bdf23c54e38904162211d26711374 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2015 12:05:23 +0100 Subject: [PATCH 176/588] debug: use consolas font for watch expressions input box. --- src/vs/workbench/parts/debug/browser/media/debugViewlet.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/parts/debug/browser/media/debugViewlet.css b/src/vs/workbench/parts/debug/browser/media/debugViewlet.css index 1c0499ae22c..097d9ee3b74 100644 --- a/src/vs/workbench/parts/debug/browser/media/debugViewlet.css +++ b/src/vs/workbench/parts/debug/browser/media/debugViewlet.css @@ -124,6 +124,7 @@ .debug-viewlet .monaco-inputbox { width: 100%; line-height: normal; + font-family: Monaco, Menlo, Consolas, "Droid Sans Mono", "Inconsolata", "Courier New", monospace, "Droid Sans Fallback"; } .debug-viewlet .monaco-inputbox.idle { From ca4d5a03d469d7c8cb630c260fccf028d64314cb Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 27 Nov 2015 12:58:56 +0100 Subject: [PATCH 177/588] fade out out of scope git changes --- .../git/browser/views/changes/changesView.css | 14 +++-- .../browser/views/changes/changesViewer.ts | 61 +++++++++++++------ 2 files changed, 51 insertions(+), 24 deletions(-) diff --git a/src/vs/workbench/parts/git/browser/views/changes/changesView.css b/src/vs/workbench/parts/git/browser/views/changes/changesView.css index 205d1b4c312..ce38ce65488 100644 --- a/src/vs/workbench/parts/git/browser/views/changes/changesView.css +++ b/src/vs/workbench/parts/git/browser/views/changes/changesView.css @@ -60,7 +60,7 @@ .git-viewlet > .changes-view > .status-view > .monaco-tree .monaco-tree-row .status-group { font-size: 11px; - font-weight: bold; + font-weight: bold; text-transform: uppercase; cursor: default; } @@ -84,6 +84,10 @@ color: inherit; } +.git-viewlet > .changes-view > .status-view > .monaco-tree .monaco-tree-row .file-status.out-of-workspace { + opacity: 0.5; +} + .git-viewlet > .changes-view > .status-view > .monaco-tree .monaco-tree-row .file-status .status { position: absolute; top: 4px; @@ -99,7 +103,7 @@ } .git-viewlet > .changes-view > .status-view > .monaco-tree .monaco-tree-row .file-status .name { - margin-left: 20px; + margin-left: 20px; } .git-viewlet > .changes-view > .status-view > .monaco-tree .monaco-tree-row .file-status.modified .status { background-color: #007ACC; } @@ -123,7 +127,7 @@ .git-viewlet > .changes-view > .status-view > .monaco-tree .monaco-tree-row .file-status.both-deleted .name, .git-viewlet > .changes-view > .status-view > .monaco-tree .monaco-tree-row .file-status.deleted-by-them .name, .git-viewlet > .changes-view > .status-view > .monaco-tree .monaco-tree-row .file-status.deleted-by-us .name { - text-decoration: line-through; + text-decoration: line-through; } .git-viewlet > .changes-view > .status-view > .monaco-tree .monaco-tree-row .file-status:not(.renamed) > .rename { @@ -159,8 +163,8 @@ .hc-black .git-viewlet > .changes-view > .status-view > .monaco-tree .monaco-tree-row .file-status.untracked .status, .hc-black .git-viewlet > .changes-view > .status-view > .monaco-tree .monaco-tree-row .file-status.ignored .status, .hc-black .git-viewlet > .changes-view > .status-view > .monaco-tree .monaco-tree-row .file-status.conflict .status, -.hc-black .git-viewlet > .changes-view > .status-view > .monaco-tree .monaco-tree-row.selected .file-status .status { - background-color: #000; +.hc-black .git-viewlet > .changes-view > .status-view > .monaco-tree .monaco-tree-row.selected .file-status .status { + background-color: #000; color: #fff; border: 1px solid #6FC3DF; } \ No newline at end of file diff --git a/src/vs/workbench/parts/git/browser/views/changes/changesViewer.ts b/src/vs/workbench/parts/git/browser/views/changes/changesViewer.ts index 1d5cff6f5e9..bcacf8d6111 100644 --- a/src/vs/workbench/parts/git/browser/views/changes/changesViewer.ts +++ b/src/vs/workbench/parts/git/browser/views/changes/changesViewer.ts @@ -8,6 +8,7 @@ import winjs = require('vs/base/common/winjs.base'); import nls = require('vs/nls'); import platform = require('vs/base/common/platform'); import errors = require('vs/base/common/errors'); +import paths = require('vs/base/common/paths'); import severity from 'vs/base/common/severity'; import lifecycle = require('vs/base/common/lifecycle'); import dom = require('vs/base/browser/dom'); @@ -24,10 +25,12 @@ import actionsrenderer = require('vs/base/parts/tree/browser/actionsRenderer'); import git = require('vs/workbench/parts/git/common/git'); import gitmodel = require('vs/workbench/parts/git/common/gitModel'); import gitactions = require('vs/workbench/parts/git/browser/gitActions'); -import {IContextMenuService} from 'vs/platform/contextview/browser/contextView'; -import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; -import {IMessageService} from 'vs/platform/message/common/message'; -import {CommonKeybindings} from 'vs/base/common/keyCodes'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IMessageService } from 'vs/platform/message/common/message'; +import { CommonKeybindings } from 'vs/base/common/keyCodes'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import URI from 'vs/base/common/uri'; import IGitService = git.IGitService @@ -218,10 +221,14 @@ interface IStatusGroupTemplateData { export class Renderer implements tree.IRenderer { - private messageService: IMessageService; - - constructor(private actionProvider:ActionProvider, private actionRunner: actions.IActionRunner, @IMessageService messageService: IMessageService) { - this.messageService = messageService; + constructor( + private actionProvider:ActionProvider, + private actionRunner: actions.IActionRunner, + @IMessageService private messageService: IMessageService, + @IGitService private gitService: IGitService, + @IWorkspaceContextService private contextService: IWorkspaceContextService + ) { + // noop } public getHeight(tree:tree.ITree, element:any): number { @@ -298,7 +305,7 @@ export class Renderer implements tree.IRenderer { public renderElement(tree: tree.ITree, element: any, templateId: string, templateData: any): void { if (/^file:/.test(templateId)) { - Renderer.renderFileStatus(tree, element, templateData); + this.renderFileStatus(tree, element, templateData); } else { Renderer.renderStatusGroup( element, templateData); } @@ -309,30 +316,46 @@ export class Renderer implements tree.IRenderer { data.count.setCount(statusGroup.all().length); } - private static renderFileStatus(tree: tree.ITree, fileStatus: git.IFileStatus, data: IFileStatusTemplateData): void { + private renderFileStatus(tree: tree.ITree, fileStatus: git.IFileStatus, data: IFileStatusTemplateData): void { data.actionBar.context = { tree: tree, fileStatus: fileStatus }; - var status = fileStatus.getStatus(); - var renamePath = fileStatus.getRename(); - var path = fileStatus.getPath(); - var lastSlashIndex = path.lastIndexOf('/'); - var name = lastSlashIndex === -1 ? path : path.substr(lastSlashIndex + 1, path.length); - var folder = (lastSlashIndex === -1 ? '' : path.substr(0, lastSlashIndex)); + const repositoryRoot = this.gitService.getModel().getRepositoryRoot(); + const workspaceRoot = this.contextService.getWorkspace().resource.fsPath; + + const status = fileStatus.getStatus(); + const renamePath = fileStatus.getRename(); + const path = fileStatus.getPath(); + const lastSlashIndex = path.lastIndexOf('/'); + const name = lastSlashIndex === -1 ? path : path.substr(lastSlashIndex + 1, path.length); + const folder = (lastSlashIndex === -1 ? '' : path.substr(0, lastSlashIndex)); data.root.className = 'file-status ' + Renderer.statusToClass(status); data.status.textContent = Renderer.statusToChar(status); data.status.title = Renderer.statusToTitle(status); + const resource = URI.file(paths.normalize(paths.join(repositoryRoot, path))); + let isInWorkspace = paths.isEqualOrParent(resource.fsPath, workspaceRoot) + + let rename = ''; + let renameFolder = ''; + if (renamePath) { - var renameLastSlashIndex = renamePath.lastIndexOf('/'); - var rename = renameLastSlashIndex === -1 ? renamePath : renamePath.substr(renameLastSlashIndex + 1, renamePath.length); - var renameFolder = (renameLastSlashIndex === -1 ? '' : renamePath.substr(0, renameLastSlashIndex)); + const renameLastSlashIndex = renamePath.lastIndexOf('/'); + rename = renameLastSlashIndex === -1 ? renamePath : renamePath.substr(renameLastSlashIndex + 1, renamePath.length); + renameFolder = (renameLastSlashIndex === -1 ? '' : renamePath.substr(0, renameLastSlashIndex)); data.renameName.textContent = name; data.renameFolder.textContent = folder; + + const resource = URI.file(paths.normalize(paths.join(repositoryRoot, renamePath))); + isInWorkspace = paths.isEqualOrParent(resource.fsPath, workspaceRoot) + } + + if (!isInWorkspace) { + data.root.className += ' out-of-workspace'; } data.name.textContent = rename || name; From 6497432d1c1ea05dea06e32c5decc989fd74562e Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 27 Nov 2015 13:03:11 +0100 Subject: [PATCH 178/588] first steps in exposing language featues as command. done with: hover, definition, workspace symbols --- src/vs/base/common/marshalling.ts | 2 +- .../goToDeclaration/common/goToDeclaration.ts | 21 +- src/vs/editor/contrib/hover/common/hover.ts | 20 +- .../keybinding/common/commandsUtils.ts | 26 +++ .../api/browser/pluginHost.api.impl.ts | 2 + .../common/extHostLanguageFeatureCommands.ts | 107 +++++++++ .../api/common/extHostLanguageFeatures.ts | 29 +-- .../api/common/pluginHostCommands.ts | 14 +- .../api/common/pluginHostTypeConverters.ts | 126 +++++++---- .../workbench/parts/search/common/search.ts | 13 +- .../extHostLanguageFeatureCommands.test.ts | 212 ++++++++++++++++++ .../api/extHostLanguageFeatures.test.ts | 1 + 12 files changed, 498 insertions(+), 75 deletions(-) create mode 100644 src/vs/platform/keybinding/common/commandsUtils.ts create mode 100644 src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts create mode 100644 src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts diff --git a/src/vs/base/common/marshalling.ts b/src/vs/base/common/marshalling.ts index 30dc89ca52d..fb03d036071 100644 --- a/src/vs/base/common/marshalling.ts +++ b/src/vs/base/common/marshalling.ts @@ -29,7 +29,7 @@ var currentDynamicContrib:IMarshallingContribution = null; export function canSerialize(obj: any): boolean { for (let contrib of marshallingContributions) { - if (contrib.canDeserialize(obj)) { + if (contrib.canSerialize(obj)) { return true; } } diff --git a/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts index 2af92d98124..2bccc0b3a44 100644 --- a/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts @@ -7,11 +7,13 @@ import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; -import {onUnexpectedError} from 'vs/base/common/errors'; +import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; import {IModel, IPosition} from 'vs/editor/common/editorCommon'; import {IDeclarationSupport} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import {IReference} from 'vs/editor/common/modes'; +import {IModelService} from 'vs/editor/common/services/modelService'; +import {registerCommand} from 'vs/platform/keybinding/common/commandsUtils'; export const DeclarationRegistry = new LanguageFeatureRegistry('declarationSupport'); @@ -40,4 +42,19 @@ export function getDeclarationsAtPosition(model: IModel, position: IPosition): T } return result; }); -} \ No newline at end of file +} + +registerCommand('_executeDefinitionProvider', function(accessor, args) { + + let {resource, position} = args; + if (!URI.isURI(resource)) { + throw illegalArgument(); + } + + let model = accessor.get(IModelService).getModel(resource); + if (!model) { + throw illegalArgument(resource + ' not found'); + } + + return getDeclarationsAtPosition(model, position); +}); \ No newline at end of file diff --git a/src/vs/editor/contrib/hover/common/hover.ts b/src/vs/editor/contrib/hover/common/hover.ts index 0ffc441ae9c..687cdd4def4 100644 --- a/src/vs/editor/contrib/hover/common/hover.ts +++ b/src/vs/editor/contrib/hover/common/hover.ts @@ -10,8 +10,10 @@ import {IExtraInfoSupport, IComputeExtraInfoResult} from 'vs/editor/common/modes import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import {TPromise} from 'vs/base/common/winjs.base'; import {coalesce} from 'vs/base/common/arrays'; -import {onUnexpectedError} from 'vs/base/common/errors'; +import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; import {IPosition, IModel} from 'vs/editor/common/editorCommon'; +import {IModelService} from 'vs/editor/common/services/modelService'; +import {registerCommand} from 'vs/platform/keybinding/common/commandsUtils'; export const ExtraInfoRegistry = new LanguageFeatureRegistry('extraInfoSupport'); @@ -37,4 +39,18 @@ export function getExtraInfoAtPosition(model: IModel, position: IPosition): TPro }); return TPromise.join(promises).then(() => coalesce(values)); -} \ No newline at end of file +} + +registerCommand('_executeHoverProvider', function(accessor, args) { + + let {resource, position} = args; + if (!URI.isURI(resource)) { + throw illegalArgument(); + } + let model = accessor.get(IModelService).getModel(resource); + if (!model) { + throw illegalArgument(resource + ' not found'); + } + + return getExtraInfoAtPosition(model, position); +}); \ No newline at end of file diff --git a/src/vs/platform/keybinding/common/commandsUtils.ts b/src/vs/platform/keybinding/common/commandsUtils.ts new file mode 100644 index 00000000000..dec5138e8fd --- /dev/null +++ b/src/vs/platform/keybinding/common/commandsUtils.ts @@ -0,0 +1,26 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import {illegalArgument} from 'vs/base/common/errors'; +import {ServicesAccessor} from 'vs/platform/instantiation/common/instantiation'; +import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry'; + +export function registerCommand(id: string, handler: (accessor: ServicesAccessor, args: { [n: string]: any }) => any) { + + KeybindingsRegistry.registerCommandDesc({ + id, + handler(accessor, args: any[]) { + if (args && args.length > 1 || typeof args[0] !== 'object') { + throw illegalArgument(); + } + + return handler(accessor, args && args[0]); + }, + weight: KeybindingsRegistry.WEIGHT.editorContrib(), + primary: undefined, + context: undefined, + }); +} \ No newline at end of file diff --git a/src/vs/workbench/api/browser/pluginHost.api.impl.ts b/src/vs/workbench/api/browser/pluginHost.api.impl.ts index bdc5061e270..85c58b2b349 100644 --- a/src/vs/workbench/api/browser/pluginHost.api.impl.ts +++ b/src/vs/workbench/api/browser/pluginHost.api.impl.ts @@ -22,6 +22,7 @@ import {PluginHostTelemetryService} from 'vs/workbench/api/common/pluginHostTele import {PluginHostEditors} from 'vs/workbench/api/common/pluginHostEditors'; import {ExtHostLanguages} from 'vs/workbench/api/common/extHostLanguages'; import {ExtHostLanguageFeatures} from 'vs/workbench/api/common/extHostLanguageFeatures'; +import {ExtHostLanguageFeatureCommands} from 'vs/workbench/api/common/extHostLanguageFeatureCommands'; import * as extHostTypes from 'vs/workbench/api/common/pluginHostTypes'; import 'vs/workbench/api/common/pluginHostTypes.marshalling'; import {wrapAsWinJSPromise} from 'vs/base/common/async'; @@ -251,6 +252,7 @@ export class PluginHostAPIImplementation { const languages = new ExtHostLanguages(this._threadService); const pluginHostDiagnostics = new PluginHostDiagnostics(this._threadService); const languageFeatures = threadService.getRemotable(ExtHostLanguageFeatures); + const languageFeatureCommand = new ExtHostLanguageFeatureCommands(threadService.getRemotable(PluginHostCommands)); this.languages = { createDiagnosticCollection(name?: string): vscode.DiagnosticCollection { diff --git a/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts new file mode 100644 index 00000000000..ccdd2b7f4dd --- /dev/null +++ b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts @@ -0,0 +1,107 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import URI from 'vs/base/common/uri'; +import Event, {Emitter} from 'vs/base/common/event'; +import Severity from 'vs/base/common/severity'; +import {DefaultFilter} from 'vs/editor/common/modes/modesFilters'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {onUnexpectedError} from 'vs/base/common/errors'; +import {sequence} from 'vs/base/common/async'; +import {Range as EditorRange} from 'vs/editor/common/core/range'; +import {IDisposable} from 'vs/base/common/lifecycle'; +import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; +import {Remotable, IThreadService} from 'vs/platform/thread/common/thread'; +import * as vscode from 'vscode'; +import * as typeConverters from 'vs/workbench/api/common/pluginHostTypeConverters'; +import * as types from 'vs/workbench/api/common/pluginHostTypes'; +import {IPosition, IRange, ISingleEditOperation} from 'vs/editor/common/editorCommon'; +import * as modes from 'vs/editor/common/modes'; +import {CancellationTokenSource} from 'vs/base/common/cancellation'; +import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; +import {IMarkerService, IMarker} from 'vs/platform/markers/common/markers'; +import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; +import {DeclarationRegistry} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; +import {ExtraInfoRegistry} from 'vs/editor/contrib/hover/common/hover'; +import {OccurrencesRegistry} from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; +import {ReferenceRegistry} from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; +import {QuickFixRegistry} from 'vs/editor/contrib/quickFix/common/quickFix'; +import {OutlineRegistry, IOutlineEntry, IOutlineSupport} from 'vs/editor/contrib/quickOpen/common/quickOpen'; +import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; +import {NavigateTypesSupportRegistry, INavigateTypesSupport, ITypeBearing} from 'vs/workbench/parts/search/common/search' +import {RenameRegistry} from 'vs/editor/contrib/rename/common/rename'; +import {FormatRegistry, FormatOnTypeRegistry} from 'vs/editor/contrib/format/common/format'; +import {CodeLensRegistry} from 'vs/editor/contrib/codelens/common/codelens'; +import {ParameterHintsRegistry} from 'vs/editor/contrib/parameterHints/common/parameterHints'; +import {SuggestRegistry} from 'vs/editor/contrib/suggest/common/suggest'; + +// vscode.executeWorkspaceSymbolProvider +// vscode.executeDefinitionProvider +// vscode.executeHoverProvider + +// vscode.executeDocumentHighlights +// vscode.executeReferenceProvider +// vscode.executeCodeActionProvider +// vscode.executeCodeLensProvider +// vscode.executeDocumentSymbolProvider +// vscode.executeDocumentRenameProvider +// vscode.executeFormatDocumentProvider +// vscode.executeFormatRangeProvider +// vscode.executeFormatOnTypeProvider +// vscode.executeSignatureHelpProvider +// vscode.executeCompletionItemProvider + +export class ExtHostLanguageFeatureCommands { + + private _commands: PluginHostCommands; + private _disposables: IDisposable[] = []; + + constructor(commands: PluginHostCommands) { + this._commands = commands; + + this._register('vscode.executeWorkspaceSymbolProvider', this._executeWorkspaceSymbolProvider); + this._register('vscode.executeDefinitionProvider', this._executeDefinitionProvider); + this._register('vscode.executeHoverProvider', this._executeHoverProvider); + } + + private _register(id: string, callback: (...args: any[]) => any): void { + this._disposables.push(this._commands.registerCommand(id, callback, this)); + } + + // --- command impl + + private _executeWorkspaceSymbolProvider(query: string): Thenable { + return this._commands.executeCommand('_executeWorkspaceSymbolProvider', { query }).then(value => { + if (Array.isArray(value)) { + return value.map(typeConverters.toSymbolInformation); + } + }); + } + + private _executeDefinitionProvider(resource: URI, position: types.Position): Thenable { + const args = { + resource, + position: position && typeConverters.fromPosition(position) + }; + return this._commands.executeCommand('_executeDefinitionProvider', args).then(value => { + if (Array.isArray(value)) { + return value.map(typeConverters.toLocation) + } + }); + } + + private _executeHoverProvider(resource: URI, position: types.Position): Thenable { + const args = { + resource, + position: position && typeConverters.fromPosition(position) + }; + return this._commands.executeCommand('_executeHoverProvider', args).then(value => { + if (Array.isArray(value)) { + return value.map(typeConverters.toHover) + } + }); + } +} \ No newline at end of file diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index e638636c307..fe0552a08b4 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -215,20 +215,14 @@ class ExtraInfoAdapter implements modes.IExtraInfoSupport { if (!value) { return; } - - let {range, contents} = value; - - if (!range) { - range = doc.getWordRangeAtPosition(pos); + if (!value.range) { + value.range = doc.getWordRangeAtPosition(pos); } - if (!range) { - range = new Range(pos, pos); + if (!value.range) { + value.range = new Range(pos, pos); } - return { - range: TypeConverters.fromRange(range), - htmlContent: contents && contents.map(TypeConverters.fromFormattedString) - } + return TypeConverters.fromHover(value); }); } } @@ -438,21 +432,10 @@ class NavigateTypeAdapter implements INavigateTypesSupport { getNavigateToItems(search: string): TPromise { return asWinJsPromise(token => this._provider.provideWorkspaceSymbols(search, token)).then(value => { if (Array.isArray(value)) { - return value.map(NavigateTypeAdapter._fromSymbolInformation); + return value.map(TypeConverters.fromSymbolInformation); } }); } - - private static _fromSymbolInformation(info: vscode.SymbolInformation): ITypeBearing { - return { - name: info.name, - type: SymbolKind[info.kind || SymbolKind.Property].toLowerCase(), - range: TypeConverters.fromRange(info.location.range), - resourceUri: info.location.uri, - containerName: info.containerName, - parameters: '', - }; - } } class RenameAdapter implements modes.IRenameSupport { diff --git a/src/vs/workbench/api/common/pluginHostCommands.ts b/src/vs/workbench/api/common/pluginHostCommands.ts index 43e01007d31..bc57ffe3992 100644 --- a/src/vs/workbench/api/common/pluginHostCommands.ts +++ b/src/vs/workbench/api/common/pluginHostCommands.ts @@ -78,13 +78,13 @@ export class PluginHostCommands { return this._executeContributedCommand(id, ...args); } else { - // check that we can get all parameters over to - // the other side - for (let i = 0; i < args.length; i++) { - if (typeof args[i] === 'object' && !canSerialize(args[i])) { - throw new Error('illegal argument - can not serialize argument number: ' + i) - } - } + // // check that we can get all parameters over to + // // the other side + // for (let i = 0; i < args.length; i++) { + // if (args[i] !== null && typeof args[i] === 'object' && !canSerialize(args[i])) { + // throw new Error('illegal argument - can not serialize argument number: ' + i) + // } + // } return this._proxy._executeCommand(id, args); } diff --git a/src/vs/workbench/api/common/pluginHostTypeConverters.ts b/src/vs/workbench/api/common/pluginHostTypeConverters.ts index f87fa4d2617..80448162cd4 100644 --- a/src/vs/workbench/api/common/pluginHostTypeConverters.ts +++ b/src/vs/workbench/api/common/pluginHostTypeConverters.ts @@ -6,10 +6,12 @@ import Severity from 'vs/base/common/severity'; import * as objects from 'vs/base/common/objects'; +import * as modes from 'vs/editor/common/modes'; +import * as types from './pluginHostTypes'; import {Position as EditorPosition} from 'vs/platform/editor/common/editor'; -import {Selection, Range, Position, SymbolKind, DiagnosticSeverity, ViewColumn} from './pluginHostTypes'; import {IPosition, ISelection, IRange, IRangeWithMessage, ISingleEditOperation} from 'vs/editor/common/editorCommon'; import {IHTMLContentElement} from 'vs/base/common/htmlContent'; +import {ITypeBearing} from 'vs/workbench/parts/search/common/search' export interface PositionLike { line: number; @@ -26,11 +28,11 @@ export interface SelectionLike extends RangeLike { active: PositionLike; } -export function toSelection(selection: ISelection): Selection { +export function toSelection(selection: ISelection): types.Selection { let {selectionStartLineNumber, selectionStartColumn, positionLineNumber, positionColumn} = selection; - let start = new Position(selectionStartLineNumber - 1, selectionStartColumn - 1); - let end = new Position(positionLineNumber - 1, positionColumn - 1); - return new Selection(start, end); + let start = new types.Position(selectionStartLineNumber - 1, selectionStartColumn - 1); + let end = new types.Position(positionLineNumber - 1, positionColumn - 1); + return new types.Selection(start, end); } export function fromSelection(selection: SelectionLike): ISelection { @@ -53,46 +55,50 @@ export function fromRange(range: RangeLike): IRange { }; } -export function toRange(range: IRange): Range { +export function toRange(range: IRange): types.Range { let {startLineNumber, startColumn, endLineNumber, endColumn} = range; - return new Range(startLineNumber - 1, startColumn - 1, endLineNumber - 1, endColumn - 1); + return new types.Range(startLineNumber - 1, startColumn - 1, endLineNumber - 1, endColumn - 1); } -export function toPosition(position: IPosition): Position { - return new Position(position.lineNumber - 1, position.column - 1); +export function toPosition(position: IPosition): types.Position { + return new types.Position(position.lineNumber - 1, position.column - 1); } -export function fromSymbolKind(kind: number | SymbolKind): string { +export function fromPosition(position: types.Position):IPosition { + return { lineNumber: position.line + 1, column: position.character + 1}; +} + +export function fromSymbolKind(kind: number | types.SymbolKind): string { switch (kind) { - case SymbolKind.Method: + case types.SymbolKind.Method: return 'method'; - case SymbolKind.Function: + case types.SymbolKind.Function: return 'function'; - case SymbolKind.Constructor: + case types.SymbolKind.Constructor: return 'constructor'; - case SymbolKind.Variable: + case types.SymbolKind.Variable: return 'variable'; - case SymbolKind.Class: + case types.SymbolKind.Class: return 'class'; - case SymbolKind.Interface: + case types.SymbolKind.Interface: return 'interface'; - case SymbolKind.Module: - case SymbolKind.Namespace: - case SymbolKind.Package: + case types.SymbolKind.Module: + case types.SymbolKind.Namespace: + case types.SymbolKind.Package: return 'module'; - case SymbolKind.Property: + case types.SymbolKind.Property: return 'property'; - case SymbolKind.Enum: + case types.SymbolKind.Enum: return 'enum'; - case SymbolKind.String: + case types.SymbolKind.String: return 'string'; - case SymbolKind.File: + case types.SymbolKind.File: return 'file'; - case SymbolKind.Array: + case types.SymbolKind.Array: return 'array'; - case SymbolKind.Number: + case types.SymbolKind.Number: return 'number'; - case SymbolKind.Boolean: + case types.SymbolKind.Boolean: return 'boolean'; } @@ -101,39 +107,39 @@ export function fromSymbolKind(kind: number | SymbolKind): string { export function fromDiagnosticSeverity(value: number): Severity { switch (value) { - case DiagnosticSeverity.Error: + case types.DiagnosticSeverity.Error: return Severity.Error; - case DiagnosticSeverity.Warning: + case types.DiagnosticSeverity.Warning: return Severity.Warning; - case DiagnosticSeverity.Information: + case types.DiagnosticSeverity.Information: return Severity.Info; - case DiagnosticSeverity.Hint: + case types.DiagnosticSeverity.Hint: return Severity.Ignore; } return Severity.Error; } -export function toDiagnosticSeverty(value: Severity): DiagnosticSeverity { +export function toDiagnosticSeverty(value: Severity): types.DiagnosticSeverity { switch (value) { case Severity.Info: - return DiagnosticSeverity.Information; + return types.DiagnosticSeverity.Information; case Severity.Warning: - return DiagnosticSeverity.Warning; + return types.DiagnosticSeverity.Warning; case Severity.Error: - return DiagnosticSeverity.Error; + return types.DiagnosticSeverity.Error; case Severity.Ignore: - return DiagnosticSeverity.Hint; + return types.DiagnosticSeverity.Hint; } - return DiagnosticSeverity.Error; + return types.DiagnosticSeverity.Error; } export function fromViewColumn(column?: vscode.ViewColumn): EditorPosition { let editorColumn = EditorPosition.LEFT; if (typeof column !== 'number') { // stick with LEFT - } else if (column === ViewColumn.Two) { + } else if (column === types.ViewColumn.Two) { editorColumn = EditorPosition.CENTER; - } else if (column === ViewColumn.Three) { + } else if (column === types.ViewColumn.Three) { editorColumn = EditorPosition.RIGHT; } return editorColumn; @@ -148,6 +154,14 @@ export function fromFormattedString(value: vscode.MarkedString): IHTMLContentEle } } +export function toFormattedString(value: IHTMLContentElement): vscode.MarkedString { + if (typeof value.code === 'string') { + return value.code; + } + let {formattedText, text} = value; + return formattedText || text || ''; +} + function isMarkedStringArr(something: vscode.MarkedString | vscode.MarkedString[]): something is vscode.MarkedString[] { return Array.isArray(something); } @@ -195,4 +209,40 @@ export function fromTextEdit(edit: vscode.TextEdit) { text: edit.newText, range: fromRange(edit.range) } +} + +export function fromSymbolInformation(info: vscode.SymbolInformation): ITypeBearing { + return { + name: info.name, + type: types.SymbolKind[info.kind || types.SymbolKind.Property].toLowerCase(), + range: fromRange(info.location.range), + resourceUri: info.location.uri, + containerName: info.containerName, + parameters: '', + }; +} + +export function toSymbolInformation(bearing: ITypeBearing): types.SymbolInformation { + return new types.SymbolInformation(bearing.name, + types.SymbolKind[bearing.type.charAt(0).toUpperCase() + bearing.type.substr(1)], + toRange(bearing.range), + bearing.resourceUri, + bearing.containerName); +} + + +export function toLocation(reference: modes.IReference): types.Location { + return new types.Location(reference.resource, toRange(reference.range)); +} + + +export function fromHover(hover: vscode.Hover): modes.IComputeExtraInfoResult { + return { + range: fromRange(hover.range), + htmlContent: hover.contents.map(fromFormattedString) + } +} + +export function toHover(info: modes.IComputeExtraInfoResult): types.Hover { + return new types.Hover(info.htmlContent.map(toFormattedString), toRange(info.range)); } \ No newline at end of file diff --git a/src/vs/workbench/parts/search/common/search.ts b/src/vs/workbench/parts/search/common/search.ts index b62874ccf73..b8e13192400 100644 --- a/src/vs/workbench/parts/search/common/search.ts +++ b/src/vs/workbench/parts/search/common/search.ts @@ -6,11 +6,12 @@ 'use strict'; import {TPromise} from 'vs/base/common/winjs.base'; -import {onUnexpectedError} from 'vs/base/common/errors'; +import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; import {IDisposable} from 'vs/base/common/lifecycle'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import {IRange} from 'vs/editor/common/editorCommon'; import URI from 'vs/base/common/uri'; +import {registerCommand} from 'vs/platform/keybinding/common/commandsUtils'; /** * Interface used to navigate to types by value. @@ -72,4 +73,12 @@ export function getNavigateToItems(query: string): TPromise { } return result; }); -} \ No newline at end of file +} + +registerCommand('_executeWorkspaceSymbolProvider', function(accessor, args: { query: string;}) { + let {query} = args; + if (typeof query !== 'string') { + throw illegalArgument(); + } + return getNavigateToItems(query); +}); diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts new file mode 100644 index 00000000000..c5eeb9052ea --- /dev/null +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts @@ -0,0 +1,212 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as assert from 'assert'; +import {setUnexpectedErrorHandler, errorHandler} from 'vs/base/common/errors'; +import {create} from 'vs/base/common/types'; +import URI from 'vs/base/common/uri'; +import {URL} from 'vs/base/common/network'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {PluginHostDocument} from 'vs/workbench/api/common/pluginHostDocuments'; +import * as types from 'vs/workbench/api/common/pluginHostTypes'; +import {Range as CodeEditorRange} from 'vs/editor/common/core/range'; +import * as EditorCommon from 'vs/editor/common/editorCommon'; +import {Model as EditorModel} from 'vs/editor/common/model/model'; +import threadService from './testThreadService' +import {create as createInstantiationService} from 'vs/platform/instantiation/common/instantiationService'; +import {MarkerService} from 'vs/platform/markers/common/markerService'; +import {IMarkerService} from 'vs/platform/markers/common/markers'; +import {IThreadService} from 'vs/platform/thread/common/thread'; +import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; +import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry'; +import {IModelService} from 'vs/editor/common/services/modelService'; +import {ExtHostLanguageFeatures, MainThreadLanguageFeatures} from 'vs/workbench/api/common/extHostLanguageFeatures'; +import {ExtHostLanguageFeatureCommands} from 'vs/workbench/api/common/extHostLanguageFeatureCommands'; +import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; +import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; +import {SyncDescriptor0} from 'vs/platform/instantiation/common/descriptors'; +import {LanguageSelector, ModelLike} from 'vs/editor/common/modes/languageSelector'; +import {OutlineRegistry, getOutlineEntries} from 'vs/editor/contrib/quickOpen/common/quickOpen'; +import {CodeLensRegistry, getCodeLensData} from 'vs/editor/contrib/codelens/common/codelens'; +import {DeclarationRegistry, getDeclarationsAtPosition} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; +import {ExtraInfoRegistry, getExtraInfoAtPosition} from 'vs/editor/contrib/hover/common/hover'; +import {OccurrencesRegistry, getOccurrencesAtPosition} from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; +import {ReferenceRegistry, findReferences} from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; +import {getQuickFixes} from 'vs/editor/contrib/quickFix/common/quickFix'; +import {getNavigateToItems} from 'vs/workbench/parts/search/common/search'; +import {rename} from 'vs/editor/contrib/rename/common/rename'; +import {getParameterHints} from 'vs/editor/contrib/parameterHints/common/parameterHints'; + +const defaultSelector = { scheme: 'far' }; +const model: EditorCommon.IModel = new EditorModel( + [ + 'This is the first line', + 'This is the second line', + 'This is the third line', + ].join('\n'), + undefined, + URL.fromUri(URI.parse('far://testing/file.b'))); + +let extHost: ExtHostLanguageFeatures; +let mainThread: MainThreadLanguageFeatures; +let commands: PluginHostCommands; +let disposables: vscode.Disposable[] = []; + +suite('ExtHostLanguageFeatureCommands', function() { + + suiteSetup(() => { + + let instantiationService = createInstantiationService(); + threadService.setInstantiationService(instantiationService); + instantiationService.addSingleton(IMarkerService, new MarkerService(threadService)); + instantiationService.addSingleton(IThreadService, threadService); + instantiationService.addSingleton(IModelService, { + serviceId: IModelService, + getModel():any { return model; }, + createModel():any { throw new Error(); }, + destroyModel():any { throw new Error(); }, + getModels():any { throw new Error(); }, + onModelAdded: undefined, + onModelModeChanged: undefined, + onModelRemoved: undefined + }); + instantiationService.addSingleton(IKeybindingService, { + executeCommand(id, args):any { + let handler = KeybindingsRegistry.getCommands()[id]; + return TPromise.as(instantiationService.invokeFunction(handler, args)); + } + }) + + threadService.getRemotable(PluginHostModelService)._acceptModelAdd({ + isDirty: false, + versionId: model.getVersionId(), + modeId: model.getModeId(), + url: model.getAssociatedResource(), + value: { + EOL: model.getEOL(), + lines: model.getValue().split(model.getEOL()), + BOM: '', + length: -1 + }, + }); + + threadService.getRemotable(MainThreadCommands); + commands = threadService.getRemotable(PluginHostCommands); + new ExtHostLanguageFeatureCommands(commands); + mainThread = threadService.getRemotable(MainThreadLanguageFeatures); + extHost = threadService.getRemotable(ExtHostLanguageFeatures); + }); + + suiteTeardown(() => { + model.dispose(); + }); + + teardown(function(done) { + while (disposables.length) { + disposables.pop().dispose(); + } + threadService.sync() + .then(() => done(), err => done(err)); + }); + + // --- workspace symbols + + test('WorkspaceSymbols, invalid arguments', function(done) { + let promises = [ + commands.executeCommand('vscode.executeWorkspaceSymbolProvider'), + commands.executeCommand('vscode.executeWorkspaceSymbolProvider', null), + commands.executeCommand('vscode.executeWorkspaceSymbolProvider', undefined), + commands.executeCommand('vscode.executeWorkspaceSymbolProvider', true) + ]; + + threadService.sync().then(() => { + TPromise.join(promises).then(undefined, (err: any[]) => { + assert.equal(err.length, 4); + done(); + return []; + }); + }); + }); + + test('WorkspaceSymbols, ⇔ back and forth', function(done) { + + disposables.push(extHost.registerWorkspaceSymbolProvider({ + provideWorkspaceSymbols(query): any { + return [ + new types.SymbolInformation(query, types.SymbolKind.Array, new types.Range(0, 0, 1, 1), URI.parse('far://testing/first')), + new types.SymbolInformation(query, types.SymbolKind.Array, new types.Range(0, 0, 1, 1), URI.parse('far://testing/second')) + ] + } + })); + + disposables.push(extHost.registerWorkspaceSymbolProvider({ + provideWorkspaceSymbols(query): any { + return [ + new types.SymbolInformation(query, types.SymbolKind.Array, new types.Range(0, 0, 1, 1), URI.parse('far://testing/first')) + ] + } + })); + + threadService.sync().then(() => { + commands.executeCommand('vscode.executeWorkspaceSymbolProvider', 'testing').then(value => { + + for (let info of value) { + assert.ok(info instanceof types.SymbolInformation); + assert.equal(info.name, 'testing'); + assert.equal(info.kind, types.SymbolKind.Array); + } + assert.equal(value.length, 3); + done(); + }); + }); + }); + + + // --- definition + + test('Definition, invalid arguments', function(done) { + let promises = [ + commands.executeCommand('vscode.executeDefinitionProvider'), + commands.executeCommand('vscode.executeDefinitionProvider', null), + commands.executeCommand('vscode.executeDefinitionProvider', undefined), + commands.executeCommand('vscode.executeDefinitionProvider', true, false) + ]; + + threadService.sync().then(() => { + TPromise.join(promises).then(undefined, (err: any[]) => { + assert.equal(err.length, 4); + done(); + return []; + }); + }); + }); + + test('Definition, ⇔ back and forth', function(done) { + + disposables.push(extHost.registerDefinitionProvider(defaultSelector, { + provideDefinition(doc:any): any { + return new types.Location(doc.uri, new types.Range(0, 0, 0, 0)); + } + })); + disposables.push(extHost.registerDefinitionProvider(defaultSelector, { + provideDefinition(doc: any): any { + return [ + new types.Location(doc.uri, new types.Range(0, 0, 0, 0)), + new types.Location(doc.uri, new types.Range(0, 0, 0, 0)), + new types.Location(doc.uri, new types.Range(0, 0, 0, 0)), + ] + } + })); + + threadService.sync().then(() => { + commands.executeCommand('vscode.executeDefinitionProvider', model.getAssociatedResource(), new types.Position(0, 0)).then(values => { + assert.equal(values.length, 4); + done(); + }); + }); + }) +}); \ No newline at end of file diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts index 6c5073e6325..875d3fd2a20 100644 --- a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts @@ -85,6 +85,7 @@ suite('ExtHostLanguageFeatures', function() { suiteTeardown(() => { setUnexpectedErrorHandler(originalErrorHandler); + model.dispose(); }); teardown(function(done) { From d433dfd6d89e18236013bcd792d449c14c2c8894 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 27 Nov 2015 14:54:30 +0100 Subject: [PATCH 179/588] add utility method for the 80% case, add doc highlights command --- src/vs/editor/common/core/position.ts | 2 +- .../editor/common/editorCommonExtensions.ts | 39 ++++++++++++++++++- .../goToDeclaration/common/goToDeclaration.ts | 20 ++-------- src/vs/editor/contrib/hover/common/hover.ts | 20 ++-------- .../wordHighlighter/common/wordHighlighter.ts | 5 ++- .../keybinding/common/commandsUtils.ts | 26 ------------- .../common/extHostLanguageFeatureCommands.ts | 15 ++++++- .../api/common/pluginHostTypeConverters.ts | 5 +++ .../workbench/parts/search/common/search.ts | 4 +- .../test/common/api/testThreadService.ts | 2 +- 10 files changed, 70 insertions(+), 68 deletions(-) delete mode 100644 src/vs/platform/keybinding/common/commandsUtils.ts diff --git a/src/vs/editor/common/core/position.ts b/src/vs/editor/common/core/position.ts index 6be595f7927..a0b8e7e1af6 100644 --- a/src/vs/editor/common/core/position.ts +++ b/src/vs/editor/common/core/position.ts @@ -54,7 +54,7 @@ export class Position implements EditorCommon.IEditorPosition { return new Position(pos.lineNumber, pos.column); } - public static isIPosition(obj: any): boolean { + public static isIPosition(obj: any): obj is EditorCommon.IPosition { return ( obj && (typeof obj.lineNumber === 'number') diff --git a/src/vs/editor/common/editorCommonExtensions.ts b/src/vs/editor/common/editorCommonExtensions.ts index 231adc2bdcb..cc9c9b2f6aa 100644 --- a/src/vs/editor/common/editorCommonExtensions.ts +++ b/src/vs/editor/common/editorCommonExtensions.ts @@ -5,10 +5,13 @@ 'use strict'; import EditorCommon = require('vs/editor/common/editorCommon'); +import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; +import URI from 'vs/base/common/uri'; +import {Position} from 'vs/editor/common/core/position'; import {ServicesAccessor} from 'vs/platform/instantiation/common/instantiation'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; +import {IModelService} from 'vs/editor/common/services/modelService'; import {Registry} from 'vs/platform/platform'; -import Errors = require('vs/base/common/errors'); import {KeybindingsRegistry,ICommandDescriptor} from 'vs/platform/keybinding/common/keybindingsRegistry'; import config = require('vs/editor/common/config/config'); import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; @@ -84,6 +87,38 @@ export module CommonEditorRegistry { KeybindingsRegistry.registerCommandDesc(commandDesc); } + + export function registerLanguageCommand(id: string, handler: (accessor: ServicesAccessor, args: { [n: string]: any }) => any) { + KeybindingsRegistry.registerCommandDesc({ + id, + handler(accessor, args: any[]) { + if (args && args.length > 1 || typeof args[0] !== 'object') { + throw illegalArgument(); + } + return handler(accessor, args && args[0]); + }, + weight: KeybindingsRegistry.WEIGHT.editorContrib(), + primary: undefined, + context: undefined, + }); + } + + export function registerDefaultLanguageCommand(id: string, handler: (model: EditorCommon.IModel, position: EditorCommon.IPosition) => any) { + registerLanguageCommand(id, function(accessor, args) { + + const {resource, position} = args; + if (!URI.isURI(resource) || !Position.isIPosition(position)) { + throw illegalArgument(); + } + + const model = accessor.get(IModelService).getModel(resource); + if (!model) { + throw illegalArgument(); + } + + return handler(model, position); + }); + } } class SimpleEditorContributionDescriptor implements EditorCommon.ICommonEditorContributionDescriptor { @@ -193,7 +228,7 @@ function triggerEditorActionGlobal(actionId: string, accessor: ServicesAccessor, var action = activeEditor.getAction(actionId); if (action) { accessor.get(ITelemetryService).publicLog('editorActionInvoked', {name: action.label} ); - action.run().done(null, Errors.onUnexpectedError); + action.run().done(null, onUnexpectedError); } return; } diff --git a/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts index 2bccc0b3a44..c2839a915d3 100644 --- a/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts @@ -7,13 +7,12 @@ import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; -import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; +import {onUnexpectedError} from 'vs/base/common/errors'; import {IModel, IPosition} from 'vs/editor/common/editorCommon'; import {IDeclarationSupport} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import {IReference} from 'vs/editor/common/modes'; -import {IModelService} from 'vs/editor/common/services/modelService'; -import {registerCommand} from 'vs/platform/keybinding/common/commandsUtils'; +import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; export const DeclarationRegistry = new LanguageFeatureRegistry('declarationSupport'); @@ -44,17 +43,4 @@ export function getDeclarationsAtPosition(model: IModel, position: IPosition): T }); } -registerCommand('_executeDefinitionProvider', function(accessor, args) { - - let {resource, position} = args; - if (!URI.isURI(resource)) { - throw illegalArgument(); - } - - let model = accessor.get(IModelService).getModel(resource); - if (!model) { - throw illegalArgument(resource + ' not found'); - } - - return getDeclarationsAtPosition(model, position); -}); \ No newline at end of file +CommonEditorRegistry.registerDefaultLanguageCommand('_executeDefinitionProvider', getDeclarationsAtPosition) \ No newline at end of file diff --git a/src/vs/editor/contrib/hover/common/hover.ts b/src/vs/editor/contrib/hover/common/hover.ts index 687cdd4def4..127e658672b 100644 --- a/src/vs/editor/contrib/hover/common/hover.ts +++ b/src/vs/editor/contrib/hover/common/hover.ts @@ -5,15 +5,13 @@ 'use strict'; -import URI from 'vs/base/common/uri'; import {IExtraInfoSupport, IComputeExtraInfoResult} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import {TPromise} from 'vs/base/common/winjs.base'; import {coalesce} from 'vs/base/common/arrays'; -import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; +import {onUnexpectedError} from 'vs/base/common/errors'; import {IPosition, IModel} from 'vs/editor/common/editorCommon'; -import {IModelService} from 'vs/editor/common/services/modelService'; -import {registerCommand} from 'vs/platform/keybinding/common/commandsUtils'; +import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; export const ExtraInfoRegistry = new LanguageFeatureRegistry('extraInfoSupport'); @@ -41,16 +39,4 @@ export function getExtraInfoAtPosition(model: IModel, position: IPosition): TPro return TPromise.join(promises).then(() => coalesce(values)); } -registerCommand('_executeHoverProvider', function(accessor, args) { - - let {resource, position} = args; - if (!URI.isURI(resource)) { - throw illegalArgument(); - } - let model = accessor.get(IModelService).getModel(resource); - if (!model) { - throw illegalArgument(resource + ' not found'); - } - - return getExtraInfoAtPosition(model, position); -}); \ No newline at end of file +CommonEditorRegistry.registerDefaultLanguageCommand('_executeHoverProvider', getExtraInfoAtPosition); \ No newline at end of file diff --git a/src/vs/editor/contrib/wordHighlighter/common/wordHighlighter.ts b/src/vs/editor/contrib/wordHighlighter/common/wordHighlighter.ts index 5d817a7ad28..45f31cc9be9 100644 --- a/src/vs/editor/contrib/wordHighlighter/common/wordHighlighter.ts +++ b/src/vs/editor/contrib/wordHighlighter/common/wordHighlighter.ts @@ -10,9 +10,10 @@ import * as EditorCommon from 'vs/editor/common/editorCommon'; import {IOccurrencesSupport, IOccurence} from 'vs/editor/common/modes'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; import {Range} from 'vs/editor/common/core/range'; -import {onUnexpectedError} from 'vs/base/common/errors'; +import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; import {INullService} from 'vs/platform/instantiation/common/instantiation'; import {sequence} from 'vs/base/common/async'; +import {IModelService} from 'vs/editor/common/services/modelService'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; export const OccurrencesRegistry = new LanguageFeatureRegistry('occurrencesSupport'); @@ -44,6 +45,8 @@ export function getOccurrencesAtPosition(model: EditorCommon.IModel, position: E }); } +CommonEditorRegistry.registerDefaultLanguageCommand('_executeDocumentHighlights', getOccurrencesAtPosition); + class WordHighlighter { private editor: EditorCommon.ICommonCodeEditor; diff --git a/src/vs/platform/keybinding/common/commandsUtils.ts b/src/vs/platform/keybinding/common/commandsUtils.ts deleted file mode 100644 index dec5138e8fd..00000000000 --- a/src/vs/platform/keybinding/common/commandsUtils.ts +++ /dev/null @@ -1,26 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import {illegalArgument} from 'vs/base/common/errors'; -import {ServicesAccessor} from 'vs/platform/instantiation/common/instantiation'; -import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry'; - -export function registerCommand(id: string, handler: (accessor: ServicesAccessor, args: { [n: string]: any }) => any) { - - KeybindingsRegistry.registerCommandDesc({ - id, - handler(accessor, args: any[]) { - if (args && args.length > 1 || typeof args[0] !== 'object') { - throw illegalArgument(); - } - - return handler(accessor, args && args[0]); - }, - weight: KeybindingsRegistry.WEIGHT.editorContrib(), - primary: undefined, - context: undefined, - }); -} \ No newline at end of file diff --git a/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts index ccdd2b7f4dd..d437b726624 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts @@ -41,8 +41,8 @@ import {SuggestRegistry} from 'vs/editor/contrib/suggest/common/suggest'; // vscode.executeWorkspaceSymbolProvider // vscode.executeDefinitionProvider // vscode.executeHoverProvider - // vscode.executeDocumentHighlights + // vscode.executeReferenceProvider // vscode.executeCodeActionProvider // vscode.executeCodeLensProvider @@ -65,6 +65,7 @@ export class ExtHostLanguageFeatureCommands { this._register('vscode.executeWorkspaceSymbolProvider', this._executeWorkspaceSymbolProvider); this._register('vscode.executeDefinitionProvider', this._executeDefinitionProvider); this._register('vscode.executeHoverProvider', this._executeHoverProvider); + this._register('vscode.executeDocumentHighlights', this._executeDocumentHighlights); } private _register(id: string, callback: (...args: any[]) => any): void { @@ -104,4 +105,16 @@ export class ExtHostLanguageFeatureCommands { } }); } + + private _executeDocumentHighlights(resource: URI, position: types.Position): Thenable { + const args = { + resource, + position: position && typeConverters.fromPosition(position) + }; + return this._commands.executeCommand('_executeDocumentHighlights', args).then(value => { + if (Array.isArray(value)) { + return value.map(typeConverters.toDocumentHighlight) + } + }); + } } \ No newline at end of file diff --git a/src/vs/workbench/api/common/pluginHostTypeConverters.ts b/src/vs/workbench/api/common/pluginHostTypeConverters.ts index 80448162cd4..2dddc1b71ae 100644 --- a/src/vs/workbench/api/common/pluginHostTypeConverters.ts +++ b/src/vs/workbench/api/common/pluginHostTypeConverters.ts @@ -245,4 +245,9 @@ export function fromHover(hover: vscode.Hover): modes.IComputeExtraInfoResult { export function toHover(info: modes.IComputeExtraInfoResult): types.Hover { return new types.Hover(info.htmlContent.map(toFormattedString), toRange(info.range)); +} + +export function toDocumentHighlight(occurrence: modes.IOccurence): types.DocumentHighlight { + return new types.DocumentHighlight(toRange(occurrence.range), + types.DocumentHighlightKind[occurrence.kind.charAt(0).toUpperCase() + occurrence.kind.substr(1)]); } \ No newline at end of file diff --git a/src/vs/workbench/parts/search/common/search.ts b/src/vs/workbench/parts/search/common/search.ts index b8e13192400..07418a9d381 100644 --- a/src/vs/workbench/parts/search/common/search.ts +++ b/src/vs/workbench/parts/search/common/search.ts @@ -9,9 +9,9 @@ import {TPromise} from 'vs/base/common/winjs.base'; import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; import {IDisposable} from 'vs/base/common/lifecycle'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; +import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; import {IRange} from 'vs/editor/common/editorCommon'; import URI from 'vs/base/common/uri'; -import {registerCommand} from 'vs/platform/keybinding/common/commandsUtils'; /** * Interface used to navigate to types by value. @@ -75,7 +75,7 @@ export function getNavigateToItems(query: string): TPromise { }); } -registerCommand('_executeWorkspaceSymbolProvider', function(accessor, args: { query: string;}) { +CommonEditorRegistry.registerLanguageCommand('_executeWorkspaceSymbolProvider', function(accessor, args: { query: string;}) { let {query} = args; if (typeof query !== 'string') { throw illegalArgument(); diff --git a/src/vs/workbench/test/common/api/testThreadService.ts b/src/vs/workbench/test/common/api/testThreadService.ts index 6bf5118e96a..39755b1f3a0 100644 --- a/src/vs/workbench/test/common/api/testThreadService.ts +++ b/src/vs/workbench/test/common/api/testThreadService.ts @@ -24,7 +24,7 @@ export class TestThreadService extends NullThreadService { private set _callCount(value:number) { this._callCountValue = value; if (this._callCountValue === 0) { - this._completeIdle(); + this._completeIdle && this._completeIdle(); this._idle = undefined; } } From 9a8acb1d693e903c36d37ebf33d817fa7f633c75 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 27 Nov 2015 15:01:48 +0100 Subject: [PATCH 180/588] outside workspace title --- .../parts/git/browser/views/changes/changesViewer.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/git/browser/views/changes/changesViewer.ts b/src/vs/workbench/parts/git/browser/views/changes/changesViewer.ts index bcacf8d6111..5d0873ee16f 100644 --- a/src/vs/workbench/parts/git/browser/views/changes/changesViewer.ts +++ b/src/vs/workbench/parts/git/browser/views/changes/changesViewer.ts @@ -354,7 +354,10 @@ export class Renderer implements tree.IRenderer { isInWorkspace = paths.isEqualOrParent(resource.fsPath, workspaceRoot) } - if (!isInWorkspace) { + if (isInWorkspace) { + data.root.title = ''; + } else { + data.root.title = nls.localize('outsideOfWorkspace', "This file is located outside the current workspace."); data.root.className += ' out-of-workspace'; } From bd08c298692dae2d7d29c3320f062c8bcdb11aad Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 27 Nov 2015 15:03:23 +0100 Subject: [PATCH 181/588] semicolon --- .../workbench/parts/git/browser/views/changes/changesViewer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/git/browser/views/changes/changesViewer.ts b/src/vs/workbench/parts/git/browser/views/changes/changesViewer.ts index 5d0873ee16f..05c61e0ec70 100644 --- a/src/vs/workbench/parts/git/browser/views/changes/changesViewer.ts +++ b/src/vs/workbench/parts/git/browser/views/changes/changesViewer.ts @@ -337,7 +337,7 @@ export class Renderer implements tree.IRenderer { data.status.title = Renderer.statusToTitle(status); const resource = URI.file(paths.normalize(paths.join(repositoryRoot, path))); - let isInWorkspace = paths.isEqualOrParent(resource.fsPath, workspaceRoot) + let isInWorkspace = paths.isEqualOrParent(resource.fsPath, workspaceRoot); let rename = ''; let renameFolder = ''; From d0e5e4ad315c688c8aed9b4fce284799cf504552 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 27 Nov 2015 15:06:02 +0100 Subject: [PATCH 182/588] executeReferenceProvider-command --- .../referenceSearch/common/referenceSearch.ts | 4 +++- .../api/common/extHostLanguageFeatureCommands.ts | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/referenceSearch/common/referenceSearch.ts b/src/vs/editor/contrib/referenceSearch/common/referenceSearch.ts index df94dd6e558..143886d49fc 100644 --- a/src/vs/editor/contrib/referenceSearch/common/referenceSearch.ts +++ b/src/vs/editor/contrib/referenceSearch/common/referenceSearch.ts @@ -10,12 +10,12 @@ import {IModel, IPosition} from 'vs/editor/common/editorCommon'; import {TPromise} from 'vs/base/common/winjs.base'; import {onUnexpectedError} from 'vs/base/common/errors'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; +import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; export const ReferenceRegistry = new LanguageFeatureRegistry('referenceSupport'); export function findReferences(model: IModel, position: IPosition): TPromise { - // collect references from all providers const promises = ReferenceRegistry.ordered(model).map(provider => { return provider.findReferences(model.getAssociatedResource(), position, true).then(result => { @@ -37,3 +37,5 @@ export function findReferences(model: IModel, position: IPosition): TPromise any): void { @@ -117,4 +118,16 @@ export class ExtHostLanguageFeatureCommands { } }); } + + private _executeReferenceProvider(resource: URI, position: types.Position): Thenable { + const args = { + resource, + position: position && typeConverters.fromPosition(position) + }; + return this._commands.executeCommand('_executeDocumentHighlights', args).then(value => { + if (Array.isArray(value)) { + return value.map(typeConverters.toLocation) + } + }); + } } \ No newline at end of file From abeba5d17674eb81b36592c6c6cf8a678ce81c9c Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 27 Nov 2015 15:06:44 +0100 Subject: [PATCH 183/588] fix git services onEditorInputChanged --- .../git/browser/views/changes/changesView.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/parts/git/browser/views/changes/changesView.ts b/src/vs/workbench/parts/git/browser/views/changes/changesView.ts index f454db50a1b..85ab5b36bc1 100644 --- a/src/vs/workbench/parts/git/browser/views/changes/changesView.ts +++ b/src/vs/workbench/parts/git/browser/views/changes/changesView.ts @@ -12,6 +12,7 @@ import Lifecycle = require('vs/base/common/lifecycle'); import EventEmitter = require('vs/base/common/eventEmitter'); import Strings = require('vs/base/common/strings'); import Errors = require('vs/base/common/errors'); +import * as paths from 'vs/base/common/paths'; import WinJS = require('vs/base/common/winjs.base'); import Builder = require('vs/base/browser/builder'); import Keyboard = require('vs/base/browser/keyboardEvent'); @@ -404,19 +405,27 @@ export class ChangesView extends EventEmitter.EventEmitter implements GitView.IV } if (input instanceof Files.FileEditorInput) { - var fileInput = input; + const fileInput = input; + const resource = fileInput.getResource(); - var workspaceRelativePath = this.contextService.toWorkspaceRelativePath(fileInput.getResource()); - if (!workspaceRelativePath) { + const workspaceRoot = this.contextService.getWorkspace().resource.fsPath; + if (!paths.isEqualOrParent(resource.fsPath, workspaceRoot)) { return null; // out of workspace not yet supported } - var status = this.gitService.getModel().getStatus().getWorkingTreeStatus().find(workspaceRelativePath); + const repositoryRoot = this.gitService.getModel().getRepositoryRoot(); + if (!paths.isEqualOrParent(resource.fsPath, repositoryRoot)) { + return null; // out of repository not supported + } + + const repositoryRelativePath = paths.normalize(paths.relative(repositoryRoot, resource.fsPath)); + + var status = this.gitService.getModel().getStatus().getWorkingTreeStatus().find(repositoryRelativePath); if (status && (status.getStatus() === git.Status.UNTRACKED || status.getStatus() === git.Status.IGNORED)) { return status; } - status = this.gitService.getModel().getStatus().getMergeStatus().find(workspaceRelativePath); + status = this.gitService.getModel().getStatus().getMergeStatus().find(repositoryRelativePath); if (status) { return status; } From 0a642440efe7213048371318a2e85b5714e1a658 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 27 Nov 2015 12:26:49 +0100 Subject: [PATCH 184/588] Remove hc-white theme --- .../browser/ui/messagelist/messageList.css | 2 +- src/vs/editor/browser/widget/media/tokens.css | 94 ------------- src/vs/editor/css/hc-white-theme.css | 130 ------------------ src/vs/languages/markdown/common/tokens.css | 93 ------------- 4 files changed, 1 insertion(+), 318 deletions(-) delete mode 100644 src/vs/editor/css/hc-white-theme.css diff --git a/src/vs/base/browser/ui/messagelist/messageList.css b/src/vs/base/browser/ui/messagelist/messageList.css index 29e3afb272b..2567d03bd71 100644 --- a/src/vs/base/browser/ui/messagelist/messageList.css +++ b/src/vs/base/browser/ui/messagelist/messageList.css @@ -24,7 +24,7 @@ box-shadow: 0 2px 8px #000; } -.hc-dark .global-message-list { +.hc-black .global-message-list { box-shadow: none; } diff --git a/src/vs/editor/browser/widget/media/tokens.css b/src/vs/editor/browser/widget/media/tokens.css index b4af3c7731a..e14a8c9d099 100644 --- a/src/vs/editor/browser/widget/media/tokens.css +++ b/src/vs/editor/browser/widget/media/tokens.css @@ -202,100 +202,6 @@ /* -------------------------------- End vs-dark tokens -------------------------------- */ - - -/* -------------------------------- Begin hc-white tokens -------------------------------- */ -/* Tokens */ -.monaco-editor.hc-white .token { color: #000; } -.monaco-editor.hc-white .token.whitespace { color: #0000FF !important; } -.monaco-editor.hc-white .token.terminal { color: #e00000; } -.monaco-editor.hc-white .token.terminal.code1 { font-weight: bold; } -.monaco-editor.hc-white .token.variable { color: #001188; } -.monaco-editor.hc-white .token.variable.predefined { color: #4864AA; } -.monaco-editor.hc-white .token.constant { color: #dd0000; } -.monaco-editor.hc-white .token.string { color: #A31515; } -.monaco-editor.hc-white .token.string.escape { color: #A31515; } -.monaco-editor.hc-white .token.comment { color: #008000; } -.monaco-editor.hc-white .token.comment.shebang { color: #929292; } -.monaco-editor.hc-white .token.literal { color: #e00000; } -.monaco-editor.hc-white .token.literal.hex { color: #e07000; } - -.monaco-editor.hc-white .token.number { color: #000; } -.monaco-editor.hc-white .token.number.hex { color: #3030c0; } -.monaco-editor.hc-white .token.number.octal { color: #204070; } -.monaco-editor.hc-white .token.number.binary { color: #e07070; } -.monaco-editor.hc-white .token.regexp { color: #800000; } -.monaco-editor.hc-white .token.delimiter { color: #0000FF; } -.monaco-editor.hc-white .token.tag { color: #800000; } -.monaco-editor.hc-white .token.metatag { color: #e00000; } -.monaco-editor.hc-white .token.annotation { color: #cc6666; } -.monaco-editor.hc-white .token.key { color: #863B00; } -.monaco-editor.hc-white .token.attribute.name { color: #FF0000; } -.monaco-editor.hc-white .token.attribute.value { color: #0000FF; } -.monaco-editor.hc-white .token.info-token { color: #6796e6; } -.monaco-editor.hc-white .token.warn-token { color: #008000; } -.monaco-editor.hc-white .token.error-token { color: #FF0000; } -.monaco-editor.hc-white .token.debug-token { color: #b267e6; } -/* Keywords should come at the end in order to match cases like token.keyword.string */ -.monaco-editor.hc-white .token.keyword { color: #0000FF; } -.monaco-editor.hc-white .token.keyword.flow { color: #AF00DB; } - -/* PHP */ -.monaco-editor.hc-white .token.metatag.php { font-weight: bold; } - -/* Ruby */ -.monaco-editor.hc-white .token.predefined.ruby { color: #0000FF; } - -/* Markdown */ -.monaco-editor.hc-white .token.emphasis { font-style: italic;} -.monaco-editor.hc-white .token.strong { font-weight: bold; } -.monaco-editor.hc-white .token.header { color: navy ;} - -/* JSON */ -.monaco-editor.hc-white .token.string.key { color: #A31515; } -.monaco-editor.hc-white .token.string.value { color: #0451A5; } - -/* YAML */ -.monaco-editor.hc-white .token.string.yaml { color: #0451A5; } - -/* C# */ -.monaco-editor.hc-white .token.type { color: #008080; } -.monaco-editor.hc-white .token.identifier.method { color: #e07000; } - -/* SQL */ -.monaco-editor.hc-white .token.string.sql { color: #FF0000; } -.monaco-editor.hc-white .token.predefined.sql { color: #FF00FF; } -.monaco-editor.hc-white .token.operator.sql { color: #778899; } - - -/* HTML */ -.monaco-editor.hc-white .token.tag.html { color: #800000; } -.monaco-editor.hc-white .token.delimiter.html { color: #0000FF; } -.monaco-editor.hc-white .token.metatag.content.html { color: #FF0000; } -.monaco-editor.hc-white .token.metatag.html { color: #569CD6; } - -.monaco-editor.hc-white .token.string.html { color: blue; } - - -/* XML */ -.monaco-editor.hc-white .token.tag.xml { color: #800000; } -.monaco-editor.hc-white .token.delimiter.xml { color: #0000FF; } -.monaco-editor.hc-white .token.metatag.content.xml { color: #FF0000; } -.monaco-editor.hc-white .token.metatag.xml { color: #569CD6; } - -/* CSS */ -.monaco-editor.hc-white .token.attribute.name.css { color: #FF0000; } -.monaco-editor.hc-white .token.attribute.value.css { color: #0000FF; } -.monaco-editor.hc-white .token.tag.css { color: #800000; } -.monaco-editor.hc-white .token.delimiter.css { color: #000; } - -/* VSXML */ -.monaco-editor.hc-white .token.vs { color: #000; } - -/* -------------------------------- End hc-white tokens -------------------------------- */ - - - /* -------------------------------- Begin hc-black tokens -------------------------------- */ .monaco-editor.hc-black .token { color: #FFFFFF; } .monaco-editor.hc-black .token.whitespace { color: #FFFF00 !important; } diff --git a/src/vs/editor/css/hc-white-theme.css b/src/vs/editor/css/hc-white-theme.css deleted file mode 100644 index 1665544a9e6..00000000000 --- a/src/vs/editor/css/hc-white-theme.css +++ /dev/null @@ -1,130 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -/* The editor */ -.monaco-editor.hc-white, -.monaco-editor.hc-white .zone-widget .monaco-editor { - color: #000; - background: #fff; -} - -/* Background */ -.monaco-editor.hc-white .monaco-editor-background { - background: #fff; -} - -/* Highlight a line */ -.monaco-editor.hc-white .focus-mode { - background-color: #1E1E1E; - opacity: 0.333; -} - -/* Caret */ -.monaco-editor.hc-white .cursor { - background: #000; -} - -/* Current line */ -.monaco-editor.hc-white .current-line { - background: #fff; - border: 2px solid #EEE; - box-sizing: border-box; -} -.monaco-editor.hc-white.focused .current-line { - background: #fff; - border: 2px solid #EEE; - box-sizing: border-box; -} - -/* Highlight a line */ -.monaco-editor.hc-white .lineHighlight { - background-color: rgba(243, 240, 245, 0.2); -} - -/* Selection */ -.monaco-editor.hc-white .view-overlays.focused .selected-text { - background: #3399FF; -} -.monaco-editor.hc-white .view-overlays .selected-text { - background: #BFCDDB; -} - -/* Line Numbers */ -.monaco-editor.hc-white .line-numbers { - color: #2B91AF; -} - -/* Diff Editor overview */ -.monaco-diff-editor.hc-white .diffOverview { - background-color: #fff; -} -.monaco-scrollable-element.hc-white.modified-in-monaco-diff-editor .scrollbar { - background: rgba(0,0,0,0); -} - -/* ---------- Word Highlight ---------- */ -.monaco-editor.hc-white .wordHighlight { - background-color: #E2E6D6; -/* -webkit-animation-duration: 0.2s; - -webkit-animation-name: darkWordHighlight; - -moz-animation-duration: 0.2s; - -moz-animation-name: darkWordHighlight; - -ms-animation-duration: 0.2s; - -ms-animation-name: darkWordHighlight; - animation-duration: 0.2s; - animation-name: darkWordHighlight;*/ -} - -/*@-webkit-keyframes darkWordHighlight { from { background-color: inherit; } to { background-color: #E2E6D6; } } -@-moz-keyframes darkWordHighlight { from { background-color: inherit; } to { background-color: #E2E6D6; } } -@-ms-keyframes darkWordHighlight { from { background-color: inherit; } to { background-color: #E2E6D6; } } -@keyframes darkWordHighlight { from { background-color: inherit; } to { background-color: #E2E6D6; } }*/ - -/* Hover */ -.monaco-editor.hc-white .editor-hover { - color: #D5D8D6; - box-shadow: none; -} - -/* Bracket Match */ -.monaco-editor.hc-white .bracket-match { box-shadow: inset 0 0 0 1px #000; } - -/* Linked Editing */ -.monaco-editor.hc-white .linked-editing { box-shadow: inset 0 0 0 1px #000; } - -/* Snippets */ -.monaco-editor.hc-white .new-snippet { background-color: rgba(100, 105, 110, 0.1); } -.monaco-editor.hc-white .snippet-placeholder { background-color: rgba(124, 124, 124, 0.1); } -.monaco-editor.hc-white .finish-snippet-placeholder { outline: #525252 solid 1px; } - -/* Scrollbar */ -.monaco-scrollable-element.hc-white .slider { - background: rgba(121, 121, 121, .4); -} -.monaco-scrollable-element.hc-white .slider.active { - background: rgba(191, 191, 191, .4); -} - -/* RWC */ -.hc-white .monaco-findInput > .custom-checkbox { - color: #848484; - border-color: #848484; -} - -.hc-white .monaco-findInput > .custom-checkbox:hover { - color: #D4D4D4; - border-color: #D4D4D4; -} - -.hc-white .monaco-findInput > .custom-checkbox.checked { - color: #D4D4D4; - border-color: #D4D4D4; -} - -.monaco-editor.hc-white .findMatch { - background-color: #F6B94D; -} - - -/* Tokens colors are defined in tokens.css */ \ No newline at end of file diff --git a/src/vs/languages/markdown/common/tokens.css b/src/vs/languages/markdown/common/tokens.css index 7aa3fef41fe..8af0921fc9c 100644 --- a/src/vs/languages/markdown/common/tokens.css +++ b/src/vs/languages/markdown/common/tokens.css @@ -203,99 +203,6 @@ /* -------------------------------- End vs-dark tokens -------------------------------- */ - -/* -------------------------------- Begin hc-white tokens -------------------------------- */ -/* Tokens */ -.monaco-editor.hc-white .token { color: #000; } -.monaco-editor.hc-white .token.whitespace { color: #0000FF !important; } -.monaco-editor.hc-white .token.terminal { color: #e00000; } -.monaco-editor.hc-white .token.terminal.code1 { font-weight: bold; } -.monaco-editor.hc-white .token.variable { color: #001188; } -.monaco-editor.hc-white .token.variable.predefined { color: #4864AA; } -.monaco-editor.hc-white .token.constant { color: #dd0000; } -.monaco-editor.hc-white .token.string { color: #A31515; } -.monaco-editor.hc-white .token.string.escape { color: #A31515; } -.monaco-editor.hc-white .token.comment { color: #008000; } -.monaco-editor.hc-white .token.comment.shebang { color: #929292; } -.monaco-editor.hc-white .token.literal { color: #e00000; } -.monaco-editor.hc-white .token.literal.hex { color: #e07000; } - -.monaco-editor.hc-white .token.number { color: #000; } -.monaco-editor.hc-white .token.number.hex { color: #3030c0; } -.monaco-editor.hc-white .token.number.octal { color: #204070; } -.monaco-editor.hc-white .token.number.binary { color: #e07070; } -.monaco-editor.hc-white .token.regexp { color: #800000; } -.monaco-editor.hc-white .token.delimiter { color: #0000FF; } -.monaco-editor.hc-white .token.tag { color: #800000; } -.monaco-editor.hc-white .token.metatag { color: #e00000; } -.monaco-editor.hc-white .token.annotation { color: #cc6666; } -.monaco-editor.hc-white .token.key { color: #863B00; } -.monaco-editor.hc-white .token.attribute.name { color: #FF0000; } -.monaco-editor.hc-white .token.attribute.value { color: #0000FF; } -.monaco-editor.hc-white .token.info-token { color: #6796e6; } -.monaco-editor.hc-white .token.warn-token { color: #008000; } -.monaco-editor.hc-white .token.error-token { color: #FF0000; } -.monaco-editor.hc-white .token.debug-token { color: #b267e6; } -/* Keywords should come at the end in order to match cases like token.keyword.string */ -.monaco-editor.hc-white .token.keyword { color: #0000FF; } -.monaco-editor.hc-white .token.keyword.flow { color: #AF00DB; } - -/* PHP */ -.monaco-editor.hc-white .token.metatag.php { font-weight: bold; } - -/* Ruby */ -.monaco-editor.hc-white .token.predefined.ruby { color: #0000FF; } - -/* Markdown */ -.monaco-editor.hc-white .token.emphasis { font-style: italic;} -.monaco-editor.hc-white .token.strong { font-weight: bold; } -.monaco-editor.hc-white .token.header { color: navy ;} - -/* JSON */ -.monaco-editor.hc-white .token.string.key { color: #A31515; } -.monaco-editor.hc-white .token.string.value { color: #0451A5; } - -/* YAML */ -.monaco-editor.hc-white .token.string.yaml { color: #0451A5; } - -/* C# */ -.monaco-editor.hc-white .token.type { color: #008080; } -.monaco-editor.hc-white .token.identifier.method { color: #e07000; } - -/* SQL */ -.monaco-editor.hc-white .token.string.sql { color: #FF0000; } -.monaco-editor.hc-white .token.predefined.sql { color: #FF00FF; } -.monaco-editor.hc-white .token.operator.sql { color: #778899; } - - -/* HTML */ -.monaco-editor.hc-white .token.tag.html { color: #800000; } -.monaco-editor.hc-white .token.delimiter.html { color: #0000FF; } -.monaco-editor.hc-white .token.metatag.content.html { color: #FF0000; } -.monaco-editor.hc-white .token.metatag.html { color: #569CD6; } - -.monaco-editor.hc-white .token.string.html { color: blue; } - - -/* XML */ -.monaco-editor.hc-white .token.tag.xml { color: #800000; } -.monaco-editor.hc-white .token.delimiter.xml { color: #0000FF; } -.monaco-editor.hc-white .token.metatag.content.xml { color: #FF0000; } -.monaco-editor.hc-white .token.metatag.xml { color: #569CD6; } - -/* CSS */ -.monaco-editor.hc-white .token.attribute.name.css { color: #FF0000; } -.monaco-editor.hc-white .token.attribute.value.css { color: #0000FF; } -.monaco-editor.hc-white .token.tag.css { color: #800000; } -.monaco-editor.hc-white .token.delimiter.css { color: #000; } - -/* VSXML */ -.monaco-editor.hc-white .token.vs { color: #000; } - -/* -------------------------------- End hc-white tokens -------------------------------- */ - - - /* -------------------------------- Begin hc-black tokens -------------------------------- */ .monaco-editor.hc-black .token { color: #FFFFFF; } .monaco-editor.hc-black .token.whitespace { color: #FFFF00 !important; } From c48da2e1319d392013503d6400ceb8b82c3ad472 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 27 Nov 2015 15:07:24 +0100 Subject: [PATCH 185/588] [js] Cannot read property 'then' of undefined #664 --- .../languages/typescript/common/features/quickFixMainActions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/languages/typescript/common/features/quickFixMainActions.ts b/src/vs/languages/typescript/common/features/quickFixMainActions.ts index fbc6ac18fb6..9f362b422e5 100644 --- a/src/vs/languages/typescript/common/features/quickFixMainActions.ts +++ b/src/vs/languages/typescript/common/features/quickFixMainActions.ts @@ -48,7 +48,7 @@ export class QuickFixMainActions { var dtsFileResource = this._contextService.toResource(dtsFile); var jsConfigResource = this._contextService.toResource('jsconfig.json'); if (!dtsFileResource || !jsConfigResource) { - return; + return winjs.Promise.as(null); } var resourcePath = this._contextService.toWorkspaceRelativePath(resource); From 67084502b55c23b455632b88b88b804b82cac811 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 27 Nov 2015 15:35:13 +0100 Subject: [PATCH 186/588] commands: executeSignatureHelpProvider, executeDocumentRenameProvider --- .../editor/common/editorCommonExtensions.ts | 4 +- .../parameterHints/common/parameterHints.ts | 13 +++- src/vs/editor/contrib/rename/common/rename.ts | 13 +++- .../common/extHostLanguageFeatureCommands.ts | 40 +++++++++++- .../api/common/extHostLanguageFeatures.ts | 42 +----------- .../api/common/pluginHostTypeConverters.ts | 64 +++++++++++++++++++ 6 files changed, 127 insertions(+), 49 deletions(-) diff --git a/src/vs/editor/common/editorCommonExtensions.ts b/src/vs/editor/common/editorCommonExtensions.ts index cc9c9b2f6aa..4fce04b71b5 100644 --- a/src/vs/editor/common/editorCommonExtensions.ts +++ b/src/vs/editor/common/editorCommonExtensions.ts @@ -103,7 +103,7 @@ export module CommonEditorRegistry { }); } - export function registerDefaultLanguageCommand(id: string, handler: (model: EditorCommon.IModel, position: EditorCommon.IPosition) => any) { + export function registerDefaultLanguageCommand(id: string, handler: (model: EditorCommon.IModel, position: EditorCommon.IPosition, args: { [n: string]: any }) => any) { registerLanguageCommand(id, function(accessor, args) { const {resource, position} = args; @@ -116,7 +116,7 @@ export module CommonEditorRegistry { throw illegalArgument(); } - return handler(model, position); + return handler(model, position, args); }); } } diff --git a/src/vs/editor/contrib/parameterHints/common/parameterHints.ts b/src/vs/editor/contrib/parameterHints/common/parameterHints.ts index 58b4bd073bc..a7be3b7046c 100644 --- a/src/vs/editor/contrib/parameterHints/common/parameterHints.ts +++ b/src/vs/editor/contrib/parameterHints/common/parameterHints.ts @@ -8,8 +8,9 @@ import {IParameterHintsSupport, IParameterHints} from 'vs/editor/common/modes'; import {IModel, IPosition} from 'vs/editor/common/editorCommon'; import {TPromise} from 'vs/base/common/winjs.base'; -import {onUnexpectedError} from 'vs/base/common/errors'; +import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; +import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; export const ParameterHintsRegistry = new LanguageFeatureRegistry('parameterHintsSupport'); @@ -21,4 +22,12 @@ export function getParameterHints(model:IModel, position:IPosition, triggerChara } return support.getParameterHints(model.getAssociatedResource(), position, triggerCharacter); -} \ No newline at end of file +} + +CommonEditorRegistry.registerDefaultLanguageCommand('_executeSignatureHelpProvider', function(model, position, args) { + let {triggerCharacter} = args; + if (triggerCharacter && typeof triggerCharacter !== 'string') { + throw illegalArgument('triggerCharacter'); + } + return getParameterHints(model, position, triggerCharacter); +}); \ No newline at end of file diff --git a/src/vs/editor/contrib/rename/common/rename.ts b/src/vs/editor/contrib/rename/common/rename.ts index a7e122a87a9..07746e1bddc 100644 --- a/src/vs/editor/contrib/rename/common/rename.ts +++ b/src/vs/editor/contrib/rename/common/rename.ts @@ -10,8 +10,9 @@ import {IModel, IPosition} from 'vs/editor/common/editorCommon'; import {TPromise} from 'vs/base/common/winjs.base'; import {localize} from 'vs/nls'; import {sequence} from 'vs/base/common/async'; -import {onUnexpectedError} from 'vs/base/common/errors'; +import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; +import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; export const RenameRegistry = new LanguageFeatureRegistry('renameSupport'); @@ -57,4 +58,12 @@ export function rename(model: IModel, position: IPosition, newName: string): TPr return result; } }); -} \ No newline at end of file +} + +CommonEditorRegistry.registerDefaultLanguageCommand('_executeDocumentRenameProvider', function(model, position, args) { + let {newName} = args; + if (typeof newName !== 'string') { + throw illegalArgument('newName'); + } + return rename(model, position, newName); +}); \ No newline at end of file diff --git a/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts index 7933e6af917..3e413da1e18 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts @@ -43,15 +43,15 @@ import {SuggestRegistry} from 'vs/editor/contrib/suggest/common/suggest'; // vscode.executeHoverProvider // vscode.executeDocumentHighlights // vscode.executeReferenceProvider +// vscode.executeDocumentRenameProvider +// vscode.executeSignatureHelpProvider // vscode.executeCodeActionProvider // vscode.executeCodeLensProvider // vscode.executeDocumentSymbolProvider -// vscode.executeDocumentRenameProvider // vscode.executeFormatDocumentProvider // vscode.executeFormatRangeProvider // vscode.executeFormatOnTypeProvider -// vscode.executeSignatureHelpProvider // vscode.executeCompletionItemProvider export class ExtHostLanguageFeatureCommands { @@ -67,6 +67,8 @@ export class ExtHostLanguageFeatureCommands { this._register('vscode.executeHoverProvider', this._executeHoverProvider); this._register('vscode.executeDocumentHighlights', this._executeDocumentHighlights); this._register('vscode.executeReferenceProvider', this._executeReferenceProvider); + this._register('vscode.executeDocumentRenameProvider', this._executeDocumentRenameProvider); + this._register('vscode.executeSignatureHelpProvider', this._executeSignatureHelpProvider); } private _register(id: string, callback: (...args: any[]) => any): void { @@ -130,4 +132,38 @@ export class ExtHostLanguageFeatureCommands { } }); } + + private _executeDocumentRenameProvider(resource: URI, position: types.Position, newName: string): Thenable { + const args = { + resource, + position: position && typeConverters.fromPosition(position), + newName + }; + return this._commands.executeCommand('_executeDocumentRenameProvider', args).then(value => { + if (!value) { + return; + } + if (value.rejectReason) { + return TPromise.wrapError(value.rejectReason); + } + let workspaceEdit = new types.WorkspaceEdit(); + for (let edit of value.edits) { + workspaceEdit.replace(edit.resource, typeConverters.toRange(edit.range), edit.newText); + } + return workspaceEdit; + }); + } + + private _executeSignatureHelpProvider(resource: URI, position: types.Position, triggerCharacter: string): Thenable { + const args = { + resource, + position: position && typeConverters.fromPosition(position), + triggerCharacter + }; + return this._commands.executeCommand('_executeSignatureHelpProvider', args).then(value => { + if (value) { + return typeConverters.SignatureHelp.to(value); + } + }); + } } \ No newline at end of file diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index fe0552a08b4..cb91662ab87 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -617,51 +617,11 @@ class ParameterHintsAdapter implements modes.IParameterHintsSupport { return asWinJsPromise(token => this._provider.provideSignatureHelp(doc, pos, token)).then(value => { if (value instanceof SignatureHelp) { - return ParameterHintsAdapter._convertSignatureHelp(value); + return TypeConverters.SignatureHelp.from(value); } }); } - private static _convertSignatureHelp(signatureHelp: SignatureHelp): modes.IParameterHints { - - let result: modes.IParameterHints = { - currentSignature: signatureHelp.activeSignature, - currentParameter: signatureHelp.activeParameter, - signatures: [] - } - - for (let signature of signatureHelp.signatures) { - - let signatureItem: modes.ISignature = { - label: signature.label, - documentation: signature.documentation, - parameters: [] - }; - - let idx = 0; - for (let parameter of signature.parameters) { - - let parameterItem: modes.IParameter = { - label: parameter.label, - documentation: parameter.documentation, - }; - - signatureItem.parameters.push(parameterItem); - idx = signature.label.indexOf(parameter.label, idx); - - if (idx >= 0) { - parameterItem.signatureLabelOffset = idx; - idx += parameter.label.length; - parameterItem.signatureLabelEnd = idx; - } - } - - result.signatures.push(signatureItem); - } - - return result; - } - getParameterHintsTriggerCharacters(): string[] { throw new Error('illegal state'); } diff --git a/src/vs/workbench/api/common/pluginHostTypeConverters.ts b/src/vs/workbench/api/common/pluginHostTypeConverters.ts index 2dddc1b71ae..fbe21b4c8c5 100644 --- a/src/vs/workbench/api/common/pluginHostTypeConverters.ts +++ b/src/vs/workbench/api/common/pluginHostTypeConverters.ts @@ -250,4 +250,68 @@ export function toHover(info: modes.IComputeExtraInfoResult): types.Hover { export function toDocumentHighlight(occurrence: modes.IOccurence): types.DocumentHighlight { return new types.DocumentHighlight(toRange(occurrence.range), types.DocumentHighlightKind[occurrence.kind.charAt(0).toUpperCase() + occurrence.kind.substr(1)]); +} + +export namespace SignatureHelp { + + export function from(signatureHelp: types.SignatureHelp): modes.IParameterHints { + + let result: modes.IParameterHints = { + currentSignature: signatureHelp.activeSignature, + currentParameter: signatureHelp.activeParameter, + signatures: [] + } + + for (let signature of signatureHelp.signatures) { + + let signatureItem: modes.ISignature = { + label: signature.label, + documentation: signature.documentation, + parameters: [] + }; + + let idx = 0; + for (let parameter of signature.parameters) { + + let parameterItem: modes.IParameter = { + label: parameter.label, + documentation: parameter.documentation, + }; + + signatureItem.parameters.push(parameterItem); + idx = signature.label.indexOf(parameter.label, idx); + + if (idx >= 0) { + parameterItem.signatureLabelOffset = idx; + idx += parameter.label.length; + parameterItem.signatureLabelEnd = idx; + } + } + + result.signatures.push(signatureItem); + } + + return result; + } + + export function to(hints: modes.IParameterHints): types.SignatureHelp { + + const result = new types.SignatureHelp(); + result.activeSignature = hints.currentSignature; + result.activeParameter = hints.currentParameter; + + for (let signature of hints.signatures) { + + const signatureItem = new types.SignatureInformation(signature.label, signature.documentation); + result.signatures.push(signatureItem); + + for (let parameter of signature.parameters) { + + const parameterItem = new types.ParameterInformation(parameter.label, parameter.documentation); + signatureItem.parameters.push(parameterItem); + } + } + + return result; + } } \ No newline at end of file From 893a78374d2aab18df2a9c12a3ee3ecc411d0e63 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 27 Nov 2015 16:08:52 +0100 Subject: [PATCH 187/588] commands: executeDocumentSymbolProvider --- .../contrib/quickOpen/common/quickOpen.ts | 25 +++- .../common/extHostLanguageFeatureCommands.ts | 16 ++- .../api/common/extHostLanguageFeatures.ts | 12 +- .../api/common/pluginHostTypeConverters.ts | 134 +++++++++++++----- .../extHostLanguageFeatureCommands.test.ts | 27 +++- 5 files changed, 160 insertions(+), 54 deletions(-) diff --git a/src/vs/editor/contrib/quickOpen/common/quickOpen.ts b/src/vs/editor/contrib/quickOpen/common/quickOpen.ts index 4b135a963da..b232934917f 100644 --- a/src/vs/editor/contrib/quickOpen/common/quickOpen.ts +++ b/src/vs/editor/contrib/quickOpen/common/quickOpen.ts @@ -5,12 +5,15 @@ 'use strict'; -import {onUnexpectedError} from 'vs/base/common/errors'; +import URI from 'vs/base/common/uri'; +import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; import {TPromise} from 'vs/base/common/winjs.base'; import {Range} from 'vs/editor/common/core/range'; import {IModel} from 'vs/editor/common/editorCommon'; import {IOutlineEntry, IOutlineSupport} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; +import {IModelService} from 'vs/editor/common/services/modelService'; +import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; const OutlineRegistry = new LanguageFeatureRegistry('outlineSupport'); @@ -20,7 +23,12 @@ export { IOutlineSupport } -export function getOutlineEntries(model: IModel): TPromise<{ entries: IOutlineEntry[], outlineGroupLabel: { [n: string]: string;} }> { +export interface IOutline { + entries: IOutlineEntry[]; + outlineGroupLabel: { [n: string]: string; }; +} + +export function getOutlineEntries(model: IModel): TPromise { let groupLabels: { [n: string]: string } = Object.create(null); let entries: IOutlineEntry[] = []; @@ -74,3 +82,16 @@ function flatten(bucket: IOutlineEntry[], entries: IOutlineEntry[], overrideCont } } } + + +CommonEditorRegistry.registerLanguageCommand('_executeDocumentSymbolProvider', function(accessor, args) { + const {resource} = args; + if (!URI.isURI(resource)) { + throw illegalArgument('resource'); + } + const model = accessor.get(IModelService).getModel(resource); + if (!model) { + throw illegalArgument('resource'); + } + return getOutlineEntries(model); +}); \ No newline at end of file diff --git a/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts index 3e413da1e18..4f22bacbe26 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts @@ -29,7 +29,7 @@ import {ExtraInfoRegistry} from 'vs/editor/contrib/hover/common/hover'; import {OccurrencesRegistry} from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; import {ReferenceRegistry} from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; import {QuickFixRegistry} from 'vs/editor/contrib/quickFix/common/quickFix'; -import {OutlineRegistry, IOutlineEntry, IOutlineSupport} from 'vs/editor/contrib/quickOpen/common/quickOpen'; +import {IOutline} from 'vs/editor/contrib/quickOpen/common/quickOpen'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import {NavigateTypesSupportRegistry, INavigateTypesSupport, ITypeBearing} from 'vs/workbench/parts/search/common/search' import {RenameRegistry} from 'vs/editor/contrib/rename/common/rename'; @@ -45,10 +45,10 @@ import {SuggestRegistry} from 'vs/editor/contrib/suggest/common/suggest'; // vscode.executeReferenceProvider // vscode.executeDocumentRenameProvider // vscode.executeSignatureHelpProvider +// vscode.executeDocumentSymbolProvider // vscode.executeCodeActionProvider // vscode.executeCodeLensProvider -// vscode.executeDocumentSymbolProvider // vscode.executeFormatDocumentProvider // vscode.executeFormatRangeProvider // vscode.executeFormatOnTypeProvider @@ -69,6 +69,7 @@ export class ExtHostLanguageFeatureCommands { this._register('vscode.executeReferenceProvider', this._executeReferenceProvider); this._register('vscode.executeDocumentRenameProvider', this._executeDocumentRenameProvider); this._register('vscode.executeSignatureHelpProvider', this._executeSignatureHelpProvider); + this._register('vscode.executeDocumentSymbolProvider', this._executeDocumentSymbolProvider); } private _register(id: string, callback: (...args: any[]) => any): void { @@ -166,4 +167,15 @@ export class ExtHostLanguageFeatureCommands { } }); } + + private _executeDocumentSymbolProvider(resource: URI): Thenable { + const args = { + resource + }; + return this._commands.executeCommand('_executeDocumentSymbolProvider', args).then(value => { + if (value && Array.isArray(value.entries)) { + return value.entries.map(typeConverters.SymbolInformation.fromOutlineEntry); + } + }); + } } \ No newline at end of file diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index cb91662ab87..6a117f040bb 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -72,20 +72,10 @@ class OutlineAdapter implements IOutlineSupport { let doc = this._documents.getDocument(resource); return asWinJsPromise(token => this._provider.provideDocumentSymbols(doc, token)).then(value => { if (Array.isArray(value)) { - return value.map(OutlineAdapter._convertSymbolInfo); + return value.map(TypeConverters.SymbolInformation.toOutlineEntry); } }); } - - private static _convertSymbolInfo(symbol: vscode.SymbolInformation): IOutlineEntry { - return { - type: TypeConverters.fromSymbolKind(symbol.kind), - range: TypeConverters.fromRange(symbol.location.range), - containerLabel: symbol.containerName, - label: symbol.name, - icon: undefined, - }; - } } class CodeLensAdapter implements modes.ICodeLensSupport { diff --git a/src/vs/workbench/api/common/pluginHostTypeConverters.ts b/src/vs/workbench/api/common/pluginHostTypeConverters.ts index fbe21b4c8c5..1f8e6433c65 100644 --- a/src/vs/workbench/api/common/pluginHostTypeConverters.ts +++ b/src/vs/workbench/api/common/pluginHostTypeConverters.ts @@ -68,43 +68,6 @@ export function fromPosition(position: types.Position):IPosition { return { lineNumber: position.line + 1, column: position.character + 1}; } -export function fromSymbolKind(kind: number | types.SymbolKind): string { - switch (kind) { - case types.SymbolKind.Method: - return 'method'; - case types.SymbolKind.Function: - return 'function'; - case types.SymbolKind.Constructor: - return 'constructor'; - case types.SymbolKind.Variable: - return 'variable'; - case types.SymbolKind.Class: - return 'class'; - case types.SymbolKind.Interface: - return 'interface'; - case types.SymbolKind.Module: - case types.SymbolKind.Namespace: - case types.SymbolKind.Package: - return 'module'; - case types.SymbolKind.Property: - return 'property'; - case types.SymbolKind.Enum: - return 'enum'; - case types.SymbolKind.String: - return 'string'; - case types.SymbolKind.File: - return 'file'; - case types.SymbolKind.Array: - return 'array'; - case types.SymbolKind.Number: - return 'number'; - case types.SymbolKind.Boolean: - return 'boolean'; - } - - return 'property'; -} - export function fromDiagnosticSeverity(value: number): Severity { switch (value) { case types.DiagnosticSeverity.Error: @@ -211,6 +174,103 @@ export function fromTextEdit(edit: vscode.TextEdit) { } } +export namespace SymbolKind { + + export function from(kind: number | types.SymbolKind): string { + switch (kind) { + case types.SymbolKind.Method: + return 'method'; + case types.SymbolKind.Function: + return 'function'; + case types.SymbolKind.Constructor: + return 'constructor'; + case types.SymbolKind.Variable: + return 'variable'; + case types.SymbolKind.Class: + return 'class'; + case types.SymbolKind.Interface: + return 'interface'; + case types.SymbolKind.Module: + case types.SymbolKind.Namespace: + case types.SymbolKind.Package: + return 'module'; + case types.SymbolKind.Property: + return 'property'; + case types.SymbolKind.Enum: + return 'enum'; + case types.SymbolKind.String: + return 'string'; + case types.SymbolKind.File: + return 'file'; + case types.SymbolKind.Array: + return 'array'; + case types.SymbolKind.Number: + return 'number'; + case types.SymbolKind.Boolean: + return 'boolean'; + } + return 'property'; + } + + export function to(type: string): types.SymbolKind { + switch (type) { + case 'method': + return types.SymbolKind.Method; + case 'function': + return types.SymbolKind.Function; + case 'constructor': + return types.SymbolKind.Constructor; + case 'variable': + return types.SymbolKind.Variable; + case 'class': + return types.SymbolKind.Class; + case 'interface': + return types.SymbolKind.Interface; + case 'module': + // case types.SymbolKind.Namespace: + // case types.SymbolKind.Package: + return types.SymbolKind.Module; + case 'property': + return types.SymbolKind.Property; + case 'enum': + return types.SymbolKind.Enum; + case 'string': + return types.SymbolKind.String; + case 'file': + return types.SymbolKind.File; + case 'array': + return types.SymbolKind.Array; + case 'number': + return types.SymbolKind.Number; + case 'boolean': + return types.SymbolKind.Boolean; + } + return types.SymbolKind.Property + } +} + +export namespace SymbolInformation { + + export function fromOutlineEntry(entry: modes.IOutlineEntry): types.SymbolInformation { + return new types.SymbolInformation(entry.label, + SymbolKind.to(entry.type), + toRange(entry.range), + undefined, + entry.containerLabel) + } + + export function toOutlineEntry(symbol: vscode.SymbolInformation): modes.IOutlineEntry { + return { + type: SymbolKind.from(symbol.kind), + range: fromRange(symbol.location.range), + containerLabel: symbol.containerName, + label: symbol.name, + icon: undefined, + }; + } + +} + export function fromSymbolInformation(info: vscode.SymbolInformation): ITypeBearing { return { name: info.name, diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts index c5eeb9052ea..b3fe6b701dc 100644 --- a/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts @@ -188,7 +188,7 @@ suite('ExtHostLanguageFeatureCommands', function() { test('Definition, ⇔ back and forth', function(done) { disposables.push(extHost.registerDefinitionProvider(defaultSelector, { - provideDefinition(doc:any): any { + provideDefinition(doc: any): any { return new types.Location(doc.uri, new types.Range(0, 0, 0, 0)); } })); @@ -208,5 +208,28 @@ suite('ExtHostLanguageFeatureCommands', function() { done(); }); }); - }) + }); + + // --- outline + + test('Outline, back and forth', function(done) { + disposables.push(extHost.registerDocumentSymbolProvider(defaultSelector, { + provideDocumentSymbols(): any { + return [ + new types.SymbolInformation('testing1', types.SymbolKind.Enum, new types.Range(1, 0, 1, 0)), + new types.SymbolInformation('testing2', types.SymbolKind.Enum, new types.Range(0, 1, 0, 3)), + ] + } + })); + + threadService.sync().then(() => { + commands.executeCommand('vscode.executeDocumentSymbolProvider', model.getAssociatedResource()).then(values => { + assert.equal(values.length, 2); + let [first, second] = values; + assert.equal(first.name, 'testing2'); + assert.equal(second.name, 'testing1'); + done(); + }); + }); + }); }); \ No newline at end of file From d575ff926142522252a92f72edda268c7f2f5201 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 27 Nov 2015 16:10:32 +0100 Subject: [PATCH 188/588] fix npe in context menu service fixes #738 --- .../contextview/browser/contextView.ts | 10 +-- .../electron-browser/contextmenuService.ts | 73 ++++++++++--------- 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/src/vs/platform/contextview/browser/contextView.ts b/src/vs/platform/contextview/browser/contextView.ts index 894ee4eff0f..0d98de4eb32 100644 --- a/src/vs/platform/contextview/browser/contextView.ts +++ b/src/vs/platform/contextview/browser/contextView.ts @@ -5,9 +5,9 @@ 'use strict'; import Lifecycle = require('vs/base/common/lifecycle'); -import Actions = require('vs/base/common/actions'); +import { IAction } from 'vs/base/common/actions'; import ActionBar = require('vs/base/browser/ui/actionbar/actionbar'); -import winjs = require('vs/base/common/winjs.base'); +import { TPromise } from 'vs/base/common/winjs.base'; import {Keybinding} from 'vs/base/common/keyCodes'; import {createDecorator, ServiceIdentifier} from 'vs/platform/instantiation/common/instantiation'; @@ -37,10 +37,10 @@ export interface IContextMenuService { export interface IContextMenuDelegate { getAnchor():HTMLElement|{x: number; y: number; } - getActions(): winjs.Promise; - getActionItem?(action: Actions.IAction): ActionBar.IActionItem; + getActions(): TPromise; + getActionItem?(action: IAction): ActionBar.IActionItem; getActionsContext?():any; - getKeyBinding?(action: Actions.IAction): Keybinding; + getKeyBinding?(action: IAction): Keybinding; getMenuClassName?():string; onHide?(didCancel: boolean): void; } diff --git a/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts b/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts index 3a8db008f2c..620ca028448 100644 --- a/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts +++ b/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts @@ -5,6 +5,7 @@ 'use strict'; +import { TPromise } from 'vs/base/common/winjs.base'; import severity from 'vs/base/common/severity'; import actions = require('vs/base/common/actions'); import {Separator} from 'vs/base/browser/ui/actionbar/actionbar'; @@ -31,24 +32,25 @@ export class ContextMenuService implements IContextMenuService { } public showContextMenu(delegate: IContextMenuDelegate): void { - let menu = new Menu(); - let actionToRun: actions.IAction = null; + delegate.getActions().then(actions => { + if (!actions.length) { + return TPromise.as(null); + } + + let menu = new Menu(); + let actionToRun: actions.IAction = null; - delegate.getActions().done((actions: actions.IAction[]) => { actions.forEach(a => { if (a instanceof Separator) { menu.append(new MenuItem({ type: 'separator' })); } else { - let keybinding = !!delegate.getKeyBinding ? delegate.getKeyBinding(a) : undefined; - let accelerator: string; - if (keybinding) { - accelerator = keybinding.toElectronAccelerator(); - } + const keybinding = !!delegate.getKeyBinding ? delegate.getKeyBinding(a) : undefined; + const accelerator = keybinding && keybinding.toElectronAccelerator(); - let item = new MenuItem({ + const item = new MenuItem({ label: a.label, checked: a.checked, - accelerator: accelerator, + accelerator, click: () => { actionToRun = a; } @@ -58,39 +60,38 @@ export class ContextMenuService implements IContextMenuService { menu.append(item); } }); - }); - let anchor = delegate.getAnchor(); - let x: number, y: number; + const anchor = delegate.getAnchor(); + let x: number, y: number; - if (dom.isHTMLElement(anchor)) { - let $anchor = $( anchor); - let elementPosition = $anchor.getPosition(); - let elementSize = $anchor.getTotalSize(); + if (dom.isHTMLElement(anchor)) { + const $anchor = $( anchor); + const elementPosition = $anchor.getPosition(); + const elementSize = $anchor.getTotalSize(); - x = elementPosition.left; - y = elementPosition.top + elementSize.height; - } else { - let pos = <{ x: number; y: number; }> anchor; - x = pos.x; - y = pos.y; - } + x = elementPosition.left; + y = elementPosition.top + elementSize.height; + } else { + const pos = <{ x: number; y: number; }> anchor; + x = pos.x; + y = pos.y; + } - menu.popup(remote.getCurrentWindow(), Math.floor(x), Math.floor(y)); + menu.popup(remote.getCurrentWindow(), Math.floor(x), Math.floor(y)); - if (delegate.onHide) { - delegate.onHide(false); - } + if (delegate.onHide) { + delegate.onHide(false); + } - if (!actionToRun) { - return; - } + if (!actionToRun) { + return; + } - this.telemetryService.publicLog('workbenchActionExecuted', { id: actionToRun.id, from: 'contextMenu' }); - let result = actionToRun.run(delegate.getActionsContext ? delegate.getActionsContext() : null); + this.telemetryService.publicLog('workbenchActionExecuted', { id: actionToRun.id, from: 'contextMenu' }); - if (result) { - result.done(null, e => this.messageService.show(severity.Error, e)); - } + const context = delegate.getActionsContext ? delegate.getActionsContext() : null; + return actionToRun.run(context) || TPromise.as(null); + }) + .done(null, e => this.messageService.show(severity.Error, e)); } } \ No newline at end of file From 5c1d9f976216786b92c5677757f2a21d2e1dc526 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2015 16:13:05 +0100 Subject: [PATCH 189/588] debug: function breakpoints first steps. --- src/vs/workbench/parts/debug/common/debug.ts | 5 ++++ .../parts/debug/common/debugModel.ts | 25 ++++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index b20f7356cfb..cdd7f3ceb5d 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -74,6 +74,10 @@ export interface IBreakpoint extends IEnablement { condition: string; } +export interface IFunctionBreakpoint extends IEnablement { + functionName: string; +} + export interface IExceptionBreakpoint extends IEnablement { name: string; } @@ -119,6 +123,7 @@ export interface IModel extends ee.IEventEmitter, ITreeElement { getThreads(): { [reference: number]: IThread; }; getBreakpoints(): IBreakpoint[]; areBreakpointsActivated(): boolean; + getFunctionBreakpoints(): IFunctionBreakpoint[]; getExceptionBreakpoints(): IExceptionBreakpoint[]; getWatchExpressions(): IExpression[]; getReplElements(): ITreeElement[]; diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index 1094bf447d3..3ae588b9d77 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -267,6 +267,19 @@ export class Breakpoint implements debug.IBreakpoint { } } +export class FunctionBreakpoint implements debug.IFunctionBreakpoint { + + private id: string; + + constructor(public functionName: string, public enabled: boolean) { + this.id = uuid.generateUuid(); + } + + public getId(): string { + return this.id; + } +} + export class ExceptionBreakpoint implements debug.IExceptionBreakpoint { private id: string; @@ -286,7 +299,7 @@ export class Model extends ee.EventEmitter implements debug.IModel { private toDispose: lifecycle.IDisposable[]; private replElements: debug.ITreeElement[]; - constructor(private breakpoints: debug.IBreakpoint[], private breakpointsActivated: boolean, + constructor(private breakpoints: debug.IBreakpoint[], private breakpointsActivated: boolean, private functionBreakpoints: debug.IFunctionBreakpoint[], private exceptionBreakpoints: debug.IExceptionBreakpoint[], private watchExpressions: Expression[]) { super(); @@ -331,6 +344,10 @@ export class Model extends ee.EventEmitter implements debug.IModel { return this.breakpoints; } + public getFunctionBreakpoints(): debug.IFunctionBreakpoint[] { + return this.functionBreakpoints; + } + public getExceptionBreakpoints(): debug.IExceptionBreakpoint[] { return this.exceptionBreakpoints; } @@ -378,9 +395,8 @@ export class Model extends ee.EventEmitter implements debug.IModel { bp.lineNumber = bp.desiredLineNumber; } }); - this.exceptionBreakpoints.forEach(ebp => { - ebp.enabled = enabled; - }); + this.exceptionBreakpoints.forEach(ebp => ebp.enabled = enabled); + this.functionBreakpoints.forEach(fbp => fbp.enabled = enabled); this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); } @@ -600,6 +616,7 @@ export class Model extends ee.EventEmitter implements debug.IModel { this.threads = null; this.breakpoints = null; this.exceptionBreakpoints = null; + this.functionBreakpoints = null; this.watchExpressions = null; this.replElements = null; this.toDispose = lifecycle.disposeAll(this.toDispose); From 74acc249ce5dbb3409bbf9058de9262e71544e9e Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 27 Nov 2015 16:15:06 +0100 Subject: [PATCH 190/588] fix calls to reveal (promise) fixes #696 --- src/vs/base/parts/tree/browser/treeDefaults.ts | 8 ++++---- src/vs/base/parts/tree/common/treeModel.ts | 2 +- .../contrib/quickFix/browser/quickFixSelectionWidget.ts | 2 +- .../referenceSearch/browser/referenceSearchWidget.ts | 9 ++++++--- src/vs/editor/contrib/suggest/browser/suggestWidget.ts | 2 +- .../parts/git/browser/views/changes/changesView.ts | 2 +- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/vs/base/parts/tree/browser/treeDefaults.ts b/src/vs/base/parts/tree/browser/treeDefaults.ts index b8aa7e347d2..19bd9fca080 100644 --- a/src/vs/base/parts/tree/browser/treeDefaults.ts +++ b/src/vs/base/parts/tree/browser/treeDefaults.ts @@ -262,7 +262,7 @@ export class DefaultController implements _.IController { tree.clearHighlight(payload); } else { tree.focusPrevious(1, payload); - tree.reveal(tree.getFocus()); + tree.reveal(tree.getFocus()).done(null, errors.onUnexpectedError); } return true; } @@ -274,7 +274,7 @@ export class DefaultController implements _.IController { tree.clearHighlight(payload); } else { tree.focusPreviousPage(payload); - tree.reveal(tree.getFocus()); + tree.reveal(tree.getFocus()).done(null, errors.onUnexpectedError); } return true; } @@ -286,7 +286,7 @@ export class DefaultController implements _.IController { tree.clearHighlight(payload); } else { tree.focusNext(1, payload); - tree.reveal(tree.getFocus()); + tree.reveal(tree.getFocus()).done(null, errors.onUnexpectedError); } return true; } @@ -298,7 +298,7 @@ export class DefaultController implements _.IController { tree.clearHighlight(payload); } else { tree.focusNextPage(payload); - tree.reveal(tree.getFocus()); + tree.reveal(tree.getFocus()).done(null, errors.onUnexpectedError); } return true; } diff --git a/src/vs/base/parts/tree/common/treeModel.ts b/src/vs/base/parts/tree/common/treeModel.ts index 14215513dfa..0152bcab3a2 100644 --- a/src/vs/base/parts/tree/common/treeModel.ts +++ b/src/vs/base/parts/tree/common/treeModel.ts @@ -944,7 +944,7 @@ export class TreeModel extends Events.EventEmitter { var item = this.getItem(element); if (item) { - item.reveal(relativeTop); + return item.reveal(relativeTop); } }); } diff --git a/src/vs/editor/contrib/quickFix/browser/quickFixSelectionWidget.ts b/src/vs/editor/contrib/quickFix/browser/quickFixSelectionWidget.ts index bc2a685d294..76345771792 100644 --- a/src/vs/editor/contrib/quickFix/browser/quickFixSelectionWidget.ts +++ b/src/vs/editor/contrib/quickFix/browser/quickFixSelectionWidget.ts @@ -281,7 +281,7 @@ export class QuickFixSelectionWidget implements EditorBrowser.IContentWidget { this.updateWidgetHeight(); if (focus) { - this.tree.reveal(focus, (payload && payload.firstSuggestion) ? 0 : null); + return this.tree.reveal(focus, (payload && payload.firstSuggestion) ? 0 : null); } }, Errors.onUnexpectedError); })); diff --git a/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts b/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts index 6d2ad7c7091..c0e868875a3 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts @@ -602,9 +602,12 @@ export class ReferenceWidget extends peekViewWidget.PeekViewWidget { }, errors.onUnexpectedError); // show in tree - this.tree.reveal(reference); - this.tree.setSelection([reference]); - this.tree.setFocus(reference); + this.tree.reveal(reference) + .then(() => { + this.tree.setSelection([reference]); + this.tree.setFocus(reference); + }) + .done(null, errors.onUnexpectedError); } public dispose(): void { diff --git a/src/vs/editor/contrib/suggest/browser/suggestWidget.ts b/src/vs/editor/contrib/suggest/browser/suggestWidget.ts index 34ce3582176..daae94af704 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestWidget.ts @@ -384,7 +384,7 @@ export class SuggestWidget implements EditorBrowser.IContentWidget { this.updateWidgetHeight(); if (focus) { - this.tree.reveal(focus, (payload && payload.firstSuggestion) ? 0 : null); + return this.tree.reveal(focus, (payload && payload.firstSuggestion) ? 0 : null); } }, Errors.onUnexpectedError); })); diff --git a/src/vs/workbench/parts/git/browser/views/changes/changesView.ts b/src/vs/workbench/parts/git/browser/views/changes/changesView.ts index 6c886ac5204..6bea2ae9707 100644 --- a/src/vs/workbench/parts/git/browser/views/changes/changesView.ts +++ b/src/vs/workbench/parts/git/browser/views/changes/changesView.ts @@ -185,7 +185,7 @@ export class ChangesView extends EventEmitter.EventEmitter implements GitView.IV public focus():void { var selection = this.tree.getSelection(); if (selection.length > 0) { - this.tree.reveal(selection[0], 0.5); + this.tree.reveal(selection[0], 0.5).done(null, Errors.onUnexpectedError); } this.commitInputBox.focus(); From 6e08df36b7069758ae44a050ac56db3f7b30eda5 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2015 16:45:15 +0100 Subject: [PATCH 191/588] debug: add function breakpoint actions. --- .../parts/debug/browser/debugActions.ts | 14 ++++++++++++++ .../parts/debug/browser/debugViewer.ts | 3 +++ .../parts/debug/browser/debugViewlet.ts | 1 + .../parts/debug/browser/media/debugViewlet.css | 3 ++- src/vs/workbench/parts/debug/common/debug.ts | 1 + .../workbench/parts/debug/common/debugModel.ts | 5 +++++ .../debug/electron-browser/debugService.ts | 17 ++++++++++++++++- .../parts/debug/test/common/debugModel.test.ts | 2 +- 8 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugActions.ts b/src/vs/workbench/parts/debug/browser/debugActions.ts index 538c4d86b4e..fec08545911 100644 --- a/src/vs/workbench/parts/debug/browser/debugActions.ts +++ b/src/vs/workbench/parts/debug/browser/debugActions.ts @@ -379,6 +379,20 @@ export class ReapplyBreakpointsAction extends AbstractDebugAction { } } +export class AddFunctionBreakpointAction extends AbstractDebugAction { + static ID = 'workbench.debug.viewlet.action.addFunctionBreakpointAction'; + static LABEL = nls.localize('addFunctionBreakpoint', "Add Function Breakpoint"); + + constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { + super(id, label, 'debug-action add-function-breakpoint', debugService, keybindingService); + } + + public run(): Promise { + this.debugService.addFunctionBreakpoint(); + return Promise.as(null); + } +} + export class ToggleBreakpointAction extends EditorAction { static ID = 'editor.debug.action.toggleBreakpoint'; diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index 5a60da69030..b303da8b6c8 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -703,6 +703,9 @@ export class BreakpointsActionProvider extends SimpleActionProvider { actions.push(this.instantiationService.createInstance(debugactions.DisableAllBreakpointsAction, debugactions.DisableAllBreakpointsAction.ID, debugactions.DisableAllBreakpointsAction.LABEL)); actions.push(new actionbar.Separator()); + actions.push(this.instantiationService.createInstance(debugactions.AddFunctionBreakpointAction, debugactions.AddFunctionBreakpointAction.ID, debugactions.AddFunctionBreakpointAction.LABEL)); + actions.push(new actionbar.Separator()); + actions.push(this.instantiationService.createInstance(debugactions.ReapplyBreakpointsAction, debugactions.ReapplyBreakpointsAction.ID, debugactions.ReapplyBreakpointsAction.LABEL)); return Promise.as(actions); diff --git a/src/vs/workbench/parts/debug/browser/debugViewlet.ts b/src/vs/workbench/parts/debug/browser/debugViewlet.ts index 1512580c31e..663c11dea6d 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewlet.ts @@ -369,6 +369,7 @@ class BreakpointsView extends viewlet.AdaptiveCollapsibleViewletView { public getActions(): actions.IAction[] { return [ + this.instantiationService.createInstance(dbgactions.AddFunctionBreakpointAction, dbgactions.AddFunctionBreakpointAction.ID, dbgactions.AddFunctionBreakpointAction.LABEL), this.instantiationService.createInstance(dbgactions.ReapplyBreakpointsAction, dbgactions.ReapplyBreakpointsAction.ID, dbgactions.ReapplyBreakpointsAction.LABEL), this.instantiationService.createInstance(dbgactions.ToggleBreakpointsActivatedAction, dbgactions.ToggleBreakpointsActivatedAction.ID, dbgactions.ToggleBreakpointsActivatedAction.LABEL), this.instantiationService.createInstance(dbgactions.RemoveAllBreakpointsAction, dbgactions.RemoveAllBreakpointsAction.ID, dbgactions.RemoveAllBreakpointsAction.LABEL) diff --git a/src/vs/workbench/parts/debug/browser/media/debugViewlet.css b/src/vs/workbench/parts/debug/browser/media/debugViewlet.css index 097d9ee3b74..8ff2b3edb8e 100644 --- a/src/vs/workbench/parts/debug/browser/media/debugViewlet.css +++ b/src/vs/workbench/parts/debug/browser/media/debugViewlet.css @@ -135,7 +135,8 @@ padding: 1px 2px; } -.debug-viewlet .debug-action.add-watch-expression { +.debug-viewlet .debug-action.add-watch-expression, +.debug-viewlet .debug-action.add-function-breakpoint { background: url('add.svg') center center no-repeat; } diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index cdd7f3ceb5d..028cacc7828 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -222,6 +222,7 @@ export interface IDebugService extends ee.IEventEmitter { clearBreakpoints(modelUri?: uri): Promise; toggleBreakpointsActivated(): Promise; sendAllBreakpoints(): Promise; + addFunctionBreakpoint(functionName?: string): void; addReplExpression(name: string): Promise; clearReplExpressions(): void; diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index 3ae588b9d77..fbbd4febe78 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -424,6 +424,11 @@ export class Model extends ee.EventEmitter implements debug.IModel { this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); } + public addFunctionBreakpoint(functionName: string): void { + this.functionBreakpoints.push(new FunctionBreakpoint(functionName, true)); + this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); + } + public getReplElements(): debug.ITreeElement[] { return this.replElements; } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 56a324afa9f..2a6f8ab7684 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -48,6 +48,7 @@ import { ILogEntry, PLUGIN_LOG_BROADCAST_CHANNEL } from 'vs/workbench/services/t var DEBUG_BREAKPOINTS_KEY = 'debug.breakpoint'; var DEBUG_BREAKPOINTS_ACTIVATED_KEY = 'debug.breakpointactivated'; +var DEBUG_FUNCTION_BREAKPOINTS_KEY = 'debug.functionbreakpoint'; var DEBUG_EXCEPTION_BREAKPOINTS_KEY = 'debug.exceptionbreakpoint'; var DEBUG_WATCH_EXPRESSIONS_KEY = 'debug.watchexpressions'; var DEBUG_SELECTED_CONFIG_NAME_KEY = 'debug.selectedconfigname'; @@ -99,7 +100,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService this.configurationManager = this.instantiationService.createInstance(ConfigurationManager, this.storageService.get(DEBUG_SELECTED_CONFIG_NAME_KEY, StorageScope.WORKSPACE, 'null')); this.inDebugMode = keybindingService.createKey(debug.CONTEXT_IN_DEBUG_MODE, false); - this.model = new model.Model(this.loadBreakpoints(), this.storageService.getBoolean(DEBUG_BREAKPOINTS_ACTIVATED_KEY, StorageScope.WORKSPACE, true), + this.model = new model.Model(this.loadBreakpoints(), this.storageService.getBoolean(DEBUG_BREAKPOINTS_ACTIVATED_KEY, StorageScope.WORKSPACE, true), this.loadFunctionBreakpoints(), this.loadExceptionBreakpoints(), this.loadWatchExpressions()); this.viewModel = new viewmodel.ViewModel(); @@ -313,6 +314,16 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService } } + private loadFunctionBreakpoints(): debug.IFunctionBreakpoint[] { + try { + return JSON.parse(this.storageService.get(DEBUG_FUNCTION_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((fb: any) => { + return new model.FunctionBreakpoint(fb.functionName, fb.enabled); + }); + } catch (e) { + return []; + } + } + private loadExceptionBreakpoints(): debug.IExceptionBreakpoint[] { var result: debug.IExceptionBreakpoint[] = null; try { @@ -395,6 +406,10 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService return this.sendAllBreakpoints(); } + public addFunctionBreakpoint(functionName?: string): void { + this.model.addFunctionBreakpoint(functionName); + } + public addReplExpression(name: string): Promise { return this.model.addReplExpression(this.session, this.viewModel.getFocusedStackFrame(), name); } diff --git a/src/vs/workbench/parts/debug/test/common/debugModel.test.ts b/src/vs/workbench/parts/debug/test/common/debugModel.test.ts index afcdd5a5b1b..d7ffef7e142 100644 --- a/src/vs/workbench/parts/debug/test/common/debugModel.test.ts +++ b/src/vs/workbench/parts/debug/test/common/debugModel.test.ts @@ -13,7 +13,7 @@ suite('Debug - Model', () => { var model: debugmodel.Model; setup(() => { - model = new debugmodel.Model([], true, [], []); + model = new debugmodel.Model([], true, [], [], []); }); teardown(() => { From 351b1e4571e23671a0b856aa1b5f2c47f1b03873 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 27 Nov 2015 16:45:17 +0100 Subject: [PATCH 192/588] [json] Don't propose keys that are already existing #662 --- .../languages/json/common/jsonIntellisense.ts | 10 +++++++++- .../json/test/common/jsonworker.test.ts | 18 ++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/vs/languages/json/common/jsonIntellisense.ts b/src/vs/languages/json/common/jsonIntellisense.ts index 0e3f1c9ae0b..3a78da4e6fe 100644 --- a/src/vs/languages/json/common/jsonIntellisense.ts +++ b/src/vs/languages/json/common/jsonIntellisense.ts @@ -67,6 +67,7 @@ export class JSONIntellisense { var node = doc.getNodeFromOffsetEndInclusive(offset); var addValue = true; var currentKey = currentWord; + var currentProperty : Parser.PropertyASTNode = null; if (node) { if (node.type === 'string') { @@ -76,6 +77,7 @@ export class JSONIntellisense { result.overwriteBefore = position.column - nodeRange.startColumn; result.overwriteAfter = nodeRange.endColumn - position.column; addValue = !(node.parent && (( node.parent).value)); + currentProperty = node.parent ? node.parent : null; currentKey = modelMirror.getValueInRange({ startColumn: nodeRange.startColumn + 1, startLineNumber: nodeRange.startLineNumber, endColumn: position.column, endLineNumber: position.lineNumber }); if (node.parent) { node = node.parent.parent; @@ -91,10 +93,16 @@ export class JSONIntellisense { if (node.start === offset) { return result; } + // don't suggest properties that are already present + var properties = ( node).properties; + properties.forEach(p => { + if (!currentProperty || currentProperty !== p) { + proposed[p.key.value] = true; + } + }); if (schema) { // property proposals with schema - var properties = ( node).properties; var isLast = properties.length === 0 || offset >= properties[properties.length - 1].start; collectionPromises.push(this.getPropertySuggestions(schema, doc, node, currentKey, addValue, isLast, collector)); diff --git a/src/vs/languages/json/test/common/jsonworker.test.ts b/src/vs/languages/json/test/common/jsonworker.test.ts index 945ec46ce0c..9f52bf5159d 100644 --- a/src/vs/languages/json/test/common/jsonworker.test.ts +++ b/src/vs/languages/json/test/common/jsonworker.test.ts @@ -179,9 +179,8 @@ suite('JSON - Worker', () => { assertSuggestion(result, 'name'); }), testSuggestionsFor('[ { "name": "John", "address": { "street" : "MH Road", "number" : 5 } }, { "name": "Jack", "address": { "street" : "100 Feet Road", /**/ }', '/**/').then((result) => { - assert.strictEqual(result.suggestions.length, 2); + assert.strictEqual(result.suggestions.length, 1); assertSuggestion(result, 'number'); - assertSuggestion(result, 'street'); }) ]).done(() => testDone(), (errors:any[]) => { testDone(errors.reduce((e1, e2) => e1 || e2)); @@ -216,8 +215,7 @@ suite('JSON - Worker', () => { assertSuggestion(result, '"xoo"'); }), testSuggestionsFor('[ { "data": "foo" }, { "data": "bar" }, { "data": "xoo" /**/ } ]', '/**/').then((result) => { - assert.strictEqual(result.suggestions.length, 1); - assertSuggestion(result, 'data'); + assert.strictEqual(result.suggestions.length, 0); }) ]).done(() => testDone(), (errors:any[]) => { testDone(errors.reduce((e1, e2) => e1 || e2)); @@ -260,8 +258,7 @@ suite('JSON - Worker', () => { assertSuggestion(result, 'a', 'A'); }), testSuggestionsFor('{ "a" = 1;/**/}', '/**/', schema).then((result) => { - assert.strictEqual(result.suggestions.length, 3); - assertSuggestion(result, 'a', 'A'); + assert.strictEqual(result.suggestions.length, 2); assertSuggestion(result, 'b', 'B'); assertSuggestion(result, 'c', 'C'); }) @@ -375,8 +372,7 @@ suite('JSON - Worker', () => { assertSuggestion(result, 'd', 'D'); }), testSuggestionsFor('{ "a": "", /**/}', '/**/', schema).then((result) => { - assert.strictEqual(result.suggestions.length, 2); - assertSuggestion(result, 'a', 'A'); + assert.strictEqual(result.suggestions.length, 1); assertSuggestion(result, 'b', 'B'); }) ]).done(() => testDone(), (errors:any[]) => { @@ -417,8 +413,7 @@ suite('JSON - Worker', () => { assertSuggestion(result, 'c'); }), testSuggestionsFor('{ "type": "appartment", /**/}', '/**/', schema).then((result) => { - assert.strictEqual(result.suggestions.length, 2); - assertSuggestion(result, 'type'); + assert.strictEqual(result.suggestions.length, 1); assertSuggestion(result, 'c'); }) ]).done(() => testDone(), (errors:any[]) => { @@ -480,9 +475,8 @@ suite('JSON - Worker', () => { assertSuggestion(result, 'd', 'D'); }), testSuggestionsFor('{ "b1": "", /**/}', '/**/', schema).then((result) => { - assert.strictEqual(result.suggestions.length, 3); + assert.strictEqual(result.suggestions.length, 2); assertSuggestion(result, 'a', 'A'); - assertSuggestion(result, 'b1', 'B1'); assertSuggestion(result, 'b2', 'B2'); }) ]).done(() => testDone(), (errors:any[]) => { From 015cf9111f36a35647bdf44494bd605724508450 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2015 18:45:45 +0100 Subject: [PATCH 193/588] debug: render function breakpoints in breakpoints pane. --- .../parts/debug/browser/debugViewer.ts | 45 +++++++++++++------ .../parts/debug/browser/debugViewlet.ts | 9 +++- src/vs/workbench/parts/debug/common/debug.ts | 3 +- .../parts/debug/common/debugModel.ts | 5 +++ .../debug/electron-browser/debugService.ts | 10 ++++- 5 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index b303da8b6c8..9975856e143 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -7,6 +7,7 @@ import { Promise, TPromise } from 'vs/base/common/winjs.base'; import lifecycle = require('vs/base/common/lifecycle'); import paths = require('vs/base/common/paths'); import async = require('vs/base/common/async'); +import errors = require('vs/base/common/errors'); import severity from 'vs/base/common/severity'; import strings = require('vs/base/common/strings'); import { isMacintosh } from 'vs/base/common/platform'; @@ -726,7 +727,7 @@ export class BreakpointsDataSource implements tree.IDataSource { var model = element; var exBreakpoints = model.getExceptionBreakpoints(); - return Promise.as(exBreakpoints.concat(model.getBreakpoints())); + return Promise.as(exBreakpoints.concat(model.getFunctionBreakpoints()).concat(model.getBreakpoints())); } public getParent(tree: tree.ITree, element: any): Promise { @@ -746,9 +747,14 @@ interface IBreakpointTemplateData extends IExceptionBreakpointTemplateData { filePath: HTMLElement; } +interface IFunctionBreakpointTemplateData extends IExceptionBreakpointTemplateData { + actionBar: actionbar.ActionBar; +} + export class BreakpointsRenderer implements tree.IRenderer { private static EXCEPTION_BREAKPOINT_TEMPLATE_ID = 'exceptionBreakpoint'; + private static FUNCTION_BREAKPOINT_TEMPLATE_ID = 'functionBreakpoint'; private static BREAKPOINT_TEMPLATE_ID = 'breakpoint'; constructor( @@ -769,6 +775,9 @@ export class BreakpointsRenderer implements tree.IRenderer { if (element instanceof model.Breakpoint) { return BreakpointsRenderer.BREAKPOINT_TEMPLATE_ID; } + if (element instanceof model.FunctionBreakpoint) { + return BreakpointsRenderer.FUNCTION_BREAKPOINT_TEMPLATE_ID; + } if (element instanceof model.ExceptionBreakpoint) { return BreakpointsRenderer.EXCEPTION_BREAKPOINT_TEMPLATE_ID; } @@ -802,41 +811,44 @@ export class BreakpointsRenderer implements tree.IRenderer { } public renderElement(tree: tree.ITree, element: any, templateId: string, templateData: any): void { + templateData.toDisposeBeforeRender = lifecycle.disposeAll(templateData.toDisposeBeforeRender); + templateData.toDisposeBeforeRender.push(dom.addStandardDisposableListener(templateData.checkbox, 'change', (e) => { + this.debugService.toggleEnablement(element); + })); + if (templateId === BreakpointsRenderer.EXCEPTION_BREAKPOINT_TEMPLATE_ID) { this.renderExceptionBreakpoint(element, templateData); + } else if (templateId === BreakpointsRenderer.FUNCTION_BREAKPOINT_TEMPLATE_ID) { + this.renderFunctionBreakpoint(tree, element, templateData); } else { this.renderBreakpoint(tree, element, templateData); } } private renderExceptionBreakpoint(exceptionBreakpoint: debug.IExceptionBreakpoint, data: IExceptionBreakpointTemplateData): void { - data.toDisposeBeforeRender = lifecycle.disposeAll(data.toDisposeBeforeRender); var namePascalCase = exceptionBreakpoint.name.charAt(0).toUpperCase() + exceptionBreakpoint.name.slice(1); data.name.textContent = `${ namePascalCase} exceptions`; data.checkbox.checked = exceptionBreakpoint.enabled; + } - data.toDisposeBeforeRender.push(dom.addStandardDisposableListener(data.checkbox, 'change', (e) => { - this.debugService.toggleEnablement(exceptionBreakpoint); - })); + private renderFunctionBreakpoint(tree: tree.ITree, functionBreakpoint: debug.IFunctionBreakpoint, data: IFunctionBreakpointTemplateData): void { + this.debugService.getModel().areBreakpointsActivated() ? tree.removeTraits('disabled', [functionBreakpoint]) : tree.addTraits('disabled', [functionBreakpoint]); + data.name.textContent = functionBreakpoint.functionName; + data.checkbox.checked = functionBreakpoint.enabled; } private renderBreakpoint(tree: tree.ITree, breakpoint: debug.IBreakpoint, data: IBreakpointTemplateData): void { this.debugService.getModel().areBreakpointsActivated() ? tree.removeTraits('disabled', [breakpoint]) : tree.addTraits('disabled', [breakpoint]); - data.toDisposeBeforeRender = lifecycle.disposeAll(data.toDisposeBeforeRender); data.name.textContent = labels.getPathLabel(paths.basename(breakpoint.source.uri.fsPath), this.contextService); data.lineNumber.textContent = breakpoint.desiredLineNumber !== breakpoint.lineNumber ? breakpoint.desiredLineNumber + ' \u2192 ' + breakpoint.lineNumber : '' + breakpoint.lineNumber; data.filePath.textContent = labels.getPathLabel(paths.dirname(breakpoint.source.uri.fsPath), this.contextService); data.checkbox.checked = breakpoint.enabled; data.actionBar.context = breakpoint; - - data.toDisposeBeforeRender.push(dom.addStandardDisposableListener(data.checkbox, 'change', (e) => { - this.debugService.toggleEnablement(breakpoint); - })); } public disposeTemplate(tree: tree.ITree, templateId: string, templateData: any): void { - if (templateId === BreakpointsRenderer.BREAKPOINT_TEMPLATE_ID) { + if (templateId === BreakpointsRenderer.BREAKPOINT_TEMPLATE_ID || templateId === BreakpointsRenderer.FUNCTION_BREAKPOINT_TEMPLATE_ID) { templateData.actionBar.dispose(); } } @@ -872,10 +884,15 @@ export class BreakpointsController extends BaseDebugController { } protected onDelete(tree: tree.ITree, event: keyboard.StandardKeyboardEvent): boolean { - var element = tree.getFocus(); + const element = tree.getFocus(); if (element instanceof model.Breakpoint) { - var bp = element; - this.debugService.toggleBreakpoint(bp.source.uri, bp.lineNumber); + const bp = element; + this.debugService.toggleBreakpoint(bp.source.uri, bp.lineNumber).done(null, errors.onUnexpectedError); + + return true; + } else if (element instanceof model.FunctionBreakpoint) { + const fbp = element; + this.debugService.removeFunctionBreakpoint(fbp.getId()).done(null, errors.onUnexpectedError); return true; } diff --git a/src/vs/workbench/parts/debug/browser/debugViewlet.ts b/src/vs/workbench/parts/debug/browser/debugViewlet.ts index 663c11dea6d..57828dd7dc6 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewlet.ts @@ -324,9 +324,12 @@ class BreakpointsView extends viewlet.AdaptiveCollapsibleViewletView { if (first instanceof model.ExceptionBreakpoint) { return -1; } - if (second instanceof model.ExceptionBreakpoint) { + if (second instanceof model.ExceptionBreakpoint || second instanceof model.FunctionBreakpoint) { return 1; } + if (first instanceof model.FunctionBreakpoint) { + return -1; + } if (first.source.uri.toString() !== second.source.uri.toString()) { return first.source.uri.toString().localeCompare(second.source.uri.toString()); @@ -377,7 +380,9 @@ class BreakpointsView extends viewlet.AdaptiveCollapsibleViewletView { } private onBreakpointsChange(): void { - this.expandedBodySize = BreakpointsView.getExpandedBodySize(this.debugService.getModel().getBreakpoints().length + this.debugService.getModel().getExceptionBreakpoints().length); + const model = this.debugService.getModel(); + this.expandedBodySize = BreakpointsView.getExpandedBodySize( + model.getBreakpoints().length + model.getExceptionBreakpoints().length + model.getFunctionBreakpoints().length); if (this.tree) { this.tree.refresh(); diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index 028cacc7828..1f34c288842 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -222,7 +222,8 @@ export interface IDebugService extends ee.IEventEmitter { clearBreakpoints(modelUri?: uri): Promise; toggleBreakpointsActivated(): Promise; sendAllBreakpoints(): Promise; - addFunctionBreakpoint(functionName?: string): void; + addFunctionBreakpoint(functionName?: string): Promise; + removeFunctionBreakpoint(id: string): Promise; addReplExpression(name: string): Promise; clearReplExpressions(): void; diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index fbbd4febe78..3cebdc2a811 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -429,6 +429,11 @@ export class Model extends ee.EventEmitter implements debug.IModel { this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); } + public removeFunctionBreakpoint(id: string): void { + this.functionBreakpoints = this.functionBreakpoints.filter(fbp => fbp.getId() != id); + this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); + } + public getReplElements(): debug.ITreeElement[] { return this.replElements; } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 2a6f8ab7684..d0341b80fae 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -406,8 +406,16 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService return this.sendAllBreakpoints(); } - public addFunctionBreakpoint(functionName?: string): void { + public addFunctionBreakpoint(functionName?: string): Promise { this.model.addFunctionBreakpoint(functionName); + // TODO@Isidor send updated function breakpoints + return Promise.as(true); + } + + public removeFunctionBreakpoint(id: string): Promise { + this.model.removeFunctionBreakpoint(id); + // TODO@Isidor send updated function breakpoints + return Promise.as(true); } public addReplExpression(name: string): Promise { From c3e4d5a9d3ecae922ff7e21a0e0ce534f7612b54 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2015 18:57:18 +0100 Subject: [PATCH 194/588] debug: renderRenameBox should be reusable. --- .../parts/debug/browser/debugViewer.ts | 88 +++++++++---------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index 9975856e143..baf7c992fbc 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -66,6 +66,49 @@ export function renderVariable(tree: tree.ITree, variable: model.Variable, data: } } +function renderRenameBox(debugService: debug.IDebugService, contextViewService: IContextViewService, tree: tree.ITree, expression: debug.IExpression, container: HTMLElement): void { + let inputBoxContainer = dom.append(container, $('.inputBoxContainer')); + let inputBox = new inputbox.InputBox(inputBoxContainer, contextViewService, { + validationOptions: { + validation: null, + showMessage: false + } + }); + + inputBox.value = expression.name ? expression.name : ''; + inputBox.focus(); + + var disposed = false; + var toDispose: [lifecycle.IDisposable] = [inputBox]; + + var wrapUp = async.once((renamed: boolean) => { + if (!disposed) { + disposed = true; + if (renamed && inputBox.value) { + debugService.renameWatchExpression(expression.getId(), inputBox.value); + } else if (!expression.name) { + debugService.clearWatchExpressions(expression.getId()); + } + tree.clearHighlight(); + tree.DOMFocus(); + // Need to remove the input box since this template will be reused. + container.removeChild(inputBoxContainer); + lifecycle.disposeAll(toDispose); + } + }); + + toDispose.push(dom.addStandardDisposableListener(inputBox.inputElement, 'keydown', (e: dom.IKeyboardEvent) => { + let isEscape = e.equals(CommonKeybindings.ESCAPE); + let isEnter = e.equals(CommonKeybindings.ENTER); + if (isEscape || isEnter) { + wrapUp(isEnter); + } + })); + toDispose.push(dom.addDisposableListener(inputBox.inputElement, 'blur', () => { + wrapUp(true); + })); +} + export class SimpleActionProvider implements renderer.IActionProvider { constructor() { @@ -544,7 +587,7 @@ export class WatchExpressionsRenderer implements tree.IRenderer { private renderWatchExpression(tree: tree.ITree, watchExpression: debug.IExpression, data: IWatchExpressionTemplateData): void { let selectedExpression = this.debugService.getViewModel().getSelectedExpression(); if ((selectedExpression instanceof model.Expression && selectedExpression.getId() === watchExpression.getId()) || (watchExpression instanceof model.Expression && !watchExpression.name)) { - this.renderRenameBox(tree, watchExpression, data); + renderRenameBox(this.debugService, this.contextViewService, tree, watchExpression, data.expression); } data.actionBar.context = watchExpression; @@ -558,49 +601,6 @@ export class WatchExpressionsRenderer implements tree.IRenderer { } } - private renderRenameBox(tree: tree.ITree, expression: debug.IExpression, data: IWatchExpressionTemplateData): void { - let inputBoxContainer = dom.append(data.expression, $('.inputBoxContainer')); - let inputBox = new inputbox.InputBox(inputBoxContainer, this.contextViewService, { - validationOptions: { - validation: null, - showMessage: false - } - }); - - inputBox.value = expression.name ? expression.name : ''; - inputBox.focus(); - - var disposed = false; - var toDispose: [lifecycle.IDisposable] = [inputBox]; - - var wrapUp = async.once((renamed: boolean) => { - if (!disposed) { - disposed = true; - if (renamed && inputBox.value) { - this.debugService.renameWatchExpression(expression.getId(), inputBox.value); - } else if (!expression.name) { - this.debugService.clearWatchExpressions(expression.getId()); - } - tree.clearHighlight(); - tree.DOMFocus(); - // Need to remove the input box since this template will be reused. - data.expression.removeChild(inputBoxContainer); - lifecycle.disposeAll(toDispose); - } - }); - - toDispose.push(dom.addStandardDisposableListener(inputBox.inputElement, 'keydown', (e: dom.IKeyboardEvent) => { - let isEscape = e.equals(CommonKeybindings.ESCAPE); - let isEnter = e.equals(CommonKeybindings.ENTER); - if (isEscape || isEnter) { - wrapUp(isEnter); - } - })); - toDispose.push(dom.addDisposableListener(inputBox.inputElement, 'blur', () => { - wrapUp(true); - })); - } - public disposeTemplate(tree: tree.ITree, templateId: string, templateData: any): void { // noop } From cf4b2885a8142c9dacd82fc1aee5ea709369560b Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2015 18:59:08 +0100 Subject: [PATCH 195/588] debug: rename functionBreakpoint.functionName to name --- src/vs/workbench/parts/debug/browser/debugViewer.ts | 2 +- src/vs/workbench/parts/debug/common/debug.ts | 2 +- src/vs/workbench/parts/debug/common/debugModel.ts | 2 +- src/vs/workbench/parts/debug/electron-browser/debugService.ts | 3 ++- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index baf7c992fbc..6020bc27796 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -833,7 +833,7 @@ export class BreakpointsRenderer implements tree.IRenderer { private renderFunctionBreakpoint(tree: tree.ITree, functionBreakpoint: debug.IFunctionBreakpoint, data: IFunctionBreakpointTemplateData): void { this.debugService.getModel().areBreakpointsActivated() ? tree.removeTraits('disabled', [functionBreakpoint]) : tree.addTraits('disabled', [functionBreakpoint]); - data.name.textContent = functionBreakpoint.functionName; + data.name.textContent = functionBreakpoint.name; data.checkbox.checked = functionBreakpoint.enabled; } diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index 1f34c288842..8df40ce782e 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -75,7 +75,7 @@ export interface IBreakpoint extends IEnablement { } export interface IFunctionBreakpoint extends IEnablement { - functionName: string; + name: string; } export interface IExceptionBreakpoint extends IEnablement { diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index 3cebdc2a811..960bdfe17ed 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -271,7 +271,7 @@ export class FunctionBreakpoint implements debug.IFunctionBreakpoint { private id: string; - constructor(public functionName: string, public enabled: boolean) { + constructor(public name: string, public enabled: boolean) { this.id = uuid.generateUuid(); } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index d0341b80fae..9ed0e605b64 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -317,7 +317,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService private loadFunctionBreakpoints(): debug.IFunctionBreakpoint[] { try { return JSON.parse(this.storageService.get(DEBUG_FUNCTION_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((fb: any) => { - return new model.FunctionBreakpoint(fb.functionName, fb.enabled); + return new model.FunctionBreakpoint(fb.name, fb.enabled); }); } catch (e) { return []; @@ -763,6 +763,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService private store(): void { this.storageService.store(DEBUG_BREAKPOINTS_KEY, JSON.stringify(this.model.getBreakpoints()), StorageScope.WORKSPACE); this.storageService.store(DEBUG_BREAKPOINTS_ACTIVATED_KEY, this.model.areBreakpointsActivated() ? 'true' : 'false', StorageScope.WORKSPACE); + this.storageService.store(DEBUG_FUNCTION_BREAKPOINTS_KEY, JSON.stringify(this.model.getFunctionBreakpoints()), StorageScope.WORKSPACE); this.storageService.store(DEBUG_EXCEPTION_BREAKPOINTS_KEY, JSON.stringify(this.model.getExceptionBreakpoints()), StorageScope.WORKSPACE); this.storageService.store(DEBUG_SELECTED_CONFIG_NAME_KEY, this.configurationManager.getConfigurationName(), StorageScope.WORKSPACE); this.storageService.store(DEBUG_WATCH_EXPRESSIONS_KEY, JSON.stringify(this.model.getWatchExpressions()), StorageScope.WORKSPACE); From 5da0947edd3598894064ef4738b5941c32c99698 Mon Sep 17 00:00:00 2001 From: Resi Respati Date: Sat, 28 Nov 2015 01:15:32 +0700 Subject: [PATCH 196/588] editorconfig updates * Define `indent_size` so it will indent properly on VSCode * `package.json` always uses 2-space indentation --- .editorconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 361c815c1a7..763de517a34 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,7 +6,10 @@ root = true # Tab indentation (no size specified) [*] indent_style = tab +indent_size = 4 -[{.travis.yml,npm-shrinkwrap.json}] +# The indent size used in the `package.json` file cannot be changed +# https://github.com/npm/npm/pull/3180#issuecomment-16336516 +[{.travis.yml,npm-shrinkwrap.json,package.json}] indent_style = space indent_size = 2 From 87145f8d4b3c96a28591f4f57597ce53c973c141 Mon Sep 17 00:00:00 2001 From: Resi Respati Date: Sat, 28 Nov 2015 01:15:44 +0700 Subject: [PATCH 197/588] Fixed whitespace --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 50b241f37a9..a0044874ec1 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ }, "scripts": { "test": "node node_modules/mocha/bin/_mocha", - "preinstall": "node build/npm/preinstall.js", + "preinstall": "node build/npm/preinstall.js", "postinstall": "npm --prefix extensions/csharp-o/ install extensions/csharp-o/ && npm --prefix extensions/vscode-api-tests/ install extensions/vscode-api-tests/" }, "dependencies": { From 40b59aa913acf7c8b547288e4ea710b7766aab7e Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2015 19:48:46 +0100 Subject: [PATCH 198/588] debug: renameFunctionBreakpoint --- src/vs/workbench/parts/debug/common/debug.ts | 2 ++ src/vs/workbench/parts/debug/common/debugModel.ts | 8 ++++++++ .../parts/debug/electron-browser/debugService.ts | 6 ++++++ 3 files changed, 16 insertions(+) diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index 8df40ce782e..13c813b8c50 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -222,7 +222,9 @@ export interface IDebugService extends ee.IEventEmitter { clearBreakpoints(modelUri?: uri): Promise; toggleBreakpointsActivated(): Promise; sendAllBreakpoints(): Promise; + addFunctionBreakpoint(functionName?: string): Promise; + renameFunctionBreakpoint(id: string, newFunctionName: string): Promise; removeFunctionBreakpoint(id: string): Promise; addReplExpression(name: string): Promise; diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index 960bdfe17ed..667c147e109 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -429,6 +429,14 @@ export class Model extends ee.EventEmitter implements debug.IModel { this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); } + public renameFunctionBreakpoint(id: string, newFunctionName: string): void { + const fbp = this.functionBreakpoints.filter(bp => bp.getId() === id).pop(); + if (fbp) { + fbp.name = newFunctionName; + this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); + } + } + public removeFunctionBreakpoint(id: string): void { this.functionBreakpoints = this.functionBreakpoints.filter(fbp => fbp.getId() != id); this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 9ed0e605b64..94b5cd5d325 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -412,6 +412,12 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService return Promise.as(true); } + public renameFunctionBreakpoint(id: string, newFunctionName: string): Promise { + this.model.renameFunctionBreakpoint(id, newFunctionName); + // TODO@Isidor send updated function breakpoints + return Promise.as(true); + } + public removeFunctionBreakpoint(id: string): Promise { this.model.removeFunctionBreakpoint(id); // TODO@Isidor send updated function breakpoints From e0614e64fdc5ed51be94b51ea5fd58ceb1ce6683 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2015 19:49:03 +0100 Subject: [PATCH 199/588] debug: render inputbox to enter function breakpoint name. --- .../parts/debug/browser/debugViewer.ts | 47 ++++++++++++------- .../parts/debug/browser/debugViewlet.ts | 3 +- .../debug/browser/media/debugViewlet.css | 3 ++ 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index 6020bc27796..3230169eeeb 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import nls = require('vs/nls'); import { Promise, TPromise } from 'vs/base/common/winjs.base'; import lifecycle = require('vs/base/common/lifecycle'); import paths = require('vs/base/common/paths'); @@ -66,16 +67,17 @@ export function renderVariable(tree: tree.ITree, variable: model.Variable, data: } } -function renderRenameBox(debugService: debug.IDebugService, contextViewService: IContextViewService, tree: tree.ITree, expression: debug.IExpression, container: HTMLElement): void { +function renderRenameBox(debugService: debug.IDebugService, contextViewService: IContextViewService, tree: tree.ITree, element: any, container: HTMLElement, placeholder: string): void { let inputBoxContainer = dom.append(container, $('.inputBoxContainer')); let inputBox = new inputbox.InputBox(inputBoxContainer, contextViewService, { validationOptions: { validation: null, showMessage: false - } + }, + placeholder: placeholder }); - inputBox.value = expression.name ? expression.name : ''; + inputBox.value = element.name ? element.name : ''; inputBox.focus(); var disposed = false; @@ -84,11 +86,16 @@ function renderRenameBox(debugService: debug.IDebugService, contextViewService: var wrapUp = async.once((renamed: boolean) => { if (!disposed) { disposed = true; - if (renamed && inputBox.value) { - debugService.renameWatchExpression(expression.getId(), inputBox.value); - } else if (!expression.name) { - debugService.clearWatchExpressions(expression.getId()); + if (element instanceof model.Expression && renamed && inputBox.value) { + debugService.renameWatchExpression(element.getId(), inputBox.value).done(null, errors.onUnexpectedError); + } else if (element instanceof model.Expression && !element.name) { + debugService.clearWatchExpressions(element.getId()); + } else if (element instanceof model.FunctionBreakpoint && renamed && inputBox.value) { + debugService.renameFunctionBreakpoint(element.getId(), inputBox.value).done(null, errors.onUnexpectedError); + } else if (element instanceof model.FunctionBreakpoint && !element.name) { + debugService.removeFunctionBreakpoint(element.getId()).done(null, errors.onUnexpectedError); } + tree.clearHighlight(); tree.DOMFocus(); // Need to remove the input box since this template will be reused. @@ -587,7 +594,7 @@ export class WatchExpressionsRenderer implements tree.IRenderer { private renderWatchExpression(tree: tree.ITree, watchExpression: debug.IExpression, data: IWatchExpressionTemplateData): void { let selectedExpression = this.debugService.getViewModel().getSelectedExpression(); if ((selectedExpression instanceof model.Expression && selectedExpression.getId() === watchExpression.getId()) || (watchExpression instanceof model.Expression && !watchExpression.name)) { - renderRenameBox(this.debugService, this.contextViewService, tree, watchExpression, data.expression); + renderRenameBox(this.debugService, this.contextViewService, tree, watchExpression, data.expression, nls.localize('watchExpressionPlaceholder', "Expression to watch")); } data.actionBar.context = watchExpression; @@ -736,6 +743,7 @@ export class BreakpointsDataSource implements tree.IDataSource { } interface IExceptionBreakpointTemplateData { + breakpoint: HTMLElement; name: HTMLElement; checkbox: HTMLInputElement; toDisposeBeforeRender: lifecycle.IDisposable[]; @@ -762,7 +770,8 @@ export class BreakpointsRenderer implements tree.IRenderer { private actionRunner: actions.IActionRunner, @IMessageService private messageService: IMessageService, @IWorkspaceContextService private contextService: IWorkspaceContextService, - @debug.IDebugService private debugService: debug.IDebugService + @debug.IDebugService private debugService: debug.IDebugService, + @IContextViewService private contextViewService: IContextViewService ) { // noop } @@ -792,19 +801,19 @@ export class BreakpointsRenderer implements tree.IRenderer { data.actionBar.push(this.actionProvider.getBreakpointActions(), { icon: true, label: false }); } - var el = dom.append(container, $('.breakpoint')); + data.breakpoint = dom.append(container, $('.breakpoint')); data.toDisposeBeforeRender = []; data.checkbox = $('input'); data.checkbox.type = 'checkbox'; data.checkbox.className = 'checkbox'; - dom.append(el, data.checkbox); + dom.append(data.breakpoint, data.checkbox); - data.name = dom.append(el, $('span.name')); + data.name = dom.append(data.breakpoint, $('span.name')); if (templateId === BreakpointsRenderer.BREAKPOINT_TEMPLATE_ID) { - data.lineNumber = dom.append(el, $('span.line-number')); - data.filePath = dom.append(el, $('span.file-path')); + data.lineNumber = dom.append(data.breakpoint, $('span.line-number')); + data.filePath = dom.append(data.breakpoint, $('span.file-path')); } return data; @@ -832,9 +841,13 @@ export class BreakpointsRenderer implements tree.IRenderer { } private renderFunctionBreakpoint(tree: tree.ITree, functionBreakpoint: debug.IFunctionBreakpoint, data: IFunctionBreakpointTemplateData): void { - this.debugService.getModel().areBreakpointsActivated() ? tree.removeTraits('disabled', [functionBreakpoint]) : tree.addTraits('disabled', [functionBreakpoint]); - data.name.textContent = functionBreakpoint.name; - data.checkbox.checked = functionBreakpoint.enabled; + if (!functionBreakpoint.name) { + renderRenameBox(this.debugService, this.contextViewService, tree, functionBreakpoint, data.breakpoint, nls.localize('functionBreakpointPlaceholder', "Function to break on")); + } else { + this.debugService.getModel().areBreakpointsActivated() ? tree.removeTraits('disabled', [functionBreakpoint]) : tree.addTraits('disabled', [functionBreakpoint]); + data.name.textContent = functionBreakpoint.name; + data.checkbox.checked = functionBreakpoint.enabled; + } } private renderBreakpoint(tree: tree.ITree, breakpoint: debug.IBreakpoint, data: IBreakpointTemplateData): void { diff --git a/src/vs/workbench/parts/debug/browser/debugViewlet.ts b/src/vs/workbench/parts/debug/browser/debugViewlet.ts index 57828dd7dc6..693bbdaef81 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewlet.ts @@ -297,7 +297,8 @@ class BreakpointsView extends viewlet.AdaptiveCollapsibleViewletView { @IInstantiationService private instantiationService: IInstantiationService ) { super(actionRunner, BreakpointsView.getExpandedBodySize( - debugService.getModel().getBreakpoints().length + debugService.getModel().getExceptionBreakpoints().length), !!settings[BreakpointsView.MEMENTO], 'breakpointsView', messageService, contextMenuService); + debugService.getModel().getBreakpoints().length + debugService.getModel().getFunctionBreakpoints().length + debugService.getModel().getExceptionBreakpoints().length), + !!settings[BreakpointsView.MEMENTO], 'breakpointsView', messageService, contextMenuService); this.toDispose.push(this.debugService.getModel().addListener2(debug.ModelEvents.BREAKPOINTS_UPDATED,() => this.onBreakpointsChange())); } diff --git a/src/vs/workbench/parts/debug/browser/media/debugViewlet.css b/src/vs/workbench/parts/debug/browser/media/debugViewlet.css index 8ff2b3edb8e..dc143561340 100644 --- a/src/vs/workbench/parts/debug/browser/media/debugViewlet.css +++ b/src/vs/workbench/parts/debug/browser/media/debugViewlet.css @@ -124,6 +124,9 @@ .debug-viewlet .monaco-inputbox { width: 100%; line-height: normal; +} + +.debug-viewlet .debug-watch .monaco-inputbox { font-family: Monaco, Menlo, Consolas, "Droid Sans Mono", "Inconsolata", "Courier New", monospace, "Droid Sans Fallback"; } From 11bc6762ae0ae87fe8fae4837525a311936abc8c Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2015 19:52:00 +0100 Subject: [PATCH 200/588] debug: clearBreakpoints -> removeBreakpoints --- src/vs/workbench/parts/debug/browser/debugActions.ts | 2 +- src/vs/workbench/parts/debug/common/debug.ts | 2 +- src/vs/workbench/parts/debug/common/debugModel.ts | 4 ++-- .../workbench/parts/debug/electron-browser/debugService.ts | 6 +++--- src/vs/workbench/parts/debug/test/common/debugModel.test.ts | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugActions.ts b/src/vs/workbench/parts/debug/browser/debugActions.ts index fec08545911..e7897e90495 100644 --- a/src/vs/workbench/parts/debug/browser/debugActions.ts +++ b/src/vs/workbench/parts/debug/browser/debugActions.ts @@ -280,7 +280,7 @@ export class RemoveAllBreakpointsAction extends AbstractDebugAction { } public run(): Promise { - return this.debugService.clearBreakpoints(); + return this.debugService.removeBreakpoints(); } protected isEnabled(): boolean { diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index 13c813b8c50..5d89d1e465f 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -219,7 +219,7 @@ export interface IDebugService extends ee.IEventEmitter { toggleBreakpoint(modelUri: uri, lineNumber: number, condition?: string): Promise; enableOrDisableAllBreakpoints(enabled: boolean): Promise; toggleEnablement(element: IEnablement): Promise; - clearBreakpoints(modelUri?: uri): Promise; + removeBreakpoints(modelUri?: uri): Promise; toggleBreakpointsActivated(): Promise; sendAllBreakpoints(): Promise; diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index 667c147e109..fcd840d19d6 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -412,14 +412,14 @@ export class Model extends ee.EventEmitter implements debug.IModel { } public setBreakpointsForModel(modelUri: uri, data: { lineNumber: number; enabled: boolean; condition?: string; }[]): void { - this.clearBreakpoints(modelUri); + this.removeBreakpoints(modelUri); for (var i = 0, len = data.length; i < len; i++) { this.breakpoints.push(new Breakpoint(Source.fromUri(modelUri), data[i].lineNumber, data[i].enabled, data[i].condition)); } this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); } - public clearBreakpoints(modelUri: uri): void { + public removeBreakpoints(modelUri: uri): void { this.breakpoints = this.breakpoints.filter(bp => modelUri && modelUri.toString() !== bp.source.uri.toString()); this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 94b5cd5d325..56491faca1e 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -394,9 +394,9 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService return this.sendExceptionBreakpoints(); } - public clearBreakpoints(modelUri: uri = null): Promise { + public removeBreakpoints(modelUri: uri = null): Promise { var urisToClear = modelUri ? [modelUri] : arrays.distinct(this.model.getBreakpoints(), bp => bp.source.uri.toString()).map(bp => bp.source.uri); - this.model.clearBreakpoints(modelUri); + this.model.removeBreakpoints(modelUri); return Promise.join(urisToClear.map(uri => this.sendBreakpoints(uri))); } @@ -760,7 +760,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService var uri = breakpoints[i].source.uri; var uriStr = uri.toString(); if (!clearedUris[uriStr] && fileChangesEvent.contains(uri, FileChangeType.DELETED)) { - this.clearBreakpoints(uri); + this.removeBreakpoints(uri); clearedUris[uriStr] = true; } } diff --git a/src/vs/workbench/parts/debug/test/common/debugModel.test.ts b/src/vs/workbench/parts/debug/test/common/debugModel.test.ts index d7ffef7e142..56315e167e3 100644 --- a/src/vs/workbench/parts/debug/test/common/debugModel.test.ts +++ b/src/vs/workbench/parts/debug/test/common/debugModel.test.ts @@ -28,7 +28,7 @@ suite('Debug - Model', () => { assert.equal(model.areBreakpointsActivated(), true); assert.equal(model.getBreakpoints().length, 2); - model.clearBreakpoints(modelUri); + model.removeBreakpoints(modelUri); assert.equal(model.getBreakpoints().length, 0); }); @@ -66,7 +66,7 @@ suite('Debug - Model', () => { model.toggleEnablement(bp); assert.equal(bp.enabled, true); - model.clearBreakpoints(modelUri1); + model.removeBreakpoints(modelUri1); assert.equal(model.getBreakpoints().length, 3); }); From 5e4f976ac41772b5b1544f8609d9e783234305c5 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2015 19:55:33 +0100 Subject: [PATCH 201/588] debug: remove all breakpoint removes also function breakpoints. --- src/vs/workbench/parts/debug/browser/debugActions.ts | 2 +- src/vs/workbench/parts/debug/browser/debugViewer.ts | 4 ++-- src/vs/workbench/parts/debug/common/debug.ts | 2 +- src/vs/workbench/parts/debug/common/debugModel.ts | 4 ++-- src/vs/workbench/parts/debug/electron-browser/debugService.ts | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugActions.ts b/src/vs/workbench/parts/debug/browser/debugActions.ts index e7897e90495..808d2d4ec24 100644 --- a/src/vs/workbench/parts/debug/browser/debugActions.ts +++ b/src/vs/workbench/parts/debug/browser/debugActions.ts @@ -280,7 +280,7 @@ export class RemoveAllBreakpointsAction extends AbstractDebugAction { } public run(): Promise { - return this.debugService.removeBreakpoints(); + return Promise.join([this.debugService.removeBreakpoints(), this.debugService.removeFunctionBreakpoints()]); } protected isEnabled(): boolean { diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index 3230169eeeb..a81750767b9 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -93,7 +93,7 @@ function renderRenameBox(debugService: debug.IDebugService, contextViewService: } else if (element instanceof model.FunctionBreakpoint && renamed && inputBox.value) { debugService.renameFunctionBreakpoint(element.getId(), inputBox.value).done(null, errors.onUnexpectedError); } else if (element instanceof model.FunctionBreakpoint && !element.name) { - debugService.removeFunctionBreakpoint(element.getId()).done(null, errors.onUnexpectedError); + debugService.removeFunctionBreakpoints(element.getId()).done(null, errors.onUnexpectedError); } tree.clearHighlight(); @@ -905,7 +905,7 @@ export class BreakpointsController extends BaseDebugController { return true; } else if (element instanceof model.FunctionBreakpoint) { const fbp = element; - this.debugService.removeFunctionBreakpoint(fbp.getId()).done(null, errors.onUnexpectedError); + this.debugService.removeFunctionBreakpoints(fbp.getId()).done(null, errors.onUnexpectedError); return true; } diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index 5d89d1e465f..65927a6c39e 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -225,7 +225,7 @@ export interface IDebugService extends ee.IEventEmitter { addFunctionBreakpoint(functionName?: string): Promise; renameFunctionBreakpoint(id: string, newFunctionName: string): Promise; - removeFunctionBreakpoint(id: string): Promise; + removeFunctionBreakpoints(id?: string): Promise; addReplExpression(name: string): Promise; clearReplExpressions(): void; diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index fcd840d19d6..985cfa0a4b6 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -437,8 +437,8 @@ export class Model extends ee.EventEmitter implements debug.IModel { } } - public removeFunctionBreakpoint(id: string): void { - this.functionBreakpoints = this.functionBreakpoints.filter(fbp => fbp.getId() != id); + public removeFunctionBreakpoints(id?: string): void { + this.functionBreakpoints = id ? this.functionBreakpoints.filter(fbp => fbp.getId() != id) : []; this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 56491faca1e..28c52b54112 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -418,8 +418,8 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService return Promise.as(true); } - public removeFunctionBreakpoint(id: string): Promise { - this.model.removeFunctionBreakpoint(id); + public removeFunctionBreakpoints(id?: string): Promise { + this.model.removeFunctionBreakpoints(id); // TODO@Isidor send updated function breakpoints return Promise.as(true); } From 3211a79031b2ec73cb7b15a2a28fad2cb4d3bb05 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2015 20:08:41 +0100 Subject: [PATCH 202/588] debug: enable context menu on function breakpoints. --- src/vs/workbench/parts/debug/browser/debugActions.ts | 3 ++- src/vs/workbench/parts/debug/browser/debugViewer.ts | 2 +- src/vs/workbench/parts/debug/browser/debugViewlet.ts | 5 ++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugActions.ts b/src/vs/workbench/parts/debug/browser/debugActions.ts index 808d2d4ec24..13dd2d5df81 100644 --- a/src/vs/workbench/parts/debug/browser/debugActions.ts +++ b/src/vs/workbench/parts/debug/browser/debugActions.ts @@ -266,7 +266,8 @@ export class RemoveBreakpointAction extends AbstractDebugAction { } public run(breakpoint: debug.IBreakpoint): Promise { - return this.debugService.toggleBreakpoint(breakpoint.source.uri, breakpoint.lineNumber); + return breakpoint instanceof model.Breakpoint ? this.debugService.toggleBreakpoint(breakpoint.source.uri, breakpoint.lineNumber) + : this.debugService.removeFunctionBreakpoints(breakpoint.getId()); } } diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index a81750767b9..b8eb425eca1 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -681,7 +681,7 @@ export class BreakpointsActionProvider extends SimpleActionProvider { } public hasSecondaryActions(tree: tree.ITree, element: any): boolean { - return element instanceof model.Breakpoint || element instanceof model.ExceptionBreakpoint; + return element instanceof model.Breakpoint || element instanceof model.ExceptionBreakpoint || element instanceof model.FunctionBreakpoint; } public getActions(tree: tree.ITree, element: any): TPromise { diff --git a/src/vs/workbench/parts/debug/browser/debugViewlet.ts b/src/vs/workbench/parts/debug/browser/debugViewlet.ts index 693bbdaef81..52bc38d9d78 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewlet.ts @@ -325,12 +325,15 @@ class BreakpointsView extends viewlet.AdaptiveCollapsibleViewletView { if (first instanceof model.ExceptionBreakpoint) { return -1; } - if (second instanceof model.ExceptionBreakpoint || second instanceof model.FunctionBreakpoint) { + if (second instanceof model.ExceptionBreakpoint) { return 1; } if (first instanceof model.FunctionBreakpoint) { return -1; } + if(second instanceof model.FunctionBreakpoint) { + return 1; + } if (first.source.uri.toString() !== second.source.uri.toString()) { return first.source.uri.toString().localeCompare(second.source.uri.toString()); From c48286aaf29f2315f8bea1cee8864024c1660067 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2015 20:18:51 +0100 Subject: [PATCH 203/588] debug: remove vertical-align middle for breakpoints. --- src/vs/workbench/parts/debug/browser/media/debugViewlet.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/media/debugViewlet.css b/src/vs/workbench/parts/debug/browser/media/debugViewlet.css index dc143561340..ec1e88b6efa 100644 --- a/src/vs/workbench/parts/debug/browser/media/debugViewlet.css +++ b/src/vs/workbench/parts/debug/browser/media/debugViewlet.css @@ -158,10 +158,6 @@ text-overflow: ellipsis; } -.debug-viewlet .debug-breakpoints .breakpoint > * { - vertical-align: middle; -} - .debug-viewlet .debug-breakpoints .breakpoint > .file-path { opacity: 0.7; font-size: 0.9em; From b04ab81a41efb77979c954423e21266fe74d3222 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 27 Nov 2015 20:29:33 +0100 Subject: [PATCH 204/588] debug: render action bar for function breakpoints. --- src/vs/workbench/parts/debug/browser/debugViewer.ts | 3 ++- src/vs/workbench/parts/debug/electron-browser/debugService.ts | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index b8eb425eca1..038ef827bdb 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -796,7 +796,7 @@ export class BreakpointsRenderer implements tree.IRenderer { public renderTemplate(tree: tree.ITree, templateId: string, container: HTMLElement): any { var data: IBreakpointTemplateData = Object.create(null); - if (templateId === BreakpointsRenderer.BREAKPOINT_TEMPLATE_ID) { + if (templateId === BreakpointsRenderer.BREAKPOINT_TEMPLATE_ID || templateId === BreakpointsRenderer.FUNCTION_BREAKPOINT_TEMPLATE_ID) { data.actionBar = new actionbar.ActionBar(container, { actionRunner: this.actionRunner }); data.actionBar.push(this.actionProvider.getBreakpointActions(), { icon: true, label: false }); } @@ -848,6 +848,7 @@ export class BreakpointsRenderer implements tree.IRenderer { data.name.textContent = functionBreakpoint.name; data.checkbox.checked = functionBreakpoint.enabled; } + data.actionBar.context = functionBreakpoint; } private renderBreakpoint(tree: tree.ITree, breakpoint: debug.IBreakpoint, data: IBreakpointTemplateData): void { diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 28c52b54112..38f1498e71b 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -389,6 +389,8 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService if (element instanceof model.Breakpoint) { var breakpoint = element; return this.sendBreakpoints(breakpoint.source.uri); + } else if (element instanceof model.FunctionBreakpoint) { + // TODO@Isidor send function breakpoints and return } return this.sendExceptionBreakpoints(); From 1fc2350af752c1d3046163ea1bee13476836baad Mon Sep 17 00:00:00 2001 From: Resi Respati Date: Sat, 28 Nov 2015 13:23:56 +0700 Subject: [PATCH 205/588] Fixed comments --- .editorconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 763de517a34..bb63c97c9e5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,7 +3,7 @@ # top-most EditorConfig file root = true -# Tab indentation (no size specified) +# Tab indentation [*] indent_style = tab indent_size = 4 From b223a5e626015862566d7b92c87164e05453e6f6 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 28 Nov 2015 18:13:23 -0800 Subject: [PATCH 206/588] Make xml extension list flat --- extensions/xml/package.json | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/extensions/xml/package.json b/extensions/xml/package.json index 720107072d1..c85e2670672 100644 --- a/extensions/xml/package.json +++ b/extensions/xml/package.json @@ -6,13 +6,28 @@ "contributes": { "languages": [{ "id": "xml", - "extensions": [ ".xml", ".dtd", ".ascx", ".csproj", ".config", ".wxi", ".wxl", ".wxs", ".xaml", ".svg", ".svgz" ], + "extensions": [ + ".xml", + ".dtd", + ".ascx", + ".csproj", + ".config", + ".wxi", + ".wxl", + ".wxs", + ".xaml", + ".svg", + ".svgz" + ], "firstLine" : "(\\<\\?xml.*)|(\\ Date: Sat, 28 Nov 2015 18:14:35 -0800 Subject: [PATCH 207/588] Add more XML extensions --- extensions/xml/package.json | 53 +++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/extensions/xml/package.json b/extensions/xml/package.json index c85e2670672..ac954202901 100644 --- a/extensions/xml/package.json +++ b/extensions/xml/package.json @@ -7,17 +7,60 @@ "languages": [{ "id": "xml", "extensions": [ - ".xml", - ".dtd", ".ascx", - ".csproj", + ".axml", + ".bpmn", ".config", + ".cpt", + ".csl", + ".csproj", + ".csproj.user", + ".dita", + ".ditamap", + ".dtd", + ".dtml", + ".fsproj", + ".fxml", + ".iml", + ".isml", + ".jmx", + ".jsp", + ".launch", + ".menu", + ".mxml", + ".nuspec", + ".opml", + ".owl", + ".proj", + ".pt", + ".pubxml", + ".pubxml.user", + ".rdf", + ".rng", + ".rss", + ".shproj", + ".storyboard", + ".svg", + ".svgz", + ".targets", + ".tld", + ".vbproj", + ".vbproj.user", + ".vcxproj", + ".vcxproj.filters", + ".wsdl", ".wxi", ".wxl", ".wxs", ".xaml", - ".svg", - ".svgz" + ".xbl", + ".xib", + ".xlf", + ".xliff", + ".xml", + ".xpdl", + ".xsd", + ".xul" ], "firstLine" : "(\\<\\?xml.*)|(\\ Date: Sat, 28 Nov 2015 18:17:53 -0800 Subject: [PATCH 208/588] Remove svgz from xml extensions svgz is a gzipped version of svg so syntax highlighting does not apply --- extensions/xml/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/extensions/xml/package.json b/extensions/xml/package.json index ac954202901..3ad9fd5ad6b 100644 --- a/extensions/xml/package.json +++ b/extensions/xml/package.json @@ -41,7 +41,6 @@ ".shproj", ".storyboard", ".svg", - ".svgz", ".targets", ".tld", ".vbproj", From f7c4f21d6f11e9a8e235be224d97adf3b65101b7 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 29 Nov 2015 15:57:58 -0800 Subject: [PATCH 209/588] Remove dead code in html.ts Function is duplicated in htmlTags, this version is never used. --- src/vs/languages/html/common/html.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/vs/languages/html/common/html.ts b/src/vs/languages/html/common/html.ts index a2164c183ff..3dc0c03fbc5 100644 --- a/src/vs/languages/html/common/html.ts +++ b/src/vs/languages/html/common/html.ts @@ -38,15 +38,8 @@ export enum States { AttributeValue } -// list of empty elements - for performance reasons we won't open a bracket for them -var emptyElements:string[] = ['area', 'base', 'basefont', 'br', 'col', 'command', 'embed', 'frame', 'hr', 'img', 'input', 'isindex', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr']; - -function isEmptyElement(e: string) : boolean { - return arrays.binarySearch(emptyElements, e,(s1: string, s2: string) => s1.localeCompare(s2)) >= 0; -} - // list of element that embedd other content -var tagsEmbeddingContent:any = ['script', 'style']; +var tagsEmbeddingContent:string[] = ['script', 'style']; From f29945809a62c61cbe8a75e46205e4a3bb517311 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 29 Nov 2015 16:05:41 -0800 Subject: [PATCH 210/588] Fix typos --- src/vs/languages/html/common/html.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/languages/html/common/html.ts b/src/vs/languages/html/common/html.ts index 3dc0c03fbc5..f4e1b4de717 100644 --- a/src/vs/languages/html/common/html.ts +++ b/src/vs/languages/html/common/html.ts @@ -38,7 +38,7 @@ export enum States { AttributeValue } -// list of element that embedd other content +// list of elements that embed other content var tagsEmbeddingContent:string[] = ['script', 'style']; From 704bc0b72b720b2801bc344b1522bd44fe45e6ac Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 29 Nov 2015 16:29:51 -0800 Subject: [PATCH 211/588] Remove hardcoded string in favor of constant This also fixes an inconsistency on what is considered an empty tag in html.ts and htmlTags.ts. html.ts contained the deprecated basefont and frame, and did not contain command and menuitem tags. --- src/vs/languages/html/common/html.ts | 3 ++- src/vs/languages/html/common/htmlTags.ts | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vs/languages/html/common/html.ts b/src/vs/languages/html/common/html.ts index f4e1b4de717..22c495dce0e 100644 --- a/src/vs/languages/html/common/html.ts +++ b/src/vs/languages/html/common/html.ts @@ -23,6 +23,7 @@ import {OnEnterSupport} from 'vs/editor/common/modes/supports/onEnter'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IThreadService } from 'vs/platform/thread/common/thread'; import * as htmlTokenTypes from 'vs/languages/html/common/htmlTokenTypes'; +import {EMPTY_ELEMENTS} from 'vs/languages/html/common/htmlTags'; export { htmlTokenTypes }; // export to be used by Razor. We are the main module, so Razor should get ot from use. @@ -300,7 +301,7 @@ export class HTMLMode extends AbstractMode i brackets: [], regexBrackets:[ { tokenType: htmlTokenTypes.getTag('$1'), - open: /<(?!(?:area|base|basefont|br|col|command|embed|frame|hr|img|input|link|meta|param|source|track|wbr))(\w[\w\d]*)([^\/>]*(?!\/)>)[^<]*$/i, + open: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join("|")}))(\w[\w\d]*)([^\/>]*(?!\/)>)[^<]*$`, 'i'), closeComplete: '', close: /<\/(\w[\w\d]*)\s*>$/i }], caseInsensitive:true, diff --git a/src/vs/languages/html/common/htmlTags.ts b/src/vs/languages/html/common/htmlTags.ts index a1fbbae2389..30ba62713e9 100644 --- a/src/vs/languages/html/common/htmlTags.ts +++ b/src/vs/languages/html/common/htmlTags.ts @@ -6,10 +6,10 @@ import strings = require('vs/base/common/strings'); import arrays = require('vs/base/common/arrays'); -var emptyElements:string[] = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr']; +export const EMPTY_ELEMENTS:string[] = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr']; export function isEmptyElement(e: string) : boolean { - return arrays.binarySearch(emptyElements, e,(s1: string, s2: string) => s1.localeCompare(s2)) >= 0; + return arrays.binarySearch(EMPTY_ELEMENTS, e,(s1: string, s2: string) => s1.localeCompare(s2)) >= 0; } export interface IHTMLTagProvider { From eab5782e1e0728c8f051d68fa7e7685cc5e6e523 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 29 Nov 2015 17:30:54 -0800 Subject: [PATCH 212/588] Fix tests due to different regexp format --- src/vs/languages/html/common/html.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/languages/html/common/html.ts b/src/vs/languages/html/common/html.ts index 22c495dce0e..3c7796992ac 100644 --- a/src/vs/languages/html/common/html.ts +++ b/src/vs/languages/html/common/html.ts @@ -301,7 +301,7 @@ export class HTMLMode extends AbstractMode i brackets: [], regexBrackets:[ { tokenType: htmlTokenTypes.getTag('$1'), - open: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join("|")}))(\w[\w\d]*)([^\/>]*(?!\/)>)[^<]*$`, 'i'), + open: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join("|")}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'), closeComplete: '', close: /<\/(\w[\w\d]*)\s*>$/i }], caseInsensitive:true, From 4aaeb38785004db4a5aadd43c06522196790382f Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 30 Nov 2015 11:34:29 +0100 Subject: [PATCH 213/588] [json] JSON Schema wrong path encoding #789 --- .../json/common/jsonSchemaService.ts | 20 +++++++++++++++---- .../services/request/common/requestService.ts | 4 ++-- .../services/request/node/requestService.ts | 4 ++-- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/vs/languages/json/common/jsonSchemaService.ts b/src/vs/languages/json/common/jsonSchemaService.ts index 6b14c1ae8f6..dffa500260d 100644 --- a/src/vs/languages/json/common/jsonSchemaService.ts +++ b/src/vs/languages/json/common/jsonSchemaService.ts @@ -351,23 +351,23 @@ export class JSONSchemaService implements IJSONSchemaService { schemaURL: url }); } - + return this.requestService.makeRequest({ url: url }).then( request => { var content = request.responseText; if (!content) { - var errorMessage = nls.localize('json.schema.nocontent', 'Unable to load schema from \'{0}\': No content.', url) ; + var errorMessage = nls.localize('json.schema.nocontent', 'Unable to load schema from \'{0}\': No content.', toDisplayString(url)); return new UnresolvedSchema( {}, [ errorMessage ]); } var schemaContent: IJSONSchema = {}; var jsonErrors = []; schemaContent = Json.parse(content, errors); - var errors = jsonErrors.length ? [ nls.localize('json.schema.invalidFormat', 'Unable to parse content from \'{0}\': {1}.', url, jsonErrors[0])] : []; + var errors = jsonErrors.length ? [ nls.localize('json.schema.invalidFormat', 'Unable to parse content from \'{0}\': {1}.', toDisplayString(url), jsonErrors[0])] : []; return new UnresolvedSchema(schemaContent, errors); }, error => { - var errorMessage = nls.localize('json.schema.unabletoload', 'Unable to load schema from \'{0}\': {1}.', url, error.statusText || error.toString()); + var errorMessage = nls.localize('json.schema.unabletoload', 'Unable to load schema from \'{0}\': {1}', toDisplayString(url), error.responseText || error.toString()); return new UnresolvedSchema( {}, [ errorMessage ]); } ); @@ -1562,4 +1562,16 @@ export class JSONSchemaService implements IJSONSchemaService { }); } +} + +function toDisplayString(url:string) { + try { + var uri = URI.parse(url); + if (uri.scheme === 'file') { + return uri.fsPath; + } + } catch (e) { + // ignore + } + return url; } \ No newline at end of file diff --git a/src/vs/workbench/services/request/common/requestService.ts b/src/vs/workbench/services/request/common/requestService.ts index 5fce063a1ae..ccbbdca3531 100644 --- a/src/vs/workbench/services/request/common/requestService.ts +++ b/src/vs/workbench/services/request/common/requestService.ts @@ -46,7 +46,7 @@ export class WorkerRequestService extends BaseRequestService implements IThreadS public makeRequest(options:http.IXHROptions):TPromise { let url = options.url; if (!url) { - throw new Error('IRequestService.makeRequest: Url is required'); + throw new Error('IRequestService.makeRequest: Url is required.'); } // Support file:// in worker environment through XHR @@ -56,7 +56,7 @@ export class WorkerRequestService extends BaseRequestService implements IThreadS return xhr; // loading resources locally returns a status of 0 which in WinJS is an error so we need to handle it here } - return Promise.wrapError(new Error(nls.localize('localFileNotFound', "File not found"))); + return Promise.wrapError({ status: 404, responseText: nls.localize('localFileNotFound', "File not found.")}); }); } diff --git a/src/vs/workbench/services/request/node/requestService.ts b/src/vs/workbench/services/request/node/requestService.ts index b8c73e58e5e..226b818976d 100644 --- a/src/vs/workbench/services/request/node/requestService.ts +++ b/src/vs/workbench/services/request/node/requestService.ts @@ -80,7 +80,7 @@ export class RequestService extends BaseRequestService implements IThreadSynchro public makeRequest(options: http.IXHROptions): TPromise { let url = options.url; if (!url) { - throw new Error('IRequestService.makeRequest: Url is required'); + throw new Error('IRequestService.makeRequest: Url is required.'); } // Support file:// in native environment through XHR @@ -90,7 +90,7 @@ export class RequestService extends BaseRequestService implements IThreadSynchro return xhr; // loading resources locally returns a status of 0 which in WinJS is an error so we need to handle it here } - return Promise.wrapError(new Error(nls.localize('localFileNotFound', "File not found"))); + return Promise.wrapError({ status: 404, responseText: nls.localize('localFileNotFound', "File not found.")}); }); } From 30381dbcefd242a56c4ad7368f42013faa66a881 Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Mon, 30 Nov 2015 12:14:44 +0100 Subject: [PATCH 214/588] Fixes #539 --- extensions/typescript/src/typescriptMain.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/typescript/src/typescriptMain.ts b/extensions/typescript/src/typescriptMain.ts index 7ea1c5ef78f..168b78f5394 100644 --- a/extensions/typescript/src/typescriptMain.ts +++ b/extensions/typescript/src/typescriptMain.ts @@ -149,7 +149,9 @@ class TypeScriptServiceClientHost implements ITypescriptServiceClientHost { this.triggerAllDiagnostics(); }; let handleProjectChange = () => { - this.triggerAllDiagnostics(); + setTimeout(() => { + this.triggerAllDiagnostics(); + }, 1500); } let watcher = workspace.createFileSystemWatcher('**/tsconfig.json'); watcher.onDidCreate(handleProjectCreateOrDelete); From 047f55b3b7ba90c2983eb95870c8f4dd0aac5148 Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Mon, 30 Nov 2015 12:41:50 +0100 Subject: [PATCH 215/588] Merged #336 --- extensions/php/src/features/validationProvider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/php/src/features/validationProvider.ts b/extensions/php/src/features/validationProvider.ts index 5092125a328..1c2ece56c10 100644 --- a/extensions/php/src/features/validationProvider.ts +++ b/extensions/php/src/features/validationProvider.ts @@ -152,7 +152,7 @@ export default class PHPValidationProvider { let delayer = this.delayers[key]; if (!delayer) { delayer = new ThrottledDelayer(this.trigger === RunTrigger.onType ? 250 : 0); - this.delayers[key]; + this.delayers[key] = delayer; } delayer.trigger(() => this.doValidate(textDocument) ); } From 75c27c16d576e31391c9e6b241497d60066828ce Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Mon, 30 Nov 2015 15:17:17 +0100 Subject: [PATCH 216/588] fix npe --- .../workbench/parts/git/browser/views/changes/changesViewer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/git/browser/views/changes/changesViewer.ts b/src/vs/workbench/parts/git/browser/views/changes/changesViewer.ts index 05c61e0ec70..ff660c489b7 100644 --- a/src/vs/workbench/parts/git/browser/views/changes/changesViewer.ts +++ b/src/vs/workbench/parts/git/browser/views/changes/changesViewer.ts @@ -828,7 +828,7 @@ export class Controller extends treedefaults.DefaultController { } private canSelect(tree: tree.ITree, ...elements: any[]): boolean { - if (elements.some(e => e instanceof gitmodel.StatusGroup)) { + if (elements.some(e => e instanceof gitmodel.StatusGroup || e instanceof gitmodel.StatusModel)) { return false; } From b18c92e6c32e715fa82c30ac0f633c7eed37cae6 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Mon, 30 Nov 2015 16:02:32 +0100 Subject: [PATCH 217/588] remove quick suggest delay upper bound --- src/vs/editor/contrib/suggest/browser/suggestModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/suggest/browser/suggestModel.ts b/src/vs/editor/contrib/suggest/browser/suggestModel.ts index 386fec8aa63..0afd9d9ee49 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestModel.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestModel.ts @@ -491,7 +491,7 @@ export class SuggestModel extends EventEmitter { private onEditorConfigurationChange(): void { this.autoSuggestDelay = this.editor.getConfiguration().quickSuggestionsDelay; - if (isNaN(this.autoSuggestDelay) || (!this.autoSuggestDelay && this.autoSuggestDelay !== 0) || this.autoSuggestDelay > 2000 || this.autoSuggestDelay < 0) { + if (isNaN(this.autoSuggestDelay) || (!this.autoSuggestDelay && this.autoSuggestDelay !== 0) || this.autoSuggestDelay < 0) { this.autoSuggestDelay = 10; } } From 10212f2e1c51aa58e970a7414d559668ae3df28b Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 30 Nov 2015 16:25:18 +0100 Subject: [PATCH 218/588] Improvements to the defineKeybindings contrib --- .../defineKeybinding/browser/defineKeybinding.css | 7 +++---- .../defineKeybinding/browser/defineKeybinding.ts | 15 ++++++--------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.css b/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.css index bf06fd067b0..5c8e9edb53e 100644 --- a/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.css +++ b/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.css @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ .monaco-editor .defineKeybindingLauncher { + font-family: 'Segoe WPC', 'Segoe UI', "SFUIText-Light", HelveticaNeue-Light, sans-serif, "Droid Sans Fallback"; background: rgba(0,255,0,0.3); padding: 10px; border-radius: 5px; @@ -11,6 +12,7 @@ } .monaco-editor .defineKeybindingWidget { + font-family: 'Segoe WPC', 'Segoe UI', "SFUIText-Light", HelveticaNeue-Light, sans-serif, "Droid Sans Fallback"; width: 340px; height: 60px; padding: 10px; @@ -22,12 +24,9 @@ } .monaco-editor .defineKeybindingWidget .input { + margin-top:10px; width: 320px; display: block; -} - -.monaco-editor .defineKeybindingWidget .output { - width: 320px; text-align: center; } diff --git a/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts b/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts index 750e2d54bc4..f35e229fdb4 100644 --- a/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts +++ b/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts @@ -158,7 +158,6 @@ class DefineKeybindingWidget implements EditorBrowser.IContentWidget { private _messageNode: HTMLElement; private _inputNode: HTMLInputElement; - private _outputNode: HTMLElement; private _lastKeybinding: Keybinding; private _onAccepted: (keybinding:string) => void; @@ -182,10 +181,6 @@ class DefineKeybindingWidget implements EditorBrowser.IContentWidget { this._inputNode.className = 'input'; this._domNode.appendChild(this._inputNode); - this._outputNode = document.createElement('div'); - this._outputNode.className = 'output'; - this._domNode.appendChild(this._outputNode); - this._toDispose.push(DomUtils.addDisposableListener(this._inputNode, 'keydown', (e) => { let keyEvent = new StandardKeyboardEvent(e); keyEvent.preventDefault(); @@ -207,8 +202,8 @@ class DefineKeybindingWidget implements EditorBrowser.IContentWidget { this._lastKeybinding = kb; - this._outputNode.innerText = this._lastKeybinding.toUserSettingsLabel().toLowerCase(); - this._outputNode.title = 'keyCode: ' + keyEvent.browserEvent.keyCode; + this._inputNode.value = this._lastKeybinding.toUserSettingsLabel().toLowerCase(); + this._inputNode.title = 'keyCode: ' + keyEvent.browserEvent.keyCode; })); this._toDispose.push(DomUtils.addDisposableListener(this._inputNode, 'blur', (e) => this._stop())); @@ -248,8 +243,7 @@ class DefineKeybindingWidget implements EditorBrowser.IContentWidget { this._editor.getOffsetForColumn(this._position.lineNumber, this._position.column); this._lastKeybinding = null; - this._outputNode.innerText = ''; - this._outputNode.title = ''; + this._inputNode.value = ''; this._inputNode.focus(); } @@ -285,6 +279,9 @@ export class DefineKeybindingAction extends EditorAction { const INTERESTING_FILE = /keybindings\.json$/; function isInterestingEditorModel(editor:EditorCommon.ICommonCodeEditor): boolean { + if (editor.getConfiguration().readOnly) { + return false; + } let model = editor.getModel(); if (!model) { return false; From d5dde44ff008eca306176543e87541a9c8bda80b Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 30 Nov 2015 16:27:47 +0100 Subject: [PATCH 219/588] update vscode-textmate to 1.0.8 --- build/gulpfile.hygiene.js | 1 + npm-shrinkwrap.json | 6 +++--- package.json | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js index 4a97747e272..21a7c85db46 100644 --- a/build/gulpfile.hygiene.js +++ b/build/gulpfile.hygiene.js @@ -32,6 +32,7 @@ var indentationFilter = [ '!extensions/typescript/server/**', '!test/assert.js', '!**/package.json', + '!**/npm-shrinkwrap.json', '!**/octicons/**', '!**/vs/languages/sass/test/common/example.scss', '!**/vs/languages/less/common/parser/less.grammar.txt', diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index e94516a8b22..b6efefc2d5a 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -416,9 +416,9 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz" }, "vscode-textmate": { - "version": "1.0.7", - "from": "vscode-textmate@1.0.7", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-1.0.7.tgz", + "version": "1.0.8", + "from": "vscode-textmate@1.0.8", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-1.0.8.tgz", "dependencies": { "oniguruma": { "version": "5.1.1", diff --git a/package.json b/package.json index 50b241f37a9..a8ead689440 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "iconv-lite": "^0.4.13", "sax": "^1.1.1", "semver": "^4.2.0", - "vscode-textmate": "^1.0.7", + "vscode-textmate": "^1.0.8", "winreg": "0.0.12", "yauzl": "^2.3.1" }, From b6c33d1f85921b6020b694b0b645dededc2e1184 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Mon, 30 Nov 2015 17:05:35 +0100 Subject: [PATCH 220/588] add windows-mutex optional dependency --- npm-shrinkwrap.json | 16 ++++++++++++++++ package.json | 5 ++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index b6efefc2d5a..d9d2f180afd 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -460,6 +460,22 @@ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz" } } + }, + "windows-mutex": { + "version": "0.1.3", + "from": "windows-mutex@0.1.3", + "dependencies": { + "bindings": { + "version": "1.2.1", + "from": "bindings@>=1.2.1 <2.0.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" + }, + "nan": { + "version": "2.1.0", + "from": "nan@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.1.0.tgz" + } + } } } } diff --git a/package.json b/package.json index a8ead689440..ce64bea165c 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ }, "scripts": { "test": "node node_modules/mocha/bin/_mocha", - "preinstall": "node build/npm/preinstall.js", + "preinstall": "node build/npm/preinstall.js", "postinstall": "npm --prefix extensions/csharp-o/ install extensions/csharp-o/ && npm --prefix extensions/vscode-api-tests/ install extensions/vscode-api-tests/" }, "dependencies": { @@ -89,5 +89,8 @@ "ghooks": { "pre-commit": "node build/gulpfile.hygiene.js" } + }, + "optionalDependencies": { + "windows-mutex": "^0.1.3" } } From 5d9853d679a3f3437ce3f345baed71234a90a9e9 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Mon, 30 Nov 2015 18:09:00 +0100 Subject: [PATCH 221/588] call CreateMutex whenever Code is running --- src/typings/windows-mutex.ts | 12 ++++++++++++ src/vs/workbench/electron-main/main.ts | 11 ++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/typings/windows-mutex.ts diff --git a/src/typings/windows-mutex.ts b/src/typings/windows-mutex.ts new file mode 100644 index 00000000000..039dffcc2ad --- /dev/null +++ b/src/typings/windows-mutex.ts @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'windows-mutex' { + export class Mutex { + constructor(name: string); + isActive(): boolean; + release(): void; + } +} \ No newline at end of file diff --git a/src/vs/workbench/electron-main/main.ts b/src/vs/workbench/electron-main/main.ts index 1a26f9a059a..2970c2fee28 100644 --- a/src/vs/workbench/electron-main/main.ts +++ b/src/vs/workbench/electron-main/main.ts @@ -9,7 +9,6 @@ import app = require('app'); import fs = require('fs'); import dialog = require('dialog'); import shell = require('shell'); - import nls = require('vs/nls'); import {assign} from 'vs/base/common/objects'; import platform = require('vs/base/common/platform'); @@ -233,6 +232,15 @@ function setupIPC(): TPromise { return setup(true); } +function setupMutex() { + try { + var Mutex = ( require.__$__nodeRequire('windows-mutex')).Mutex; + new Mutex('vscode'); + } catch (e) { + // noop + } +} + // On some platforms we need to manually read from the global environment variables // and assign them to the process environment (e.g. when doubleclick app on Mac) getUserEnvironment() @@ -241,6 +249,7 @@ getUserEnvironment() return timebomb() .then(setupIPC) + .then(ipcServer => { setupMutex(); return ipcServer; }) .then(ipcServer => main(ipcServer, userEnv)); }) .done(null, quit); From 1ebaa4f036ab6953888fa996b412263b1b772082 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 30 Nov 2015 20:45:55 +0100 Subject: [PATCH 222/588] Consistency in JS/TS light and dark themes (#796, #148) --- src/vs/editor/browser/widget/media/tokens.css | 43 ++++++++++++++----- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/src/vs/editor/browser/widget/media/tokens.css b/src/vs/editor/browser/widget/media/tokens.css index e14a8c9d099..9a0e8239462 100644 --- a/src/vs/editor/browser/widget/media/tokens.css +++ b/src/vs/editor/browser/widget/media/tokens.css @@ -351,7 +351,7 @@ .monaco-editor.vs .token.entity { color: #A31515; } .monaco-editor.vs .token.entity.name { color: #800000; } .monaco-editor.vs .token.entity.name.tag { color: #800000; } -.monaco-editor.vs .token.entity.name.function { color: #444444; } +.monaco-editor.vs .token.entity.name.function { color: #000000; } .monaco-editor.vs .token.entity.name.class { color: #2B91AF; } .monaco-editor.vs .token.entity.name.selector { color: #800000; } .monaco-editor.vs .token.entity.other.selector { color: #800000; } @@ -387,9 +387,14 @@ .monaco-editor.vs .token.meta { color: #000000; } .monaco-editor.vs .token.meta.selector { color: #800000; } .monaco-editor.vs .token.meta.tag { color: #800000; } +.monaco-editor.vs .token.meta.preprocessor { color: #0000FF; } +.monaco-editor.vs .token.meta.preprocessor.string { color: #A31515; } +.monaco-editor.vs .token.meta.preprocessor.numeric { color: #09885A; } +.monaco-editor.vs .token.meta.object.type { color: #2B91AF; } +.monaco-editor.vs .token.meta.object.type.variable { color: #000000; } -.monaco-editor.vs .token.storage { color: gray }; -.monaco-editor.vs .token.storage.content { color: red }; +.monaco-editor.vs .token.storage { color: #0000FF; } +.monaco-editor.vs .token.storage.content { color: red; } .monaco-editor.vs .token.storage.type { color: #0000FF; } .monaco-editor.vs .token.storage.modifier { color: #0000FF; } .monaco-editor.vs .token.cast.storage.type, @@ -410,7 +415,9 @@ .monaco-editor.vs .token.string.regexp { color: #811f3f; } /*.monaco-editor.vs .token.string.other*/ -.monaco-editor.vs .token.support { color: #800000; } +.monaco-editor.vs .token.support { color: #0000FF; } +.monaco-editor.vs .token.support.function { color: #000000; } +.monaco-editor.vs .token.support.method { color: #000000; } .monaco-editor.vs .token.support.type { color: red; } .monaco-editor.vs .token.support.type.json { color: #A31515; } .monaco-editor.vs .token.support.property-value { color: #0451A5; } @@ -515,9 +522,14 @@ .monaco-editor.vs-dark .token.meta { color: #D4D4D4; } .monaco-editor.vs-dark .token.meta.selector { color: #569CD6; } .monaco-editor.vs-dark .token.meta.tag { color: #CE9178; } +.monaco-editor.vs-dark .token.meta.preprocessor { color: #569CD6; } +.monaco-editor.vs-dark .token.meta.preprocessor.string { color: #CE9178; } +.monaco-editor.vs-dark .token.meta.preprocessor.numeric { color: #B5CEA8; } +.monaco-editor.vs-dark .token.meta.object.type { color: #569CD6; } +.monaco-editor.vs-dark .token.meta.object.type.variable { color: #9CDCFE; } -.monaco-editor.vs-dark .token.storage { color: #569CD6 }; -.monaco-editor.vs-dark .token.storage.content { color: #9CDCFE }; +.monaco-editor.vs-dark .token.storage { color: #569CD6; } +.monaco-editor.vs-dark .token.storage.content { color: #9CDCFE; } .monaco-editor.vs-dark .token.storage.type { color: #569CD6; } .monaco-editor.vs-dark .token.storage.modifier { color: #569CD6; } .monaco-editor.vs-dark .token.annotation.storage.type, @@ -540,7 +552,9 @@ .monaco-editor.vs-dark .token.string.regexp { color: #D16969; } /*.monaco-editor.vs-dark .token.string.other*/ -.monaco-editor.vs-dark .token.support { color: #A79873; } +.monaco-editor.vs-dark .token.support { color: #569CD6; } +.monaco-editor.vs-dark .token.support.function { color: #D4D4D4; } +.monaco-editor.vs-dark .token.support.method { color: #D4D4D4; } .monaco-editor.vs-dark .token.support.type { color: #9CDCFE; } .monaco-editor.vs-dark .token.support.property-value { color: #CE9178; } /*.monaco-editor.vs-dark .token.support.function @@ -635,7 +649,7 @@ /*.monaco-editor.hc-black .token.markup.underline.link*/ .monaco-editor.hc-black .token.markup.bold { font-weight: bold; } .monaco-editor.hc-black .token.markup.heading { color: #6796e6; } -.monaco-editor.hc-black .token.markup.italic { font-style: italic;} +.monaco-editor.hc-black .token.markup.italic { font-style: italic; } /*.monaco-editor.hc-black .token.markup.list .monaco-editor.hc-black .token.markup.list.numbered .monaco-editor.hc-black .token.markup.list.unnumbered @@ -646,9 +660,14 @@ .monaco-editor.hc-black .token.meta { color: #D4D4D4; } .monaco-editor.hc-black .token.meta.selector { color: #569CD6; } .monaco-editor.hc-black .token.meta.tag { color: #CE9178; } +.monaco-editor.hc-black .token.meta.preprocessor { color: #569CD6; } +.monaco-editor.hc-black .token.meta.preprocessor.string { color: #CE9178; } +.monaco-editor.hc-black .token.meta.preprocessor.numeric { color: #B5CEA8; } +.monaco-editor.hc-black .token.meta.object.type { color: #569CD6; } +.monaco-editor.hc-black .token.meta.object.type.variable { color: #D4D4D4; } -.monaco-editor.hc-black .token.storage { color: #569CD6 }; -.monaco-editor.hc-black .token.storage.content { color: #9CDCFE }; +.monaco-editor.hc-black .token.storage { color: #569CD6; } +.monaco-editor.hc-black .token.storage.content { color: #9CDCFE; } .monaco-editor.hc-black .token.storage.type { color: #569CD6; } .monaco-editor.hc-black .token.storage.modifier { color: #569CD6; } .monaco-editor.hc-black .token.annotation.storage.type, @@ -671,7 +690,9 @@ .monaco-editor.hc-black .token.string.regexp { color: #D16969; } /*.monaco-editor.hc-black .token.string.other*/ -.monaco-editor.hc-black .token.support { color: #800000; } +.monaco-editor.hc-black .token.support { color: #569CD6; } +.monaco-editor.hc-black .token.support.function { color: #D4D4D4; } +.monaco-editor.hc-black .token.support.method { color: #D4D4D4; } .monaco-editor.hc-black .token.support.type { color: #9CDCFE; } .monaco-editor.hc-black .token.support.property-value { color: #CE9178; } /*.monaco-editor.hc-black .token.support.function From 72e16bb216837652df72092da5c4eddfb3766ea4 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 30 Nov 2015 12:21:15 -0800 Subject: [PATCH 223/588] Move tag specs back to htmlTags.ts and externalize strings --- .../html/common/htmlTagSpecifications.ts | 295 ------------- src/vs/languages/html/common/htmlTags.ts | 410 +++++++++++++++++- 2 files changed, 409 insertions(+), 296 deletions(-) delete mode 100644 src/vs/languages/html/common/htmlTagSpecifications.ts diff --git a/src/vs/languages/html/common/htmlTagSpecifications.ts b/src/vs/languages/html/common/htmlTagSpecifications.ts deleted file mode 100644 index 89b2246c111..00000000000 --- a/src/vs/languages/html/common/htmlTagSpecifications.ts +++ /dev/null @@ -1,295 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export class HTMLTagSpecification { - constructor(public label: string, public attributes: string[] = []) {} -} - -// HTML tag information sourced from http://www.w3.org/TR/2015/WD-html51-20151008/ -export const HTML_TAGS : { [tag:string]: HTMLTagSpecification } = { - // The root element - html: new HTMLTagSpecification( - 'The html element represents the root of an HTML document.', - ['manifest']), - // Document metadata - head: new HTMLTagSpecification( - 'The head element represents a collection of metadata for the Document.'), - title: new HTMLTagSpecification( - 'The title element represents the document\'s title or name. Authors should use titles that identify their documents even when they are used out of context, for example in a user\'s history or bookmarks, or in search results. The document\'s title is often different from its first heading, since the first heading does not have to stand alone when taken out of context.'), - base: new HTMLTagSpecification( - 'The base element allows authors to specify the document base URL for the purposes of resolving relative URLs, and the name of the default browsing context for the purposes of following hyperlinks. The element does not represent any content beyond this information.', - ['href', 'target']), - link: new HTMLTagSpecification( - 'The link element allows authors to link their document to other resources.', - ['href', 'crossorigin:xo', 'rel', 'media', 'hreflang', 'type', 'sizes']), - meta: new HTMLTagSpecification( - 'The meta element represents various kinds of metadata that cannot be expressed using the title, base, link, style, and script elements.', - ['name', 'http-equiv', 'content', 'charset']), - style: new HTMLTagSpecification( - 'The style element allows authors to embed style information in their documents. The style element is one of several inputs to the styling processing model. The element does not represent content for the user.', - ['media', 'nonce', 'type', 'scoped:v']), - // Sections - body: new HTMLTagSpecification( - 'The body element represents the content of the document.', - ['onafterprint', 'onbeforeprint', 'onbeforeunload', 'onhashchange', 'onlanguagechange', 'onmessage', 'onoffline', 'ononline', 'onpagehide', 'onpageshow', 'onpopstate', 'onstorage', 'onunload']), - article: new HTMLTagSpecification( - 'The article element represents a complete, or self-contained, composition in a document, page, application, or site and that is, in principle, independently distributable or reusable, e.g. in syndication. This could be a forum post, a magazine or newspaper article, a blog entry, a user-submitted comment, an interactive widget or gadget, or any other independent item of content. Each article should be identified, typically by including a heading (h1–h6 element) as a child of the article element.'), - section: new HTMLTagSpecification( - 'The section element represents a generic section of a document or application. A section, in this context, is a thematic grouping of content. Each section should be identified, typically by including a heading ( h1- h6 element) as a child of the section element.'), - nav: new HTMLTagSpecification( - 'The nav element represents a section of a page that links to other pages or to parts within the page: a section with navigation links.'), - aside: new HTMLTagSpecification( - 'The aside element represents a section of a page that consists of content that is tangentially related to the content around the aside element, and which could be considered separate from that content. Such sections are often represented as sidebars in printed typography.'), - h1: new HTMLTagSpecification( - 'The h1 element represents a section heading.'), - h2: new HTMLTagSpecification( - 'The h2 element represents a section heading.'), - h3: new HTMLTagSpecification( - 'The h3 element represents a section heading.'), - h4: new HTMLTagSpecification( - 'The h4 element represents a section heading.'), - h5: new HTMLTagSpecification( - 'The h5 element represents a section heading.'), - h6: new HTMLTagSpecification( - 'The h6 element represents a section heading.'), - header: new HTMLTagSpecification( - 'The header element represents introductory content for its nearest ancestor sectioning content or sectioning root element. A header typically contains a group of introductory or navigational aids. When the nearest ancestor sectioning content or sectioning root element is the body element, then it applies to the whole page.'), - footer: new HTMLTagSpecification( - 'The footer element represents a footer for its nearest ancestor sectioning content or sectioning root element. A footer typically contains information about its section such as who wrote it, links to related documents, copyright data, and the like.'), - address: new HTMLTagSpecification( - 'The address element represents the contact information for its nearest article or body element ancestor. If that is the body element, then the contact information applies to the document as a whole.'), - // Grouping content - p: new HTMLTagSpecification( - 'The p element represents a paragraph.'), - hr: new HTMLTagSpecification( - 'The hr element represents a paragraph-level thematic break, e.g. a scene change in a story, or a transition to another topic within a section of a reference book.'), - pre: new HTMLTagSpecification( - 'The pre element represents a block of preformatted text, in which structure is represented by typographic conventions rather than by elements.'), - blockquote: new HTMLTagSpecification( - 'The blockquote element represents content that is quoted from another source, optionally with a citation which must be within a footer or cite element, and optionally with in-line changes such as annotations and abbreviations.', - ['cite']), - ol: new HTMLTagSpecification( - 'The ol element represents a list of items, where the items have been intentionally ordered, such that changing the order would change the meaning of the document.', - ['reversed:v', 'start', 'type:lt']), - ul: new HTMLTagSpecification( - 'The ul element represents a list of items, where the order of the items is not important — that is, where changing the order would not materially change the meaning of the document.'), - li: new HTMLTagSpecification( - 'The li element represents a list item. If its parent element is an ol, ul, or menu element, then the element is an item of the parent element\'s list, as defined for those elements. Otherwise, the list item has no defined list-related relationship to any other li element.', - ['value']), - dl: new HTMLTagSpecification( - 'The dl element represents an association list consisting of zero or more name-value groups (a description list). A name-value group consists of one or more names (dt elements) followed by one or more values (dd elements), ignoring any nodes other than dt and dd elements. Within a single dl element, there should not be more than one dt element for each name.'), - dt: new HTMLTagSpecification( - 'The dt element represents the term, or name, part of a term-description group in a description list (dl element).'), - dd: new HTMLTagSpecification( - 'The dd element represents the description, definition, or value, part of a term-description group in a description list (dl element).'), - figure: new HTMLTagSpecification( - 'The figure element represents some flow content, optionally with a caption, that is self-contained (like a complete sentence) and is typically referenced as a single unit from the main flow of the document.'), - figcaption: new HTMLTagSpecification( - 'The figcaption element represents a caption or legend for the rest of the contents of the figcaption element\'s parent figure element, if any.'), - main: new HTMLTagSpecification( - 'The main element represents the main content of the body of a document or application. The main content area consists of content that is directly related to or expands upon the central topic of a document or central functionality of an application.'), - div: new HTMLTagSpecification( - 'The div element has no special meaning at all. It represents its children. It can be used with the class, lang, and title attributes to mark up semantics common to a group of consecutive elements.'), - // Text-level semantics - a: new HTMLTagSpecification( - 'If the a element has an href attribute, then it represents a hyperlink (a hypertext anchor) labeled by its contents.', - ['href', 'target', 'download', 'ping', 'rel', 'hreflang', 'type']), - em: new HTMLTagSpecification( - 'The em element represents stress emphasis of its contents.'), - strong: new HTMLTagSpecification( - 'The strong element represents strong importance, seriousness, or urgency for its contents.'), - small: new HTMLTagSpecification( - 'The small element represents side comments such as small print.'), - s: new HTMLTagSpecification( - 'The s element represents contents that are no longer accurate or no longer relevant.'), - cite: new HTMLTagSpecification( - 'The cite element represents a reference to a creative work. It must include the title of the work or the name of the author(person, people or organization) or an URL reference, or a reference in abbreviated form as per the conventions used for the addition of citation metadata.'), - q: new HTMLTagSpecification( - 'The q element represents some phrasing content quoted from another source.', - ['cite']), - dfn: new HTMLTagSpecification( - 'The dfn element represents the defining instance of a term. The paragraph, description list group, or section that is the nearest ancestor of the dfn element must also contain the definition(s) for the term given by the dfn element.'), - abbr: new HTMLTagSpecification( - 'The abbr element represents an abbreviation or acronym, optionally with its expansion. The title attribute may be used to provide an expansion of the abbreviation. The attribute, if specified, must contain an expansion of the abbreviation, and nothing else.'), - ruby: new HTMLTagSpecification( - 'The ruby element allows one or more spans of phrasing content to be marked with ruby annotations. Ruby annotations are short runs of text presented alongside base text, primarily used in East Asian typography as a guide for pronunciation or to include other annotations. In Japanese, this form of typography is also known as furigana. Ruby text can appear on either side, and sometimes both sides, of the base text, and it is possible to control its position using CSS. A more complete introduction to ruby can be found in the Use Cases & Exploratory Approaches for Ruby Markup document as well as in CSS Ruby Module Level 1. [RUBY-UC] [CSSRUBY]'), - rb: new HTMLTagSpecification( - 'The rb element marks the base text component of a ruby annotation. When it is the child of a ruby element, it doesn\'t represent anything itself, but its parent ruby element uses it as part of determining what it represents.'), - rt: new HTMLTagSpecification( - 'The rt element marks the ruby text component of a ruby annotation. When it is the child of a ruby element or of an rtc element that is itself the child of a ruby element, it doesn\'t represent anything itself, but its ancestor ruby element uses it as part of determining what it represents.'), - rtc: new HTMLTagSpecification( - 'The rtc element marks a ruby text container for ruby text components in a ruby annotation. When it is the child of a ruby element it doesn\'t represent anything itself, but its parent ruby element uses it as part of determining what it represents.'), - rp: new HTMLTagSpecification( - 'The rp element is used to provide fallback text to be shown by user agents that don\'t support ruby annotations. One widespread convention is to provide parentheses around the ruby text component of a ruby annotation.'), - data: new HTMLTagSpecification( - 'The data element represents its contents, along with a machine-readable form of those contents in the value attribute.'), - time: new HTMLTagSpecification( - 'The time element represents its contents, along with a machine-readable form of those contents in the datetime attribute. The kind of content is limited to various kinds of dates, times, time-zone offsets, and durations, as described below.', - ['datetime']), - code: new HTMLTagSpecification( - 'The code element represents a fragment of computer code. This could be an XML element name, a file name, a computer program, or any other string that a computer would recognize.'), - var: new HTMLTagSpecification( - 'The var element represents a variable. This could be an actual variable in a mathematical expression or programming context, an identifier representing a constant, a symbol identifying a physical quantity, a function parameter, or just be a term used as a placeholder in prose.'), - samp: new HTMLTagSpecification( - 'The samp element represents sample or quoted output from another program or computing system.'), - kbd: new HTMLTagSpecification( - 'The kbd element represents user input (typically keyboard input, although it may also be used to represent other input, such as voice commands).'), - sub: new HTMLTagSpecification( - 'The sub element represents a subscript.'), - sup: new HTMLTagSpecification( - 'The sup element represents a superscript.'), - i: new HTMLTagSpecification( - 'The i element represents a span of text in an alternate voice or mood, or otherwise offset from the normal prose in a manner indicating a different quality of text, such as a taxonomic designation, a technical term, an idiomatic phrase from another language, transliteration, a thought, or a ship name in Western texts.'), - b: new HTMLTagSpecification( - 'The b element represents a span of text to which attention is being drawn for utilitarian purposes without conveying any extra importance and with no implication of an alternate voice or mood, such as key words in a document abstract, product names in a review, actionable words in interactive text-driven software, or an article lede.'), - u: new HTMLTagSpecification( - 'The u element represents a span of text with an unarticulated, though explicitly rendered, non-textual annotation, such as labeling the text as being a proper name in Chinese text (a Chinese proper name mark), or labeling the text as being misspelt.'), - mark: new HTMLTagSpecification( - 'The mark element represents a run of text in one document marked or highlighted for reference purposes, due to its relevance in another context. When used in a quotation or other block of text referred to from the prose, it indicates a highlight that was not originally present but which has been added to bring the reader\'s attention to a part of the text that might not have been considered important by the original author when the block was originally written, but which is now under previously unexpected scrutiny. When used in the main prose of a document, it indicates a part of the document that has been highlighted due to its likely relevance to the user\'s current activity.'), - bdi: new HTMLTagSpecification( - 'The bdi element represents a span of text that is to be isolated from its surroundings for the purposes of bidirectional text formatting. [BIDI]'), - bdo: new HTMLTagSpecification( - 'The bdo element represents explicit text directionality formatting control for its children. It allows authors to override the Unicode bidirectional algorithm by explicitly specifying a direction override. [BIDI]'), - span: new HTMLTagSpecification( - 'The span element doesn\'t mean anything on its own, but can be useful when used together with the global attributes, e.g. class, lang, or dir. It represents its children.'), - br: new HTMLTagSpecification( - 'The br element represents a line break.'), - wbr: new HTMLTagSpecification( - 'The wbr element represents a line break opportunity.'), - // Edits - ins: new HTMLTagSpecification( - 'The ins element represents an addition to the document.'), - del: new HTMLTagSpecification( - 'The del element represents a removal from the document.', - ['cite', 'datetime']), - // Embedded content - picture: new HTMLTagSpecification( - 'The picture element is a container which provides multiple sources to its contained img element to allow authors to declaratively control or give hints to the user agent about which image resource to use, based on the screen pixel density, viewport size, image format, and other factors. It represents its children.'), - img: new HTMLTagSpecification( - 'An img element represents an image.', - ['alt', 'src', 'srcset', 'crossorigin:xo', 'usemap', 'ismap:v', 'width', 'height']), - iframe: new HTMLTagSpecification( - 'The iframe element represents a nested browsing context.', - ['src', 'srcdoc', 'name', 'sandbox:sb', 'seamless:v', 'allowfullscreen:v', 'width', 'height']), - embed: new HTMLTagSpecification( - 'The embed element provides an integration point for an external (typically non-HTML) application or interactive content.', - ['src', 'type', 'width', 'height']), - object: new HTMLTagSpecification( - 'The object element can represent an external resource, which, depending on the type of the resource, will either be treated as an image, as a nested browsing context, or as an external resource to be processed by a plugin.', - ['data', 'type', 'typemustmatch:v', 'name', 'usemap', 'form', 'width', 'height']), - param: new HTMLTagSpecification( - 'The param element defines parameters for plugins invoked by object elements. It does not represent anything on its own.', - ['name', 'value']), - video: new HTMLTagSpecification( - 'A video element is used for playing videos or movies, and audio files with captions.', - ['src', 'crossorigin:xo', 'poster', 'preload:pl', 'autoplay:v', 'mediagroup', 'loop:v', 'muted:v', 'controls:v', 'width', 'height']), - audio: new HTMLTagSpecification( - 'An audio element represents a sound or audio stream.', - ['src', 'crossorigin:xo', 'preload:pl', 'autoplay:v', 'mediagroup', 'loop:v', 'muted:v', 'controls:v']), - source: new HTMLTagSpecification( - 'The source element allows authors to specify multiple alternative media resources for media elements. It does not represent anything on its own.', - // 'When the source element has a parent that is a picture element, the source element allows authors to specify multiple alternative source sets for img elements.' - ['src', 'type']), - track: new HTMLTagSpecification( - 'The track element allows authors to specify explicit external timed text tracks for media elements. It does not represent anything on its own.', - ['default:v', 'kind:tk', 'label', 'src', 'srclang']), - map: new HTMLTagSpecification( - 'The map element, in conjunction with an img element and any area element descendants, defines an image map. The element represents its children.', - ['name']), - area: new HTMLTagSpecification( - 'The area element represents either a hyperlink with some text and a corresponding area on an image map, or a dead area on an image map.', - ['alt', 'coords', 'shape:sh', 'href', 'target', 'download', 'ping', 'rel', 'hreflang', 'type']), - // Tabular data - table: new HTMLTagSpecification( - 'The table element represents data with more than one dimension, in the form of a table.', - ['sortable:v', 'border']), - caption: new HTMLTagSpecification( - 'The caption element represents the title of the table that is its parent, if it has a parent and that is a table element.'), - colgroup: new HTMLTagSpecification( - 'The colgroup element represents a group of one or more columns in the table that is its parent, if it has a parent and that is a table element.', - ['span']), - col: new HTMLTagSpecification( - 'If a col element has a parent and that is a colgroup element that itself has a parent that is a table element, then the col element represents one or more columns in the column group represented by that colgroup.', - ['span']), - tbody: new HTMLTagSpecification( - 'The tbody element represents a block of rows that consist of a body of data for the parent table element, if the tbody element has a parent and it is a table.'), - thead: new HTMLTagSpecification( - 'The thead element represents the block of rows that consist of the column labels (headers) for the parent table element, if the thead element has a parent and it is a table.'), - tfoot: new HTMLTagSpecification( - 'The tfoot element represents the block of rows that consist of the column summaries (footers) for the parent table element, if the tfoot element has a parent and it is a table.'), - tr: new HTMLTagSpecification( - 'The tr element represents a row of cells in a table.'), - td: new HTMLTagSpecification( - 'The td element represents a data cell in a table.', - ['colspan', 'rowspan', 'headers']), - th: new HTMLTagSpecification( - 'The th element represents a header cell in a table.', - ['colspan', 'rowspan', 'headers', 'scope:s', 'sorted', 'abbr']), - // Forms - form: new HTMLTagSpecification( - 'The form element represents a collection of form-associated elements, some of which can represent editable values that can be submitted to a server for processing.', - ['accept-charset', 'action', 'autocomplete:o', 'enctype:et', 'method:m', 'name', 'novalidate:v', 'target']), - label: new HTMLTagSpecification( - 'The label element represents a caption in a user interface. The caption can be associated with a specific form control, known as the label element\'s labeled control, either using the for attribute, or by putting the form control inside the label element itself.', - ['form', 'for']), - input: new HTMLTagSpecification( - 'The input element represents a typed data field, usually with a form control to allow the user to edit the data.', - ['accept', 'alt', 'autocomplete:o', 'autofocus:v', 'checked:v', 'dirname', 'disabled:v', 'form', 'formaction', 'formenctype:et', 'formmethod:fm', 'formnovalidate:v', 'formtarget', 'height', 'inputmode:im', 'list', 'max', 'maxlength', 'min', 'minlength', 'multiple:v', 'name', 'pattern', 'placeholder', 'readonly:v', 'required:v', 'size', 'src', 'step', 'type:t', 'value', 'width']), - button: new HTMLTagSpecification( - 'The button element represents a button labeled by its contents.', - ['autofocus:v', 'disabled:v', 'form', 'formaction', 'formenctype:et', 'formmethod:fm', 'formnovalidate:v', 'formtarget', 'name', 'type:bt', 'value']), - select: new HTMLTagSpecification( - 'The select element represents a control for selecting amongst a set of options.', - ['autocomplete:o', 'autofocus:v', 'disabled:v', 'form', 'multiple:v', 'name', 'required:v', 'size']), - datalist: new HTMLTagSpecification( - 'The datalist element represents a set of option elements that represent predefined options for other controls. In the rendering, the datalist element represents nothing and it, along with its children, should be hidden.'), - optgroup: new HTMLTagSpecification( - 'The optgroup element represents a group of option elements with a common label.', - ['disabled:v', 'label']), - option: new HTMLTagSpecification( - 'The option element represents an option in a select element or as part of a list of suggestions in a datalist element.', - ['disabled:v', 'label', 'selected:v', 'value']), - textarea: new HTMLTagSpecification( - 'The textarea element represents a multiline plain text edit control for the element\'s raw value. The contents of the control represent the control\'s default value.', - ['autocomplete:o', 'autofocus:v', 'cols', 'dirname', 'disabled:v', 'form', 'inputmode:im', 'maxlength', 'minlength', 'name', 'placeholder', 'readonly:v', 'required:v', 'rows', 'wrap:w']), - output: new HTMLTagSpecification( - 'The output element represents the result of a calculation performed by the application, or the result of a user action.', - ['for', 'form', 'name']), - progress: new HTMLTagSpecification( - 'The progress element represents the completion progress of a task. The progress is either indeterminate, indicating that progress is being made but that it is not clear how much more work remains to be done before the task is complete (e.g. because the task is waiting for a remote host to respond), or the progress is a number in the range zero to a maximum, giving the fraction of work that has so far been completed.', - ['value', 'max']), - meter: new HTMLTagSpecification( - 'The meter element represents a scalar measurement within a known range, or a fractional value; for example disk usage, the relevance of a query result, or the fraction of a voting population to have selected a particular candidate.', - ['value', 'min', 'max', 'low', 'high', 'optimum']), - fieldset: new HTMLTagSpecification( - 'The fieldset element represents a set of form controls optionally grouped under a common name.', - ['disabled:v', 'form', 'name']), - legend: new HTMLTagSpecification( - 'The legend element represents a caption for the rest of the contents of the legend element\'s parent fieldset element, if any.'), - // Interactive elements - details: new HTMLTagSpecification( - 'The details element represents a disclosure widget from which the user can obtain additional information or controls.', - ['open:v']), - summary: new HTMLTagSpecification( - 'The summary element represents a summary, caption, or legend for the rest of the contents of the summary element\'s parent details element, if any.'), - menu: new HTMLTagSpecification( - 'The menu element represents a list of commands.', - ['type:mt', 'label']), - menuitem: new HTMLTagSpecification( - 'The menuitem element represents a command that the user can invoke from a popup menu (either a context menu or the menu of a menu button).'), - dialog: new HTMLTagSpecification( - 'The dialog element represents a part of an application that a user interacts with to perform a task, for example a dialog box, inspector, or window.'), - // Scripting - script: new HTMLTagSpecification( - 'The script element allows authors to include dynamic script and data blocks in their documents. The element does not represent content for the user.', - ['src', 'type', 'charset', 'async:v', 'defer:v', 'crossorigin:xo', 'nonce']), - noscript: new HTMLTagSpecification( - 'The noscript element represents nothing if scripting is enabled, and represents its children if scripting is disabled. It is used to present different markup to user agents that support scripting and those that don\'t support scripting, by affecting how the document is parsed.'), - template: new HTMLTagSpecification( - 'The template element is used to declare fragments of HTML that can be cloned and inserted in the document by script.'), - canvas: new HTMLTagSpecification( - 'The canvas element provides scripts with a resolution-dependent bitmap canvas, which can be used for rendering graphs, game graphics, art, or other visual images on the fly.', - ['width', 'height']) -}; diff --git a/src/vs/languages/html/common/htmlTags.ts b/src/vs/languages/html/common/htmlTags.ts index 34078133565..a9422850148 100644 --- a/src/vs/languages/html/common/htmlTags.ts +++ b/src/vs/languages/html/common/htmlTags.ts @@ -5,7 +5,7 @@ import strings = require('vs/base/common/strings'); import arrays = require('vs/base/common/arrays'); -import {HTML_TAGS} from 'vs/languages/html/common/htmlTagSpecifications'; +import nls = require('vs/nls'); var emptyElements:string[] = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr']; @@ -19,6 +19,414 @@ export interface IHTMLTagProvider { collectValues(tag: string, attribute: string, collector: (value: string) => void): void; } +export class HTMLTagSpecification { + public label: string; + + constructor(tagName: string, label: string, public attributes: string[] = []) { + this.label = nls.localize(`tags.${tagName}`, label); + } +} + +// HTML tag information sourced from http://www.w3.org/TR/2015/WD-html51-20151008/ +export const HTML_TAGS : { [tag:string]: HTMLTagSpecification } = { + // The root element + html: new HTMLTagSpecification( + 'html', + 'The html element represents the root of an HTML document.', + ['manifest']), + // Document metadata + head: new HTMLTagSpecification( + 'head', + 'The head element represents a collection of metadata for the Document.'), + title: new HTMLTagSpecification( + 'title', + 'The title element represents the document\'s title or name. Authors should use titles that identify their documents even when they are used out of context, for example in a user\'s history or bookmarks, or in search results. The document\'s title is often different from its first heading, since the first heading does not have to stand alone when taken out of context.'), + base: new HTMLTagSpecification( + 'base', + 'The base element allows authors to specify the document base URL for the purposes of resolving relative URLs, and the name of the default browsing context for the purposes of following hyperlinks. The element does not represent any content beyond this information.', + ['href', 'target']), + link: new HTMLTagSpecification( + 'link', + 'The link element allows authors to link their document to other resources.', + ['href', 'crossorigin:xo', 'rel', 'media', 'hreflang', 'type', 'sizes']), + meta: new HTMLTagSpecification( + 'meta', + 'The meta element represents various kinds of metadata that cannot be expressed using the title, base, link, style, and script elements.', + ['name', 'http-equiv', 'content', 'charset']), + style: new HTMLTagSpecification( + 'style', + 'The style element allows authors to embed style information in their documents. The style element is one of several inputs to the styling processing model. The element does not represent content for the user.', + ['media', 'nonce', 'type', 'scoped:v']), + // Sections + body: new HTMLTagSpecification( + 'body', + 'The body element represents the content of the document.', + ['onafterprint', 'onbeforeprint', 'onbeforeunload', 'onhashchange', 'onlanguagechange', 'onmessage', 'onoffline', 'ononline', 'onpagehide', 'onpageshow', 'onpopstate', 'onstorage', 'onunload']), + article: new HTMLTagSpecification( + 'article', + 'The article element represents a complete, or self-contained, composition in a document, page, application, or site and that is, in principle, independently distributable or reusable, e.g. in syndication. This could be a forum post, a magazine or newspaper article, a blog entry, a user-submitted comment, an interactive widget or gadget, or any other independent item of content. Each article should be identified, typically by including a heading (h1–h6 element) as a child of the article element.'), + section: new HTMLTagSpecification( + 'section', + 'The section element represents a generic section of a document or application. A section, in this context, is a thematic grouping of content. Each section should be identified, typically by including a heading ( h1- h6 element) as a child of the section element.'), + nav: new HTMLTagSpecification( + 'nav', + 'The nav element represents a section of a page that links to other pages or to parts within the page: a section with navigation links.'), + aside: new HTMLTagSpecification( + 'aside', + 'The aside element represents a section of a page that consists of content that is tangentially related to the content around the aside element, and which could be considered separate from that content. Such sections are often represented as sidebars in printed typography.'), + h1: new HTMLTagSpecification( + 'h1', + 'The h1 element represents a section heading.'), + h2: new HTMLTagSpecification( + 'h2', + 'The h2 element represents a section heading.'), + h3: new HTMLTagSpecification( + 'h3', + 'The h3 element represents a section heading.'), + h4: new HTMLTagSpecification( + 'h4', + 'The h4 element represents a section heading.'), + h5: new HTMLTagSpecification( + 'h5', + 'The h5 element represents a section heading.'), + h6: new HTMLTagSpecification( + 'h6', + 'The h6 element represents a section heading.'), + header: new HTMLTagSpecification( + 'header', + 'The header element represents introductory content for its nearest ancestor sectioning content or sectioning root element. A header typically contains a group of introductory or navigational aids. When the nearest ancestor sectioning content or sectioning root element is the body element, then it applies to the whole page.'), + footer: new HTMLTagSpecification( + 'footer', + 'The footer element represents a footer for its nearest ancestor sectioning content or sectioning root element. A footer typically contains information about its section such as who wrote it, links to related documents, copyright data, and the like.'), + address: new HTMLTagSpecification( + 'address', + 'The address element represents the contact information for its nearest article or body element ancestor. If that is the body element, then the contact information applies to the document as a whole.'), + // Grouping content + p: new HTMLTagSpecification( + 'p', + 'The p element represents a paragraph.'), + hr: new HTMLTagSpecification( + 'hr', + 'The hr element represents a paragraph-level thematic break, e.g. a scene change in a story, or a transition to another topic within a section of a reference book.'), + pre: new HTMLTagSpecification( + 'pre', + 'The pre element represents a block of preformatted text, in which structure is represented by typographic conventions rather than by elements.'), + blockquote: new HTMLTagSpecification( + 'blockquote', + 'The blockquote element represents content that is quoted from another source, optionally with a citation which must be within a footer or cite element, and optionally with in-line changes such as annotations and abbreviations.', + ['cite']), + ol: new HTMLTagSpecification( + 'ol', + 'The ol element represents a list of items, where the items have been intentionally ordered, such that changing the order would change the meaning of the document.', + ['reversed:v', 'start', 'type:lt']), + ul: new HTMLTagSpecification( + 'ul', + 'The ul element represents a list of items, where the order of the items is not important — that is, where changing the order would not materially change the meaning of the document.'), + li: new HTMLTagSpecification( + 'li', + 'The li element represents a list item. If its parent element is an ol, ul, or menu element, then the element is an item of the parent element\'s list, as defined for those elements. Otherwise, the list item has no defined list-related relationship to any other li element.', + ['value']), + dl: new HTMLTagSpecification( + 'dl', + 'The dl element represents an association list consisting of zero or more name-value groups (a description list). A name-value group consists of one or more names (dt elements) followed by one or more values (dd elements), ignoring any nodes other than dt and dd elements. Within a single dl element, there should not be more than one dt element for each name.'), + dt: new HTMLTagSpecification( + 'dt', + 'The dt element represents the term, or name, part of a term-description group in a description list (dl element).'), + dd: new HTMLTagSpecification( + 'dd', + 'The dd element represents the description, definition, or value, part of a term-description group in a description list (dl element).'), + figure: new HTMLTagSpecification( + 'figure', + 'The figure element represents some flow content, optionally with a caption, that is self-contained (like a complete sentence) and is typically referenced as a single unit from the main flow of the document.'), + figcaption: new HTMLTagSpecification( + 'figcaption', + 'The figcaption element represents a caption or legend for the rest of the contents of the figcaption element\'s parent figure element, if any.'), + main: new HTMLTagSpecification( + 'main', + 'The main element represents the main content of the body of a document or application. The main content area consists of content that is directly related to or expands upon the central topic of a document or central functionality of an application.'), + div: new HTMLTagSpecification( + 'div', + 'The div element has no special meaning at all. It represents its children. It can be used with the class, lang, and title attributes to mark up semantics common to a group of consecutive elements.'), + // Text-level semantics + a: new HTMLTagSpecification( + 'a', + 'If the a element has an href attribute, then it represents a hyperlink (a hypertext anchor) labeled by its contents.', + ['href', 'target', 'download', 'ping', 'rel', 'hreflang', 'type']), + em: new HTMLTagSpecification( + 'em', + 'The em element represents stress emphasis of its contents.'), + strong: new HTMLTagSpecification( + 'strong', + 'The strong element represents strong importance, seriousness, or urgency for its contents.'), + small: new HTMLTagSpecification( + 'small', + 'The small element represents side comments such as small print.'), + s: new HTMLTagSpecification( + 's', + 'The s element represents contents that are no longer accurate or no longer relevant.'), + cite: new HTMLTagSpecification( + 'cite', + 'The cite element represents a reference to a creative work. It must include the title of the work or the name of the author(person, people or organization) or an URL reference, or a reference in abbreviated form as per the conventions used for the addition of citation metadata.'), + q: new HTMLTagSpecification( + 'q', + 'The q element represents some phrasing content quoted from another source.', + ['cite']), + dfn: new HTMLTagSpecification( + 'dfn', + 'The dfn element represents the defining instance of a term. The paragraph, description list group, or section that is the nearest ancestor of the dfn element must also contain the definition(s) for the term given by the dfn element.'), + abbr: new HTMLTagSpecification( + 'abbr', + 'The abbr element represents an abbreviation or acronym, optionally with its expansion. The title attribute may be used to provide an expansion of the abbreviation. The attribute, if specified, must contain an expansion of the abbreviation, and nothing else.'), + ruby: new HTMLTagSpecification( + 'ruby', + 'The ruby element allows one or more spans of phrasing content to be marked with ruby annotations. Ruby annotations are short runs of text presented alongside base text, primarily used in East Asian typography as a guide for pronunciation or to include other annotations. In Japanese, this form of typography is also known as furigana. Ruby text can appear on either side, and sometimes both sides, of the base text, and it is possible to control its position using CSS. A more complete introduction to ruby can be found in the Use Cases & Exploratory Approaches for Ruby Markup document as well as in CSS Ruby Module Level 1. [RUBY-UC] [CSSRUBY]'), + rb: new HTMLTagSpecification( + 'rb', + 'The rb element marks the base text component of a ruby annotation. When it is the child of a ruby element, it doesn\'t represent anything itself, but its parent ruby element uses it as part of determining what it represents.'), + rt: new HTMLTagSpecification( + 'rt', + 'The rt element marks the ruby text component of a ruby annotation. When it is the child of a ruby element or of an rtc element that is itself the child of a ruby element, it doesn\'t represent anything itself, but its ancestor ruby element uses it as part of determining what it represents.'), + rtc: new HTMLTagSpecification( + 'rtc', + 'The rtc element marks a ruby text container for ruby text components in a ruby annotation. When it is the child of a ruby element it doesn\'t represent anything itself, but its parent ruby element uses it as part of determining what it represents.'), + rp: new HTMLTagSpecification( + 'rp', + 'The rp element is used to provide fallback text to be shown by user agents that don\'t support ruby annotations. One widespread convention is to provide parentheses around the ruby text component of a ruby annotation.'), + data: new HTMLTagSpecification( + 'data', + 'The data element represents its contents, along with a machine-readable form of those contents in the value attribute.'), + time: new HTMLTagSpecification( + 'time', + 'The time element represents its contents, along with a machine-readable form of those contents in the datetime attribute. The kind of content is limited to various kinds of dates, times, time-zone offsets, and durations, as described below.', + ['datetime']), + code: new HTMLTagSpecification( + 'code', + 'The code element represents a fragment of computer code. This could be an XML element name, a file name, a computer program, or any other string that a computer would recognize.'), + var: new HTMLTagSpecification( + 'var', + 'The var element represents a variable. This could be an actual variable in a mathematical expression or programming context, an identifier representing a constant, a symbol identifying a physical quantity, a function parameter, or just be a term used as a placeholder in prose.'), + samp: new HTMLTagSpecification( + 'samp', + 'The samp element represents sample or quoted output from another program or computing system.'), + kbd: new HTMLTagSpecification( + 'kbd', + 'The kbd element represents user input (typically keyboard input, although it may also be used to represent other input, such as voice commands).'), + sub: new HTMLTagSpecification( + 'sub', + 'The sub element represents a subscript.'), + sup: new HTMLTagSpecification( + 'sup', + 'The sup element represents a superscript.'), + i: new HTMLTagSpecification( + 'i', + 'The i element represents a span of text in an alternate voice or mood, or otherwise offset from the normal prose in a manner indicating a different quality of text, such as a taxonomic designation, a technical term, an idiomatic phrase from another language, transliteration, a thought, or a ship name in Western texts.'), + b: new HTMLTagSpecification( + 'b', + 'The b element represents a span of text to which attention is being drawn for utilitarian purposes without conveying any extra importance and with no implication of an alternate voice or mood, such as key words in a document abstract, product names in a review, actionable words in interactive text-driven software, or an article lede.'), + u: new HTMLTagSpecification( + 'u', + 'The u element represents a span of text with an unarticulated, though explicitly rendered, non-textual annotation, such as labeling the text as being a proper name in Chinese text (a Chinese proper name mark), or labeling the text as being misspelt.'), + mark: new HTMLTagSpecification( + 'mark', + 'The mark element represents a run of text in one document marked or highlighted for reference purposes, due to its relevance in another context. When used in a quotation or other block of text referred to from the prose, it indicates a highlight that was not originally present but which has been added to bring the reader\'s attention to a part of the text that might not have been considered important by the original author when the block was originally written, but which is now under previously unexpected scrutiny. When used in the main prose of a document, it indicates a part of the document that has been highlighted due to its likely relevance to the user\'s current activity.'), + bdi: new HTMLTagSpecification( + 'bdi', + 'The bdi element represents a span of text that is to be isolated from its surroundings for the purposes of bidirectional text formatting. [BIDI]'), + bdo: new HTMLTagSpecification( + 'bdo', + 'The bdo element represents explicit text directionality formatting control for its children. It allows authors to override the Unicode bidirectional algorithm by explicitly specifying a direction override. [BIDI]'), + span: new HTMLTagSpecification( + 'span', + 'The span element doesn\'t mean anything on its own, but can be useful when used together with the global attributes, e.g. class, lang, or dir. It represents its children.'), + br: new HTMLTagSpecification( + 'br', + 'The br element represents a line break.'), + wbr: new HTMLTagSpecification( + 'wbr', + 'The wbr element represents a line break opportunity.'), + // Edits + ins: new HTMLTagSpecification( + 'ins', + 'The ins element represents an addition to the document.'), + del: new HTMLTagSpecification( + 'del', + 'The del element represents a removal from the document.', + ['cite', 'datetime']), + // Embedded content + picture: new HTMLTagSpecification( + 'picture', + 'The picture element is a container which provides multiple sources to its contained img element to allow authors to declaratively control or give hints to the user agent about which image resource to use, based on the screen pixel density, viewport size, image format, and other factors. It represents its children.'), + img: new HTMLTagSpecification( + 'img', + 'An img element represents an image.', + ['alt', 'src', 'srcset', 'crossorigin:xo', 'usemap', 'ismap:v', 'width', 'height']), + iframe: new HTMLTagSpecification( + 'iframe', + 'The iframe element represents a nested browsing context.', + ['src', 'srcdoc', 'name', 'sandbox:sb', 'seamless:v', 'allowfullscreen:v', 'width', 'height']), + embed: new HTMLTagSpecification( + 'embed', + 'The embed element provides an integration point for an external (typically non-HTML) application or interactive content.', + ['src', 'type', 'width', 'height']), + object: new HTMLTagSpecification( + 'object', + 'The object element can represent an external resource, which, depending on the type of the resource, will either be treated as an image, as a nested browsing context, or as an external resource to be processed by a plugin.', + ['data', 'type', 'typemustmatch:v', 'name', 'usemap', 'form', 'width', 'height']), + param: new HTMLTagSpecification( + 'param', + 'The param element defines parameters for plugins invoked by object elements. It does not represent anything on its own.', + ['name', 'value']), + video: new HTMLTagSpecification( + 'video', + 'A video element is used for playing videos or movies, and audio files with captions.', + ['src', 'crossorigin:xo', 'poster', 'preload:pl', 'autoplay:v', 'mediagroup', 'loop:v', 'muted:v', 'controls:v', 'width', 'height']), + audio: new HTMLTagSpecification( + 'audio', + 'An audio element represents a sound or audio stream.', + ['src', 'crossorigin:xo', 'preload:pl', 'autoplay:v', 'mediagroup', 'loop:v', 'muted:v', 'controls:v']), + source: new HTMLTagSpecification( + 'source', + 'The source element allows authors to specify multiple alternative media resources for media elements. It does not represent anything on its own.', + // 'When the source element has a parent that is a picture element, the source element allows authors to specify multiple alternative source sets for img elements.' + ['src', 'type']), + track: new HTMLTagSpecification( + 'track', + 'The track element allows authors to specify explicit external timed text tracks for media elements. It does not represent anything on its own.', + ['default:v', 'kind:tk', 'label', 'src', 'srclang']), + map: new HTMLTagSpecification( + 'map', + 'The map element, in conjunction with an img element and any area element descendants, defines an image map. The element represents its children.', + ['name']), + area: new HTMLTagSpecification( + 'area', + 'The area element represents either a hyperlink with some text and a corresponding area on an image map, or a dead area on an image map.', + ['alt', 'coords', 'shape:sh', 'href', 'target', 'download', 'ping', 'rel', 'hreflang', 'type']), + // Tabular data + table: new HTMLTagSpecification( + 'table', + 'The table element represents data with more than one dimension, in the form of a table.', + ['sortable:v', 'border']), + caption: new HTMLTagSpecification( + 'caption', + 'The caption element represents the title of the table that is its parent, if it has a parent and that is a table element.'), + colgroup: new HTMLTagSpecification( + 'colgroup', + 'The colgroup element represents a group of one or more columns in the table that is its parent, if it has a parent and that is a table element.', + ['span']), + col: new HTMLTagSpecification( + 'col', + 'If a col element has a parent and that is a colgroup element that itself has a parent that is a table element, then the col element represents one or more columns in the column group represented by that colgroup.', + ['span']), + tbody: new HTMLTagSpecification( + 'tbody', + 'The tbody element represents a block of rows that consist of a body of data for the parent table element, if the tbody element has a parent and it is a table.'), + thead: new HTMLTagSpecification( + 'thead', + 'The thead element represents the block of rows that consist of the column labels (headers) for the parent table element, if the thead element has a parent and it is a table.'), + tfoot: new HTMLTagSpecification( + 'tfoot', + 'The tfoot element represents the block of rows that consist of the column summaries (footers) for the parent table element, if the tfoot element has a parent and it is a table.'), + tr: new HTMLTagSpecification( + 'tr', + 'The tr element represents a row of cells in a table.'), + td: new HTMLTagSpecification( + 'td', + 'The td element represents a data cell in a table.', + ['colspan', 'rowspan', 'headers']), + th: new HTMLTagSpecification( + 'th', + 'The th element represents a header cell in a table.', + ['colspan', 'rowspan', 'headers', 'scope:s', 'sorted', 'abbr']), + // Forms + form: new HTMLTagSpecification( + 'form', + 'The form element represents a collection of form-associated elements, some of which can represent editable values that can be submitted to a server for processing.', + ['accept-charset', 'action', 'autocomplete:o', 'enctype:et', 'method:m', 'name', 'novalidate:v', 'target']), + label: new HTMLTagSpecification( + 'label', + 'The label element represents a caption in a user interface. The caption can be associated with a specific form control, known as the label element\'s labeled control, either using the for attribute, or by putting the form control inside the label element itself.', + ['form', 'for']), + input: new HTMLTagSpecification( + 'input', + 'The input element represents a typed data field, usually with a form control to allow the user to edit the data.', + ['accept', 'alt', 'autocomplete:o', 'autofocus:v', 'checked:v', 'dirname', 'disabled:v', 'form', 'formaction', 'formenctype:et', 'formmethod:fm', 'formnovalidate:v', 'formtarget', 'height', 'inputmode:im', 'list', 'max', 'maxlength', 'min', 'minlength', 'multiple:v', 'name', 'pattern', 'placeholder', 'readonly:v', 'required:v', 'size', 'src', 'step', 'type:t', 'value', 'width']), + button: new HTMLTagSpecification( + 'button', + 'The button element represents a button labeled by its contents.', + ['autofocus:v', 'disabled:v', 'form', 'formaction', 'formenctype:et', 'formmethod:fm', 'formnovalidate:v', 'formtarget', 'name', 'type:bt', 'value']), + select: new HTMLTagSpecification( + 'select', + 'The select element represents a control for selecting amongst a set of options.', + ['autocomplete:o', 'autofocus:v', 'disabled:v', 'form', 'multiple:v', 'name', 'required:v', 'size']), + datalist: new HTMLTagSpecification( + 'datalist', + 'The datalist element represents a set of option elements that represent predefined options for other controls. In the rendering, the datalist element represents nothing and it, along with its children, should be hidden.'), + optgroup: new HTMLTagSpecification( + 'optgroup', + 'The optgroup element represents a group of option elements with a common label.', + ['disabled:v', 'label']), + option: new HTMLTagSpecification( + 'option', + 'The option element represents an option in a select element or as part of a list of suggestions in a datalist element.', + ['disabled:v', 'label', 'selected:v', 'value']), + textarea: new HTMLTagSpecification( + 'textarea', + 'The textarea element represents a multiline plain text edit control for the element\'s raw value. The contents of the control represent the control\'s default value.', + ['autocomplete:o', 'autofocus:v', 'cols', 'dirname', 'disabled:v', 'form', 'inputmode:im', 'maxlength', 'minlength', 'name', 'placeholder', 'readonly:v', 'required:v', 'rows', 'wrap:w']), + output: new HTMLTagSpecification( + 'output', + 'The output element represents the result of a calculation performed by the application, or the result of a user action.', + ['for', 'form', 'name']), + progress: new HTMLTagSpecification( + 'progress', + 'The progress element represents the completion progress of a task. The progress is either indeterminate, indicating that progress is being made but that it is not clear how much more work remains to be done before the task is complete (e.g. because the task is waiting for a remote host to respond), or the progress is a number in the range zero to a maximum, giving the fraction of work that has so far been completed.', + ['value', 'max']), + meter: new HTMLTagSpecification( + 'meter', + 'The meter element represents a scalar measurement within a known range, or a fractional value; for example disk usage, the relevance of a query result, or the fraction of a voting population to have selected a particular candidate.', + ['value', 'min', 'max', 'low', 'high', 'optimum']), + fieldset: new HTMLTagSpecification( + 'fieldset', + 'The fieldset element represents a set of form controls optionally grouped under a common name.', + ['disabled:v', 'form', 'name']), + legend: new HTMLTagSpecification( + 'legend', + 'The legend element represents a caption for the rest of the contents of the legend element\'s parent fieldset element, if any.'), + // Interactive elements + details: new HTMLTagSpecification( + 'details', + 'The details element represents a disclosure widget from which the user can obtain additional information or controls.', + ['open:v']), + summary: new HTMLTagSpecification( + 'summary', + 'The summary element represents a summary, caption, or legend for the rest of the contents of the summary element\'s parent details element, if any.'), + menu: new HTMLTagSpecification( + 'menu', + 'The menu element represents a list of commands.', + ['type:mt', 'label']), + menuitem: new HTMLTagSpecification( + 'menuitem', + 'The menuitem element represents a command that the user can invoke from a popup menu (either a context menu or the menu of a menu button).'), + dialog: new HTMLTagSpecification( + 'dialog', + 'The dialog element represents a part of an application that a user interacts with to perform a task, for example a dialog box, inspector, or window.'), + // Scripting + script: new HTMLTagSpecification( + 'script', + 'The script element allows authors to include dynamic script and data blocks in their documents. The element does not represent content for the user.', + ['src', 'type', 'charset', 'async:v', 'defer:v', 'crossorigin:xo', 'nonce']), + noscript: new HTMLTagSpecification( + 'noscript', + 'The noscript element represents nothing if scripting is enabled, and represents its children if scripting is disabled. It is used to present different markup to user agents that support scripting and those that don\'t support scripting, by affecting how the document is parsed.'), + template: new HTMLTagSpecification( + 'template', + 'The template element is used to declare fragments of HTML that can be cloned and inserted in the document by script.'), + canvas: new HTMLTagSpecification( + 'canvas', + 'The canvas element provides scripts with a resolution-dependent bitmap canvas, which can be used for rendering graphs, game graphics, art, or other visual images on the fly.', + ['width', 'height']) +}; + export function getHTML5TagProvider(): IHTMLTagProvider { var globalAttributes = [ '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', From 545b62b80df16713a5823888aa732ee583b2f3c8 Mon Sep 17 00:00:00 2001 From: Dick van den Brink Date: Mon, 30 Nov 2015 21:24:03 +0100 Subject: [PATCH 224/588] Fixed mime-type detection because of different capitalization fixes #770 --- src/vs/base/browser/ui/resourceviewer/resourceViewer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/browser/ui/resourceviewer/resourceViewer.ts b/src/vs/base/browser/ui/resourceviewer/resourceViewer.ts index bfc83c0b89b..dd4454650a0 100644 --- a/src/vs/base/browser/ui/resourceviewer/resourceViewer.ts +++ b/src/vs/base/browser/ui/resourceviewer/resourceViewer.ts @@ -79,7 +79,7 @@ export class ResourceViewer { let mime: string; const ext = paths.extname(resource.toString()); if (ext) { - mime = mapExtToMediaMimes[ext]; + mime = mapExtToMediaMimes[ext.toLowerCase()]; } if (!mime) { From 926f1e092cea98aea309294aa45901352b88525f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 30 Nov 2015 12:25:33 -0800 Subject: [PATCH 225/588] Remove menu and menuitem from tag list as they aren't widely adopted As per #806 --- 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 a9422850148..fc760f0cbf9 100644 --- a/src/vs/languages/html/common/htmlTags.ts +++ b/src/vs/languages/html/common/htmlTags.ts @@ -400,13 +400,14 @@ export const HTML_TAGS : { [tag:string]: HTMLTagSpecification } = { summary: new HTMLTagSpecification( 'summary', 'The summary element represents a summary, caption, or legend for the rest of the contents of the summary element\'s parent details element, if any.'), - menu: new HTMLTagSpecification( - 'menu', - 'The menu element represents a list of commands.', - ['type:mt', 'label']), - menuitem: new HTMLTagSpecification( - 'menuitem', - 'The menuitem element represents a command that the user can invoke from a popup menu (either a context menu or the menu of a menu button).'), + // and are not yet supported by 2+ browsers + //menu: new HTMLTagSpecification( + // 'menu', + // 'The menu element represents a list of commands.', + // ['type:mt', 'label']), + //menuitem: new HTMLTagSpecification( + // 'menuitem', + // 'The menuitem element represents a command that the user can invoke from a popup menu (either a context menu or the menu of a menu button).'), dialog: new HTMLTagSpecification( 'dialog', 'The dialog element represents a part of an application that a user interacts with to perform a task, for example a dialog box, inspector, or window.'), From 7bca0cd1c3c19a70bb25eb2342911fa9a1d9b872 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 30 Nov 2015 21:35:09 +0100 Subject: [PATCH 226/588] [fsharp] update tm grammar (1.4.11) --- extensions/fsharp/syntaxes/fsharp.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/fsharp/syntaxes/fsharp.json b/extensions/fsharp/syntaxes/fsharp.json index f248027a9e9..f65bba136d3 100644 --- a/extensions/fsharp/syntaxes/fsharp.json +++ b/extensions/fsharp/syntaxes/fsharp.json @@ -96,7 +96,7 @@ "patterns": [ { "name": "comment.block.fsharp", - "begin": "(\\(\\*)", + "begin": "(\\(\\*(?!\\)))", "end": "(\\*\\))", "beginCaptures": { "1": { From 87b408b33b8515eecd2f719ebad9486b66beff65 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 1 Dec 2015 08:52:13 +0100 Subject: [PATCH 227/588] TextFileEditorModel tests seldom fail in Appveyor (fixes #766) --- .../workbench/parts/files/test/browser/fileEditorModel.test.ts | 2 ++ src/vs/workbench/services/files/test/node/fileService.test.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/files/test/browser/fileEditorModel.test.ts b/src/vs/workbench/parts/files/test/browser/fileEditorModel.test.ts index 1c189ca6ad2..aa718579925 100644 --- a/src/vs/workbench/parts/files/test/browser/fileEditorModel.test.ts +++ b/src/vs/workbench/parts/files/test/browser/fileEditorModel.test.ts @@ -209,6 +209,8 @@ suite('Files - TextFileEditorModel', () => { }); test("Change after auto save triggered will cause another autosave and twice the events", function(done) { + this.timeout(10000); // TODO@Ben test tends to need longer? + let eventCounter = 0; let m1 = baseInstantiationService.createInstance(TextFileEditorModel, toResource("/path/index.txt"), "utf8"); diff --git a/src/vs/workbench/services/files/test/node/fileService.test.ts b/src/vs/workbench/services/files/test/node/fileService.test.ts index e715e98c9f2..edeecf7bc32 100644 --- a/src/vs/workbench/services/files/test/node/fileService.test.ts +++ b/src/vs/workbench/services/files/test/node/fileService.test.ts @@ -57,7 +57,7 @@ suite('FileService', () => { }); test('createFile', function(done: () => void) { - this.timeout(10000); // test tends to need longer? + this.timeout(10000); // TODO@Ben test tends to need longer? let contents = 'Hello World'; service.createFile(uri.file(path.join(testDir, 'test.txt')), contents).done(s => { From 13a1295973a87a3d710d57bc5806c3b2f0b919d5 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 1 Dec 2015 09:06:42 +0100 Subject: [PATCH 228/588] bundle optional dependencies too --- build/gulpfile.vscode.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 0274aa68427..ecc27136cbb 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -183,8 +183,9 @@ function packageTask(platform, arch, opts) { var license = gulp.src(['Credits_*', 'LICENSE.txt', 'ThirdPartyNotices.txt'], { base: '.' }); var api = gulp.src('src/vs/vscode.d.ts').pipe(rename('out/vs/vscode.d.ts')); - var depsSrc = _.flatten(Object.keys(packagejson.dependencies) - .map(function (d) { return ['node_modules/' + d + '/**', '!node_modules/' + d + '/**/{test,tests}/**']; })); + var depsSrc = _.flatten(Object.keys(packagejson.dependencies).concat(Object.keys(packagejson.optionalDependencies)) + .map(function (d) { return ['node_modules/' + d + '/**', '!node_modules/' + d + '/**/{test,tests}/**']; }) + ); var deps = gulp.src(depsSrc, { base: '.', dot: true }) .pipe(util.cleanNodeModule('fsevents', ['binding.gyp', 'fsevents.cc', 'build/**', 'src/**', 'test/**'], true)) From 2db39ed034a56f26caaf82e43cb88340b3944150 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 1 Dec 2015 09:39:17 +0100 Subject: [PATCH 229/588] Markdown preview does not show images with relative file path (fixes #803) --- src/vs/languages/markdown/common/markdown.ts | 9 ++--- .../markdown/common/markdownWorker.ts | 36 +++++++------------ .../markdown/browser/markdownEditorModel.ts | 2 +- 3 files changed, 17 insertions(+), 30 deletions(-) diff --git a/src/vs/languages/markdown/common/markdown.ts b/src/vs/languages/markdown/common/markdown.ts index 45b2474ffe2..3109e33847b 100644 --- a/src/vs/languages/markdown/common/markdown.ts +++ b/src/vs/languages/markdown/common/markdown.ts @@ -7,6 +7,7 @@ import WinJS = require('vs/base/common/winjs.base'); import Monarch = require('vs/editor/common/modes/monarch/monarch'); import Network = require('vs/base/common/network'); +import URI from 'vs/base/common/uri'; import Types = require('vs/editor/common/modes/monarch/monarchTypes'); import Compile = require('vs/editor/common/modes/monarch/monarchCompile'); import EditorCommon = require('vs/editor/common/editorCommon'); @@ -204,7 +205,6 @@ export const language = }; export class MarkdownMode extends Monarch.MonarchMode implements Modes.IEmitOutputSupport { - private baseUrl: string; public emitOutputSupport: Modes.IEmitOutputSupport; @@ -219,9 +219,6 @@ export class MarkdownMode extends Monarch.MonarchMode { // TODO@Ben technical debt: worker cannot resolve paths absolute - return this._worker((w) => w.getEmitOutput(resource, this.baseUrl, absoluteWorkerResourcesPath)); + public getEmitOutput(resource: URI, absoluteWorkerResourcesPath?: string): WinJS.TPromise { // TODO@Ben technical debt: worker cannot resolve paths absolute + return this._worker((w) => w.getEmitOutput(resource, absoluteWorkerResourcesPath)); } protected _getWorkerDescriptor(): AsyncDescriptor2 { diff --git a/src/vs/languages/markdown/common/markdownWorker.ts b/src/vs/languages/markdown/common/markdownWorker.ts index bb9e9da5fa7..f6accd507ff 100644 --- a/src/vs/languages/markdown/common/markdownWorker.ts +++ b/src/vs/languages/markdown/common/markdownWorker.ts @@ -7,6 +7,7 @@ import WinJS = require('vs/base/common/winjs.base'); import {AbstractModeWorker} from 'vs/editor/common/modes/abstractModeWorker'; import Network = require('vs/base/common/network'); +import URI from 'vs/base/common/uri'; import Types = require('vs/base/common/types'); import EditorCommon = require('vs/editor/common/editorCommon'); import Modes = require('vs/editor/common/modes'); @@ -101,7 +102,7 @@ export class MarkdownWorker extends AbstractModeWorker { private modeService: IModeService; constructor(mode: Modes.IMode, participants: Modes.IWorkerParticipant[], @IResourceService resourceService: IResourceService, - @IMarkerService markerService: IMarkerService, @IModeService modeService:IModeService) { + @IMarkerService markerService: IMarkerService, @IModeService modeService: IModeService) { super(mode, participants, resourceService, markerService); this.modeService = modeService; @@ -119,15 +120,15 @@ export class MarkdownWorker extends AbstractModeWorker { return WinJS.TPromise.as(false); } - public getEmitOutput(resource: Network.URL, baseUrl: string, absoluteWorkersResourcePath: string): WinJS.TPromise { // TODO@Ben technical debt: worker cannot resolve paths absolute - let model = this.resourceService.get(resource); + public getEmitOutput(resource: URI, absoluteWorkersResourcePath: string): WinJS.TPromise { // TODO@Ben technical debt: worker cannot resolve paths absolute + let model = this.resourceService.get(Network.URL.fromUri(resource)); let cssLinks: string[] = this.cssLinks || []; // Custom Renderer to fix href in images let renderer = new Marked.marked.Renderer(); let $this = this; renderer.image = function(href: string, title: string, text: string): string { - let out = '' + text + '', (cssLinks.length === 0) ? '' : '', (cssLinks.length === 0) ? '' : '', - '', (this.theme === Theme.LIGHT) ? MarkdownWorker.LIGHT_SCROLLBAR_CSS : (this.theme === Theme.DARK) ? MarkdownWorker.DARK_SCROLLBAR_CSS : MarkdownWorker.HC_BLACK_SCROLLBAR_CSS, cssLinks.map((style) => { - return ''; + return ''; }).join('\n'), '', isMacintosh ? '' : '' @@ -213,26 +213,16 @@ export class MarkdownWorker extends AbstractModeWorker { }); } - private fixHref(resource: Network.URL, href: string, baseUrl: string): string { + private fixHref(resource: URI, href: string): string { if (href) { - let url = new Network.URL(href); - // URL is actually a path - if (!url.getScheme()) { - let path = href; - - // the user might have used windows backslash, but we only support slashes in URLs, so fix up - path = Strings.replaceAll(path, '\\', '/'); - - // Absolute path: resolve against base URL - if (path[0] === '/') { - return Paths.join(baseUrl, path); - } - - // Relative path: resolve against resource URL - let resourcePath = resource.getPath(); - return Paths.join(Paths.dirname(resourcePath), path); + // Return early if href is already a URL + if (new Network.URL(href).getScheme()) { + return href; } + + // Otherwise convert to a file URI by joining the href with the resource location + return URI.file(Paths.join(Paths.dirname(resource.fsPath), href)).toString(); } return href; diff --git a/src/vs/workbench/parts/markdown/browser/markdownEditorModel.ts b/src/vs/workbench/parts/markdown/browser/markdownEditorModel.ts index f183ee22e2d..adcef8574e1 100644 --- a/src/vs/workbench/parts/markdown/browser/markdownEditorModel.ts +++ b/src/vs/workbench/parts/markdown/browser/markdownEditorModel.ts @@ -65,7 +65,7 @@ export class MarkdownEditorModel extends IFrameEditorModel { let mode = model.getMode(); let absoluteWorkerResourcesPath = require.toUrl('vs/languages/markdown/common'); // TODO@Ben technical debt: worker cannot resolve path absolute if (mode && !!mode.emitOutputSupport && mode.getId() === MARKDOWN_MODE_ID) { - (mode).emitOutputSupport.getEmitOutput(model.getAssociatedResource(), absoluteWorkerResourcesPath).then((output: IMarkdownWorkerOutput) => { + (mode).emitOutputSupport.getEmitOutput(this.resource, absoluteWorkerResourcesPath).then((output: IMarkdownWorkerOutput) => { this.setContents(output.head, output.body, output.tail); c(this); From c70b486631209d5c71a030b536eb036924958902 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 1 Dec 2015 09:52:23 +0100 Subject: [PATCH 230/588] silence service lib orphans fixes #808 --- src/vs/base/node/service.cp.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/node/service.cp.ts b/src/vs/base/node/service.cp.ts index 4bc07c8fcb7..ed14c03acf8 100644 --- a/src/vs/base/node/service.cp.ts +++ b/src/vs/base/node/service.cp.ts @@ -13,7 +13,7 @@ import { IServiceCtor, Server as IPCServer, Client as IPCClient, IServiceMap } f export class Server extends IPCServer { constructor() { super({ - send: r => process.send(r), + send: r => { try { process.send(r); } catch (e) { /* not much to do */ } }, onMessage: cb => process.on('message', cb) }); From c1d7172433e9bd7fa438aa583d46951e5c5897eb Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 1 Dec 2015 11:11:42 +0100 Subject: [PATCH 231/588] fix npe in non git workspaces --- .../workbench/parts/git/electron-browser/gitApp.ts | 12 ++++++++++-- src/vs/workbench/parts/git/node/git.lib.ts | 4 ++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/parts/git/electron-browser/gitApp.ts b/src/vs/workbench/parts/git/electron-browser/gitApp.ts index aa031d25ce6..03cdc8b1641 100644 --- a/src/vs/workbench/parts/git/electron-browser/gitApp.ts +++ b/src/vs/workbench/parts/git/electron-browser/gitApp.ts @@ -8,7 +8,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { Server } from 'vs/base/node/service.cp'; import objects = require('vs/base/common/objects'); import uri from 'vs/base/common/uri'; -import { IRawGitService } from 'vs/workbench/parts/git/common/git'; +import { IRawGitService, GitErrorCodes } from 'vs/workbench/parts/git/common/git'; import gitlib = require('vs/workbench/parts/git/node/git.lib'); import { RawGitService, DelayedRawGitService } from 'vs/workbench/parts/git/node/rawGitService'; import { join, dirname, normalize } from 'path'; @@ -23,6 +23,7 @@ class IPCRawGitService extends DelayedRawGitService { } else { const gitRootPath = uri.parse(require.toUrl('vs/workbench/parts/git/electron-main')).fsPath; const bootstrapPath = `${ uri.parse(require.toUrl('bootstrap')).fsPath }.js`; + workspaceRoot = normalize(workspaceRoot); const env = objects.assign({}, process.env, { GIT_ASKPASS: join(gitRootPath, 'askpass.sh'), @@ -38,8 +39,15 @@ class IPCRawGitService extends DelayedRawGitService { env: env }); - const repo = git.open(normalize(workspaceRoot)); + const repo = git.open(workspaceRoot); const promise = repo.getRoot() + .then(null, (err: gitlib.GitError) => { + if (err instanceof gitlib.GitError && err.gitErrorCode === GitErrorCodes.NotAGitRepository) { + return workspaceRoot; + } + + return TPromise.wrapError(err); + }) .then(root => realpath(root)) .then(root => git.open(root)) .then(repo => new RawGitService(repo)); diff --git a/src/vs/workbench/parts/git/node/git.lib.ts b/src/vs/workbench/parts/git/node/git.lib.ts index 102b012f8d5..bd8173162a8 100644 --- a/src/vs/workbench/parts/git/node/git.lib.ts +++ b/src/vs/workbench/parts/git/node/git.lib.ts @@ -186,6 +186,8 @@ export class Git { if (/Authentication failed/.test(result.stderr)) { gitErrorCode = GitErrorCodes.AuthenticationFailed; + } else if (/Not a git repository/.test(result.stderr)) { + gitErrorCode = GitErrorCodes.NotAGitRepository; } else if (/bad config file/.test(result.stderr)) { gitErrorCode = GitErrorCodes.BadConfigFile; } else if (/cannot make pipe for command substitution|cannot create standard input pipe/.test(result.stderr)) { @@ -496,8 +498,6 @@ export class Repository { return this.run(['fetch']).then(null, (err: GitError) => { if (/No remote repository specified\./.test(err.stderr)) { err.gitErrorCode = GitErrorCodes.NoRemoteRepositorySpecified; - } else if (/Not a git repository/.test(err.stderr)) { - err.gitErrorCode = GitErrorCodes.NotAGitRepository; } else if (/Could not read from remote repository/.test(err.stderr)) { err.gitErrorCode = GitErrorCodes.RemoteConnectionError; } From ebac96772ed71d3788b0635ae46ba398b06d2c44 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 1 Dec 2015 11:45:01 +0100 Subject: [PATCH 232/588] update electron to 0.34.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ce64bea165c..b00d85bfffd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "Code", "version": "0.10.3", - "electronVersion": "0.34.1", + "electronVersion": "0.34.5", "author": { "name": "Microsoft Corporation" }, From 679e0f5b9824c4f50da2537463d336f556d6b52d Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 1 Dec 2015 11:53:06 +0100 Subject: [PATCH 233/588] debug: better action enablement with respect to function breakpoints. --- src/vs/workbench/parts/debug/browser/debugActions.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugActions.ts b/src/vs/workbench/parts/debug/browser/debugActions.ts index 13dd2d5df81..a8285926ec9 100644 --- a/src/vs/workbench/parts/debug/browser/debugActions.ts +++ b/src/vs/workbench/parts/debug/browser/debugActions.ts @@ -285,7 +285,7 @@ export class RemoveAllBreakpointsAction extends AbstractDebugAction { } protected isEnabled(): boolean { - return super.isEnabled() && this.debugService.getModel().getBreakpoints().length > 0; + return super.isEnabled() && (this.debugService.getModel().getBreakpoints().length > 0 || this.debugService.getModel().getFunctionBreakpoints().length > 0); } } @@ -316,8 +316,8 @@ export class EnableAllBreakpointsAction extends AbstractDebugAction { } protected isEnabled(): boolean { - return super.isEnabled() && this.debugService.getModel().getBreakpoints().filter(bp => !bp.enabled).length > 0 || - this.debugService.getModel().getExceptionBreakpoints().filter(bp => !bp.enabled).length > 0; + const model = this.debugService.getModel(); + return super.isEnabled() && ( model.getBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getExceptionBreakpoints()).some(bp => !bp.enabled); } } @@ -335,8 +335,8 @@ export class DisableAllBreakpointsAction extends AbstractDebugAction { } protected isEnabled(): boolean { - return super.isEnabled() && this.debugService.getModel().getBreakpoints().filter(bp => bp.enabled).length > 0 || - this.debugService.getModel().getExceptionBreakpoints().filter(bp => bp.enabled).length > 0; + const model = this.debugService.getModel(); + return super.isEnabled() && ( model.getBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getExceptionBreakpoints()).some(bp => bp.enabled); } } From 1d7819f05264b795fd9278349eb53028342b5d1d Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 1 Dec 2015 11:54:48 +0100 Subject: [PATCH 234/588] command: executeCompletionItemProvider --- .../contrib/suggest/browser/suggestModel.ts | 36 ++---- .../editor/contrib/suggest/common/suggest.ts | 85 +++++++++++++- .../common/extHostLanguageFeatureCommands.ts | 25 ++++- .../api/common/extHostLanguageFeatures.ts | 2 +- .../api/common/pluginHostTypeConverters.ts | 33 ++++++ .../extHostLanguageFeatureCommands.test.ts | 23 ++++ .../api/extHostLanguageFeatures.test.ts | 105 ++++++++++++++++++ 7 files changed, 279 insertions(+), 30 deletions(-) diff --git a/src/vs/editor/contrib/suggest/browser/suggestModel.ts b/src/vs/editor/contrib/suggest/browser/suggestModel.ts index 0afd9d9ee49..cfe307fe3ba 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestModel.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestModel.ts @@ -17,7 +17,7 @@ import { ISuggestSupport, ISuggestions, ISuggestion, ISorter } from 'vs/editor/c import {DefaultFilter} from 'vs/editor/common/modes/modesFilters'; import { CodeSnippet } from 'vs/editor/contrib/snippet/common/snippet'; import { IDisposable, disposeAll } from 'vs/base/common/lifecycle'; -import {SuggestRegistry} from '../common/suggest'; +import {SuggestRegistry, ISuggestions2, suggest} from '../common/suggest'; enum SuggestState { NOT_ACTIVE = 0, @@ -76,13 +76,13 @@ class RawModel { public size: number = 0; public incomplete: boolean = false; - insertSuggestions(rank: number, suggestions: ISuggestions[], support: ISuggestSupport): boolean { + insertSuggestions(rank: number, suggestions: ISuggestions2[]): boolean { if (suggestions) { let items: CompletionItem[] = []; for (let _suggestions of suggestions) { for (let suggestionItem of _suggestions.suggestions) { - items.push(new CompletionItem(support, suggestionItem, _suggestions)); + items.push(new CompletionItem(_suggestions.support, suggestionItem, _suggestions)); } this.size += _suggestions.suggestions.length; @@ -384,35 +384,17 @@ export class SuggestModel extends EventEmitter { // Send mode request var $tRequest = timer.start(timer.Topic.EDITOR, 'suggest/REQUEST'); var position = this.editor.getPosition(); - var resource = model.getAssociatedResource(); let raw = new RawModel(); let rank = 0; - let factory = groups.map((supports, index) => { - return () => { - - // stop as soon as a group produced a result - if (raw.size !== 0) { - return; + this.requestPromise = suggest(model, position, triggerCharacter, groups).then(all => { + for (let suggestions of all) { + if (raw.insertSuggestions(rank, suggestions)) { + rank++; } - - // for each support in the group as for suggestions - let promises = supports.map(support => { - return support.suggest(resource, position, triggerCharacter).then(value => { - if (raw.insertSuggestions(rank, value, support)) { - rank++; - } - }, err => { - onUnexpectedError(err); - }); - }); - - return TPromise.join(promises); - }; + } }); - this.requestPromise = sequence(factory).then(() => { }); - this.requestPromise.then(() => { $tRequest.stop(); this.requestPromise = null; @@ -423,7 +405,7 @@ export class SuggestModel extends EventEmitter { var snippets = getSnippets(model, position); if (snippets && snippets.suggestions && snippets.suggestions.length > 0) { - raw.insertSuggestions(rank, [snippets], undefined); + raw.insertSuggestions(rank, [snippets]); } if(raw.size > 0) { diff --git a/src/vs/editor/contrib/suggest/common/suggest.ts b/src/vs/editor/contrib/suggest/common/suggest.ts index 5f86243c407..c5177e2d00f 100644 --- a/src/vs/editor/contrib/suggest/common/suggest.ts +++ b/src/vs/editor/contrib/suggest/common/suggest.ts @@ -4,11 +4,94 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {ISuggestSupport} from 'vs/editor/common/modes'; +import {sequence} from 'vs/base/common/async'; +import {IModel, IPosition} from 'vs/editor/common/editorCommon'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {mixin} from 'vs/base/common/objects'; +import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; +import {ISuggestSupport, ISuggestions} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; +import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; export var CONTEXT_SUGGEST_WIDGET_VISIBLE = 'suggestWidgetVisible'; export var CONTEXT_SUGGESTION_SUPPORTS_ACCEPT_ON_KEY = 'suggestionSupportsAcceptOnKey'; export var ACCEPT_SELECTED_SUGGESTION_CMD = 'acceptSelectedSuggestion'; export var SuggestRegistry = new LanguageFeatureRegistry('suggestSupport'); + +export interface ISuggestions2 extends ISuggestions { + support?: ISuggestSupport; +} + +export function suggest(model: IModel, position: IPosition, triggerCharacter: string, groups?: ISuggestSupport[][]): TPromise { + + if (!groups) { + groups = SuggestRegistry.orderedGroups(model); + } + + const resource = model.getAssociatedResource(); + const suggestions: ISuggestions[][] = []; + + const factory = groups.map((supports, index) => { + return () => { + + // stop as soon as a group produced a result + if (suggestions.length > 0) { + return; + } + + // for each support in the group ask for suggestions + let promises = supports.map(support => { + return support.suggest(resource, position, triggerCharacter).then(value => { + + let result: ISuggestions2[] = []; + for (let suggestions of value) { + + if (!suggestions + || !Array.isArray(suggestions.suggestions) + || suggestions.suggestions.length === 0) { + + continue; + } + + const suggestions2: ISuggestions2 = { + support, + currentWord: suggestions.currentWord, + incomplete: suggestions.incomplete, + overwriteAfter: suggestions.overwriteAfter, + overwriteBefore: suggestions.overwriteBefore, + suggestions: suggestions.suggestions + } + + // add additional properties + mixin(suggestions2, suggestions, false); + result.push(suggestions2); + } + + return result; + + }, onUnexpectedError); + }); + + return TPromise.join(promises).then(values => { + for (let value of values) { + if (Array.isArray(value) && value.length > 0) { + suggestions.push(value); + } + } + }); + }; + }); + + return sequence(factory).then(() => suggestions); +} + +CommonEditorRegistry.registerDefaultLanguageCommand('_executeCompletionItemProvider', (model, position, args) => { + + let triggerCharacter = args['triggerCharacter']; + if (typeof triggerCharacter !== 'undefined' && typeof triggerCharacter !== 'string') { + throw illegalArgument('triggerCharacter'); + } + + return suggest(model, position, triggerCharacter); +}); \ No newline at end of file diff --git a/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts index 4f22bacbe26..cd8d0eb77a2 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts @@ -46,13 +46,13 @@ import {SuggestRegistry} from 'vs/editor/contrib/suggest/common/suggest'; // vscode.executeDocumentRenameProvider // vscode.executeSignatureHelpProvider // vscode.executeDocumentSymbolProvider +// vscode.executeCompletionItemProvider // vscode.executeCodeActionProvider // vscode.executeCodeLensProvider // vscode.executeFormatDocumentProvider // vscode.executeFormatRangeProvider // vscode.executeFormatOnTypeProvider -// vscode.executeCompletionItemProvider export class ExtHostLanguageFeatureCommands { @@ -70,6 +70,7 @@ export class ExtHostLanguageFeatureCommands { this._register('vscode.executeDocumentRenameProvider', this._executeDocumentRenameProvider); this._register('vscode.executeSignatureHelpProvider', this._executeSignatureHelpProvider); this._register('vscode.executeDocumentSymbolProvider', this._executeDocumentSymbolProvider); + this._register('vscode.executeCompletionItemProvider', this._executeCompletionItemProvider); } private _register(id: string, callback: (...args: any[]) => any): void { @@ -168,6 +169,28 @@ export class ExtHostLanguageFeatureCommands { }); } + private _executeCompletionItemProvider(resource: URI, position: types.Position, triggerCharacter: string): Thenable { + const args = { + resource, + position: position && typeConverters.fromPosition(position), + triggerCharacter + }; + return this._commands.executeCommand('_executeCompletionItemProvider', args).then(value => { + if (value) { + let items: types.CompletionItem[] = []; + for (let group of value) { + for (let suggestions of group) { + for (let suggestion of suggestions.suggestions) { + const item = typeConverters.Suggest.to(suggestion, suggestions); + items.push(item); + } + } + } + return items; + } + }); + } + private _executeDocumentSymbolProvider(resource: URI): Thenable { const args = { resource diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 6a117f040bb..9c81d46167a 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -509,7 +509,7 @@ class SuggestAdapter implements modes.ISuggestSupport { for (let i = 0; i < value.length; i++) { const item = value[i]; - const suggestion = SuggestAdapter._convertCompletionItem(item); + const [suggestion] = TypeConverters.Suggest.from(item, defaultSuggestions); SuggestAdapter._convertCompletionItem(item); if (item.textEdit) { diff --git a/src/vs/workbench/api/common/pluginHostTypeConverters.ts b/src/vs/workbench/api/common/pluginHostTypeConverters.ts index 1f8e6433c65..b29f889b853 100644 --- a/src/vs/workbench/api/common/pluginHostTypeConverters.ts +++ b/src/vs/workbench/api/common/pluginHostTypeConverters.ts @@ -312,6 +312,39 @@ export function toDocumentHighlight(occurrence: modes.IOccurence): types.Documen types.DocumentHighlightKind[occurrence.kind.charAt(0).toUpperCase() + occurrence.kind.substr(1)]); } +export const Suggest = { + + from(item: vscode.CompletionItem, defaultContainer: modes.ISuggestions): [modes.ISuggestion, modes.ISuggestions] { + const suggestion: modes.ISuggestion = { + label: item.label, + codeSnippet: item.insertText || item.label, + type: types.CompletionItemKind[item.kind || types.CompletionItemKind.Text].toString().toLowerCase(), + typeLabel: item.detail, + documentationLabel: item.documentation, + sortText: item.sortText, + filterText: item.filterText + }; + + if (item.textEdit) { + // TODO@joh + } + + return [suggestion, defaultContainer]; + }, + + to(suggestion: modes.ISuggestion, container: modes.ISuggestions): types.CompletionItem { + const result = new types.CompletionItem(suggestion.label); + result.insertText = suggestion.codeSnippet; + result.kind = types.CompletionItemKind[suggestion.type.charAt(0).toUpperCase() + suggestion.type.substr(1)]; + result.detail = suggestion.typeLabel; + result.documentation = suggestion.documentationLabel; + result.sortText = suggestion.sortText; + result.filterText = suggestion.filterText; + // todo@joh edit range! + return result; + } +} + export namespace SignatureHelp { export function from(signatureHelp: types.SignatureHelp): modes.IParameterHints { diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts index b3fe6b701dc..e50bede365c 100644 --- a/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts @@ -232,4 +232,27 @@ suite('ExtHostLanguageFeatureCommands', function() { }); }); }); + + // --- suggest + + test('Suggest, back and forth', function(done) { + disposables.push(extHost.registerCompletionItemProvider(defaultSelector, { + provideCompletionItems(): any { + return [ + new types.CompletionItem('item1'), + new types.CompletionItem('item2') + ]; + } + }, [])); + + threadService.sync().then(() => { + commands.executeCommand('vscode.executeCompletionItemProvider', model.getAssociatedResource(), new types.Position(0, 0)).then(values => { + assert.equal(values.length, 2); + let [first, second] = values; + assert.equal(first.label, 'item1'); + assert.equal(second.label, 'item2'); + done(); + }); + }); + }); }); \ No newline at end of file diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts index 875d3fd2a20..048e37d4853 100644 --- a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts @@ -36,6 +36,7 @@ import {getQuickFixes} from 'vs/editor/contrib/quickFix/common/quickFix'; import {getNavigateToItems} from 'vs/workbench/parts/search/common/search'; import {rename} from 'vs/editor/contrib/rename/common/rename'; import {getParameterHints} from 'vs/editor/contrib/parameterHints/common/parameterHints'; +import {suggest} from 'vs/editor/contrib/suggest/common/suggest'; const defaultSelector = { scheme: 'far' }; const model: EditorCommon.IModel = new EditorModel( @@ -801,5 +802,109 @@ suite('ExtHostLanguageFeatures', function() { done(); }) }); + }); + + // --- suggestions + + test('Suggest, order 1/3', function(done) { + + disposables.push(extHost.registerCompletionItemProvider('*', { + provideCompletionItems(): any { + return [new types.CompletionItem('testing1')]; + } + }, [])); + + disposables.push(extHost.registerCompletionItemProvider(defaultSelector, { + provideCompletionItems(): any { + return [new types.CompletionItem('testing2')]; + } + }, [])); + + threadService.sync().then(() => { + suggest(model, { lineNumber: 1, column: 1 }, ',').then(value => { + assert.equal(value.length, 1); + let [[first]] = value; + assert.equal(first.suggestions.length, 1) + assert.equal(first.suggestions[0].codeSnippet, 'testing2') + done(); + }); + }); + }); + + test('Suggest, order 2/3', function(done) { + + disposables.push(extHost.registerCompletionItemProvider('*', { + provideCompletionItems(): any { + return [new types.CompletionItem('weak-selector')]; // weaker selector but result + } + }, [])); + + disposables.push(extHost.registerCompletionItemProvider(defaultSelector, { + provideCompletionItems(): any { + return []; // stronger selector but not a good result; + } + }, [])); + + threadService.sync().then(() => { + suggest(model, { lineNumber: 1, column: 1 }, ',').then(value => { + assert.equal(value.length, 1); + let [[first]] = value; + assert.equal(first.suggestions.length, 1) + assert.equal(first.suggestions[0].codeSnippet, 'weak-selector') + done(); + }); + }); }) + + test('Suggest, order 2/3', function(done) { + + disposables.push(extHost.registerCompletionItemProvider(defaultSelector, { + provideCompletionItems(): any { + return [new types.CompletionItem('strong-1')]; + } + }, [])); + + setTimeout(function() { + disposables.push(extHost.registerCompletionItemProvider(defaultSelector, { + provideCompletionItems(): any { + return [new types.CompletionItem('strong-2')]; + } + }, [])); + + threadService.sync().then(() => { + suggest(model, { lineNumber: 1, column: 1 }, ',').then(value => { + assert.equal(value.length, 2); + let [[first], [second]] = value; + assert.equal(first.suggestions.length, 1) + assert.equal(first.suggestions[0].codeSnippet, 'strong-2') // last wins + assert.equal(second.suggestions[0].codeSnippet, 'strong-1') + done(); + }); + }); + }, 5); + }) + + test('Suggest, evil provider', function(done) { + + disposables.push(extHost.registerCompletionItemProvider(defaultSelector, { + provideCompletionItems(): any { + throw new Error('evil'); + } + }, [])); + + disposables.push(extHost.registerCompletionItemProvider(defaultSelector, { + provideCompletionItems(): any { + return [new types.CompletionItem('testing')]; + } + }, [])); + + + threadService.sync().then(() => { + + suggest(model, { lineNumber: 1, column: 1 }, ',').then(value => { + assert.equal(value.length, 1); + done(); + }); + }); + }); }); \ No newline at end of file From c44731e247e485088e335374c5aa5d8d8c1a9ea1 Mon Sep 17 00:00:00 2001 From: thomas michael wallace Date: Tue, 1 Dec 2015 11:55:20 +0000 Subject: [PATCH 235/588] Add Windows Workflow (.xoml) extension. --- extensions/xml/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extensions/xml/package.json b/extensions/xml/package.json index 3ad9fd5ad6b..e092fe44205 100644 --- a/extensions/xml/package.json +++ b/extensions/xml/package.json @@ -59,7 +59,8 @@ ".xml", ".xpdl", ".xsd", - ".xul" + ".xul", + ".xoml" ], "firstLine" : "(\\<\\?xml.*)|(\\ Date: Tue, 1 Dec 2015 14:54:54 +0100 Subject: [PATCH 236/588] command: executeCodeActionProvider --- src/vs/editor/common/core/range.ts | 2 +- .../contrib/quickFix/common/quickFix.ts | 23 +++++++++++++++++-- .../common/extHostLanguageFeatureCommands.ts | 18 +++++++++++++-- .../extHostLanguageFeatureCommands.test.ts | 21 +++++++++++++++++ 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/vs/editor/common/core/range.ts b/src/vs/editor/common/core/range.ts index 54978a06bcf..f1625a43a25 100644 --- a/src/vs/editor/common/core/range.ts +++ b/src/vs/editor/common/core/range.ts @@ -90,7 +90,7 @@ export class Range implements EditorCommon.IEditorRange { return new Range(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn); } - public static isIRange(obj: any): boolean { + public static isIRange(obj: any): obj is EditorCommon.IRange { return ( obj && (typeof obj.startLineNumber === 'number') diff --git a/src/vs/editor/contrib/quickFix/common/quickFix.ts b/src/vs/editor/contrib/quickFix/common/quickFix.ts index 4e7e841c8ae..9c4d90c2b43 100644 --- a/src/vs/editor/contrib/quickFix/common/quickFix.ts +++ b/src/vs/editor/contrib/quickFix/common/quickFix.ts @@ -5,10 +5,14 @@ 'use strict'; +import URI from 'vs/base/common/uri'; +import {Range} from 'vs/editor/common/core/range'; import {IModel, IRange} from 'vs/editor/common/editorCommon'; import {TPromise} from 'vs/base/common/winjs.base'; -import {onUnexpectedError} from 'vs/base/common/errors'; +import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; import {IQuickFixSupport, IQuickFix} from 'vs/editor/common/modes'; +import {IModelService} from 'vs/editor/common/services/modelService'; +import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; export const QuickFixRegistry = new LanguageFeatureRegistry('quickFixSupport'); @@ -40,4 +44,19 @@ export function getQuickFixes(model: IModel, range: IRange): TPromise quickFixes); -} \ No newline at end of file +} + +CommonEditorRegistry.registerLanguageCommand('_executeCodeActionProvider', function(accessor, args) { + + const {resource, range} = args; + if (!URI.isURI(resource) || !Range.isIRange(range)) { + throw illegalArgument(); + } + + const model = accessor.get(IModelService).getModel(resource); + if (!model) { + throw illegalArgument(); + } + + return getQuickFixes(model, range); +}); \ No newline at end of file diff --git a/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts index cd8d0eb77a2..b0c82ee65c3 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts @@ -28,7 +28,7 @@ import {DeclarationRegistry} from 'vs/editor/contrib/goToDeclaration/common/goTo import {ExtraInfoRegistry} from 'vs/editor/contrib/hover/common/hover'; import {OccurrencesRegistry} from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; import {ReferenceRegistry} from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; -import {QuickFixRegistry} from 'vs/editor/contrib/quickFix/common/quickFix'; +import {IQuickFix2, QuickFixRegistry, getQuickFixes} from 'vs/editor/contrib/quickFix/common/quickFix'; import {IOutline} from 'vs/editor/contrib/quickOpen/common/quickOpen'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import {NavigateTypesSupportRegistry, INavigateTypesSupport, ITypeBearing} from 'vs/workbench/parts/search/common/search' @@ -47,8 +47,8 @@ import {SuggestRegistry} from 'vs/editor/contrib/suggest/common/suggest'; // vscode.executeSignatureHelpProvider // vscode.executeDocumentSymbolProvider // vscode.executeCompletionItemProvider - // vscode.executeCodeActionProvider + // vscode.executeCodeLensProvider // vscode.executeFormatDocumentProvider // vscode.executeFormatRangeProvider @@ -71,6 +71,7 @@ export class ExtHostLanguageFeatureCommands { this._register('vscode.executeSignatureHelpProvider', this._executeSignatureHelpProvider); this._register('vscode.executeDocumentSymbolProvider', this._executeDocumentSymbolProvider); this._register('vscode.executeCompletionItemProvider', this._executeCompletionItemProvider); + this._register('vscode.executeCodeActionProvider', this._executeCodeActionProvider); } private _register(id: string, callback: (...args: any[]) => any): void { @@ -201,4 +202,17 @@ export class ExtHostLanguageFeatureCommands { } }); } + + private _executeCodeActionProvider(resource: URI, range: types.Range): Thenable { + const args = { + resource, + range: typeConverters.fromRange(range) + }; + return this._commands.executeCommand('_executeCodeActionProvider', args).then(value => { + if (Array.isArray(value)) { + // TODO@joh this isn't proper! + return value.map(quickFix => ({ title: quickFix.label })); + } + }); + } } \ No newline at end of file diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts index e50bede365c..38083ec3ab4 100644 --- a/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts @@ -255,4 +255,25 @@ suite('ExtHostLanguageFeatureCommands', function() { }); }); }); + + // --- quickfix + + test('QuickFix, back and forth', function(done) { + disposables.push(extHost.registerCodeActionProvider(defaultSelector, { + provideCodeActions(): any { + return [{ command: 'testing', title: 'Title', arguments: [1, 2, true] }]; + } + })); + + threadService.sync().then(() => { + commands.executeCommand('vscode.executeCodeActionProvider', model.getAssociatedResource(), new types.Range(0, 0, 1, 1)).then(value => { + assert.equal(value.length, 1); + let [first] = value; + assert.equal(first.title, 'Title'); + // assert.equal(first.command, 'testing'); + // assert.deepEqual(first.arguments, [1, 2, true]); + done(); + }); + }); + }); }); \ No newline at end of file From 4dad67b8487e1c080b3666a7ccc1da996b2a5db4 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 1 Dec 2015 15:01:04 +0100 Subject: [PATCH 237/588] command: executeCodeLensProvider --- .../contrib/codelens/common/codelens.ts | 23 ++++++++++++++++--- .../common/extHostLanguageFeatureCommands.ts | 19 +++++++++++---- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/vs/editor/contrib/codelens/common/codelens.ts b/src/vs/editor/contrib/codelens/common/codelens.ts index cd2da755419..09dda5ea9c4 100644 --- a/src/vs/editor/contrib/codelens/common/codelens.ts +++ b/src/vs/editor/contrib/codelens/common/codelens.ts @@ -5,13 +5,15 @@ 'use strict'; -import {onUnexpectedError} from 'vs/base/common/errors'; +import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; import URI from 'vs/base/common/uri'; import {IAction, Action} from 'vs/base/common/actions'; +import {IModelService} from 'vs/editor/common/services/modelService'; import {TPromise} from 'vs/base/common/winjs.base'; import {IModel, IRange, IPosition} from 'vs/editor/common/editorCommon'; import {Range} from 'vs/editor/common/core/range'; import {ICodeLensSupport, ICodeLensSymbol, ICommand} from 'vs/editor/common/modes'; +import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; export const CodeLensRegistry = new LanguageFeatureRegistry('codeLensSupport'); @@ -21,7 +23,7 @@ export interface ICodeLensData { support: ICodeLensSupport; } -export function getCodeLensData(model: IModel) { +export function getCodeLensData(model: IModel):TPromise { const symbols: ICodeLensData[] = []; const promises = CodeLensRegistry.all(model).map(support => { @@ -38,4 +40,19 @@ export function getCodeLensData(model: IModel) { }); return TPromise.join(promises).then(() => symbols); -} \ No newline at end of file +} + +CommonEditorRegistry.registerLanguageCommand('_executeCodeLensProvider', function(accessor, args) { + + const {resource} = args; + if (!URI.isURI(resource)) { + throw illegalArgument(); + } + + const model = accessor.get(IModelService).getModel(resource); + if (!model) { + throw illegalArgument(); + } + + return getCodeLensData(model); +}); \ No newline at end of file diff --git a/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts index b0c82ee65c3..68452f1d16c 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts @@ -34,9 +34,8 @@ import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegis import {NavigateTypesSupportRegistry, INavigateTypesSupport, ITypeBearing} from 'vs/workbench/parts/search/common/search' import {RenameRegistry} from 'vs/editor/contrib/rename/common/rename'; import {FormatRegistry, FormatOnTypeRegistry} from 'vs/editor/contrib/format/common/format'; -import {CodeLensRegistry} from 'vs/editor/contrib/codelens/common/codelens'; -import {ParameterHintsRegistry} from 'vs/editor/contrib/parameterHints/common/parameterHints'; -import {SuggestRegistry} from 'vs/editor/contrib/suggest/common/suggest'; +import {ICodeLensData} from 'vs/editor/contrib/codelens/common/codelens'; + // vscode.executeWorkspaceSymbolProvider // vscode.executeDefinitionProvider @@ -48,8 +47,8 @@ import {SuggestRegistry} from 'vs/editor/contrib/suggest/common/suggest'; // vscode.executeDocumentSymbolProvider // vscode.executeCompletionItemProvider // vscode.executeCodeActionProvider - // vscode.executeCodeLensProvider + // vscode.executeFormatDocumentProvider // vscode.executeFormatRangeProvider // vscode.executeFormatOnTypeProvider @@ -72,6 +71,7 @@ export class ExtHostLanguageFeatureCommands { this._register('vscode.executeDocumentSymbolProvider', this._executeDocumentSymbolProvider); this._register('vscode.executeCompletionItemProvider', this._executeCompletionItemProvider); this._register('vscode.executeCodeActionProvider', this._executeCodeActionProvider); + this._register('vscode.executeCodeLensProvider', this._executeCodeLensProvider); } private _register(id: string, callback: (...args: any[]) => any): void { @@ -215,4 +215,15 @@ export class ExtHostLanguageFeatureCommands { } }); } + + private _executeCodeLensProvider(resource: URI): Thenable{ + const args = { + resource + }; + return this._commands._executeContributedCommand('_executeCodeLensProvider', args).then(value => { + if (Array.isArray(value)) { + return value.map(item => new types.CodeLens(typeConverters.toRange(item.symbol.range))); + } + }); + } } \ No newline at end of file From 374cfd1507e9808f30408f3d84667a15c3cc57b5 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 1 Dec 2015 15:26:04 +0100 Subject: [PATCH 238/588] set ELECTRON_DEFAULT_ERROR_MODE when running code.bat and crash reporter is not enabled --- scripts/code.bat | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/code.bat b/scripts/code.bat index 16ef475d615..9f8ce705cdb 100644 --- a/scripts/code.bat +++ b/scripts/code.bat @@ -15,6 +15,7 @@ if not exist out node .\node_modules\gulp\bin\gulp.js compile :: Configuration set NODE_ENV=development set VSCODE_DEV=1 +set ELECTRON_DEFAULT_ERROR_MODE=1 set ELECTRON_ENABLE_LOGGING=1 set ELECTRON_ENABLE_STACK_DUMPING=1 From 674694e6bc09e8211a85eaeddbfa7f0f27335dd5 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 1 Dec 2015 15:32:05 +0100 Subject: [PATCH 239/588] debug: expose attach to IRawDebugSession. --- src/vs/workbench/parts/debug/common/debug.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index 65927a6c39e..c62d75573c2 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -189,6 +189,7 @@ export interface IRawAdapter extends IRawEnvAdapter { export interface IRawDebugSession extends ee.EventEmitter { getType(): string; disconnect(restart?: boolean): TPromise; + attach(args: DebugProtocol.AttachRequestArguments): TPromise; next(args: DebugProtocol.NextArguments): TPromise; stepIn(args: DebugProtocol.StepInArguments): TPromise; From b8b38173bf95e247543849b76477558fdca58f91 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 1 Dec 2015 15:35:41 +0100 Subject: [PATCH 240/588] update windows-mutex --- npm-shrinkwrap.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index d9d2f180afd..0600ba12de1 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -462,8 +462,8 @@ } }, "windows-mutex": { - "version": "0.1.3", - "from": "windows-mutex@0.1.3", + "version": "0.2.0", + "from": "windows-mutex@0.2.0", "dependencies": { "bindings": { "version": "1.2.1", diff --git a/package.json b/package.json index ce64bea165c..796a603ef81 100644 --- a/package.json +++ b/package.json @@ -91,6 +91,6 @@ } }, "optionalDependencies": { - "windows-mutex": "^0.1.3" + "windows-mutex": "^0.2.0" } } From f463f8e5ff8536a8398f46af332d02dc15bf64f6 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 1 Dec 2015 15:41:04 +0100 Subject: [PATCH 241/588] disable save dialog extension filtering for now as there are issues --- .../workbench/browser/parts/editor/untitledEditorInput.ts | 2 +- .../parts/files/electron-browser/textFileServices.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/untitledEditorInput.ts b/src/vs/workbench/browser/parts/editor/untitledEditorInput.ts index 5b48fcb56b1..f261afcadcb 100644 --- a/src/vs/workbench/browser/parts/editor/untitledEditorInput.ts +++ b/src/vs/workbench/browser/parts/editor/untitledEditorInput.ts @@ -77,7 +77,7 @@ export class UntitledEditorInput extends EditorInput implements IResourceEditorI public suggestFileName(): string { if (!this.hasAssociatedFilePath) { let mime = this.getMime(); - if (mime) { + if (mime && mime !== MIME_TEXT /* do not suggest when the mime type is simple plain text */) { return suggestFilename(mime, this.getName()); } } diff --git a/src/vs/workbench/parts/files/electron-browser/textFileServices.ts b/src/vs/workbench/parts/files/electron-browser/textFileServices.ts index 3ef9539b29a..034e83c608a 100644 --- a/src/vs/workbench/parts/files/electron-browser/textFileServices.ts +++ b/src/vs/workbench/parts/files/electron-browser/textFileServices.ts @@ -371,8 +371,12 @@ export class TextFileService extends BrowserTextFileService { defaultPath: defaultPath }; - // Filters are only working well on Windows it seems - if (!isWindows) { + // Filters are working flaky in Electron and there are bugs. On Windows they are working + // somewhat but we see issues: + // - https://github.com/atom/electron/issues/3556 + // - https://github.com/Microsoft/vscode/issues/451 + // Until these issues are resolved, we disable the dialog file extension filtering. + if (true) { return options; } From 73183ff3c525787d376bb870314480d1a8e4180e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 1 Dec 2015 15:42:04 +0100 Subject: [PATCH 242/588] update more comments around save dialog --- .../parts/files/electron-browser/textFileServices.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/parts/files/electron-browser/textFileServices.ts b/src/vs/workbench/parts/files/electron-browser/textFileServices.ts index 034e83c608a..c4cc9cfae46 100644 --- a/src/vs/workbench/parts/files/electron-browser/textFileServices.ts +++ b/src/vs/workbench/parts/files/electron-browser/textFileServices.ts @@ -348,22 +348,13 @@ export class TextFileService extends BrowserTextFileService { private promptForPathAsync(defaultPath?: string): TPromise { return new TPromise((c, e) => { Dialog.showSaveDialog(remote.getCurrentWindow(), this.getSaveDialogOptions(defaultPath ? paths.normalize(defaultPath, true) : void 0), (path) => { - if (path && isWindows) { - path = strings.rtrim(path, '.*'); // Bug on Windows: When "All Files" is picked, the path gets an extra ".*" - } - c(path); }); }); } private promptForPathSync(defaultPath?: string): string { - let path = Dialog.showSaveDialog(remote.getCurrentWindow(), this.getSaveDialogOptions(defaultPath ? paths.normalize(defaultPath, true) : void 0)); - if (path && isWindows) { - path = strings.rtrim(path, '.*'); // Bug on Windows: When "All Files" is picked, the path gets an extra ".*" - } - - return path; + return Dialog.showSaveDialog(remote.getCurrentWindow(), this.getSaveDialogOptions(defaultPath ? paths.normalize(defaultPath, true) : void 0)); } private getSaveDialogOptions(defaultPath?: string): remote.ISaveDialogOptions { @@ -375,6 +366,7 @@ export class TextFileService extends BrowserTextFileService { // somewhat but we see issues: // - https://github.com/atom/electron/issues/3556 // - https://github.com/Microsoft/vscode/issues/451 + // - Bug on Windows: When "All Files" is picked, the path gets an extra ".*" // Until these issues are resolved, we disable the dialog file extension filtering. if (true) { return options; From a7f719e46ca2258616e7d7cace8f81580df7cc72 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 1 Dec 2015 15:01:04 +0100 Subject: [PATCH 243/588] command: executeCodeLensProvider --- src/vs/editor/common/modes.ts | 5 ++-- .../contrib/codelens/browser/codelens.ts | 22 ++++++++-------- .../common/extHostLanguageFeatureCommands.ts | 8 ++++-- .../api/common/extHostLanguageFeatures.ts | 17 ++++++------- .../api/common/pluginHostTypeConverters.ts | 25 ++++++++++++++++++- .../extHostLanguageFeatureCommands.test.ts | 22 ++++++++++++++++ .../api/extHostLanguageFeatures.test.ts | 12 ++++----- 7 files changed, 78 insertions(+), 33 deletions(-) diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 2f52a0d07f0..e5a4a8295d2 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -808,8 +808,7 @@ export interface ICommand { export interface ICodeLensSymbol { range: EditorCommon.IRange; id?: string; - kind?: string; - name?: string; + command?: ICommand; } /** @@ -817,7 +816,7 @@ export interface ICodeLensSymbol { */ export interface ICodeLensSupport { findCodeLensSymbols(resource: URI): TPromise; - resolveCodeLensSymbol(resource: URI, symbol: ICodeLensSymbol): TPromise; + resolveCodeLensSymbol(resource: URI, symbol: ICodeLensSymbol): TPromise; } export interface ITaskSummary { diff --git a/src/vs/editor/contrib/codelens/browser/codelens.ts b/src/vs/editor/contrib/codelens/browser/codelens.ts index a4497c8de36..711c5883254 100644 --- a/src/vs/editor/contrib/codelens/browser/codelens.ts +++ b/src/vs/editor/contrib/codelens/browser/codelens.ts @@ -103,16 +103,16 @@ class CodeLensContentWidget implements EditorBrowser.IContentWidget { } } - public withCommands(commands: Modes.ICommand[]): void { + public withCommands(symbols: Modes.ICodeLensSymbol[]): void { this._commands = Object.create(null); - if (!commands || !commands.length) { + if (!symbols || !symbols.length) { this._domNode.innerHTML = 'no commands'; return; } let html: string[] = []; - for (let i = 0; i < commands.length; i++) { - let command = commands[i]; + for (let i = 0; i < symbols.length; i++) { + let command = symbols[i].command; let part: string; if (command.id) { part = format('{1}', i, command.title); @@ -303,8 +303,8 @@ class CodeLens { return this._data; } - public updateCommands(commands: Modes.ICommand[], currentModelsVersionId: number): void { - this._contentWidget.withCommands(commands); + public updateCommands(symbols: Modes.ICodeLensSymbol[], currentModelsVersionId: number): void { + this._contentWidget.withCommands(symbols); this._lastUpdateModelsVersionId = currentModelsVersionId; } @@ -616,17 +616,15 @@ export class CodeLensContribution implements EditorCommon.IEditorContribution { var resource = model.getAssociatedResource(); var promises = toResolve.map((request, i) => { - let commands = new Array(request.length); + let resolvedSymbols = new Array(request.length); let promises = request.map((request, i) => { - return request.support.resolveCodeLensSymbol(resource, request.symbol).then(command => { - if (command) { - commands[i] = command; - } + return request.support.resolveCodeLensSymbol(resource, request.symbol).then(symbol => { + resolvedSymbols[i] = symbol; }); }); return TPromise.join(promises).then(() => { - lenses[i].updateCommands(commands, currentModelsVersionId); + lenses[i].updateCommands(resolvedSymbols, currentModelsVersionId); }) }); diff --git a/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts index 68452f1d16c..473b820863b 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts @@ -220,9 +220,13 @@ export class ExtHostLanguageFeatureCommands { const args = { resource }; - return this._commands._executeContributedCommand('_executeCodeLensProvider', args).then(value => { + + return this._commands.executeCommand('_executeCodeLensProvider', args).then(value => { if (Array.isArray(value)) { - return value.map(item => new types.CodeLens(typeConverters.toRange(item.symbol.range))); + return value.map(item => { + return new types.CodeLens(typeConverters.toRange(item.symbol.range), + typeConverters.Command.to(item.symbol.command)); + }); } }); } diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 9c81d46167a..1cfa90ea104 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -106,13 +106,14 @@ class CodeLensAdapter implements modes.ICodeLensSupport { return value.map((lens, i) => { return { id: String(i), - range: TypeConverters.fromRange(lens.range) + range: TypeConverters.fromRange(lens.range), + command: TypeConverters.Command.from(lens.command) } }); }); } - resolveCodeLensSymbol(resource: URI, symbol: modes.ICodeLensSymbol): TPromise { + resolveCodeLensSymbol(resource: URI, symbol: modes.ICodeLensSymbol): TPromise { let lenses = this._cache[resource.toString()]; if (!lenses) { @@ -140,11 +141,9 @@ class CodeLensAdapter implements modes.ICodeLensSupport { command: 'missing', } } - return { - id: command.command, - title: command.title, - arguments: command.arguments - } + + symbol.command = TypeConverters.Command.from(command); + return symbol; }); } } @@ -687,7 +686,7 @@ export class ExtHostLanguageFeatures { return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.findCodeLensSymbols(resource)); } - $resolveCodeLensSymbol(handle:number, resource: URI, symbol: modes.ICodeLensSymbol): TPromise { + $resolveCodeLensSymbol(handle:number, resource: URI, symbol: modes.ICodeLensSymbol): TPromise { return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.resolveCodeLensSymbol(resource, symbol)); } @@ -891,7 +890,7 @@ export class MainThreadLanguageFeatures { findCodeLensSymbols: (resource: URI): TPromise => { return this._proxy.$findCodeLensSymbols(handle, resource); }, - resolveCodeLensSymbol: (resource: URI, symbol: modes.ICodeLensSymbol): TPromise => { + resolveCodeLensSymbol: (resource: URI, symbol: modes.ICodeLensSymbol): TPromise => { return this._proxy.$resolveCodeLensSymbol(handle, resource, symbol); } }); diff --git a/src/vs/workbench/api/common/pluginHostTypeConverters.ts b/src/vs/workbench/api/common/pluginHostTypeConverters.ts index b29f889b853..92c7dccbaab 100644 --- a/src/vs/workbench/api/common/pluginHostTypeConverters.ts +++ b/src/vs/workbench/api/common/pluginHostTypeConverters.ts @@ -11,7 +11,8 @@ import * as types from './pluginHostTypes'; import {Position as EditorPosition} from 'vs/platform/editor/common/editor'; import {IPosition, ISelection, IRange, IRangeWithMessage, ISingleEditOperation} from 'vs/editor/common/editorCommon'; import {IHTMLContentElement} from 'vs/base/common/htmlContent'; -import {ITypeBearing} from 'vs/workbench/parts/search/common/search' +import {ITypeBearing} from 'vs/workbench/parts/search/common/search'; +import * as vscode from 'vscode'; export interface PositionLike { line: number; @@ -407,4 +408,26 @@ export namespace SignatureHelp { return result; } +} + +export const Command = { + from(command: vscode.Command): modes.ICommand { + if (command) { + return { + id: command.command, + title: command.title, + arguments: command.arguments + }; + } + }, + + to(command: modes.ICommand): vscode.Command { + if (command) { + return { + command: command.id, + title: command.title, + arguments: command.arguments + }; + } + } } \ No newline at end of file diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts index 38083ec3ab4..4e95502558d 100644 --- a/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts @@ -276,4 +276,26 @@ suite('ExtHostLanguageFeatureCommands', function() { }); }); }); + + // --- code lens + + test('CodeLens, back and forth', function(done) { + disposables.push(extHost.registerCodeLensProvider(defaultSelector, { + provideCodeLenses(): any { + return [new types.CodeLens(new types.Range(0, 0, 1, 1), { title: 'Title', command: 'cmd', arguments: [1, 2, true] })]; + } + })); + + threadService.sync().then(() => { + commands.executeCommand('vscode.executeCodeLensProvider', model.getAssociatedResource()).then(value => { + assert.equal(value.length, 1); + let [first] = value; + + assert.equal(first.command.title, 'Title'); + assert.equal(first.command.command, 'cmd'); + assert.deepEqual(first.command.arguments, [1, 2, true]); + done(); + }); + }); + }); }); \ No newline at end of file diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts index 048e37d4853..5a9710e0e96 100644 --- a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts @@ -205,9 +205,9 @@ suite('ExtHostLanguageFeatures', function() { assert.equal(value.length, 1); let data = value[0]; - data.support.resolveCodeLensSymbol(model.getAssociatedResource(), data.symbol).then(command => { - assert.equal(command.id, 'id'); - assert.equal(command.title, 'Title'); + data.support.resolveCodeLensSymbol(model.getAssociatedResource(), data.symbol).then(symbol => { + assert.equal(symbol.command.id, 'id'); + assert.equal(symbol.command.title, 'Title'); done(); }); }); @@ -228,10 +228,10 @@ suite('ExtHostLanguageFeatures', function() { assert.equal(value.length, 1); let data = value[0]; - data.support.resolveCodeLensSymbol(model.getAssociatedResource(), data.symbol).then(command => { + data.support.resolveCodeLensSymbol(model.getAssociatedResource(), data.symbol).then(symbol => { - assert.equal(command.id, 'missing'); - assert.equal(command.title, '<>'); + assert.equal(symbol.command.id, 'missing'); + assert.equal(symbol.command.title, '<>'); done(); }); }); From e08e52dc54ea151448ca39dafd532e6552b2935b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 1 Dec 2015 16:06:05 +0100 Subject: [PATCH 244/588] Add a command line flag to disable loading of extensions (users, dev) --- src/vs/platform/workspace/common/workspace.ts | 1 + src/vs/workbench/electron-main/env.ts | 4 +++- src/vs/workbench/node/pluginHostMain.ts | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/workspace/common/workspace.ts b/src/vs/platform/workspace/common/workspace.ts index 540ef30e9eb..96ca0786824 100644 --- a/src/vs/platform/workspace/common/workspace.ts +++ b/src/vs/platform/workspace/common/workspace.ts @@ -120,6 +120,7 @@ export interface IEnvironment { debugPluginHostPort: number; debugBrkPluginHost: boolean; + disablePlugins: boolean; logPluginHostCommunication: boolean; verboseLogging: boolean; diff --git a/src/vs/workbench/electron-main/env.ts b/src/vs/workbench/electron-main/env.ts index a84deb92cf3..76096440054 100644 --- a/src/vs/workbench/electron-main/env.ts +++ b/src/vs/workbench/electron-main/env.ts @@ -124,6 +124,7 @@ export interface ICommandLineArguments { debugPluginHostPort: number; debugBrkPluginHost: boolean; logPluginHostCommunication: boolean; + disablePlugins: boolean; pluginHomePath: string; pluginDevelopmentPath: string; @@ -202,7 +203,8 @@ function parseCli(): ICommandLineArguments { gotoLineMode: gotoLineMode, pluginHomePath: normalizePath(parseString(args, '--extensionHomePath')), pluginDevelopmentPath: normalizePath(parseString(args, '--extensionDevelopmentPath')), - pluginTestsPath: normalizePath(parseString(args, '--extensionTestsPath')) + pluginTestsPath: normalizePath(parseString(args, '--extensionTestsPath')), + disablePlugins: !!opts['disableExtensions'] || !!opts['disable-extensions'] }; } diff --git a/src/vs/workbench/node/pluginHostMain.ts b/src/vs/workbench/node/pluginHostMain.ts index 5e7125e8e02..76a74bb1a42 100644 --- a/src/vs/workbench/node/pluginHostMain.ts +++ b/src/vs/workbench/node/pluginHostMain.ts @@ -118,7 +118,7 @@ export class PluginHostMain { let collector = new PluginsMessageCollector(); let env = this.contextService.getConfiguration().env; - return PluginHostMain.scanPlugins(collector, BUILTIN_PLUGINS_PATH, env.userPluginsHome, env.pluginDevelopmentPath, env.version) + return PluginHostMain.scanPlugins(collector, BUILTIN_PLUGINS_PATH, !env.disablePlugins ? env.userPluginsHome : void 0, !env.disablePlugins ? env.pluginDevelopmentPath : void 0, env.version) .then(null, err => { collector.error('', err); return []; From 6c32610551b589e2a45b1b3a4578bad0591f67b8 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 1 Dec 2015 16:19:25 +0100 Subject: [PATCH 245/588] mixing extra suggestion support fixes #741 --- src/vs/editor/contrib/suggest/browser/suggestModel.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/suggest/browser/suggestModel.ts b/src/vs/editor/contrib/suggest/browser/suggestModel.ts index 0afd9d9ee49..a39244091db 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestModel.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestModel.ts @@ -6,6 +6,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import {sequence} from 'vs/base/common/async'; +import { assign } from 'vs/base/common/objects'; import { EventEmitter, ListenerUnbind } from 'vs/base/common/eventEmitter'; import {onUnexpectedError, isPromiseCanceledError} from 'vs/base/common/errors'; import strings = require('vs/base/common/strings'); @@ -53,7 +54,7 @@ export class CompletionItem { this._resolveDetails = TPromise.as(this); } else { this._resolveDetails = this.support.getSuggestionDetails(resource, position, this.suggestion).then(value => { - this.suggestion = value; + this.suggestion = assign(this.suggestion, value); return this; }, err => { if (isPromiseCanceledError(err)) { From 2767b596c1b197a8dbb855345412a2955b182305 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 1 Dec 2015 16:22:43 +0100 Subject: [PATCH 246/588] [js] TypeError: e.split is not a function #829 --- .../typescript/common/features/quickFix.ts | 11 ++-- .../test/common/features/quickfix.test.ts | 65 +++++++++++++++---- 2 files changed, 60 insertions(+), 16 deletions(-) diff --git a/src/vs/languages/typescript/common/features/quickFix.ts b/src/vs/languages/typescript/common/features/quickFix.ts index b27c13f8b17..8699d805925 100644 --- a/src/vs/languages/typescript/common/features/quickFix.ts +++ b/src/vs/languages/typescript/common/features/quickFix.ts @@ -168,7 +168,8 @@ var sinonDD = 'sinon/sinon.d.ts'; var jasmineDD = 'jasmine/jasmine.d.ts'; var handlebarsDD = 'handlebars/handlebars.d.ts'; -var typingsMap: { [key: string]: string | string[] } = { +// exported for tests +export var typingsMap: { [key: string]: string | string[] } = { 'angular': angularDD, '$': jqueryDD, 'jquery': jqueryDD, 'jQuery': jqueryDD, 'process': nodejsDD, '__dirname': nodejsDD, @@ -195,13 +196,13 @@ function computeAddTypeDefinitionProposals(languageService: ts.LanguageService, offset = converter.getOffset(sourceFile, { lineNumber: range.endLineNumber, column: range.endColumn }), token = ts.findTokenOnLeftOfPosition(sourceFile, offset); - if (!token || token.getWidth() === 0) { + if (!token || token.getWidth() === 0 || (network.schemas.inMemory === resource.scheme)) { return; } var currentWord = ts.getTextOfNode(token); - var mapping = typingsMap[currentWord]; - if (mapping && (network.schemas.inMemory !== resource.scheme)) { + if (typingsMap.hasOwnProperty(currentWord)) { + var mapping = typingsMap[currentWord]; var dtsRefs: string[] = Array.isArray(mapping) ? mapping : [ mapping ]; dtsRefs.forEach((dtsRef) => { result.push({ @@ -212,7 +213,7 @@ function computeAddTypeDefinitionProposals(languageService: ts.LanguageService, }); } - if (strings.endsWith(resource.fsPath, '.js')) { + if (strings.endsWith(resource.path, '.js')) { result.push({ label: nls.localize('typescript.quickfix.addAsGlobal', "Mark '{0}' as global", currentWord), id: JSON.stringify({ type: 'addglobal', name: currentWord }), diff --git a/src/vs/languages/typescript/test/common/features/quickfix.test.ts b/src/vs/languages/typescript/test/common/features/quickfix.test.ts index bc4d1598147..aef59bcd220 100644 --- a/src/vs/languages/typescript/test/common/features/quickfix.test.ts +++ b/src/vs/languages/typescript/test/common/features/quickfix.test.ts @@ -16,30 +16,73 @@ import Options = require('vs/languages/typescript/common/options'); suite('TS - quick fix', () => { - function assertQuickFix(code: string, callback: (outline: Modes.IQuickFix[]) => any): void { - var fileName = 'a.ts'; - var host = new utils.LanguageServiceHost().add(fileName, code); + function assertQuickFix(code: string, fileName: string, callback: (outline: Modes.IQuickFix[]) => any): void { + var filePath = 'file://test/' + fileName; + var fileURL = network.URL.parse(filePath); + var host = new utils.LanguageServiceHost().add(filePath, code); var service = ts.createLanguageService(host, ts.createDocumentRegistry()); - var markers = diagnostics.getSemanticDiagnostics(service, network.URL.fromValue(fileName), Options.typeScriptOptions).markers; + var markers = diagnostics.getSemanticDiagnostics(service, fileURL, Options.typeScriptOptions).markers; assert.equal(markers.length, 1); var marker = markers[0]; - var elements = quickfix.compute(service, network.URL.fromValue(fileName), marker); + var elements = quickfix.compute(service, fileURL, marker); - try { - callback(elements); - } catch(e) { - assert.ok(false, e); - } + callback(elements); } test('quickfix', function() { - assertQuickFix('class C { private hello = 0; private world = this.hell0; }', (elements) => { + assertQuickFix('class C { private hello = 0; private world = this.hell0; }', 'a.ts', (elements) => { assert.equal(elements.length, 1); assert.equal(elements[0].label, "Rename to 'hello'"); }); + assertQuickFix('_.foo();', 'a.ts', (elements) => { + assert.equal(elements.length, 2); + assert.equal(elements[0].label, "Download type definition underscore.d.ts"); + assert.equal(elements[1].label, "Download type definition lodash.d.ts"); + }); + + assertQuickFix('describe("x");', 'a.js', (elements) => { + assert.equal(elements.length, 3); + assert.equal(elements[0].label, "Download type definition mocha.d.ts"); + assert.equal(elements[1].label, "Download type definition jasmine.d.ts"); + assert.equal(elements[2].label, "Mark 'describe' as global"); + }); + + assertQuickFix('angular.foo = 1;', 'a.ts', (elements) => { + assert.equal(elements.length, 1); + assert.equal(elements[0].label, "Download type definition angular.d.ts"); + }); + + assertQuickFix('var x = __dirname;', 'a.ts', (elements) => { + assert.equal(elements.length, 1); + assert.equal(elements[0].label, "Download type definition node.d.ts"); + }); + + assertQuickFix('ko.observable(null);', 'a.ts', (elements) => { + assert.equal(elements.length, 1); + assert.equal(elements[0].label, "Download type definition knockout.d.ts"); + }); + + for (var id in quickfix.typingsMap) { + assertQuickFix(id + '.foo();', 'a.ts', (elements) => { + var value = quickfix.typingsMap[id]; + var length = Array.isArray(value) ? value.length : 1; + assert.equal(elements.length, length); + }); + } + + assertQuickFix('foo.observable(null);', 'a.js', (elements) => { + assert.equal(elements.length, 1); + assert.equal(elements[0].label, "Mark 'foo' as global"); + }); + + assertQuickFix('toString();', 'a.js', (elements) => { + assert.equal(elements.length, 1); + assert.equal(elements[0].label, "Mark 'toString' as global"); + }); + }); }); \ No newline at end of file From 78e11f23b7ddfaa46e417a2a72ca1984b5cac0cc Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 1 Dec 2015 16:38:42 +0100 Subject: [PATCH 247/588] commands: executeFormatDocumentProvider, executeFormatRangeProvider --- src/vs/editor/contrib/format/common/format.ts | 61 +++++++++++++++++- .../contrib/format/common/formatActions.ts | 34 ++++------ .../common/extHostLanguageFeatureCommands.ts | 34 ++++++++-- .../api/extHostLanguageFeatures.test.ts | 63 +++++++++++++++++++ 4 files changed, 162 insertions(+), 30 deletions(-) diff --git a/src/vs/editor/contrib/format/common/format.ts b/src/vs/editor/contrib/format/common/format.ts index 99b89717af0..d0889262cfb 100644 --- a/src/vs/editor/contrib/format/common/format.ts +++ b/src/vs/editor/contrib/format/common/format.ts @@ -5,10 +5,67 @@ 'use strict'; -import {IFormattingSupport} from 'vs/editor/common/modes'; +import {IFormattingSupport, IFormattingOptions} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; +import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; +import URI from 'vs/base/common/uri'; +import {IAction, Action} from 'vs/base/common/actions'; +import {IModelService} from 'vs/editor/common/services/modelService'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {IModel, IRange, IPosition, ISingleEditOperation} from 'vs/editor/common/editorCommon'; +import {Range} from 'vs/editor/common/core/range'; +import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; export const FormatRegistry = new LanguageFeatureRegistry('formattingSupport'); export const FormatOnTypeRegistry = new LanguageFeatureRegistry('formattingSupport'); -export {IFormattingSupport}; \ No newline at end of file +export {IFormattingSupport}; + +export function formatRange(model: IModel, range: IRange, options: IFormattingOptions): TPromise { + const support = FormatRegistry.ordered(model)[0]; + if (!support) { + return; + } + return support.formatRange(model.getAssociatedResource(), range, options); +} + +export function formatDocument(model: IModel, options: IFormattingOptions): TPromise { + const support = FormatRegistry.ordered(model)[0]; + if (!support) { + return; + } + if (typeof support.formatDocument !== 'function') { + if (typeof support.formatRange === 'function') { + return formatRange(model, model.getFullModelRange(), options); + } else { + return; + } + } + + return support.formatDocument(model.getAssociatedResource(), options); +} + +CommonEditorRegistry.registerLanguageCommand('_executeFormatRangeProvider', function(accessor, args) { + const {resource, range, options} = args; + if (!URI.isURI(resource) || !Range.isIRange(range)) { + throw illegalArgument(); + } + const model = accessor.get(IModelService).getModel(resource); + if (!model) { + throw illegalArgument('resource'); + } + return formatRange(model, range, options); +}); + +CommonEditorRegistry.registerLanguageCommand('_executeFormatDocumentProvider', function(accessor, args) { + const {resource, options} = args; + if (!URI.isURI(resource)) { + throw illegalArgument('resource'); + } + const model = accessor.get(IModelService).getModel(resource); + if (!model) { + throw illegalArgument('resource'); + } + + return formatDocument(model, options) +}); \ No newline at end of file diff --git a/src/vs/editor/contrib/format/common/formatActions.ts b/src/vs/editor/contrib/format/common/formatActions.ts index 83ddd947b62..25e5c5fce8f 100644 --- a/src/vs/editor/contrib/format/common/formatActions.ts +++ b/src/vs/editor/contrib/format/common/formatActions.ts @@ -15,7 +15,7 @@ import formatCommand = require('./formatCommand'); import {Range} from 'vs/editor/common/core/range'; import {INullService} from 'vs/platform/instantiation/common/instantiation'; import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; -import {FormatOnTypeRegistry, FormatRegistry, IFormattingSupport} from '../common/format'; +import {FormatOnTypeRegistry, FormatRegistry, IFormattingSupport, formatRange, formatDocument} from '../common/format'; interface IFormatOnTypeResult { range: EditorCommon.IEditorRange; @@ -170,31 +170,19 @@ export class FormatAction extends EditorAction { public run(): TPromise { - var model = this.editor.getModel(), - formattingSupport = FormatRegistry.ordered(model)[0], - canFormatRange = typeof formattingSupport.formatRange === 'function', - canFormatDocument = typeof formattingSupport.formatDocument === 'function', - editorSelection = this.editor.getSelection(); + const model = this.editor.getModel(), + editorSelection = this.editor.getSelection(), + options = this.editor.getIndentationOptions(); - var options = this.editor.getIndentationOptions(), - formattingPromise: TPromise; + let formattingPromise: TPromise; - if(canFormatRange) { - // format a selection/range - var formatRange: EditorCommon.IEditorRange = editorSelection; - if(!formatRange.isEmpty()) { - // Fix the selection to include the entire line to improve formatting results - formatRange.startColumn = 1; - } else { - formatRange = model.getFullModelRange(); - } - formattingPromise = formattingSupport.formatRange(model.getAssociatedResource(), formatRange, options); - - } else if(canFormatDocument) { - // format the whole document - formattingPromise = formattingSupport.formatDocument(model.getAssociatedResource(), options); + if (editorSelection.isEmpty()) { + formattingPromise = formatDocument(model, options); } else { - // broken support? + formattingPromise = formatRange(model, editorSelection, options); + } + + if (!formattingPromise) { return TPromise.as(false); } diff --git a/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts index 473b820863b..15cb18343b3 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts @@ -48,9 +48,9 @@ import {ICodeLensData} from 'vs/editor/contrib/codelens/common/codelens'; // vscode.executeCompletionItemProvider // vscode.executeCodeActionProvider // vscode.executeCodeLensProvider - // vscode.executeFormatDocumentProvider // vscode.executeFormatRangeProvider + // vscode.executeFormatOnTypeProvider export class ExtHostLanguageFeatureCommands { @@ -72,6 +72,8 @@ export class ExtHostLanguageFeatureCommands { this._register('vscode.executeCompletionItemProvider', this._executeCompletionItemProvider); this._register('vscode.executeCodeActionProvider', this._executeCodeActionProvider); this._register('vscode.executeCodeLensProvider', this._executeCodeLensProvider); + this._register('vscode.executeFormatDocumentProvider', this._executeFormatDocumentProvider); + this._register('vscode.executeFormatRangeProvider', this._executeFormatRangeProvider); } private _register(id: string, callback: (...args: any[]) => any): void { @@ -217,10 +219,7 @@ export class ExtHostLanguageFeatureCommands { } private _executeCodeLensProvider(resource: URI): Thenable{ - const args = { - resource - }; - + const args = { resource }; return this._commands.executeCommand('_executeCodeLensProvider', args).then(value => { if (Array.isArray(value)) { return value.map(item => { @@ -230,4 +229,29 @@ export class ExtHostLanguageFeatureCommands { } }); } + + private _executeFormatDocumentProvider(resource: URI, options: vscode.FormattingOptions): Thenable { + const args = { + resource, + options + }; + return this._commands.executeCommand('_executeFormatDocumentProvider', args).then(value => { + if (Array.isArray(value)) { + return value.map(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text)); + } + }); + } + + private _executeFormatRangeProvider(resource: URI, range: types.Range, options: vscode.FormattingOptions): Thenable { + const args = { + resource, + range: typeConverters.fromRange(range), + options + }; + return this._commands.executeCommand('_executeFormatRangeProvider', args).then(value => { + if (Array.isArray(value)) { + return value.map(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text)); + } + }); + } } \ No newline at end of file diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts index 5a9710e0e96..4af861e6a00 100644 --- a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts @@ -37,6 +37,7 @@ import {getNavigateToItems} from 'vs/workbench/parts/search/common/search'; import {rename} from 'vs/editor/contrib/rename/common/rename'; import {getParameterHints} from 'vs/editor/contrib/parameterHints/common/parameterHints'; import {suggest} from 'vs/editor/contrib/suggest/common/suggest'; +import {formatDocument, formatRange} from 'vs/editor/contrib/format/common/format'; const defaultSelector = { scheme: 'far' }; const model: EditorCommon.IModel = new EditorModel( @@ -907,4 +908,66 @@ suite('ExtHostLanguageFeatures', function() { }); }); }); + + // --- format + + test('Format Doc, data conversion', function(done) { + disposables.push(extHost.registerDocumentFormattingEditProvider(defaultSelector, { + provideDocumentFormattingEdits(): any { + return [new types.TextEdit(new types.Range(0, 0, 1, 1), 'testing')]; + } + })); + + threadService.sync().then(() => { + formatDocument(model, { insertSpaces: true, tabSize: 4 }).then(value => { + assert.equal(value.length, 1); + let [first] = value; + assert.equal(first.text, 'testing'); + assert.deepEqual(first.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 2, endColumn: 2 }); + done(); + }); + }); + }); + + test('Format Doc, evil provider', function(done) { + disposables.push(extHost.registerDocumentFormattingEditProvider(defaultSelector, { + provideDocumentFormattingEdits(): any { + throw new Error('evil'); + } + })); + + threadService.sync().then(() => { + formatDocument(model, { insertSpaces: true, tabSize: 4 }).then(undefined, err => done()); + }); + }); + + test('Format Range, data conversion', function(done) { + disposables.push(extHost.registerDocumentRangeFormattingEditProvider(defaultSelector, { + provideDocumentRangeFormattingEdits(): any { + return [new types.TextEdit(new types.Range(0, 0, 1, 1), 'testing')]; + } + })); + + threadService.sync().then(() => { + formatRange(model, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }, { insertSpaces: true, tabSize: 4 }).then(value => { + assert.equal(value.length, 1); + let [first] = value; + assert.equal(first.text, 'testing'); + assert.deepEqual(first.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 2, endColumn: 2 }); + done(); + }); + }); + }) + + test('Format Range, evil provider', function(done) { + disposables.push(extHost.registerDocumentRangeFormattingEditProvider(defaultSelector, { + provideDocumentRangeFormattingEdits(): any { + throw new Error('evil'); + } + })); + + threadService.sync().then(() => { + formatRange(model, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }, { insertSpaces: true, tabSize: 4 }).then(undefined, err => done()); + }); + }) }); \ No newline at end of file From fe88d384e63331a7acdaf7c212fa05c9ad7a71c6 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 1 Dec 2015 16:42:17 +0100 Subject: [PATCH 248/588] initial wip --- src/vs/workbench/electron-browser/index.html | 33 +++++++++++-------- .../workbench/electron-browser/integration.ts | 9 +++++ .../electron-browser/main.contribution.ts | 5 +++ src/vs/workbench/electron-browser/main.ts | 6 ++++ src/vs/workbench/electron-browser/shell.ts | 1 + 5 files changed, 40 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/electron-browser/index.html b/src/vs/workbench/electron-browser/index.html index f96953dd4e6..8090e635180 100644 --- a/src/vs/workbench/electron-browser/index.html +++ b/src/vs/workbench/electron-browser/index.html @@ -99,6 +99,8 @@