diff --git a/.vscode/launch.json b/.vscode/launch.json
index 73b99e84fbb..a117e3ed45d 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -147,7 +147,7 @@
},
"urlFilter": "*workbench.html*",
"runtimeArgs": [
- "--inspect=5875"
+ "--inspect=5875", "--no-cached-data"
],
"smartStep": true,
"skipFiles": [
@@ -155,6 +155,19 @@
],
"webRoot": "${workspaceFolder}"
},
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "Launch VS Code (Main Process)",
+ "runtimeExecutable": "${workspaceFolder}/scripts/code.sh",
+ "runtimeArgs": [
+ "--no-cached-data"
+ ],
+ "smartStep": true,
+ "outFiles": [
+ "${workspaceFolder}/out/**/*.js"
+ ]
+ },
{
"type": "node",
"request": "launch",
diff --git a/build/tfs/darwin/continuous-build-darwin.yml b/build/tfs/darwin/continuous-build-darwin.yml
index 28e2a6079ab..99e17e940a6 100644
--- a/build/tfs/darwin/continuous-build-darwin.yml
+++ b/build/tfs/darwin/continuous-build-darwin.yml
@@ -32,17 +32,6 @@ steps:
- script: |
./scripts/test-integration.sh --tfs "Integration Tests"
displayName: Run Integration Tests
-- script: |
- yarn smoketest --screenshots "$(Build.ArtifactStagingDirectory)/artifacts" --log "$(Build.ArtifactStagingDirectory)/artifacts/smoketest.log"
- displayName: Run Smoke Tests
- continueOnError: true
-- task: PublishBuildArtifacts@1
- displayName: Publish Smoketest Artifacts
- inputs:
- PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts'
- ArtifactName: build-artifacts-darwin
- publishLocation: Container
- condition: eq(variables['System.PullRequest.IsFork'], 'False')
- task: PublishTestResults@2
displayName: Publish Tests Results
inputs:
diff --git a/build/tfs/win32/continuous-build-win32.yml b/build/tfs/win32/continuous-build-win32.yml
index 0df397a0a6a..7145e67e2ad 100644
--- a/build/tfs/win32/continuous-build-win32.yml
+++ b/build/tfs/win32/continuous-build-win32.yml
@@ -36,17 +36,6 @@ steps:
- powershell: |
.\scripts\test-integration.bat --tfs "Integration Tests"
displayName: Run Integration Tests
-- powershell: |
- yarn smoketest --screenshots "$(Build.ArtifactStagingDirectory)\artifacts" --log "$(Build.ArtifactStagingDirectory)\artifacts\smoketest.log"
- displayName: Run Smoke Tests
- continueOnError: true
-- task: PublishBuildArtifacts@1
- displayName: Publish Smoketest Artifacts
- inputs:
- PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts'
- ArtifactName: build-artifacts-win32
- publishLocation: Container
- condition: eq(variables['System.PullRequest.IsFork'], 'False')
- task: PublishTestResults@2
displayName: Publish Tests Results
inputs:
diff --git a/extensions/css-language-features/package.json b/extensions/css-language-features/package.json
index c779f246284..069e7929d1a 100644
--- a/extensions/css-language-features/package.json
+++ b/extensions/css-language-features/package.json
@@ -143,7 +143,7 @@
"error"
],
"default": "warning",
- "description": "%css.lint.fontFaceProperties.desc%"
+ "markdownDescription": "%css.lint.fontFaceProperties.desc%"
},
"css.lint.hexColorLength": {
"type": "string",
@@ -220,7 +220,7 @@
"error"
],
"default": "ignore",
- "description": "%css.lint.important.desc%"
+ "markdownDescription": "%css.lint.important.desc%"
},
"css.lint.float": {
"type": "string",
@@ -679,7 +679,7 @@
"error"
],
"default": "ignore",
- "description": "%less.lint.important.desc%"
+ "markdownDescription": "%less.lint.important.desc%"
},
"less.lint.float": {
"type": "string",
diff --git a/extensions/css-language-features/package.nls.json b/extensions/css-language-features/package.nls.json
index f62c6fb669c..7c344718b8c 100644
--- a/extensions/css-language-features/package.nls.json
+++ b/extensions/css-language-features/package.nls.json
@@ -35,7 +35,7 @@
"less.lint.hexColorLength.desc": "Hex colors must consist of three or six hex numbers.",
"less.lint.idSelector.desc": "Selectors should not contain IDs because these rules are too tightly coupled with the HTML.",
"less.lint.ieHack.desc": "IE hacks are only necessary when supporting IE7 and older.",
- "less.lint.important.desc": "Avoid using !important. It is an indication that the specificity of the entire CSS has gotten out of control and needs to be refactored.",
+ "less.lint.important.desc": "Avoid using `!important`. It is an indication that the specificity of the entire CSS has gotten out of control and needs to be refactored.",
"less.lint.importStatement.desc": "Import statements do not load in parallel.",
"less.lint.propertyIgnoredDueToDisplay.desc": "Property is ignored due to the display. E.g. with `display: inline`, the `width`, `height`, `margin-top`, `margin-bottom`, and `float` properties have no effect.",
"less.lint.universalSelector.desc": "The universal selector (`*`) is known to be slow.",
@@ -56,7 +56,7 @@
"scss.lint.hexColorLength.desc": "Hex colors must consist of three or six hex numbers.",
"scss.lint.idSelector.desc": "Selectors should not contain IDs because these rules are too tightly coupled with the HTML.",
"scss.lint.ieHack.desc": "IE hacks are only necessary when supporting IE7 and older.",
- "scss.lint.important.desc": "Avoid using !important. It is an indication that the specificity of the entire CSS has gotten out of control and needs to be refactored.",
+ "scss.lint.important.desc": "Avoid using `!important`. It is an indication that the specificity of the entire CSS has gotten out of control and needs to be refactored.",
"scss.lint.importStatement.desc": "Import statements do not load in parallel.",
"scss.lint.propertyIgnoredDueToDisplay.desc": "Property is ignored due to the display. E.g. with `display: inline`, the `width`, `height`, `margin-top`, `margin-bottom`, and `float` properties have no effect.",
"scss.lint.universalSelector.desc": "The universal selector (`*`) is known to be slow.",
diff --git a/extensions/javascript/snippets/javascript.json b/extensions/javascript/snippets/javascript.json
index 5579e4e0c16..5da4ebe0c18 100644
--- a/extensions/javascript/snippets/javascript.json
+++ b/extensions/javascript/snippets/javascript.json
@@ -140,6 +140,15 @@
],
"description": "Set Timeout Function"
},
+ "Set Interval Function": {
+ "prefix": "setinterval",
+ "body": [
+ "setInterval(() => {",
+ "\t$0",
+ "}, ${1:interval});"
+ ],
+ "description": "Set Interval Function"
+ },
"Import external module.": {
"prefix": "import statement",
"body": [
diff --git a/extensions/markdown-language-features/src/markdownEngine.ts b/extensions/markdown-language-features/src/markdownEngine.ts
index 085b1a5e2eb..f381a0c0ae7 100644
--- a/extensions/markdown-language-features/src/markdownEngine.ts
+++ b/extensions/markdown-language-features/src/markdownEngine.ts
@@ -46,6 +46,9 @@ export class MarkdownEngine {
if (lang && lang.toLocaleLowerCase() === 'json5') {
lang = 'json';
}
+ if (lang && lang.toLocaleLowerCase() === 'c#') {
+ lang = 'cs';
+ }
if (lang && hljs.getLanguage(lang)) {
try {
return `
${hljs.highlight(lang, str, true).value}
`;
diff --git a/package.json b/package.json
index d362ad36c35..80f1b279dc7 100644
--- a/package.json
+++ b/package.json
@@ -49,10 +49,10 @@
"vscode-chokidar": "1.6.4",
"vscode-debugprotocol": "1.32.0",
"vscode-nsfw": "1.1.1",
- "vscode-ripgrep": "^1.2.2",
+ "vscode-ripgrep": "^1.2.4",
"vscode-sqlite3": "4.0.2",
"vscode-textmate": "^4.0.1",
- "vscode-xterm": "3.9.0-beta9",
+ "vscode-xterm": "3.9.0-beta11",
"winreg": "^1.2.4",
"yauzl": "^2.9.1",
"yazl": "^2.4.3"
diff --git a/scripts/code.bat b/scripts/code.bat
index 58d5ca2d6e0..6789e54fdda 100644
--- a/scripts/code.bat
+++ b/scripts/code.bat
@@ -17,7 +17,7 @@ set CODE=".build\electron\%NAMESHORT%"
node build\lib\electron.js
if %errorlevel% neq 0 node .\node_modules\gulp\bin\gulp.js electron
-:: Manage build-in extensions
+:: Manage built-in extensions
if "%1"=="--builtin" goto builtin
:: Sync built-in extensions
@@ -49,4 +49,4 @@ goto end
popd
-endlocal
\ No newline at end of file
+endlocal
diff --git a/src/main.js b/src/main.js
index 92375bc68c0..bc430b9c672 100644
--- a/src/main.js
+++ b/src/main.js
@@ -88,10 +88,7 @@ function onReady() {
const startup = nlsConfig => {
nlsConfig._languagePackSupport = true;
process.env['VSCODE_NLS_CONFIG'] = JSON.stringify(nlsConfig);
-
- if (cachedDataDir) {
- process.env['VSCODE_NODE_CACHED_DATA_DIR'] = cachedDataDir;
- }
+ process.env['VSCODE_NODE_CACHED_DATA_DIR'] = cachedDataDir || '';
// Load main in AMD
require('./bootstrap-amd').load('vs/code/electron-main/main');
diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json
index 766b4d9b2eb..1693a2a6a02 100644
--- a/src/tsconfig.strictNullChecks.json
+++ b/src/tsconfig.strictNullChecks.json
@@ -22,11 +22,18 @@
"./vs/base/browser/mouseEvent.ts",
"./vs/base/browser/touch.ts",
"./vs/base/browser/ui/aria/aria.ts",
+ "./vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts",
"./vs/base/browser/ui/button/button.ts",
+ "./vs/base/browser/ui/centered/centeredViewLayout.ts",
"./vs/base/browser/ui/contextview/contextview.ts",
"./vs/base/browser/ui/countBadge/countBadge.ts",
+ "./vs/base/browser/ui/grid/gridview.ts",
+ "./vs/base/browser/ui/highlightedlabel/highlightedLabel.ts",
+ "./vs/base/browser/ui/iconLabel/iconLabel.ts",
"./vs/base/browser/ui/keybindingLabel/keybindingLabel.ts",
"./vs/base/browser/ui/list/list.ts",
+ "./vs/base/browser/ui/list/rangeMap.ts",
+ "./vs/base/browser/ui/list/rowCache.ts",
"./vs/base/browser/ui/list/splice.ts",
"./vs/base/browser/ui/octiconLabel/octiconLabel.mock.ts",
"./vs/base/browser/ui/octiconLabel/octiconLabel.ts",
@@ -40,9 +47,13 @@
"./vs/base/browser/ui/scrollbar/scrollbarState.ts",
"./vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts",
"./vs/base/browser/ui/scrollbar/verticalScrollbar.ts",
+ "./vs/base/browser/ui/splitview/panelview.ts",
"./vs/base/browser/ui/splitview/splitview.ts",
"./vs/base/browser/ui/tree/tree.ts",
"./vs/base/browser/ui/widget.ts",
+ "./vs/base/common/json.ts",
+ "./vs/base/common/jsonEdit.ts",
+ "./vs/base/common/jsonFormatter.ts",
"./vs/base/node/console.ts",
"./vs/base/node/crypto.ts",
"./vs/base/node/decoder.ts",
@@ -62,6 +73,10 @@
"./vs/base/parts/ipc/node/ipc.ts",
"./vs/base/parts/ipc/test/node/testService.ts",
"./vs/base/parts/quickopen/common/quickOpen.ts",
+ "./vs/base/test/browser/ui/grid/util.ts",
+ "./vs/base/test/common/json.test.ts",
+ "./vs/base/test/common/jsonEdit.test.ts",
+ "./vs/base/test/common/jsonFormatter.test.ts",
"./vs/base/test/common/utils.ts",
"./vs/base/test/node/processes/fixtures/fork.ts",
"./vs/base/test/node/processes/fixtures/fork_large.ts",
@@ -238,6 +253,7 @@
"./vs/editor/contrib/codeAction/codeAction.ts",
"./vs/editor/contrib/codeAction/codeActionTrigger.ts",
"./vs/editor/contrib/colorPicker/color.ts",
+ "./vs/editor/contrib/colorPicker/colorDetector.ts",
"./vs/editor/contrib/colorPicker/colorPickerModel.ts",
"./vs/editor/contrib/comment/blockCommentCommand.ts",
"./vs/editor/contrib/comment/comment.ts",
@@ -393,7 +409,9 @@
"./vs/platform/quickOpen/common/quickOpen.ts",
"./vs/platform/quickinput/common/quickInput.ts",
"./vs/platform/registry/common/platform.ts",
+ "./vs/platform/request/electron-main/requestService.ts",
"./vs/platform/request/node/request.ts",
+ "./vs/platform/request/node/requestService.ts",
"./vs/platform/search/common/search.ts",
"./vs/platform/state/common/state.ts",
"./vs/platform/statusbar/common/statusbar.ts",
@@ -470,6 +488,7 @@
"./vs/workbench/parts/scm/electron-browser/scmUtil.ts",
"./vs/workbench/parts/search/common/constants.ts",
"./vs/workbench/parts/surveys/electron-browser/nps.contribution.ts",
+ "./vs/workbench/parts/tasks/common/problemMatcher.ts",
"./vs/workbench/parts/tasks/common/taskTemplates.ts",
"./vs/workbench/parts/terminal/browser/terminalWidgetManager.ts",
"./vs/workbench/parts/terminal/common/terminal.ts",
diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts
index 3ad8440553d..38bb0c0d511 100644
--- a/src/vs/base/browser/dom.ts
+++ b/src/vs/base/browser/dom.ts
@@ -560,7 +560,7 @@ export class Dimension {
this.height = height;
}
- static equals(a: Dimension, b: Dimension): boolean {
+ static equals(a: Dimension | undefined, b: Dimension | undefined): boolean {
if (a === b) {
return true;
}
diff --git a/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts b/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts
index 4a2b7396a9e..42f43d27322 100644
--- a/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts
+++ b/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts
@@ -118,8 +118,8 @@ export class BreadcrumbsWidget {
this._freeNodes.length = 0;
}
- layout(dim: dom.Dimension): void {
- if (dom.Dimension.equals(dim, this._dimension)) {
+ layout(dim: dom.Dimension | undefined): void {
+ if (dim && dom.Dimension.equals(dim, this._dimension)) {
return;
}
if (this._pendingLayout) {
@@ -146,9 +146,11 @@ export class BreadcrumbsWidget {
private _updateScrollbar(): IDisposable {
return dom.measure(() => {
- this._scrollable.setRevealOnScroll(false);
- this._scrollable.scanDomNode();
- this._scrollable.setRevealOnScroll(true);
+ dom.measure(() => { // double RAF
+ this._scrollable.setRevealOnScroll(false);
+ this._scrollable.scanDomNode();
+ this._scrollable.setRevealOnScroll(true);
+ });
});
}
@@ -277,8 +279,8 @@ export class BreadcrumbsWidget {
}
setItems(items: BreadcrumbsItem[]): void {
- let prefix: number;
- let removed: BreadcrumbsItem[];
+ let prefix: number | undefined;
+ let removed: BreadcrumbsItem[] = [];
try {
prefix = commonPrefixLength(this._items, items, (a, b) => a.equals(b));
removed = this._items.splice(prefix, this._items.length - prefix, ...items.slice(prefix));
@@ -302,17 +304,21 @@ export class BreadcrumbsWidget {
// case a: more nodes -> remove them
while (start < this._nodes.length) {
const free = this._nodes.pop();
- this._freeNodes.push(free);
- free.remove();
+ if (free) {
+ this._freeNodes.push(free);
+ free.remove();
+ }
}
// case b: more items -> render them
for (; start < this._items.length; start++) {
let item = this._items[start];
let node = this._freeNodes.length > 0 ? this._freeNodes.pop() : document.createElement('div');
- this._renderItem(item, node);
- this._domNode.appendChild(node);
- this._nodes.push(node);
+ if (node) {
+ this._renderItem(item, node);
+ this._domNode.appendChild(node);
+ this._nodes.push(node);
+ }
}
this.layout(undefined);
}
@@ -327,7 +333,7 @@ export class BreadcrumbsWidget {
}
private _onClick(event: IMouseEvent): void {
- for (let el = event.target; el; el = el.parentElement) {
+ for (let el: HTMLElement | null = event.target; el; el = el.parentElement) {
let idx = this._nodes.indexOf(el as any);
if (idx >= 0) {
this._focus(idx, event);
diff --git a/src/vs/base/browser/ui/centered/centeredViewLayout.ts b/src/vs/base/browser/ui/centered/centeredViewLayout.ts
index 03b876df89b..0da0a7f3b11 100644
--- a/src/vs/base/browser/ui/centered/centeredViewLayout.ts
+++ b/src/vs/base/browser/ui/centered/centeredViewLayout.ts
@@ -50,12 +50,12 @@ export interface ICenteredViewStyles extends ISplitViewStyles {
export class CenteredViewLayout {
- private splitView: SplitView;
+ private splitView?: SplitView;
private width: number = 0;
private height: number = 0;
private style: ICenteredViewStyles;
private didLayout = false;
- private emptyViews: ISplitViewView[];
+ private emptyViews: ISplitViewView[] | undefined;
private splitViewDisposables: IDisposable[] = [];
constructor(private container: HTMLElement, private view: IView, public readonly state: CenteredViewState = GOLDEN_RATIO) {
@@ -84,6 +84,9 @@ export class CenteredViewLayout {
}
private resizeMargins(): void {
+ if (!this.splitView) {
+ return;
+ }
this.splitView.resizeView(0, this.state.leftMarginRatio * this.width);
this.splitView.resizeView(2, this.state.rightMarginRatio * this.width);
}
@@ -94,7 +97,7 @@ export class CenteredViewLayout {
styles(style: ICenteredViewStyles): void {
this.style = style;
- if (this.splitView) {
+ if (this.splitView && this.emptyViews) {
this.splitView.style(this.style);
this.emptyViews[0].element.style.backgroundColor = this.style.background.toString();
this.emptyViews[1].element.style.backgroundColor = this.style.background.toString();
@@ -115,8 +118,10 @@ export class CenteredViewLayout {
});
this.splitViewDisposables.push(this.splitView.onDidSashChange(() => {
- this.state.leftMarginRatio = this.splitView.getViewSize(0) / this.width;
- this.state.rightMarginRatio = this.splitView.getViewSize(2) / this.width;
+ if (this.splitView) {
+ this.state.leftMarginRatio = this.splitView.getViewSize(0) / this.width;
+ this.state.rightMarginRatio = this.splitView.getViewSize(2) / this.width;
+ }
}));
this.splitViewDisposables.push(this.splitView.onDidSashReset(() => {
this.state.leftMarginRatio = GOLDEN_RATIO.leftMarginRatio;
@@ -130,9 +135,13 @@ export class CenteredViewLayout {
this.splitView.addView(this.emptyViews[0], this.state.leftMarginRatio * this.width, 0);
this.splitView.addView(this.emptyViews[1], this.state.rightMarginRatio * this.width, 2);
} else {
- this.container.removeChild(this.splitView.el);
+ if (this.splitView) {
+ this.container.removeChild(this.splitView.el);
+ }
this.splitViewDisposables = dispose(this.splitViewDisposables);
- this.splitView.dispose();
+ if (this.splitView) {
+ this.splitView.dispose();
+ }
this.splitView = undefined;
this.emptyViews = undefined;
this.container.appendChild(this.view.element);
diff --git a/src/vs/base/browser/ui/grid/gridview.ts b/src/vs/base/browser/ui/grid/gridview.ts
index 531575bb123..2892dde50a9 100644
--- a/src/vs/base/browser/ui/grid/gridview.ts
+++ b/src/vs/base/browser/ui/grid/gridview.ts
@@ -560,7 +560,7 @@ export class GridView implements IDisposable {
get maximumWidth(): number { return this.root.maximumHeight; }
get maximumHeight(): number { return this.root.maximumHeight; }
- private _onDidChange = new Relay<{ width: number; height: number; }>();
+ private _onDidChange = new Relay<{ width: number; height: number; } | undefined>();
readonly onDidChange = this._onDidChange.event;
constructor(options: IGridViewOptions = {}) {
diff --git a/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts b/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts
index 58e154c751e..c6f06f0f9c0 100644
--- a/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts
+++ b/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts
@@ -90,8 +90,8 @@ export class HighlightedLabel implements IDisposable {
}
dispose() {
- this.text = null;
- this.highlights = null;
+ this.text = null!; // StrictNullOverride: nulling out ok in dispose
+ this.highlights = null!; // StrictNullOverride: nulling out ok in dispose
}
static escapeNewLines(text: string, highlights: IHighlight[]): string {
diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts
index 5754251a97d..48114650609 100644
--- a/src/vs/base/browser/ui/list/listWidget.ts
+++ b/src/vs/base/browser/ui/list/listWidget.ts
@@ -751,7 +751,7 @@ function getContiguousRangeContaining(range: number[], value: number): number[]
return [];
}
- const result = [];
+ const result: number[] = [];
let i = index - 1;
while (i >= 0 && range[i] === value - (index - i)) {
result.push(range[i--]);
@@ -771,7 +771,7 @@ function getContiguousRangeContaining(range: number[], value: number): number[]
* betweem them (OR).
*/
function disjunction(one: number[], other: number[]): number[] {
- const result = [];
+ const result: number[] = [];
let i = 0, j = 0;
while (i < one.length || j < other.length) {
@@ -799,7 +799,7 @@ function disjunction(one: number[], other: number[]): number[] {
* complement between them (XOR).
*/
function relativeComplement(one: number[], other: number[]): number[] {
- const result = [];
+ const result: number[] = [];
let i = 0, j = 0;
while (i < one.length || j < other.length) {
diff --git a/src/vs/base/browser/ui/list/rangeMap.ts b/src/vs/base/browser/ui/list/rangeMap.ts
index 3c4d78563b9..d70ddf174ea 100644
--- a/src/vs/base/browser/ui/list/rangeMap.ts
+++ b/src/vs/base/browser/ui/list/rangeMap.ts
@@ -188,6 +188,6 @@ export class RangeMap {
}
dispose() {
- this.groups = null;
+ this.groups = null!; // StrictNullOverride: nulling out ok in dispose
}
}
\ No newline at end of file
diff --git a/src/vs/base/browser/ui/list/rowCache.ts b/src/vs/base/browser/ui/list/rowCache.ts
index 756b1f9a678..b7007c2fc0f 100644
--- a/src/vs/base/browser/ui/list/rowCache.ts
+++ b/src/vs/base/browser/ui/list/rowCache.ts
@@ -8,14 +8,16 @@ import { IDisposable } from 'vs/base/common/lifecycle';
import { $, removeClass } from 'vs/base/browser/dom';
export interface IRow {
- domNode: HTMLElement;
+ domNode: HTMLElement | null;
templateId: string;
templateData: any;
}
function removeFromParent(element: HTMLElement): void {
try {
- element.parentElement.removeChild(element);
+ if (element.parentElement) {
+ element.parentElement.removeChild(element);
+ }
} catch (e) {
// this will throw if this happens due to a blur event, nasty business
}
@@ -57,8 +59,10 @@ export class RowCache implements IDisposable {
private releaseRow(row: IRow): void {
const { domNode, templateId } = row;
- removeClass(domNode, 'scrolling');
- removeFromParent(domNode);
+ if (domNode) {
+ removeClass(domNode, 'scrolling');
+ removeFromParent(domNode);
+ }
const cache = this.getTemplateCache(templateId);
cache.push(row);
@@ -95,6 +99,6 @@ export class RowCache implements IDisposable {
dispose(): void {
this.garbageCollect();
this.cache.clear();
- this.renderers = null;
+ this.renderers = null!; // StrictNullOverride: nulling out ok in dispose
}
}
\ No newline at end of file
diff --git a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts
index 65a883bcb17..36b40a6995c 100644
--- a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts
+++ b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts
@@ -129,6 +129,13 @@ export class SelectBoxList implements ISelectBoxDelegate, IListVirtualDelegate {
- this.selectElement.title = e.target.value;
this.selected = e.target.selectedIndex;
this._onDidSelect.fire({
index: e.target.selectedIndex,
@@ -301,7 +307,6 @@ export class SelectBoxList implements ISelectBoxDelegate, IListVirtualDelegate document.body.removeChild(dragImage), 0);
@@ -371,7 +371,7 @@ interface IPanelItem {
export class PanelView extends Disposable {
- private dnd: IPanelDndController | null;
+ private dnd: IPanelDndController | undefined;
private dndContext: IDndContext = { draggable: null };
private el: HTMLElement;
private panelItems: IPanelItem[] = [];
diff --git a/src/vs/base/browser/ui/tree/indexTreeModel.ts b/src/vs/base/browser/ui/tree/indexTreeModel.ts
index 47f1c37607a..b55256c330f 100644
--- a/src/vs/base/browser/ui/tree/indexTreeModel.ts
+++ b/src/vs/base/browser/ui/tree/indexTreeModel.ts
@@ -406,7 +406,7 @@ export class IndexTreeModel implements ITreeModel): number[] {
- const location = [];
+ const location: number[] = [];
while (node.parent) {
location.push(node.parent.children.indexOf(node));
diff --git a/src/vs/base/common/arrays.ts b/src/vs/base/common/arrays.ts
index 7aaab83a0a8..408750697f0 100644
--- a/src/vs/base/common/arrays.ts
+++ b/src/vs/base/common/arrays.ts
@@ -6,7 +6,6 @@
import { CancellationToken } from 'vs/base/common/cancellation';
import { canceled } from 'vs/base/common/errors';
import { ISplice } from 'vs/base/common/sequence';
-import { TPromise } from 'vs/base/common/winjs.base';
/**
* Returns the last element of an array.
@@ -261,12 +260,12 @@ export function top(array: T[], compare: (a: T, b: T) => number, n: number):
* @param batch The number of elements to examine before yielding to the event loop.
* @return The first n elemnts from array when sorted with compare.
*/
-export function topAsync(array: T[], compare: (a: T, b: T) => number, n: number, batch: number, token?: CancellationToken): TPromise {
+export function topAsync(array: T[], compare: (a: T, b: T) => number, n: number, batch: number, token?: CancellationToken): Promise {
if (n === 0) {
- return TPromise.as([]);
+ return Promise.resolve([]);
}
- return new TPromise((resolve, reject) => {
+ return new Promise((resolve, reject) => {
(async () => {
const o = array.length;
const result = array.slice(0, n).sort(compare);
diff --git a/src/vs/base/common/json.ts b/src/vs/base/common/json.ts
index c0685017f82..6efede87596 100644
--- a/src/vs/base/common/json.ts
+++ b/src/vs/base/common/json.ts
@@ -2,35 +2,40 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------------------------
+ * 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 enum ScanError {
- None,
- UnexpectedEndOfComment,
- UnexpectedEndOfString,
- UnexpectedEndOfNumber,
- InvalidUnicode,
- InvalidEscapeCharacter,
- InvalidCharacter
+ None = 0,
+ UnexpectedEndOfComment = 1,
+ UnexpectedEndOfString = 2,
+ UnexpectedEndOfNumber = 3,
+ InvalidUnicode = 4,
+ InvalidEscapeCharacter = 5,
+ InvalidCharacter = 6
}
export const enum SyntaxKind {
- Unknown = 0,
- OpenBraceToken,
- CloseBraceToken,
- OpenBracketToken,
- CloseBracketToken,
- CommaToken,
- ColonToken,
- NullKeyword,
- TrueKeyword,
- FalseKeyword,
- StringLiteral,
- NumericLiteral,
- LineCommentTrivia,
- BlockCommentTrivia,
- LineBreakTrivia,
- Trivia,
- EOF
+ OpenBraceToken = 1,
+ CloseBraceToken = 2,
+ OpenBracketToken = 3,
+ CloseBracketToken = 4,
+ CommaToken = 5,
+ ColonToken = 6,
+ NullKeyword = 7,
+ TrueKeyword = 8,
+ FalseKeyword = 9,
+ StringLiteral = 10,
+ NumericLiteral = 11,
+ LineCommentTrivia = 12,
+ BlockCommentTrivia = 13,
+ LineBreakTrivia = 14,
+ Trivia = 15,
+ Unknown = 16,
+ EOF = 17
}
/**
@@ -42,7 +47,7 @@ export interface JSONScanner {
*/
setPosition(pos: number): void;
/**
- * Read the next token. Returns the tolen code.
+ * Read the next token. Returns the token code.
*/
scan(): SyntaxKind;
/**
@@ -70,6 +75,122 @@ export interface JSONScanner {
*/
getTokenError(): ScanError;
}
+
+
+export interface ParseError {
+ error: ParseErrorCode;
+ offset: number;
+ length: number;
+}
+
+export const enum ParseErrorCode {
+ InvalidSymbol = 1,
+ InvalidNumberFormat = 2,
+ PropertyNameExpected = 3,
+ ValueExpected = 4,
+ ColonExpected = 5,
+ CommaExpected = 6,
+ CloseBraceExpected = 7,
+ CloseBracketExpected = 8,
+ EndOfFileExpected = 9,
+ InvalidCommentToken = 10,
+ UnexpectedEndOfComment = 11,
+ UnexpectedEndOfString = 12,
+ UnexpectedEndOfNumber = 13,
+ InvalidUnicode = 14,
+ InvalidEscapeCharacter = 15,
+ InvalidCharacter = 16
+}
+
+export type NodeType = 'object' | 'array' | 'property' | 'string' | 'number' | 'boolean' | 'null';
+
+export interface Node {
+ readonly type: NodeType;
+ readonly value?: any;
+ readonly offset: number;
+ readonly length: number;
+ readonly colonOffset?: number;
+ readonly parent?: Node;
+ readonly children?: Node[];
+}
+
+export type Segment = string | number;
+export type JSONPath = Segment[];
+
+export interface Location {
+ /**
+ * The previous property key or literal value (string, number, boolean or null) or undefined.
+ */
+ previousNode?: Node;
+ /**
+ * The path describing the location in the JSON document. The path consists of a sequence strings
+ * representing an object property or numbers for array indices.
+ */
+ path: JSONPath;
+ /**
+ * Matches the locations path against a pattern consisting of strings (for properties) and numbers (for array indices).
+ * '*' will match a single segment, of any property name or index.
+ * '**' will match a sequece of segments or no segment, of any property name or index.
+ */
+ matches: (patterns: JSONPath) => boolean;
+ /**
+ * If set, the location's offset is at a property key.
+ */
+ isAtPropertyKey: boolean;
+}
+
+export interface ParseOptions {
+ disallowComments?: boolean;
+ allowTrailingComma?: boolean;
+}
+
+export interface JSONVisitor {
+ /**
+ * Invoked when an open brace is encountered and an object is started. The offset and length represent the location of the open brace.
+ */
+ onObjectBegin?: (offset: number, length: number) => void;
+
+ /**
+ * Invoked when a property is encountered. The offset and length represent the location of the property name.
+ */
+ onObjectProperty?: (property: string, offset: number, length: number) => void;
+
+ /**
+ * Invoked when a closing brace is encountered and an object is completed. The offset and length represent the location of the closing brace.
+ */
+ onObjectEnd?: (offset: number, length: number) => void;
+
+ /**
+ * Invoked when an open bracket is encountered. The offset and length represent the location of the open bracket.
+ */
+ onArrayBegin?: (offset: number, length: number) => void;
+
+ /**
+ * Invoked when a closing bracket is encountered. The offset and length represent the location of the closing bracket.
+ */
+ onArrayEnd?: (offset: number, length: number) => void;
+
+ /**
+ * Invoked when a literal value is encountered. The offset and length represent the location of the literal value.
+ */
+ onLiteralValue?: (value: any, offset: number, length: number) => void;
+
+ /**
+ * Invoked when a comma or colon separator is encountered. The offset and length represent the location of the separator.
+ */
+ onSeparator?: (character: string, offset: number, length: number) => void;
+
+ /**
+ * When comments are allowed, invoked when a line or block comment is encountered. The offset and length represent the location of the comment.
+ */
+ onComment?: (offset: number, length: number) => void;
+
+ /**
+ * Invoked on an error.
+ */
+ onError?: (error: ParseErrorCode, offset: number, length: number) => void;
+}
+
/**
* Creates a JSON scanner on the given text.
* If ignoreTrivia is set, whitespaces or comments are ignored.
@@ -584,53 +705,136 @@ const enum CharacterCodes {
verticalTab = 0x0B, // \v
}
-
-
-export interface ParseError {
- error: ParseErrorCode;
-}
-
-export const enum ParseErrorCode {
- InvalidSymbol,
- InvalidNumberFormat,
- PropertyNameExpected,
- ValueExpected,
- ColonExpected,
- CommaExpected,
- CloseBraceExpected,
- CloseBracketExpected,
- EndOfFileExpected
-}
-
-export type NodeType = 'object' | 'array' | 'property' | 'string' | 'number' | 'boolean' | 'null';
-
-function getLiteralNodeType(value: any): NodeType {
- switch (typeof value) {
- case 'boolean': return 'boolean';
- case 'number': return 'number';
- case 'string': return 'string';
- default: return 'null';
- }
-}
-
-export interface Node {
+interface NodeImpl extends Node {
type: NodeType;
value?: any;
offset: number;
length: number;
- columnOffset?: number;
- parent?: Node;
- children?: Node[];
+ colonOffset?: number;
+ parent?: NodeImpl;
+ children?: NodeImpl[];
}
-export type Segment = string | number;
-export type JSONPath = Segment[];
+/**
+ * For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index.
+ */
+export function getLocation(text: string, position: number): Location {
+ let segments: Segment[] = []; // strings or numbers
+ let earlyReturnException = new Object();
+ let previousNode: NodeImpl | undefined = void 0;
+ const previousNodeInst: NodeImpl = {
+ value: {},
+ offset: 0,
+ length: 0,
+ type: 'object',
+ parent: void 0
+ };
+ let isAtPropertyKey = false;
+ function setPreviousNode(value: string, offset: number, length: number, type: NodeType) {
+ previousNodeInst.value = value;
+ previousNodeInst.offset = offset;
+ previousNodeInst.length = length;
+ previousNodeInst.type = type;
+ previousNodeInst.colonOffset = void 0;
+ previousNode = previousNodeInst;
+ }
+ try {
-export interface ParseOptions {
- disallowComments?: boolean;
- disallowTrailingComma?: boolean;
+ visit(text, {
+ onObjectBegin: (offset: number, length: number) => {
+ if (position <= offset) {
+ throw earlyReturnException;
+ }
+ previousNode = void 0;
+ isAtPropertyKey = position > offset;
+ segments.push(''); // push a placeholder (will be replaced)
+ },
+ onObjectProperty: (name: string, offset: number, length: number) => {
+ if (position < offset) {
+ throw earlyReturnException;
+ }
+ setPreviousNode(name, offset, length, 'property');
+ segments[segments.length - 1] = name;
+ if (position <= offset + length) {
+ throw earlyReturnException;
+ }
+ },
+ onObjectEnd: (offset: number, length: number) => {
+ if (position <= offset) {
+ throw earlyReturnException;
+ }
+ previousNode = void 0;
+ segments.pop();
+ },
+ onArrayBegin: (offset: number, length: number) => {
+ if (position <= offset) {
+ throw earlyReturnException;
+ }
+ previousNode = void 0;
+ segments.push(0);
+ },
+ onArrayEnd: (offset: number, length: number) => {
+ if (position <= offset) {
+ throw earlyReturnException;
+ }
+ previousNode = void 0;
+ segments.pop();
+ },
+ onLiteralValue: (value: any, offset: number, length: number) => {
+ if (position < offset) {
+ throw earlyReturnException;
+ }
+ setPreviousNode(value, offset, length, getLiteralNodeType(value));
+
+ if (position <= offset + length) {
+ throw earlyReturnException;
+ }
+ },
+ onSeparator: (sep: string, offset: number, length: number) => {
+ if (position <= offset) {
+ throw earlyReturnException;
+ }
+ if (sep === ':' && previousNode && previousNode.type === 'property') {
+ previousNode.colonOffset = offset;
+ isAtPropertyKey = false;
+ previousNode = void 0;
+ } else if (sep === ',') {
+ let last = segments[segments.length - 1];
+ if (typeof last === 'number') {
+ segments[segments.length - 1] = last + 1;
+ } else {
+ isAtPropertyKey = true;
+ segments[segments.length - 1] = '';
+ }
+ previousNode = void 0;
+ }
+ }
+ });
+ } catch (e) {
+ if (e !== earlyReturnException) {
+ throw e;
+ }
+ }
+
+ return {
+ path: segments,
+ previousNode,
+ isAtPropertyKey,
+ matches: (pattern: Segment[]) => {
+ let k = 0;
+ for (let i = 0; k < pattern.length && i < segments.length; i++) {
+ if (pattern[k] === segments[i] || pattern[k] === '*') {
+ k++;
+ } else if (pattern[k] !== '**') {
+ return false;
+ }
+ }
+ return k === pattern.length;
+ }
+ };
}
+
/**
* Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.
* Therefore always check the errors list to find out if the input was valid.
@@ -673,8 +877,8 @@ export function parse(text: string, errors: ParseError[] = [], options?: ParseOp
currentParent = previousParents.pop();
},
onLiteralValue: onValue,
- onError: (error: ParseErrorCode) => {
- errors.push({ error: error });
+ onError: (error: ParseErrorCode, offset: number, length: number) => {
+ errors.push({ error, offset, length });
}
};
visit(text, visitor, options);
@@ -686,22 +890,17 @@ export function parse(text: string, errors: ParseError[] = [], options?: ParseOp
* Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.
*/
export function parseTree(text: string, errors: ParseError[] = [], options?: ParseOptions): Node {
- let currentParent: Node | undefined = { type: 'array', offset: -1, length: -1, children: [] }; // artificial root
+ let currentParent: NodeImpl = { type: 'array', offset: -1, length: -1, children: [], parent: void 0 }; // artificial root
function ensurePropertyComplete(endOffset: number) {
- if (currentParent && currentParent.type === 'property') {
+ if (currentParent.type === 'property') {
currentParent.length = endOffset - currentParent.offset;
- currentParent = currentParent.parent;
+ currentParent = currentParent.parent!;
}
}
function onValue(valueNode: Node): Node {
- if (currentParent) {
- if (!currentParent.children) {
- currentParent.children = [];
- }
- currentParent.children.push(valueNode);
- }
+ currentParent.children!.push(valueNode);
return valueNode;
}
@@ -714,22 +913,16 @@ export function parseTree(text: string, errors: ParseError[] = [], options?: Par
currentParent.children!.push({ type: 'string', value: name, offset, length, parent: currentParent });
},
onObjectEnd: (offset: number, length: number) => {
- if (!currentParent) {
- throw new Error('No current parent node');
- }
currentParent.length = offset + length - currentParent.offset;
- currentParent = currentParent.parent;
+ currentParent = currentParent.parent!;
ensurePropertyComplete(offset + length);
},
onArrayBegin: (offset: number, length: number) => {
currentParent = onValue({ type: 'array', offset, length: -1, parent: currentParent, children: [] });
},
onArrayEnd: (offset: number, length: number) => {
- if (!currentParent) {
- throw new Error('No current parent node');
- }
currentParent.length = offset + length - currentParent.offset;
- currentParent = currentParent.parent;
+ currentParent = currentParent.parent!;
ensurePropertyComplete(offset + length);
},
onLiteralValue: (value: any, offset: number, length: number) => {
@@ -737,27 +930,30 @@ export function parseTree(text: string, errors: ParseError[] = [], options?: Par
ensurePropertyComplete(offset + length);
},
onSeparator: (sep: string, offset: number, length: number) => {
- if (currentParent && currentParent.type === 'property') {
+ if (currentParent.type === 'property') {
if (sep === ':') {
- currentParent.columnOffset = offset;
+ currentParent.colonOffset = offset;
} else if (sep === ',') {
ensurePropertyComplete(offset);
}
}
},
- onError: (error: ParseErrorCode) => {
- errors.push({ error: error });
+ onError: (error: ParseErrorCode, offset: number, length: number) => {
+ errors.push({ error, offset, length });
}
};
visit(text, visitor, options);
- let result = currentParent!.children![0];
+ let result = currentParent.children![0];
if (result) {
delete result.parent;
}
return result;
}
+/**
+ * Finds the node at the given path in a JSON DOM.
+ */
export function findNodeAtLocation(root: Node, path: JSONPath): Node | undefined {
if (!root) {
return void 0;
@@ -765,12 +961,12 @@ export function findNodeAtLocation(root: Node, path: JSONPath): Node | undefined
let node = root;
for (let segment of path) {
if (typeof segment === 'string') {
- if (node.type !== 'object') {
+ if (node.type !== 'object' || !Array.isArray(node.children)) {
return void 0;
}
let found = false;
- for (const propertyNode of node.children || []) {
- if (propertyNode.children && propertyNode.children[0].value === segment) {
+ for (const propertyNode of node.children) {
+ if (Array.isArray(propertyNode.children) && propertyNode.children[0].value === segment) {
node = propertyNode.children[1];
found = true;
break;
@@ -781,26 +977,84 @@ export function findNodeAtLocation(root: Node, path: JSONPath): Node | undefined
}
} else {
let index = segment;
- if (node.type !== 'array' || index < 0 || index >= node.children!.length) {
+ if (node.type !== 'array' || index < 0 || !Array.isArray(node.children) || index >= node.children.length) {
return void 0;
}
- node = node.children![index];
+ node = node.children[index];
}
}
return node;
}
-export function getNodeValue(node: Node): any {
- if (node.type === 'array') {
- return node.children ? node.children.map(getNodeValue) : [];
- } else if (node.type === 'object') {
- let obj = {};
- for (let prop of node.children || []) {
- obj[prop.children![0].value] = getNodeValue(prop.children![1]);
- }
- return obj;
+/**
+ * Gets the JSON path of the given JSON DOM node
+ */
+export function getNodePath(node: Node): JSONPath {
+ if (!node.parent || !node.parent.children) {
+ return [];
}
- return node.value;
+ let path = getNodePath(node.parent);
+ if (node.parent.type === 'property') {
+ let key = node.parent.children[0].value;
+ path.push(key);
+ } else if (node.parent.type === 'array') {
+ let index = node.parent.children.indexOf(node);
+ if (index !== -1) {
+ path.push(index);
+ }
+ }
+ return path;
+}
+
+/**
+ * Evaluates the JavaScript object of the given JSON DOM node
+ */
+export function getNodeValue(node: Node): any {
+ switch (node.type) {
+ case 'array':
+ return node.children!.map(getNodeValue);
+ case 'object':
+ let obj = Object.create(null);
+ for (let prop of node.children!) {
+ let valueNode = prop.children![1];
+ if (valueNode) {
+ obj[prop.children![0].value] = getNodeValue(valueNode);
+ }
+ }
+ return obj;
+ case 'null':
+ case 'string':
+ case 'number':
+ case 'boolean':
+ return node.value;
+ default:
+ return void 0;
+ }
+
+}
+
+export function contains(node: Node, offset: number, includeRightBound = false): boolean {
+ return (offset >= node.offset && offset < (node.offset + node.length)) || includeRightBound && (offset === (node.offset + node.length));
+}
+
+/**
+ * Finds the most inner node at the given offset. If includeRightBound is set, also finds nodes that end at the given offset.
+ */
+export function findNodeAtOffset(node: Node, offset: number, includeRightBound = false): Node | undefined {
+ if (contains(node, offset, includeRightBound)) {
+ let children = node.children;
+ if (Array.isArray(children)) {
+ for (let i = 0; i < children.length && children[i].offset <= offset; i++) {
+ let item = findNodeAtOffset(children[i], offset, includeRightBound);
+ if (item) {
+ return item;
+ }
+ }
+
+ }
+ return node;
+ }
+ return void 0;
}
@@ -811,10 +1065,10 @@ export function visit(text: string, visitor: JSONVisitor, options?: ParseOptions
let _scanner = createScanner(text, false);
- function toNoArgVisit(visitFunction: ((offset: number, length: number) => void) | undefined): () => void {
+ function toNoArgVisit(visitFunction?: (offset: number, length: number) => void): () => void {
return visitFunction ? () => visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength()) : () => true;
}
- function toOneArgVisit(visitFunction: ((arg: T, offset: number, length: number) => void) | undefined): (arg: T) => void {
+ function toOneArgVisit(visitFunction?: (arg: T, offset: number, length: number) => void): (arg: T) => void {
return visitFunction ? (arg: T) => visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength()) : () => true;
}
@@ -825,18 +1079,43 @@ export function visit(text: string, visitor: JSONVisitor, options?: ParseOptions
onArrayEnd = toNoArgVisit(visitor.onArrayEnd),
onLiteralValue = toOneArgVisit(visitor.onLiteralValue),
onSeparator = toOneArgVisit(visitor.onSeparator),
+ onComment = toNoArgVisit(visitor.onComment),
onError = toOneArgVisit(visitor.onError);
let disallowComments = options && options.disallowComments;
- let disallowTrailingComma = options && options.disallowTrailingComma;
+ let allowTrailingComma = options && options.allowTrailingComma;
function scanNext(): SyntaxKind {
while (true) {
let token = _scanner.scan();
+ switch (_scanner.getTokenError()) {
+ case ScanError.InvalidUnicode:
+ handleError(ParseErrorCode.InvalidUnicode);
+ break;
+ case ScanError.InvalidEscapeCharacter:
+ handleError(ParseErrorCode.InvalidEscapeCharacter);
+ break;
+ case ScanError.UnexpectedEndOfNumber:
+ handleError(ParseErrorCode.UnexpectedEndOfNumber);
+ break;
+ case ScanError.UnexpectedEndOfComment:
+ if (!disallowComments) {
+ handleError(ParseErrorCode.UnexpectedEndOfComment);
+ }
+ break;
+ case ScanError.UnexpectedEndOfString:
+ handleError(ParseErrorCode.UnexpectedEndOfString);
+ break;
+ case ScanError.InvalidCharacter:
+ handleError(ParseErrorCode.InvalidCharacter);
+ break;
+ }
switch (token) {
case SyntaxKind.LineCommentTrivia:
case SyntaxKind.BlockCommentTrivia:
if (disallowComments) {
- handleError(ParseErrorCode.InvalidSymbol);
+ handleError(ParseErrorCode.InvalidCommentToken);
+ } else {
+ onComment();
}
break;
case SyntaxKind.Unknown:
@@ -940,7 +1219,7 @@ export function visit(text: string, visitor: JSONVisitor, options?: ParseOptions
}
onSeparator(',');
scanNext(); // consume comma
- if (_scanner.getToken() === SyntaxKind.CloseBraceToken && !disallowTrailingComma) {
+ if (_scanner.getToken() === SyntaxKind.CloseBraceToken && allowTrailingComma) {
break;
}
} else if (needsComma) {
@@ -972,7 +1251,7 @@ export function visit(text: string, visitor: JSONVisitor, options?: ParseOptions
}
onSeparator(',');
scanNext(); // consume comma
- if (_scanner.getToken() === SyntaxKind.CloseBracketToken && !disallowTrailingComma) {
+ if (_scanner.getToken() === SyntaxKind.CloseBracketToken && allowTrailingComma) {
break;
}
} else if (needsComma) {
@@ -1019,44 +1298,45 @@ export function visit(text: string, visitor: JSONVisitor, options?: ParseOptions
return true;
}
-export interface JSONVisitor {
- /**
- * Invoked when an open brace is encountered and an object is started. The offset and length represent the location of the open brace.
- */
- onObjectBegin?: (offset: number, length: number) => void;
+/**
+ * Takes JSON with JavaScript-style comments and remove
+ * them. Optionally replaces every none-newline character
+ * of comments with a replaceCharacter
+ */
+export function stripComments(text: string, replaceCh?: string): string {
- /**
- * Invoked when a property is encountered. The offset and length represent the location of the property name.
- */
- onObjectProperty?: (property: string, offset: number, length: number) => void;
+ let _scanner = createScanner(text),
+ parts: string[] = [],
+ kind: SyntaxKind,
+ offset = 0,
+ pos: number;
- /**
- * Invoked when a closing brace is encountered and an object is completed. The offset and length represent the location of the closing brace.
- */
- onObjectEnd?: (offset: number, length: number) => void;
+ do {
+ pos = _scanner.getPosition();
+ kind = _scanner.scan();
+ switch (kind) {
+ case SyntaxKind.LineCommentTrivia:
+ case SyntaxKind.BlockCommentTrivia:
+ case SyntaxKind.EOF:
+ if (offset !== pos) {
+ parts.push(text.substring(offset, pos));
+ }
+ if (replaceCh !== void 0) {
+ parts.push(_scanner.getTokenValue().replace(/[^\r\n]/g, replaceCh));
+ }
+ offset = _scanner.getPosition();
+ break;
+ }
+ } while (kind !== SyntaxKind.EOF);
- /**
- * Invoked when an open bracket is encountered. The offset and length represent the location of the open bracket.
- */
- onArrayBegin?: (offset: number, length: number) => void;
-
- /**
- * Invoked when a closing bracket is encountered. The offset and length represent the location of the closing bracket.
- */
- onArrayEnd?: (offset: number, length: number) => void;
-
- /**
- * Invoked when a literal value is encountered. The offset and length represent the location of the literal value.
- */
- onLiteralValue?: (value: any, offset: number, length: number) => void;
-
- /**
- * Invoked when a comma or colon separator is encountered. The offset and length represent the location of the separator.
- */
- onSeparator?: (charcter: string, offset: number, length: number) => void;
-
- /**
- * Invoked on an error.
- */
- onError?: (error: ParseErrorCode, offset: number, length: number) => void;
+ return parts.join('');
}
+
+function getLiteralNodeType(value: any): NodeType {
+ switch (typeof value) {
+ case 'boolean': return 'boolean';
+ case 'number': return 'number';
+ case 'string': return 'string';
+ default: return 'null';
+ }
+}
\ No newline at end of file
diff --git a/src/vs/base/common/jsonEdit.ts b/src/vs/base/common/jsonEdit.ts
index 6c45671e337..33ab2fdca80 100644
--- a/src/vs/base/common/jsonEdit.ts
+++ b/src/vs/base/common/jsonEdit.ts
@@ -2,15 +2,18 @@
* 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 { ParseError, Node, JSONPath, Segment, parseTree, findNodeAtLocation } from './json';
+import { Edit, format, isEOL, FormattingOptions } from './jsonFormatter';
-import { ParseError, Node, parseTree, findNodeAtLocation, JSONPath, Segment } from 'vs/base/common/json';
-import { Edit, FormattingOptions, format, applyEdit } from 'vs/base/common/jsonFormatter';
export function removeProperty(text: string, path: JSONPath, formattingOptions: FormattingOptions): Edit[] {
return setProperty(text, path, void 0, formattingOptions);
}
-export function setProperty(text: string, path: JSONPath, value: any, formattingOptions: FormattingOptions, getInsertionIndex?: (properties: string[]) => number): Edit[] {
+export function setProperty(text: string, originalPath: JSONPath, value: any, formattingOptions: FormattingOptions, getInsertionIndex?: (properties: string[]) => number): Edit[] {
+ let path = originalPath.slice();
let errors: ParseError[] = [];
let root = parseTree(text, errors);
let parent: Node | undefined = void 0;
@@ -36,20 +39,23 @@ export function setProperty(text: string, path: JSONPath, value: any, formatting
throw new Error('Can not delete in empty document');
}
return withFormatting(text, { offset: root ? root.offset : 0, length: root ? root.length : 0, content: JSON.stringify(value) }, formattingOptions);
- } else if (parent.type === 'object' && typeof lastSegment === 'string') {
+ } else if (parent.type === 'object' && typeof lastSegment === 'string' && Array.isArray(parent.children)) {
let existing = findNodeAtLocation(parent, [lastSegment]);
if (existing !== void 0) {
if (value === void 0) { // delete
- let propertyIndex = parent.children && existing.parent ? parent.children.indexOf(existing.parent) : -1;
+ if (!existing.parent) {
+ throw new Error('Malformed AST');
+ }
+ let propertyIndex = parent.children.indexOf(existing.parent);
let removeBegin: number;
- let removeEnd = existing.parent!.offset + existing.parent!.length;
+ let removeEnd = existing.parent.offset + existing.parent.length;
if (propertyIndex > 0) {
// remove the comma of the previous node
- let previous = parent.children![propertyIndex - 1];
+ let previous = parent.children[propertyIndex - 1];
removeBegin = previous.offset + previous.length;
} else {
removeBegin = parent.offset + 1;
- if (parent.children && parent.children.length > 1) {
+ if (parent.children.length > 1) {
// remove the comma of the next node
let next = parent.children[1];
removeEnd = next.offset;
@@ -65,25 +71,25 @@ export function setProperty(text: string, path: JSONPath, value: any, formatting
return []; // property does not exist, nothing to do
}
let newProperty = `${JSON.stringify(lastSegment)}: ${JSON.stringify(value)}`;
- let index = getInsertionIndex ? getInsertionIndex(parent.children!.map(p => p.children![0].value)) : parent.children!.length;
+ let index = getInsertionIndex ? getInsertionIndex(parent.children.map(p => p.children![0].value)) : parent.children.length;
let edit: Edit;
if (index > 0) {
- let previous = parent.children![index - 1];
+ let previous = parent.children[index - 1];
edit = { offset: previous.offset + previous.length, length: 0, content: ',' + newProperty };
- } else if (parent.children!.length === 0) {
+ } else if (parent.children.length === 0) {
edit = { offset: parent.offset + 1, length: 0, content: newProperty };
} else {
edit = { offset: parent.offset + 1, length: 0, content: newProperty + ',' };
}
return withFormatting(text, edit, formattingOptions);
}
- } else if (parent.type === 'array' && typeof lastSegment === 'number') {
+ } else if (parent.type === 'array' && typeof lastSegment === 'number' && Array.isArray(parent.children)) {
let insertIndex = lastSegment;
if (insertIndex === -1) {
// Insert
let newProperty = `${JSON.stringify(value)}`;
let edit: Edit;
- if (!parent.children || parent.children.length === 0) {
+ if (parent.children.length === 0) {
edit = { offset: parent.offset + 1, length: 0, content: newProperty };
} else {
let previous = parent.children[parent.children.length - 1];
@@ -91,7 +97,7 @@ export function setProperty(text: string, path: JSONPath, value: any, formatting
}
return withFormatting(text, edit, formattingOptions);
} else {
- if (value === void 0 && parent.children && parent.children.length >= 0) {
+ if (value === void 0 && parent.children.length >= 0) {
//Removal
let removalIndex = lastSegment;
let toRemove = parent.children[removalIndex];
@@ -125,6 +131,15 @@ function withFormatting(text: string, edit: Edit, formattingOptions: FormattingO
// format the new text
let begin = edit.offset;
let end = edit.offset + edit.content.length;
+ if (edit.length === 0 || edit.content.length === 0) { // insert or remove
+ while (begin > 0 && !isEOL(newText, begin - 1)) {
+ begin--;
+ }
+ while (end < newText.length && !isEOL(newText, end)) {
+ end++;
+ }
+ }
+
let edits = format(newText, { offset: begin, length: end - begin }, formattingOptions);
// apply the formatting edits and track the begin and end offsets of the changes
@@ -138,4 +153,12 @@ function withFormatting(text: string, edit: Edit, formattingOptions: FormattingO
// create a single edit with all changes
let editLength = text.length - (newText.length - end) - begin;
return [{ offset: begin, length: editLength, content: newText.substring(begin, end) }];
+}
+
+export function applyEdit(text: string, edit: Edit): string {
+ return text.substring(0, edit.offset) + edit.content + text.substring(edit.offset + edit.length);
+}
+
+export function isWS(text: string, offset: number) {
+ return '\r\n \t'.indexOf(text.charAt(offset)) !== -1;
}
\ No newline at end of file
diff --git a/src/vs/base/common/jsonFormatter.ts b/src/vs/base/common/jsonFormatter.ts
index e7b8fe6d71f..a2306b5cb28 100644
--- a/src/vs/base/common/jsonFormatter.ts
+++ b/src/vs/base/common/jsonFormatter.ts
@@ -2,64 +2,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 * as Json from './json';
+import { createScanner, SyntaxKind, ScanError } from './json';
export interface FormattingOptions {
/**
* If indentation is based on spaces (`insertSpaces` = true), then what is the number of spaces that make an indent?
*/
- tabSize: number;
+ tabSize?: number;
/**
* Is indentation based on spaces?
*/
- insertSpaces: boolean;
+ insertSpaces?: boolean;
/**
- * The default end of line line character
+ * The default 'end of line' character. If not set, '\n' is used as default.
*/
- eol: string;
+ eol?: string;
}
+/**
+ * Represents a text modification
+ */
export interface Edit {
+ /**
+ * The start offset of the modification.
+ */
offset: number;
+ /**
+ * The length of the modification. Must not be negative. Empty length represents an *insert*.
+ */
length: number;
+ /**
+ * The new content. Empty content represents a *remove*.
+ */
content: string;
}
-export function applyEdit(text: string, edit: Edit): string {
- return text.substring(0, edit.offset) + edit.content + text.substring(edit.offset + edit.length);
+/**
+ * A text range in the document
+*/
+export interface Range {
+ /**
+ * The start offset of the range.
+ */
+ offset: number;
+ /**
+ * The length of the range. Must not be negative.
+ */
+ length: number;
}
-export function applyEdits(text: string, edits: Edit[]): string {
- for (let i = edits.length - 1; i >= 0; i--) {
- text = applyEdit(text, edits[i]);
- }
- return text;
-}
-export function format(documentText: string, range: { offset: number, length: number }, options: FormattingOptions): Edit[] {
+export function format(documentText: string, range: Range | undefined, options: FormattingOptions): Edit[] {
let initialIndentLevel: number;
- let value: string;
+ let formatText: string;
+ let formatTextStart: number;
let rangeStart: number;
let rangeEnd: number;
if (range) {
rangeStart = range.offset;
rangeEnd = rangeStart + range.length;
- while (rangeStart > 0 && !isEOL(documentText, rangeStart - 1)) {
- rangeStart--;
- }
- let scanner = Json.createScanner(documentText, true);
- scanner.setPosition(rangeEnd);
- scanner.scan();
- rangeEnd = scanner.getPosition();
- value = documentText.substring(rangeStart, rangeEnd);
- initialIndentLevel = computeIndentLevel(value, 0, options);
+ formatTextStart = rangeStart;
+ while (formatTextStart > 0 && !isEOL(documentText, formatTextStart - 1)) {
+ formatTextStart--;
+ }
+ let endOffset = rangeEnd;
+ while (endOffset < documentText.length && !isEOL(documentText, endOffset)) {
+ endOffset++;
+ }
+ formatText = documentText.substring(formatTextStart, endOffset);
+ initialIndentLevel = computeIndentLevel(formatText, options);
} else {
- value = documentText;
+ formatText = documentText;
+ initialIndentLevel = 0;
+ formatTextStart = 0;
rangeStart = 0;
rangeEnd = documentText.length;
- initialIndentLevel = 0;
}
let eol = getEOL(options, documentText);
@@ -67,75 +87,78 @@ export function format(documentText: string, range: { offset: number, length: nu
let indentLevel = 0;
let indentValue: string;
if (options.insertSpaces) {
- indentValue = repeat(' ', options.tabSize);
+ indentValue = repeat(' ', options.tabSize || 4);
} else {
indentValue = '\t';
}
- let scanner = Json.createScanner(value, false);
+ let scanner = createScanner(formatText, false);
+ let hasError = false;
function newLineAndIndent(): string {
return eol + repeat(indentValue, initialIndentLevel + indentLevel);
}
- function scanNext(): Json.SyntaxKind {
+ function scanNext(): SyntaxKind {
let token = scanner.scan();
lineBreak = false;
- while (token === Json.SyntaxKind.Trivia || token === Json.SyntaxKind.LineBreakTrivia) {
- lineBreak = lineBreak || (token === Json.SyntaxKind.LineBreakTrivia);
+ while (token === SyntaxKind.Trivia || token === SyntaxKind.LineBreakTrivia) {
+ lineBreak = lineBreak || (token === SyntaxKind.LineBreakTrivia);
token = scanner.scan();
}
+ hasError = token === SyntaxKind.Unknown || scanner.getTokenError() !== ScanError.None;
return token;
}
let editOperations: Edit[] = [];
function addEdit(text: string, startOffset: number, endOffset: number) {
- if (documentText.substring(startOffset, endOffset) !== text) {
+ if (!hasError && startOffset < rangeEnd && endOffset > rangeStart && documentText.substring(startOffset, endOffset) !== text) {
editOperations.push({ offset: startOffset, length: endOffset - startOffset, content: text });
}
}
let firstToken = scanNext();
- if (firstToken !== Json.SyntaxKind.EOF) {
- let firstTokenStart = scanner.getTokenOffset() + rangeStart;
+
+ if (firstToken !== SyntaxKind.EOF) {
+ let firstTokenStart = scanner.getTokenOffset() + formatTextStart;
let initialIndent = repeat(indentValue, initialIndentLevel);
- addEdit(initialIndent, rangeStart, firstTokenStart);
+ addEdit(initialIndent, formatTextStart, firstTokenStart);
}
- while (firstToken !== Json.SyntaxKind.EOF) {
- let firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + rangeStart;
+ while (firstToken !== SyntaxKind.EOF) {
+ let firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart;
let secondToken = scanNext();
let replaceContent = '';
- while (!lineBreak && (secondToken === Json.SyntaxKind.LineCommentTrivia || secondToken === Json.SyntaxKind.BlockCommentTrivia)) {
+ while (!lineBreak && (secondToken === SyntaxKind.LineCommentTrivia || secondToken === SyntaxKind.BlockCommentTrivia)) {
// comments on the same line: keep them on the same line, but ignore them otherwise
- let commentTokenStart = scanner.getTokenOffset() + rangeStart;
+ let commentTokenStart = scanner.getTokenOffset() + formatTextStart;
addEdit(' ', firstTokenEnd, commentTokenStart);
- firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + rangeStart;
- replaceContent = secondToken === Json.SyntaxKind.LineCommentTrivia ? newLineAndIndent() : '';
+ firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart;
+ replaceContent = secondToken === SyntaxKind.LineCommentTrivia ? newLineAndIndent() : '';
secondToken = scanNext();
}
- if (secondToken === Json.SyntaxKind.CloseBraceToken) {
- if (firstToken !== Json.SyntaxKind.OpenBraceToken) {
+ if (secondToken === SyntaxKind.CloseBraceToken) {
+ if (firstToken !== SyntaxKind.OpenBraceToken) {
indentLevel--;
replaceContent = newLineAndIndent();
}
- } else if (secondToken === Json.SyntaxKind.CloseBracketToken) {
- if (firstToken !== Json.SyntaxKind.OpenBracketToken) {
+ } else if (secondToken === SyntaxKind.CloseBracketToken) {
+ if (firstToken !== SyntaxKind.OpenBracketToken) {
indentLevel--;
replaceContent = newLineAndIndent();
}
- } else if (secondToken !== Json.SyntaxKind.EOF) {
+ } else {
switch (firstToken) {
- case Json.SyntaxKind.OpenBracketToken:
- case Json.SyntaxKind.OpenBraceToken:
+ case SyntaxKind.OpenBracketToken:
+ case SyntaxKind.OpenBraceToken:
indentLevel++;
replaceContent = newLineAndIndent();
break;
- case Json.SyntaxKind.CommaToken:
- case Json.SyntaxKind.LineCommentTrivia:
+ case SyntaxKind.CommaToken:
+ case SyntaxKind.LineCommentTrivia:
replaceContent = newLineAndIndent();
break;
- case Json.SyntaxKind.BlockCommentTrivia:
+ case SyntaxKind.BlockCommentTrivia:
if (lineBreak) {
replaceContent = newLineAndIndent();
} else {
@@ -143,24 +166,37 @@ export function format(documentText: string, range: { offset: number, length: nu
replaceContent = ' ';
}
break;
- case Json.SyntaxKind.ColonToken:
+ case SyntaxKind.ColonToken:
replaceContent = ' ';
break;
- case Json.SyntaxKind.NullKeyword:
- case Json.SyntaxKind.TrueKeyword:
- case Json.SyntaxKind.FalseKeyword:
- case Json.SyntaxKind.NumericLiteral:
- if (secondToken === Json.SyntaxKind.NullKeyword || secondToken === Json.SyntaxKind.FalseKeyword || secondToken === Json.SyntaxKind.NumericLiteral) {
+ case SyntaxKind.StringLiteral:
+ if (secondToken === SyntaxKind.ColonToken) {
+ replaceContent = '';
+ break;
+ }
+ // fall through
+ case SyntaxKind.NullKeyword:
+ case SyntaxKind.TrueKeyword:
+ case SyntaxKind.FalseKeyword:
+ case SyntaxKind.NumericLiteral:
+ case SyntaxKind.CloseBraceToken:
+ case SyntaxKind.CloseBracketToken:
+ if (secondToken === SyntaxKind.LineCommentTrivia || secondToken === SyntaxKind.BlockCommentTrivia) {
replaceContent = ' ';
+ } else if (secondToken !== SyntaxKind.CommaToken && secondToken !== SyntaxKind.EOF) {
+ hasError = true;
}
break;
+ case SyntaxKind.Unknown:
+ hasError = true;
+ break;
}
- if (lineBreak && (secondToken === Json.SyntaxKind.LineCommentTrivia || secondToken === Json.SyntaxKind.BlockCommentTrivia)) {
+ if (lineBreak && (secondToken === SyntaxKind.LineCommentTrivia || secondToken === SyntaxKind.BlockCommentTrivia)) {
replaceContent = newLineAndIndent();
}
}
- let secondTokenStart = scanner.getTokenOffset() + rangeStart;
+ let secondTokenStart = scanner.getTokenOffset() + formatTextStart;
addEdit(replaceContent, firstTokenEnd, secondTokenStart);
firstToken = secondToken;
}
@@ -175,7 +211,7 @@ function repeat(s: string, count: number): string {
return result;
}
-function computeIndentLevel(content: string, offset: number, options: FormattingOptions): number {
+function computeIndentLevel(content: string, options: FormattingOptions): number {
let i = 0;
let nChars = 0;
let tabSize = options.tabSize || 4;
@@ -208,6 +244,6 @@ function getEOL(options: FormattingOptions, text: string): string {
return (options && options.eol) || '\n';
}
-function isEOL(text: string, offset: number) {
+export function isEOL(text: string, offset: number) {
return '\r\n'.indexOf(text.charAt(offset)) !== -1;
}
\ No newline at end of file
diff --git a/src/vs/base/common/uri.ts b/src/vs/base/common/uri.ts
index b4dc302fe91..69d295d568f 100644
--- a/src/vs/base/common/uri.ts
+++ b/src/vs/base/common/uri.ts
@@ -336,7 +336,7 @@ export class URI implements UriComponents {
// ---- printing/externalize ---------------------------
/**
- * Creates a string presentation for this URI. It's guardeed that calling
+ * Creates a string presentation for this URI. It's guaranteed that calling
* `URI.parse` with the result of this function creates an URI which is equal
* to this URI.
*
diff --git a/src/vs/base/node/ps.ts b/src/vs/base/node/ps.ts
index d11f9a8dc45..af7e3cf162a 100644
--- a/src/vs/base/node/ps.ts
+++ b/src/vs/base/node/ps.ts
@@ -194,7 +194,7 @@ export function listProcesses(rootPid: number): Promise {
if (process.platform === 'linux') {
// Flatten rootItem to get a list of all VSCode processes
let processes = [rootItem];
- const pids = [];
+ const pids: number[] = [];
while (processes.length) {
const process = processes.shift();
pids.push(process.pid);
diff --git a/src/vs/base/node/stats.ts b/src/vs/base/node/stats.ts
index a65797e127a..fbf895ea0a6 100644
--- a/src/vs/base/node/stats.ts
+++ b/src/vs/base/node/stats.ts
@@ -5,7 +5,7 @@
import { readdir, stat, exists, readFile } from 'fs';
import { join } from 'path';
-import { parse } from 'vs/base/common/json';
+import { parse, ParseError } from 'vs/base/common/json';
export interface WorkspaceStatItem {
name: string;
@@ -37,7 +37,7 @@ export function collectLaunchConfigs(folder: string): Promise messages.push(msg));
await timeout(0);
diff --git a/src/vs/base/parts/quickopen/common/quickOpenScorer.ts b/src/vs/base/parts/quickopen/common/quickOpenScorer.ts
index 841974aaade..ace8984e735 100644
--- a/src/vs/base/parts/quickopen/common/quickOpenScorer.ts
+++ b/src/vs/base/parts/quickopen/common/quickOpenScorer.ts
@@ -61,8 +61,8 @@ export function score(target: string, query: string, queryLower: string, fuzzy:
}
function doScore(query: string, queryLower: string, queryLength: number, target: string, targetLower: string, targetLength: number): [number, number[]] {
- const scores = [];
- const matches = [];
+ const scores: number[] = [];
+ const matches: number[] = [];
//
// Build Scorer Matrix:
@@ -121,7 +121,7 @@ function doScore(query: string, queryLower: string, queryLength: number, target:
}
// Restore Positions (starting from bottom right of matrix)
- const positions = [];
+ const positions: number[] = [];
let queryIndex = queryLength - 1;
let targetIndex = targetLength - 1;
while (queryIndex >= 0 && targetIndex >= 0) {
diff --git a/src/vs/base/test/browser/ui/tree/indexTreeModel.test.ts b/src/vs/base/test/browser/ui/tree/indexTreeModel.test.ts
index 53d2add5df4..07431d166b8 100644
--- a/src/vs/base/test/browser/ui/tree/indexTreeModel.test.ts
+++ b/src/vs/base/test/browser/ui/tree/indexTreeModel.test.ts
@@ -24,14 +24,14 @@ function toArray(list: ITreeNode[]): T[] {
suite('IndexTreeModel', function () {
test('ctor', () => {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const model = new IndexTreeModel(toSpliceable(list));
assert(model);
assert.equal(list.length, 0);
});
test('insert', () => {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const model = new IndexTreeModel(toSpliceable(list));
model.splice([0], 0, Iterator.fromArray([
@@ -53,7 +53,7 @@ suite('IndexTreeModel', function () {
});
test('deep insert', function () {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const model = new IndexTreeModel(toSpliceable(list));
model.splice([0], 0, Iterator.fromArray([
@@ -90,7 +90,7 @@ suite('IndexTreeModel', function () {
});
test('deep insert collapsed', function () {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const model = new IndexTreeModel(toSpliceable(list));
model.splice([0], 0, Iterator.fromArray([
@@ -118,7 +118,7 @@ suite('IndexTreeModel', function () {
});
test('delete', () => {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const model = new IndexTreeModel(toSpliceable(list));
model.splice([0], 0, Iterator.fromArray([
@@ -143,7 +143,7 @@ suite('IndexTreeModel', function () {
});
test('nested delete', function () {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const model = new IndexTreeModel(toSpliceable(list));
model.splice([0], 0, Iterator.fromArray([
@@ -177,7 +177,7 @@ suite('IndexTreeModel', function () {
});
test('deep delete', function () {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const model = new IndexTreeModel(toSpliceable(list));
model.splice([0], 0, Iterator.fromArray([
@@ -205,7 +205,7 @@ suite('IndexTreeModel', function () {
});
test('hidden delete', function () {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const model = new IndexTreeModel(toSpliceable(list));
model.splice([0], 0, Iterator.fromArray([
@@ -230,7 +230,7 @@ suite('IndexTreeModel', function () {
});
test('collapse', () => {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const model = new IndexTreeModel(toSpliceable(list));
model.splice([0], 0, Iterator.fromArray([
@@ -261,7 +261,7 @@ suite('IndexTreeModel', function () {
});
test('expand', () => {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const model = new IndexTreeModel(toSpliceable(list));
model.splice([0], 0, Iterator.fromArray([
@@ -301,7 +301,7 @@ suite('IndexTreeModel', function () {
});
test('collapse should recursively adjust visible count', function () {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const model = new IndexTreeModel(toSpliceable(list));
model.splice([0], 0, Iterator.fromArray([
@@ -334,7 +334,7 @@ suite('IndexTreeModel', function () {
});
test('simple filter', function () {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const filter = new class implements ITreeFilter {
filter(element: number): TreeVisibility {
return element % 2 === 0 ? TreeVisibility.Visible : TreeVisibility.Hidden;
@@ -368,7 +368,7 @@ suite('IndexTreeModel', function () {
});
test('recursive filter on initial model', function () {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const filter = new class implements ITreeFilter {
filter(element: number): TreeVisibility {
return element === 0 ? TreeVisibility.Recurse : TreeVisibility.Hidden;
@@ -390,7 +390,7 @@ suite('IndexTreeModel', function () {
});
test('refilter', function () {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
let shouldFilter = false;
const filter = new class implements ITreeFilter {
filter(element: number): TreeVisibility {
@@ -429,7 +429,7 @@ suite('IndexTreeModel', function () {
});
test('recursive filter', function () {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
let query = new RegExp('');
const filter = new class implements ITreeFilter {
filter(element: string): TreeVisibility {
@@ -475,7 +475,7 @@ suite('IndexTreeModel', function () {
});
test('recursive filter with collapse', function () {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
let query = new RegExp('');
const filter = new class implements ITreeFilter {
filter(element: string): TreeVisibility {
@@ -521,7 +521,7 @@ suite('IndexTreeModel', function () {
});
test('recursive filter while collapsed', function () {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
let query = new RegExp('');
const filter = new class implements ITreeFilter {
filter(element: string): TreeVisibility {
@@ -576,7 +576,7 @@ suite('IndexTreeModel', function () {
suite('getNodeLocation', function () {
test('simple', function () {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const model = new IndexTreeModel(toSpliceable(list));
model.splice([0], 0, Iterator.fromArray([
@@ -600,7 +600,7 @@ suite('IndexTreeModel', function () {
});
test('with filter', function () {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const filter = new class implements ITreeFilter {
filter(element: number): TreeVisibility {
return element % 2 === 0 ? TreeVisibility.Visible : TreeVisibility.Hidden;
diff --git a/src/vs/base/test/browser/ui/tree/objectTreeModel.test.ts b/src/vs/base/test/browser/ui/tree/objectTreeModel.test.ts
index 4fc0edf0f12..6aac4a6ad68 100644
--- a/src/vs/base/test/browser/ui/tree/objectTreeModel.test.ts
+++ b/src/vs/base/test/browser/ui/tree/objectTreeModel.test.ts
@@ -24,7 +24,7 @@ function toArray(list: ITreeNode[]): T[] {
suite('ObjectTreeModel', function () {
test('ctor', () => {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const model = new ObjectTreeModel(toSpliceable(list));
assert(model);
assert.equal(list.length, 0);
@@ -32,7 +32,7 @@ suite('ObjectTreeModel', function () {
});
test('flat', () => {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const model = new ObjectTreeModel(toSpliceable(list));
model.setChildren(null, Iterator.fromArray([
@@ -59,7 +59,7 @@ suite('ObjectTreeModel', function () {
});
test('nested', () => {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const model = new ObjectTreeModel(toSpliceable(list));
model.setChildren(null, Iterator.fromArray([
@@ -95,7 +95,7 @@ suite('ObjectTreeModel', function () {
});
test('setChildren on collapsed node', () => {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const model = new ObjectTreeModel(toSpliceable(list));
model.setChildren(null, Iterator.fromArray([
@@ -116,7 +116,7 @@ suite('ObjectTreeModel', function () {
});
test('setChildren on expanded, unrevealed node', () => {
- const list = [] as ITreeNode[];
+ const list: ITreeNode[] = [];
const model = new ObjectTreeModel(toSpliceable(list));
model.setChildren(null, [
diff --git a/src/vs/base/test/common/async.test.ts b/src/vs/base/test/common/async.test.ts
index 834b2545c28..23cb2ec8eca 100644
--- a/src/vs/base/test/common/async.test.ts
+++ b/src/vs/base/test/common/async.test.ts
@@ -53,7 +53,7 @@ suite('Async', () => {
// Cancelling a sync cancelable promise will fire the cancelled token.
// Also, every `then` callback runs in another execution frame.
test('CancelablePromise execution order (sync)', function () {
- const order = [];
+ const order: string[] = [];
const cancellablePromise = async.createCancelablePromise(token => {
order.push('in callback');
@@ -75,7 +75,7 @@ suite('Async', () => {
// Cancelling an async cancelable promise is just the same as a sync cancellable promise.
test('CancelablePromise execution order (async)', function () {
- const order = [];
+ const order: string[] = [];
const cancellablePromise = async.createCancelablePromise(token => {
order.push('in callback');
diff --git a/src/vs/base/test/common/json.test.ts b/src/vs/base/test/common/json.test.ts
index 1ad67bb26f1..07f67d08448 100644
--- a/src/vs/base/test/common/json.test.ts
+++ b/src/vs/base/test/common/json.test.ts
@@ -23,8 +23,8 @@ function assertScanError(text: string, expectedKind: SyntaxKind, scanError: Scan
assert.equal(scanner.getTokenError(), scanError);
}
-function assertValidParse(input: string, expected: any, options?: ParseOptions): void {
- var errors: { error: ParseErrorCode }[] = [];
+function assertValidParse(input: string, expected: any, options: ParseOptions = { allowTrailingComma: true }): void {
+ var errors: ParseError[] = [];
var actual = parse(input, errors, options);
if (errors.length !== 0) {
@@ -33,15 +33,15 @@ function assertValidParse(input: string, expected: any, options?: ParseOptions):
assert.deepEqual(actual, expected);
}
-function assertInvalidParse(input: string, expected: any, options?: ParseOptions): void {
- var errors: { error: ParseErrorCode }[] = [];
+function assertInvalidParse(input: string, expected: any, options: ParseOptions = { allowTrailingComma: true }): void {
+ var errors: ParseError[] = [];
var actual = parse(input, errors, options);
assert(errors.length > 0);
assert.deepEqual(actual, expected);
}
-function assertTree(input: string, expected: any, expectedErrors: number[] = [], options?: ParseOptions): void {
+function assertTree(input: string, expected: any, expectedErrors: number[] = [], options: ParseOptions = { allowTrailingComma: true }): void {
var errors: ParseError[] = [];
var actual = parseTree(input, errors, options);
@@ -50,7 +50,7 @@ function assertTree(input: string, expected: any, expectedErrors: number[] = [],
if (node.children) {
for (let child of node.children) {
assert.equal(node, child.parent);
- delete child.parent; // delete to avoid recursion in deep equal
+ delete (child).parent; // delete to avoid recursion in deep equal
checkParent(child);
}
}
@@ -201,7 +201,7 @@ suite('JSON', () => {
test('parse: objects with errors', () => {
assertInvalidParse('{,}', {});
- assertInvalidParse('{ "foo": true, }', { foo: true }, { disallowTrailingComma: true });
+ assertInvalidParse('{ "foo": true, }', { foo: true }, { allowTrailingComma: false });
assertInvalidParse('{ "bar": 8 "xoo": "foo" }', { bar: 8, xoo: 'foo' });
assertInvalidParse('{ ,"bar": 8 }', { bar: 8 });
assertInvalidParse('{ ,"bar": 8, "foo" }', { bar: 8 });
@@ -211,10 +211,10 @@ suite('JSON', () => {
test('parse: array with errors', () => {
assertInvalidParse('[,]', []);
- assertInvalidParse('[ 1, 2, ]', [1, 2], { disallowTrailingComma: true });
+ assertInvalidParse('[ 1, 2, ]', [1, 2], { allowTrailingComma: false });
assertInvalidParse('[ 1 2, 3 ]', [1, 2, 3]);
assertInvalidParse('[ ,1, 2, 3 ]', [1, 2, 3]);
- assertInvalidParse('[ ,1, 2, 3, ]', [1, 2, 3], { disallowTrailingComma: true });
+ assertInvalidParse('[ ,1, 2, 3, ]', [1, 2, 3], { allowTrailingComma: false });
});
test('parse: disallow commments', () => {
@@ -230,14 +230,14 @@ suite('JSON', () => {
// default is allow
assertValidParse('{ "hello": [], }', { hello: [] });
- let options = { disallowTrailingComma: false };
+ let options = { allowTrailingComma: true };
assertValidParse('{ "hello": [], }', { hello: [] }, options);
assertValidParse('{ "hello": [] }', { hello: [] }, options);
assertValidParse('{ "hello": [], "world": {}, }', { hello: [], world: {} }, options);
assertValidParse('{ "hello": [], "world": {} }', { hello: [], world: {} }, options);
assertValidParse('{ "hello": [1,] }', { hello: [1] }, options);
- options = { disallowTrailingComma: true };
+ options = { allowTrailingComma: false };
assertInvalidParse('{ "hello": [], }', { hello: [] }, options);
assertInvalidParse('{ "hello": [], "world": {}, }', { hello: [], world: {} }, options);
});
@@ -272,7 +272,7 @@ suite('JSON', () => {
assertTree('{ "val": 1 }', {
type: 'object', offset: 0, length: 12, children: [
{
- type: 'property', offset: 2, length: 8, columnOffset: 7, children: [
+ type: 'property', offset: 2, length: 8, colonOffset: 7, children: [
{ type: 'string', offset: 2, length: 5, value: 'val' },
{ type: 'number', offset: 9, length: 1, value: 1 }
]
@@ -283,13 +283,13 @@ suite('JSON', () => {
{
type: 'object', offset: 0, length: 32, children: [
{
- type: 'property', offset: 1, length: 9, columnOffset: 5, children: [
+ type: 'property', offset: 1, length: 9, colonOffset: 5, children: [
{ type: 'string', offset: 1, length: 4, value: 'id' },
{ type: 'string', offset: 7, length: 3, value: '$' }
]
},
{
- type: 'property', offset: 12, length: 18, columnOffset: 15, children: [
+ type: 'property', offset: 12, length: 18, colonOffset: 15, children: [
{ type: 'string', offset: 12, length: 3, value: 'v' },
{
type: 'array', offset: 17, length: 13, children: [
@@ -306,12 +306,12 @@ suite('JSON', () => {
{
type: 'object', offset: 0, length: 27, children: [
{
- type: 'property', offset: 3, length: 20, columnOffset: 7, children: [
+ type: 'property', offset: 3, length: 20, colonOffset: 7, children: [
{ type: 'string', offset: 3, length: 4, value: 'id' },
{
type: 'object', offset: 9, length: 14, children: [
{
- type: 'property', offset: 11, length: 10, columnOffset: 16, children: [
+ type: 'property', offset: 11, length: 10, colonOffset: 16, children: [
{ type: 'string', offset: 11, length: 5, value: 'foo' },
{ type: 'object', offset: 18, length: 3, children: [] }
]
@@ -322,6 +322,6 @@ suite('JSON', () => {
}
]
}
- , [ParseErrorCode.PropertyNameExpected, ParseErrorCode.ValueExpected], { disallowTrailingComma: true });
+ , [ParseErrorCode.PropertyNameExpected, ParseErrorCode.ValueExpected], { allowTrailingComma: false });
});
});
diff --git a/src/vs/base/test/common/jsonEdit.test.ts b/src/vs/base/test/common/jsonEdit.test.ts
index 87ced6125b0..a7c5978d96b 100644
--- a/src/vs/base/test/common/jsonEdit.test.ts
+++ b/src/vs/base/test/common/jsonEdit.test.ts
@@ -101,13 +101,13 @@ suite('JSON - edits', () => {
content = '//comment';
edits = setProperty(content, ['foo', 0], 'bar', formatterOptions);
- assertEdit(content, edits, '{\n "foo": [\n "bar"\n ]\n} //comment\n');
+ assertEdit(content, edits, '{\n "foo": [\n "bar"\n ]\n} //comment');
});
test('remove property', () => {
let content = '{\n "x": "y"\n}';
let edits = removeProperty(content, ['x'], formatterOptions);
- assertEdit(content, edits, '{}');
+ assertEdit(content, edits, '{\n}');
content = '{\n "x": "y", "a": []\n}';
edits = removeProperty(content, ['x'], formatterOptions);
diff --git a/src/vs/base/test/common/jsonFormatter.test.ts b/src/vs/base/test/common/jsonFormatter.test.ts
index 2d15812917a..2ef51e1b383 100644
--- a/src/vs/base/test/common/jsonFormatter.test.ts
+++ b/src/vs/base/test/common/jsonFormatter.test.ts
@@ -8,7 +8,7 @@ import * as assert from 'assert';
suite('JSON - formatter', () => {
function format(content: string, expected: string, insertSpaces = true) {
- let range = void 0;
+ let range: Formatter.Range | undefined = void 0;
var rangeStart = content.indexOf('|');
var rangeEnd = content.lastIndexOf('|');
if (rangeStart !== -1 && rangeEnd !== -1) {
@@ -344,12 +344,12 @@ suite('JSON - formatter', () => {
'{ "a": {},',
' |"b": [null],',
'"c": {}',
- '} |'
+ '}|'
].join('\n');
var expected = [
'{ "a": {},',
- ' "b": [',
+ ' "b": [',
' null',
' ],',
' "c": {}',
diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts
index 66189159370..1b954752d0d 100644
--- a/src/vs/code/electron-main/windows.ts
+++ b/src/vs/code/electron-main/windows.ts
@@ -830,7 +830,7 @@ export class WindowsManager implements IWindowsMainService {
}
private doExtractPathsFromAPI(openConfig: IOpenConfiguration): IPathToOpen[] {
- const pathsToOpen = [];
+ const pathsToOpen: IPathToOpen[] = [];
const cli = openConfig.cli;
let parseOptions: IPathParseOptions = { gotoLineMode: cli && cli.goto, forceOpenWorkspaceAsFile: openConfig.forceOpenWorkspaceAsFile };
for (const pathToOpen of openConfig.urisToOpen) {
@@ -868,7 +868,7 @@ export class WindowsManager implements IWindowsMainService {
}
private doExtractPathsFromCLI(cli: ParsedArgs): IPath[] {
- const pathsToOpen = [];
+ const pathsToOpen: IPathToOpen[] = [];
const parseOptions: IPathParseOptions = { ignoreFileNotFound: true, gotoLineMode: cli.goto };
// folder uris
diff --git a/src/vs/editor/browser/editorExtensions.ts b/src/vs/editor/browser/editorExtensions.ts
index 727365c539b..36171828096 100644
--- a/src/vs/editor/browser/editorExtensions.ts
+++ b/src/vs/editor/browser/editorExtensions.ts
@@ -19,6 +19,8 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ITextModel } from 'vs/editor/common/model';
import { IPosition } from 'vs/base/browser/ui/contextview/contextview';
+import { ITextModelService } from 'vs/editor/common/services/resolverService';
+import { always } from 'vs/base/common/async';
export type ServicesAccessor = ServicesAccessor;
export type IEditorContributionCtor = IConstructorSignature1;
@@ -258,13 +260,23 @@ export function registerDefaultLanguageCommand(id: string, handler: (model: ITex
}
const model = accessor.get(IModelService).getModel(resource);
- if (!model) {
- throw illegalArgument('Can not find open model for ' + resource);
+ if (model) {
+ const editorPosition = Position.lift(position);
+ return handler(model, editorPosition, args);
}
- const editorPosition = Position.lift(position);
-
- return handler(model, editorPosition, args);
+ return accessor.get(ITextModelService).createModelReference(resource).then(reference => {
+ return always(new Promise((resolve, reject) => {
+ try {
+ let result = handler(reference.object.textEditorModel, Position.lift(position), args);
+ resolve(result);
+ } catch (err) {
+ reject(err);
+ }
+ }), () => {
+ reference.dispose();
+ });
+ });
});
}
diff --git a/src/vs/editor/contrib/colorPicker/colorDetector.ts b/src/vs/editor/contrib/colorPicker/colorDetector.ts
index 9b08ce87aac..a4628ec508e 100644
--- a/src/vs/editor/contrib/colorPicker/colorDetector.ts
+++ b/src/vs/editor/contrib/colorPicker/colorDetector.ts
@@ -30,8 +30,8 @@ export class ColorDetector implements IEditorContribution {
private _globalToDispose: IDisposable[] = [];
private _localToDispose: IDisposable[] = [];
- private _computePromise: CancelablePromise;
- private _timeoutTimer: TimeoutTimer;
+ private _computePromise: CancelablePromise | null;
+ private _timeoutTimer: TimeoutTimer | null;
private _decorationsIds: string[] = [];
private _colorDatas = new Map();
@@ -108,11 +108,8 @@ export class ColorDetector implements IEditorContribution {
return;
}
const model = this._editor.getModel();
- // if (!model) {
- // return;
- // }
- if (!ColorProviderRegistry.has(model)) {
+ if (!model || !ColorProviderRegistry.has(model)) {
return;
}
@@ -129,7 +126,13 @@ export class ColorDetector implements IEditorContribution {
}
private beginCompute(): void {
- this._computePromise = createCancelablePromise(token => getColors(this._editor.getModel(), token));
+ this._computePromise = createCancelablePromise(token => {
+ const model = this._editor.getModel();
+ if (!model) {
+ return Promise.resolve([]);
+ }
+ return getColors(model, token);
+ });
this._computePromise.then((colorInfos) => {
this.updateDecorations(colorInfos);
this.updateColorDecorators(colorInfos);
@@ -226,7 +229,12 @@ export class ColorDetector implements IEditorContribution {
}
getColorData(position: Position): IColorData | null {
- const decorations = this._editor.getModel()
+ const model = this._editor.getModel();
+ if (!model) {
+ return null;
+ }
+
+ const decorations = model
.getDecorationsInRange(Range.fromPositions(position, position))
.filter(d => this._colorDatas.has(d.id));
diff --git a/src/vs/editor/contrib/documentSymbols/outlineModel.ts b/src/vs/editor/contrib/documentSymbols/outlineModel.ts
index 0d852cd9ed9..347c430e8a1 100644
--- a/src/vs/editor/contrib/documentSymbols/outlineModel.ts
+++ b/src/vs/editor/contrib/documentSymbols/outlineModel.ts
@@ -133,7 +133,11 @@ export class OutlineGroup extends TreeElement {
}
private _updateMatches(pattern: string, item: OutlineElement, topMatch: OutlineElement): OutlineElement {
- item.score = fuzzyScore(pattern, pattern.toLowerCase(), 0, item.symbol.name, item.symbol.name.toLowerCase(), 0, true);
+
+ item.score = pattern
+ ? fuzzyScore(pattern, pattern.toLowerCase(), 0, item.symbol.name, item.symbol.name.toLowerCase(), 0, true)
+ : [-100, []];
+
if (item.score && (!topMatch || item.score[0] > topMatch.score[0])) {
topMatch = item;
}
@@ -142,7 +146,7 @@ export class OutlineGroup extends TreeElement {
topMatch = this._updateMatches(pattern, child, topMatch);
if (!item.score && child.score) {
// don't filter parents with unfiltered children
- item.score = [0, []];
+ item.score = [-100, []];
}
}
return topMatch;
diff --git a/src/vs/editor/contrib/goToDefinition/goToDefinitionMouse.ts b/src/vs/editor/contrib/goToDefinition/goToDefinitionMouse.ts
index eec514c2b15..5a85fbe403f 100644
--- a/src/vs/editor/contrib/goToDefinition/goToDefinitionMouse.ts
+++ b/src/vs/editor/contrib/goToDefinition/goToDefinitionMouse.ts
@@ -23,7 +23,7 @@ import { editorActiveLinkForeground } from 'vs/platform/theme/common/colorRegist
import { EditorState, CodeEditorStateFlag } from 'vs/editor/browser/core/editorState';
import { DefinitionAction, DefinitionActionConfig } from './goToDefinitionCommands';
import { ClickLinkGesture, ClickLinkMouseEvent, ClickLinkKeyboardEvent } from 'vs/editor/contrib/goToDefinition/clickLinkGesture';
-import { IWordAtPosition, IModelDeltaDecoration, ITextModel } from 'vs/editor/common/model';
+import { IWordAtPosition, IModelDeltaDecoration, ITextModel, IFoundBracket } from 'vs/editor/common/model';
import { Position } from 'vs/editor/common/core/position';
class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorContribution {
@@ -205,7 +205,7 @@ class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorC
private getPreviewRangeBasedOnBrackets(textEditorModel: ITextModel, startLineNumber: number) {
const maxLineNumber = Math.min(textEditorModel.getLineCount(), startLineNumber + GotoDefinitionWithMouseEditorContribution.MAX_SOURCE_PREVIEW_LINES);
- const brackets = [];
+ const brackets: IFoundBracket[] = [];
let ignoreFirstEmpty = true;
let currentBracket = textEditorModel.findNextBracket(new Position(startLineNumber, 1));
diff --git a/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts b/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts
index 1950a39827c..1849c8d7ae3 100644
--- a/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts
+++ b/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts
@@ -474,7 +474,9 @@ export class ParameterHintsWidget implements IContentWidget, IDisposable {
private getParameterLabelOffsets(signature: modes.SignatureInformation, paramIdx: number): [number, number] {
const param = signature.parameters[paramIdx];
- if (Array.isArray(param.label)) {
+ if (!param) {
+ return [0, 0];
+ } else if (Array.isArray(param.label)) {
return param.label;
} else {
const idx = signature.label.lastIndexOf(param.label);
diff --git a/src/vs/editor/contrib/snippet/snippetSession.ts b/src/vs/editor/contrib/snippet/snippetSession.ts
index 68450c4f919..9928428a60c 100644
--- a/src/vs/editor/contrib/snippet/snippetSession.ts
+++ b/src/vs/editor/contrib/snippet/snippetSession.ts
@@ -357,6 +357,10 @@ export class SnippetSession {
let firstBeforeText = model.getValueInRange(SnippetSession.adjustSelection(model, editor.getSelection(), overwriteBefore, 0));
let firstAfterText = model.getValueInRange(SnippetSession.adjustSelection(model, editor.getSelection(), 0, overwriteAfter));
+ // remember the first non-whitespace column to decide if
+ // `keepWhitespace` should be overruled for secondary selections
+ let firstLineFirstNonWhitespace = model.getLineFirstNonWhitespaceColumn(editor.getSelection().positionLineNumber);
+
// sort selections by their start position but remeber
// the original index. that allows you to create correct
// offset-based selection logic without changing the
@@ -387,8 +391,10 @@ export class SnippetSession {
// adjust the template string to match the indentation and
// whitespace rules of this insert location (can be different for each cursor)
+ // happens when being asked for (default) or when this is a secondary
+ // cursor and the leading whitespace is different
const start = snippetSelection.getStartPosition();
- if (adjustWhitespace) {
+ if (adjustWhitespace || (idx > 0 && firstLineFirstNonWhitespace !== model.getLineFirstNonWhitespaceColumn(selection.positionLineNumber))) {
SnippetSession.adjustWhitespace(model, start, snippet);
}
diff --git a/src/vs/editor/contrib/suggest/media/suggest.css b/src/vs/editor/contrib/suggest/media/suggest.css
index f78a5daae87..69252a4dd81 100644
--- a/src/vs/editor/contrib/suggest/media/suggest.css
+++ b/src/vs/editor/contrib/suggest/media/suggest.css
@@ -143,17 +143,16 @@
}
/** Styles for each row in the list **/
-
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .monaco-icon-label::before {
- height: 16px;
- padding-right: 4px;
+ height: 100%;
+
}
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon {
display: block;
height: 16px;
width: 16px;
- margin-right: 2px;
+ margin-left: 2px;
background-repeat: no-repeat;
background-size: 80%;
background-position: center;
@@ -167,33 +166,39 @@
display: none;
}
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon { background-image: url('Misc_16x.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.method,
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.function,
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.constructor { background-image: url('Method_16x.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.field { background-image: url('Field_16x.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.event { background-image: url('Event_16x_vscode.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.operator { background-image: url('Operator_16x_vscode.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.variable { background-image: url('LocalVariable_16x_vscode.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.class { background-image: url('Class_16x.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.interface { background-image: url('Interface_16x.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.struct { background-image: url('Structure_16x_vscode.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.type-parameter { background-image: url('Template_16x_vscode.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.module { background-image: url('Namespace_16x.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.property { background-image: url('Property_16x.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.unit { background-image: url('Ruler_16x.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.constant { background-image: url('Constant_16x.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.value,
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.enum { background-image: url('Enumerator_16x.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.enum-member { background-image: url('EnumItem_16x.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.keyword { background-image: url('IntelliSenseKeyword_16x.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.text { background-image: url('String_16x.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.color { background-image: url('ColorPalette_16x.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.file { background-image: url('Document_16x.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.reference { background-image: url('ImportFile_16x_vscode.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.snippet { background-image: url('Snippet_16x.svg'); }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.customcolor { background-image: none; }
-.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.folder { background-image: url('Folder_16x.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .monaco-icon-label.suggest-icon::before {
+ content: ' ';
+ background-image: url('Misc_16x.svg');
+ background-repeat: no-repeat;
+ background-position: center;
+}
+
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.method::before,
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.function::before,
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.constructor::before { background-image: url('Method_16x.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.field::before { background-image: url('Field_16x.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.event::before { background-image: url('Event_16x_vscode.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.operator::before { background-image: url('Operator_16x_vscode.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.variable::before { background-image: url('LocalVariable_16x_vscode.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.class::before { background-image: url('Class_16x.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.interface::before { background-image: url('Interface_16x.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.struct::before { background-image: url('Structure_16x_vscode.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.type-parameter::before { background-image: url('Template_16x_vscode.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.module::before { background-image: url('Namespace_16x.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.property::before { background-image: url('Property_16x.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.unit::before { background-image: url('Ruler_16x.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.constant::before { background-image: url('Constant_16x.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.value::before,
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.enum::before { background-image: url('Enumerator_16x.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.enum-member::before { background-image: url('EnumItem_16x.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.keyword::before { background-image: url('IntelliSenseKeyword_16x.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.text::before { background-image: url('String_16x.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.color::before { background-image: url('ColorPalette_16x.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.file::before { background-image: url('Document_16x.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.reference::before { background-image: url('ImportFile_16x_vscode.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.snippet::before { background-image: url('Snippet_16x.svg'); }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.customcolor::before { background-image: none; }
+.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.folder::before { background-image: url('Folder_16x.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.customcolor .colorspan {
margin: 0 0 0 0.3em;
@@ -284,80 +289,80 @@
background-image: url('./close-dark.svg');
}
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon { background-image: url('Misc_inverse_16x.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon::before { background-image: url('Misc_inverse_16x.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.method,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.method,
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.function,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.function,
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.constructor,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.constructor { background-image: url('Method_inverse_16x.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.method::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.method::before,
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.function::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.function::before,
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.constructor::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.constructor::before { background-image: url('Method_inverse_16x.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.field,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.field { background-image: url('Field_inverse_16x.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.field::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.field::before { background-image: url('Field_inverse_16x.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.event,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.event { background-image: url('Event_16x_vscode_inverse.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.event::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.event::before { background-image: url('Event_16x_vscode_inverse.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.operator,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.operator { background-image: url('Operator_16x_vscode_inverse.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.operator::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.operator::before { background-image: url('Operator_16x_vscode_inverse.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.variable,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.variable { background-image: url('LocalVariable_16x_vscode_inverse.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.variable::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.variable::before { background-image: url('LocalVariable_16x_vscode_inverse.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.class,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.class { background-image: url('Class_inverse_16x.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.class::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.class::before { background-image: url('Class_inverse_16x.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.interface,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.interface { background-image: url('Interface_inverse_16x.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.interface::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.interface::before { background-image: url('Interface_inverse_16x.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.struct,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.struct { background-image: url('Structure_16x_vscode_inverse.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.struct::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.struct::before { background-image: url('Structure_16x_vscode_inverse.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.type-parameter,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.type-parameter { background-image: url('Template_16x_vscode_inverse.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.type-parameter::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.type-parameter::before { background-image: url('Template_16x_vscode_inverse.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.module,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.module { background-image: url('Namespace_inverse_16x.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.module::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.module::before { background-image: url('Namespace_inverse_16x.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.property,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.property { background-image: url('Property_inverse_16x.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.property::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.property::before { background-image: url('Property_inverse_16x.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.unit,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.unit { background-image: url('Ruler_inverse_16x.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.unit::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.unit::before { background-image: url('Ruler_inverse_16x.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.constant,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.constant { background-image: url('Constant_16x_inverse.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.constant::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.constant::before { background-image: url('Constant_16x_inverse.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.value,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.value,
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.enum,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.enum { background-image: url('Enumerator_inverse_16x.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.value::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.value::before,
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.enum::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.enum::before { background-image: url('Enumerator_inverse_16x.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.enum-member,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.enum-member { background-image: url('EnumItem_inverse_16x.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.enum-member::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.enum-member::before { background-image: url('EnumItem_inverse_16x.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.keyword,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.keyword { background-image: url('IntelliSenseKeyword_inverse_16x.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.keyword::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.keyword::before { background-image: url('IntelliSenseKeyword_inverse_16x.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.text,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.text { background-image: url('String_inverse_16x.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.text::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.text::before { background-image: url('String_inverse_16x.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.color,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.color { background-image: url('ColorPalette_inverse_16x.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.color::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.color::before { background-image: url('ColorPalette_inverse_16x.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.file,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.file { background-image: url('Document_inverse_16x.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.file::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.file::before { background-image: url('Document_inverse_16x.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.reference,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.reference { background-image: url('ImportFile_16x_vscode_inverse.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.reference::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.reference::before { background-image: url('ImportFile_16x_vscode_inverse.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.snippet,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.snippet { background-image: url('Snippet_inverse_16x.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.snippet::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.snippet::before { background-image: url('Snippet_inverse_16x.svg'); }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.customcolor,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.customcolor { background-image: none; }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.customcolor::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.customcolor::before { background-image: none; }
-.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.folder,
-.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.folder { background-image: url('Folder_inverse_16x.svg'); }
+.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.folder::before,
+.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.folder::before { background-image: url('Folder_inverse_16x.svg'); }
diff --git a/src/vs/editor/contrib/suggest/suggestWidget.ts b/src/vs/editor/contrib/suggest/suggestWidget.ts
index 8f53272b3ca..3dc19b69164 100644
--- a/src/vs/editor/contrib/suggest/suggestWidget.ts
+++ b/src/vs/editor/contrib/suggest/suggestWidget.ts
@@ -37,6 +37,7 @@ import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
import { IModelService } from 'vs/editor/common/services/modelService';
import { URI } from 'vs/base/common/uri';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
+import { FileKind } from 'vs/platform/files/common/files';
const expandSuggestionDocsByDefault = false;
const maxSuggestionsToShow = 12;
@@ -85,6 +86,7 @@ class Renderer implements IListRendererObject.create(null);
data.disposables = [];
data.root = container;
+ addClass(data.root, 'show-file-icons');
data.icon = append(container, $('.icon'));
data.colorspan = append(data.icon, $('span.colorspan'));
@@ -147,33 +150,42 @@ class Renderer implements IListRenderer {
- parseErrors.push({ error: error });
+ onError: (error: json.ParseErrorCode, offset: number, length: number) => {
+ parseErrors.push({ error, offset, length });
}
};
if (content) {
diff --git a/src/vs/platform/diagnostics/electron-main/diagnosticsService.ts b/src/vs/platform/diagnostics/electron-main/diagnosticsService.ts
index e16dc49b2e2..94cba280d74 100644
--- a/src/vs/platform/diagnostics/electron-main/diagnosticsService.ts
+++ b/src/vs/platform/diagnostics/electron-main/diagnosticsService.ts
@@ -85,10 +85,10 @@ export class DiagnosticsService implements IDiagnosticsService {
getPerformanceInfo(info: IMainProcessInfo): Promise {
return listProcesses(info.mainPID).then(rootProcess => {
- const workspaceInfoMessages = [];
+ const workspaceInfoMessages: string[] = [];
// Workspace Stats
- const workspaceStatPromises = [];
+ const workspaceStatPromises: Promise[] = [];
if (info.windows.some(window => window.folderURIs && window.folderURIs.length > 0)) {
info.windows.forEach(window => {
if (window.folderURIs.length === 0) {
@@ -173,7 +173,7 @@ export class DiagnosticsService implements IDiagnosticsService {
console.log(this.formatProcessList(info, rootProcess));
// Workspace Stats
- const workspaceStatPromises = [];
+ const workspaceStatPromises: Promise[] = [];
if (info.windows.some(window => window.folderURIs && window.folderURIs.length > 0)) {
console.log('');
console.log('Workspace Stats: ');
diff --git a/src/vs/platform/driver/electron-browser/driver.ts b/src/vs/platform/driver/electron-browser/driver.ts
index f09c8b4b9ec..7847ac043a0 100644
--- a/src/vs/platform/driver/electron-browser/driver.ts
+++ b/src/vs/platform/driver/electron-browser/driver.ts
@@ -22,7 +22,7 @@ function serializeElement(element: Element, recursive: boolean): IElement {
attributes[attr.name] = attr.value;
}
- const children = [];
+ const children: IElement[] = [];
if (recursive) {
for (let i = 0; i < element.children.length; i++) {
@@ -119,7 +119,7 @@ class WindowDriver implements IWindowDriver {
const element = document.querySelector(selector);
if (element !== document.activeElement) {
- const chain = [];
+ const chain: string[] = [];
let el = document.activeElement;
while (el) {
diff --git a/src/vs/platform/driver/electron-main/driver.ts b/src/vs/platform/driver/electron-main/driver.ts
index f308e1471f4..ff392b24669 100644
--- a/src/vs/platform/driver/electron-main/driver.ts
+++ b/src/vs/platform/driver/electron-main/driver.ts
@@ -109,7 +109,7 @@ export class Driver implements IDriver, IWindowDriverRegistry {
const resolvedKeybinding = new USLayoutResolvedKeybinding(noModifiedKeybinding, OS);
const keyCode = resolvedKeybinding.getElectronAccelerator();
- const modifiers = [];
+ const modifiers: string[] = [];
if (keybinding.ctrlKey) {
modifiers.push('ctrl');
diff --git a/src/vs/platform/extensionManagement/node/extensionGalleryService.ts b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts
index 6930c70087b..240c532f9a2 100644
--- a/src/vs/platform/extensionManagement/node/extensionGalleryService.ts
+++ b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts
@@ -628,8 +628,8 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
.withFilter(FilterType.ExtensionName, ...extensionNames);
return this.queryGallery(query, token).then(result => {
- const dependencies = [];
- const ids = [];
+ const dependencies: IGalleryExtension[] = [];
+ const ids: string[] = [];
for (let index = 0; index < result.galleryExtensions.length; index++) {
const rawExtension = result.galleryExtensions[index];
diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts
index 42dfd9148b2..1c60d7b0334 100644
--- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts
+++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts
@@ -655,7 +655,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
return [];
}
const packedExtensions = installed.filter(i => extension.manifest.extensionPack.some(id => areSameExtensions({ id }, i.galleryIdentifier)));
- const packOfPackedExtensions = [];
+ const packOfPackedExtensions: ILocalExtension[] = [];
for (const packedExtension of packedExtensions) {
packOfPackedExtensions.push(...this.getAllPackExtensionsToUninstall(packedExtension, installed, checked));
}
@@ -827,7 +827,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
private filterUninstalled(...ids: string[]): Promise {
return this.withUninstalledExtensions(allUninstalled => {
- const uninstalled = [];
+ const uninstalled: string[] = [];
for (const id of ids) {
if (!!allUninstalled[id]) {
uninstalled.push(id);
diff --git a/src/vs/platform/files/common/files.ts b/src/vs/platform/files/common/files.ts
index ba3e3e1d31d..41c6352e1c1 100644
--- a/src/vs/platform/files/common/files.ts
+++ b/src/vs/platform/files/common/files.ts
@@ -53,7 +53,7 @@ export interface IFileService {
/**
* Tries to activate a provider with the given scheme.
*/
- activateProvider(scheme: string): TPromise;
+ activateProvider(scheme: string): Thenable;
/**
* Checks if this file service can handle the given resource.
diff --git a/src/vs/platform/request/node/requestService.ts b/src/vs/platform/request/node/requestService.ts
index fe394ac1555..d8e9bfdde46 100644
--- a/src/vs/platform/request/node/requestService.ts
+++ b/src/vs/platform/request/node/requestService.ts
@@ -20,9 +20,9 @@ export class RequestService implements IRequestService {
_serviceBrand: any;
- private proxyUrl: string;
+ private proxyUrl?: string;
private strictSSL: boolean;
- private authorization: string;
+ private authorization?: string;
private disposables: IDisposable[] = [];
constructor(
@@ -35,7 +35,7 @@ export class RequestService implements IRequestService {
private configure(config: IHTTPConfiguration) {
this.proxyUrl = config.http && config.http.proxy;
- this.strictSSL = config.http && config.http.proxyStrictSSL;
+ this.strictSSL = !!(config.http && config.http.proxyStrictSSL);
this.authorization = config.http && config.http.proxyAuthorization;
}
@@ -43,7 +43,7 @@ export class RequestService implements IRequestService {
this.logService.trace('RequestService#request', options.url);
const { proxyUrl, strictSSL } = this;
- const agentPromise = options.agent ? Promise.resolve(options.agent) : Promise.resolve(getProxyAgent(options.url, { proxyUrl, strictSSL }));
+ const agentPromise = options.agent ? Promise.resolve(options.agent) : Promise.resolve(getProxyAgent(options.url || '', { proxyUrl, strictSSL }));
return agentPromise.then(agent => {
options.agent = agent;
diff --git a/src/vs/platform/search/common/search.ts b/src/vs/platform/search/common/search.ts
index 14ac2479756..387525b12d9 100644
--- a/src/vs/platform/search/common/search.ts
+++ b/src/vs/platform/search/common/search.ts
@@ -25,8 +25,9 @@ export const ISearchService = createDecorator('searchService');
*/
export interface ISearchService {
_serviceBrand: any;
- search(query: ISearchQuery, token?: CancellationToken, onProgress?: (result: ISearchProgressItem) => void): TPromise;
- extendQuery(query: ISearchQuery): void;
+ textSearch(query: ITextQuery, token?: CancellationToken, onProgress?: (result: ISearchProgressItem) => void): TPromise;
+ fileSearch(query: IFileQuery, token?: CancellationToken): TPromise;
+ extendQuery(query: ITextQuery | IFileQuery): void;
clearCache(cacheKey: string): TPromise;
registerSearchResultProvider(scheme: string, type: SearchProviderType, provider: ISearchResultProvider): IDisposable;
}
@@ -56,7 +57,8 @@ export const enum SearchProviderType {
}
export interface ISearchResultProvider {
- search(query: ISearchQuery, onProgress?: (p: ISearchProgressItem) => void, token?: CancellationToken): TPromise;
+ textSearch(query: ITextQuery, onProgress?: (p: ISearchProgressItem) => void, token?: CancellationToken): TPromise;
+ fileSearch(query: IFileQuery, token?: CancellationToken): TPromise;
clearCache(cacheKey: string): TPromise;
}
@@ -67,52 +69,61 @@ export interface IFolderQuery {
fileEncoding?: string;
disregardIgnoreFiles?: boolean;
disregardGlobalIgnoreFiles?: boolean;
+ ignoreSymlinks?: boolean;
}
-export interface ICommonQueryOptions {
+export interface ICommonQueryProps {
+ /** For telemetry - indicates what is triggering the source */
+ _reason?: string;
+
+ folderQueries?: IFolderQuery[];
+ includePattern?: glob.IExpression;
+ excludePattern?: glob.IExpression;
extraFileResources?: U[];
- filePattern?: string; // file search only
- fileEncoding?: string;
+
+ useRipgrep?: boolean;
maxResults?: number;
+ usingSearchPaths?: boolean;
+}
+
+export interface IFileQueryProps extends ICommonQueryProps {
+ type: QueryType.File;
+ filePattern?: string;
+
+ // TODO: Remove this!
+ disregardExcludeSettings?: boolean;
+
/**
* If true no results will be returned. Instead `limitHit` will indicate if at least one result exists or not.
- *
* Currently does not work with queries including a 'siblings clause'.
*/
exists?: boolean;
sortByScore?: boolean;
cacheKey?: string;
- useRipgrep?: boolean;
- disregardIgnoreFiles?: boolean;
- disregardGlobalIgnoreFiles?: boolean;
- disregardExcludeSettings?: boolean;
- ignoreSymlinks?: boolean;
- maxFileSize?: number;
- previewOptions?: ITextSearchPreviewOptions;
}
-export interface IQueryOptions extends ICommonQueryOptions {
- excludePattern?: string;
- includePattern?: string;
-}
-
-export interface ISearchQueryProps extends ICommonQueryOptions {
- type: QueryType;
-
- excludePattern?: glob.IExpression;
- includePattern?: glob.IExpression;
+export interface ITextQueryProps extends ICommonQueryProps {
+ type: QueryType.Text;
contentPattern?: IPatternInfo;
- folderQueries?: IFolderQuery[];
- usingSearchPaths?: boolean;
+
+ previewOptions?: ITextSearchPreviewOptions;
+ maxFileSize?: number;
+ usePCRE2?: boolean;
}
-export type ISearchQuery = ISearchQueryProps;
-export type IRawSearchQuery = ISearchQueryProps;
+export type IFileQuery = IFileQueryProps;
+export type IRawFileQuery = IFileQueryProps;
+export type ITextQuery = ITextQueryProps;
+export type IRawTextQuery = ITextQueryProps;
+
+export type IRawQuery = IRawTextQuery | IRawFileQuery;
+export type ISearchQuery = ITextQuery | IFileQuery;
export const enum QueryType {
File = 1,
Text = 2
}
+
/* __GDPR__FRAGMENT__
"IPatternInfo" : {
"pattern" : { "classification": "CustomerContent", "purpose": "FeatureInsight" },
@@ -134,6 +145,10 @@ export interface IPatternInfo {
isSmartCase?: boolean;
}
+export interface IExtendedExtensionSearchOptions {
+ usePCRE2?: boolean;
+}
+
export interface IFileMatch {
resource?: U;
matches?: ITextSearchResult[];
@@ -287,6 +302,7 @@ export class OneLineRange extends SearchRange {
export interface ISearchConfigurationProperties {
exclude: glob.IExpression;
useRipgrep: boolean;
+ disableRipgrep: boolean;
/**
* Use ignore file for file search.
*/
@@ -298,6 +314,7 @@ export interface ISearchConfigurationProperties {
location: 'sidebar' | 'panel';
useReplacePreview: boolean;
showLineNumbers: boolean;
+ usePCRE2: boolean;
}
export interface ISearchConfiguration extends IFilesConfiguration {
@@ -327,18 +344,18 @@ export function getExcludes(configuration: ISearchConfiguration): glob.IExpressi
return allExcludes;
}
-export function pathIncludedInQuery(query: ISearchQuery, fsPath: string): boolean {
- if (query.excludePattern && glob.match(query.excludePattern, fsPath)) {
+export function pathIncludedInQuery(queryProps: ICommonQueryProps, fsPath: string): boolean {
+ if (queryProps.excludePattern && glob.match(queryProps.excludePattern, fsPath)) {
return false;
}
- if (query.includePattern && !glob.match(query.includePattern, fsPath)) {
+ if (queryProps.includePattern && !glob.match(queryProps.includePattern, fsPath)) {
return false;
}
// If searchPaths are being used, the extra file must be in a subfolder and match the pattern, if present
- if (query.usingSearchPaths) {
- return !!query.folderQueries && query.folderQueries.every(fq => {
+ if (queryProps.usingSearchPaths) {
+ return !!queryProps.folderQueries && queryProps.folderQueries.every(fq => {
const searchPath = fq.folder.fsPath;
if (paths.isEqualOrParent(fsPath, searchPath)) {
return !fq.includePattern || !!glob.match(fq.includePattern, fsPath);
diff --git a/src/vs/platform/telemetry/node/workbenchCommonProperties.ts b/src/vs/platform/telemetry/node/workbenchCommonProperties.ts
index 5f722afccb4..a3a46751062 100644
--- a/src/vs/platform/telemetry/node/workbenchCommonProperties.ts
+++ b/src/vs/platform/telemetry/node/workbenchCommonProperties.ts
@@ -8,6 +8,8 @@ import * as uuid from 'vs/base/common/uuid';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties';
+export const lastSessionDateStorageKey = 'telemetry.lastSessionDate';
+
export function resolveWorkbenchCommonProperties(storageService: IStorageService, commit: string, version: string, machineId: string, installSourcePath: string): TPromise<{ [name: string]: string }> {
return resolveCommonProperties(commit, version, machineId, installSourcePath).then(result => {
// __GDPR__COMMON__ "common.version.shell" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
@@ -15,7 +17,7 @@ export function resolveWorkbenchCommonProperties(storageService: IStorageService
// __GDPR__COMMON__ "common.version.renderer" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
result['common.version.renderer'] = process.versions && (process).versions['chrome'];
- const lastSessionDate = storageService.get('telemetry.lastSessionDate', StorageScope.GLOBAL);
+ const lastSessionDate = storageService.get(lastSessionDateStorageKey, StorageScope.GLOBAL);
storageService.store('telemetry.lastSessionDate', new Date().toUTCString(), StorageScope.GLOBAL);
// __GDPR__COMMON__ "common.firstSessionDate" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
diff --git a/src/vs/platform/theme/common/themeService.ts b/src/vs/platform/theme/common/themeService.ts
index 8e2707a6dc4..c77d018131e 100644
--- a/src/vs/platform/theme/common/themeService.ts
+++ b/src/vs/platform/theme/common/themeService.ts
@@ -55,7 +55,7 @@ export interface ITheme {
getColor(color: ColorIdentifier, useDefault?: boolean): Color | null;
/**
- * Returns wheter the theme defines a value for the color. If not, that means the
+ * Returns whether the theme defines a value for the color. If not, that means the
* default color will be used.
*/
defines(color: ColorIdentifier): boolean;
@@ -137,4 +137,4 @@ platform.Registry.add(Extensions.ThemingContribution, themingRegistry);
export function registerThemingParticipant(participant: IThemingParticipant): IDisposable {
return themingRegistry.onThemeChange(participant);
-}
\ No newline at end of file
+}
diff --git a/src/vs/platform/theme/test/electron-browser/colorRegistry.releaseTest.ts b/src/vs/platform/theme/test/electron-browser/colorRegistry.releaseTest.ts
index 8be585ab3a7..b9bcc8db83e 100644
--- a/src/vs/platform/theme/test/electron-browser/colorRegistry.releaseTest.ts
+++ b/src/vs/platform/theme/test/electron-browser/colorRegistry.releaseTest.ts
@@ -35,7 +35,7 @@ interface DescriptionDiff {
export const forceColorLoad = [editorMarkerNavigationError, overviewRulerModifiedForeground, STATUS_BAR_DEBUGGING_BACKGROUND,
debugExceptionWidgetBackground, debugToolBarBackground, buttonBackground, embeddedEditorBackground];
-export const experimental = []; // 'settings.modifiedItemForeground', 'editorUnnecessary.foreground' ];
+export const experimental: string[] = []; // 'settings.modifiedItemForeground', 'editorUnnecessary.foreground' ];
suite('Color Registry', function () {
diff --git a/src/vs/platform/workspaces/electron-main/workspacesMainService.ts b/src/vs/platform/workspaces/electron-main/workspacesMainService.ts
index 95c909de43a..e652ff8cde4 100644
--- a/src/vs/platform/workspaces/electron-main/workspacesMainService.ts
+++ b/src/vs/platform/workspaces/electron-main/workspacesMainService.ts
@@ -19,7 +19,6 @@ import { coalesce } from 'vs/base/common/arrays';
import { createHash } from 'crypto';
import * as json from 'vs/base/common/json';
import * as jsonEdit from 'vs/base/common/jsonEdit';
-import { applyEdit } from 'vs/base/common/jsonFormatter';
import { massageFolderPathForWorkspace } from 'vs/platform/workspaces/node/workspaces';
import { toWorkspaceFolders } from 'vs/platform/workspace/common/workspace';
import { URI } from 'vs/base/common/uri';
@@ -226,7 +225,7 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain
let newRawWorkspaceContents = rawWorkspaceContents;
const edits = jsonEdit.setProperty(rawWorkspaceContents, ['folders'], storedWorkspace.folders, { insertSpaces: false, tabSize: 4, eol: (isLinux || isMacintosh) ? '\n' : '\r\n' });
edits.forEach(edit => {
- newRawWorkspaceContents = applyEdit(rawWorkspaceContents, edit);
+ newRawWorkspaceContents = jsonEdit.applyEdit(rawWorkspaceContents, edit);
});
return writeFile(targetConfigPath, newRawWorkspaceContents).then(() => {
diff --git a/src/vs/workbench/api/browser/viewsExtensionPoint.ts b/src/vs/workbench/api/browser/viewsExtensionPoint.ts
index 3ddad042b08..296f5b46f77 100644
--- a/src/vs/workbench/api/browser/viewsExtensionPoint.ts
+++ b/src/vs/workbench/api/browser/viewsExtensionPoint.ts
@@ -111,7 +111,7 @@ class ViewsContainersExtensionHandler implements IWorkbenchContribution {
container = this.viewContainersRegistry.get(EXPLORER);
}
const registeredViews = ViewsRegistry.getViews(container);
- const viewIds = [];
+ const viewIds: string[] = [];
const viewDescriptors = coalesce(entry.value.map((item, index) => {
// validate
if (viewIds.indexOf(item.id) !== -1) {
diff --git a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts
index 55bd73db626..1656cb5c4de 100644
--- a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts
+++ b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts
@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import { URI, UriComponents } from 'vs/base/common/uri';
-import { TPromise } from 'vs/base/common/winjs.base';
import { IDisposable } from 'vs/base/common/lifecycle';
import { Registry } from 'vs/platform/registry/common/platform';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
@@ -45,7 +44,7 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape {
return this.writeConfiguration(target, key, undefined, resource);
}
- private writeConfiguration(target: ConfigurationTarget, key: string, value: any, resource: URI): TPromise {
+ private writeConfiguration(target: ConfigurationTarget, key: string, value: any, resource: URI): Promise {
target = target !== null && target !== undefined ? target : this.deriveConfigurationTarget(key, resource);
return this.configurationService.updateValue(key, value, { resource }, target, true);
}
diff --git a/src/vs/workbench/api/electron-browser/mainThreadSearch.ts b/src/vs/workbench/api/electron-browser/mainThreadSearch.ts
index f5e2f7996e9..a29485a24a8 100644
--- a/src/vs/workbench/api/electron-browser/mainThreadSearch.ts
+++ b/src/vs/workbench/api/electron-browser/mainThreadSearch.ts
@@ -8,7 +8,7 @@ import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { values } from 'vs/base/common/map';
import { URI, UriComponents } from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
-import { IFileMatch, IRawFileMatch2, ISearchComplete, ISearchCompleteStats, ISearchProgressItem, ISearchQuery, ISearchResultProvider, ISearchService, QueryType, SearchProviderType } from 'vs/platform/search/common/search';
+import { IFileMatch, IRawFileMatch2, ISearchComplete, ISearchCompleteStats, ISearchProgressItem, ISearchResultProvider, ISearchService, QueryType, SearchProviderType, ITextQuery, IFileQuery } from 'vs/platform/search/common/search';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { ExtHostContext, ExtHostSearchShape, IExtHostContext, MainContext, MainThreadSearchShape } from '../node/extHost.protocol';
@@ -68,7 +68,7 @@ class SearchOperation {
private static _idPool = 0;
constructor(
- readonly progress: (match: IFileMatch) => any,
+ readonly progress?: (match: IFileMatch) => any,
readonly id: number = ++SearchOperation._idPool,
readonly matches = new Map()
) {
@@ -83,7 +83,9 @@ class SearchOperation {
this.matches.set(match.resource.toString(), match);
}
- this.progress(match);
+ if (this.progress) {
+ this.progress(match);
+ }
}
}
@@ -106,7 +108,15 @@ class RemoteSearchProvider implements ISearchResultProvider, IDisposable {
dispose(this._registrations);
}
- search(query: ISearchQuery, onProgress?: (p: ISearchProgressItem) => void, token: CancellationToken = CancellationToken.None): TPromise {
+ fileSearch(query: IFileQuery, token: CancellationToken = CancellationToken.None): TPromise {
+ return this.doSearch(query, null, token);
+ }
+
+ textSearch(query: ITextQuery, onProgress?: (p: ISearchProgressItem) => void, token: CancellationToken = CancellationToken.None): TPromise {
+ return this.doSearch(query, onProgress, token);
+ }
+
+ doSearch(query: ITextQuery | IFileQuery, onProgress?: (p: ISearchProgressItem) => void, token: CancellationToken = CancellationToken.None): TPromise {
if (isFalsyOrEmpty(query.folderQueries)) {
return TPromise.as(undefined);
}
@@ -116,7 +126,7 @@ class RemoteSearchProvider implements ISearchResultProvider, IDisposable {
const searchP = query.type === QueryType.File
? this._proxy.$provideFileSearchResults(this._handle, search.id, query, token)
- : this._proxy.$provideTextSearchResults(this._handle, search.id, query.contentPattern, query, token);
+ : this._proxy.$provideTextSearchResults(this._handle, search.id, query, token);
return TPromise.wrap(searchP).then((result: ISearchCompleteStats) => {
this._searches.delete(search.id);
diff --git a/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts b/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts
index ef702f42e53..50a345b39bb 100644
--- a/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts
+++ b/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts
@@ -133,7 +133,7 @@ class TreeViewDataProvider implements ITreeViewDataProvider {
}
private postGetChildren(elements: ITreeItem[]): ITreeItem[] {
- const result = [];
+ const result: ITreeItem[] = [];
if (elements) {
for (const element of elements) {
this.itemsMap.set(element.handle, element);
diff --git a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts
index fbf413cfb3b..b5828cf89b9 100644
--- a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts
+++ b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts
@@ -6,19 +6,18 @@
import { isPromiseCanceledError } from 'vs/base/common/errors';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { URI, UriComponents } from 'vs/base/common/uri';
-import { TPromise } from 'vs/base/common/winjs.base';
import { localize } from 'vs/nls';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ILabelService } from 'vs/platform/label/common/label';
-import { IFolderQuery, IPatternInfo, IQueryOptions, ISearchConfiguration, ISearchProgressItem, ISearchQuery, ISearchService, QueryType } from 'vs/platform/search/common/search';
+import { IFolderQuery, IPatternInfo, ISearchConfiguration, ISearchProgressItem, ISearchService, QueryType, IFileQuery } from 'vs/platform/search/common/search';
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
-import { QueryBuilder } from 'vs/workbench/parts/search/common/queryBuilder';
+import { QueryBuilder, ITextQueryBuilderOptions } from 'vs/workbench/parts/search/common/queryBuilder';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
@@ -141,13 +140,18 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
return !folderConfig.search.followSymlinks;
});
- const query: ISearchQuery = {
+ // TODO replace wth QueryBuilder
+ folderQueries.forEach(fq => {
+ fq.ignoreSymlinks = ignoreSymlinks;
+ });
+
+ const query: IFileQuery = {
folderQueries,
type: QueryType.File,
maxResults,
disregardExcludeSettings: excludePatternOrDisregardExcludes === false,
useRipgrep,
- ignoreSymlinks
+ _reason: 'startFileSearch'
};
if (typeof includePattern === 'string') {
query.includePattern = { [includePattern]: true };
@@ -159,22 +163,23 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
this._searchService.extendQuery(query);
- return this._searchService.search(query, token).then(result => {
+ return this._searchService.fileSearch(query, token).then(result => {
return result.results.map(m => m.resource);
}, err => {
if (!isPromiseCanceledError(err)) {
- return TPromise.wrapError(err);
+ return Promise.reject(err);
}
return undefined;
});
}
- $startTextSearch(pattern: IPatternInfo, options: IQueryOptions, requestId: number, token: CancellationToken): Thenable {
+ $startTextSearch(pattern: IPatternInfo, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Thenable {
const workspace = this._contextService.getWorkspace();
const folders = workspace.folders.map(folder => folder.uri);
const queryBuilder = this._instantiationService.createInstance(QueryBuilder);
const query = queryBuilder.text(pattern, folders, options);
+ query._reason = 'startTextSearch';
const onProgress = (p: ISearchProgressItem) => {
if (p.matches) {
@@ -182,13 +187,13 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
}
};
- const search = this._searchService.search(query, token, onProgress).then(
+ const search = this._searchService.textSearch(query, token, onProgress).then(
result => {
return { limitHit: result.limitHit };
},
err => {
if (!isPromiseCanceledError(err)) {
- return TPromise.wrapError(err);
+ return Promise.reject(err);
}
return undefined;
@@ -201,17 +206,18 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
const queryBuilder = this._instantiationService.createInstance(QueryBuilder);
const folders = this._contextService.getWorkspace().folders.map(folder => folder.uri);
const query = queryBuilder.file(folders, {
+ _reason: 'checkExists',
includePattern: includes.join(', '),
exists: true
});
- return this._searchService.search(query, token).then(
+ return this._searchService.fileSearch(query, token).then(
result => {
return result.limitHit;
},
err => {
if (!isPromiseCanceledError(err)) {
- return TPromise.wrapError(err);
+ return Promise.reject(err);
}
return undefined;
diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts
index 119dfefdd62..8484f983781 100644
--- a/src/vs/workbench/api/node/extHost.api.impl.ts
+++ b/src/vs/workbench/api/node/extHost.api.impl.ts
@@ -40,7 +40,6 @@ import { URI } from 'vs/base/common/uri';
import Severity from 'vs/base/common/severity';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
-import { TPromise } from 'vs/base/common/winjs.base';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import * as vscode from 'vscode';
import * as paths from 'vs/base/common/paths';
@@ -363,11 +362,11 @@ export function createApiFactory(
return extHostTerminalService.terminals;
},
showTextDocument(documentOrUri: vscode.TextDocument | vscode.Uri, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions, preserveFocus?: boolean): Thenable {
- let documentPromise: TPromise;
+ let documentPromise: Promise;
if (URI.isUri(documentOrUri)) {
- documentPromise = TPromise.wrap(workspace.openTextDocument(documentOrUri));
+ documentPromise = Promise.resolve(workspace.openTextDocument(documentOrUri));
} else {
- documentPromise = TPromise.wrap(documentOrUri);
+ documentPromise = Promise.resolve(documentOrUri);
}
return documentPromise.then(document => {
return extHostEditors.showTextDocument(document, columnOrOptions, preserveFocus);
@@ -555,9 +554,9 @@ export function createApiFactory(
let options = uriOrFileNameOrOptions as { language?: string; content?: string; };
if (typeof uriOrFileNameOrOptions === 'string') {
- uriPromise = TPromise.as(URI.file(uriOrFileNameOrOptions));
+ uriPromise = Promise.resolve(URI.file(uriOrFileNameOrOptions));
} else if (uriOrFileNameOrOptions instanceof URI) {
- uriPromise = TPromise.as(uriOrFileNameOrOptions);
+ uriPromise = Promise.resolve(uriOrFileNameOrOptions);
} else if (!options || typeof options === 'object') {
uriPromise = extHostDocuments.createDocumentData(options);
} else {
@@ -844,7 +843,7 @@ class Extension implements vscode.Extension {
}
}
-export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory): TPromise {
+export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory): Promise {
return extensionService.getExtensionPathIndex().then(trie => defineAPI(apiFactory, trie));
}
diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts
index 0736bcc56dd..5044ae0b844 100644
--- a/src/vs/workbench/api/node/extHost.protocol.ts
+++ b/src/vs/workbench/api/node/extHost.protocol.ts
@@ -24,7 +24,7 @@ import { LabelRules } from 'vs/platform/label/common/label';
import { LogLevel } from 'vs/platform/log/common/log';
import { IMarkerData } from 'vs/platform/markers/common/markers';
import { IPickOptions, IQuickInputButton, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
-import { IPatternInfo, IQueryOptions, IRawFileMatch2, IRawSearchQuery, ISearchCompleteStats } from 'vs/platform/search/common/search';
+import { IPatternInfo, IRawFileMatch2, IRawQuery, ISearchCompleteStats, IRawTextQuery } from 'vs/platform/search/common/search';
import { StatusbarAlignment as MainThreadStatusBarAlignment } from 'vs/platform/statusbar/common/statusbar';
import { ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
import { ThemeColor } from 'vs/platform/theme/common/themeService';
@@ -41,6 +41,7 @@ import { IProgressOptions, IProgressStep } from 'vs/workbench/services/progress/
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
import * as vscode from 'vscode';
import { CancellationToken } from 'vs/base/common/cancellation';
+import { ITextQueryBuilderOptions } from 'vs/workbench/parts/search/common/queryBuilder';
export interface IEnvironment {
isExtensionDevelopmentDebug: boolean;
@@ -483,7 +484,7 @@ export interface ExtHostUrlsShape {
export interface MainThreadWorkspaceShape extends IDisposable {
$startFileSearch(includePattern: string, includeFolder: URI, excludePatternOrDisregardExcludes: string | false, maxResults: number, token: CancellationToken): Thenable;
- $startTextSearch(query: IPatternInfo, options: IQueryOptions, requestId: number, token: CancellationToken): Thenable;
+ $startTextSearch(query: IPatternInfo, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Thenable;
$checkExists(includes: string[], token: CancellationToken): Thenable;
$saveAll(includeUntitled?: boolean): Thenable;
$updateWorkspaceFolders(extensionName: string, index: number, deleteCount: number, workspaceFoldersToAdd: { uri: UriComponents, name?: string }[]): Thenable;
@@ -708,9 +709,9 @@ export interface ExtHostFileSystemShape {
}
export interface ExtHostSearchShape {
- $provideFileSearchResults(handle: number, session: number, query: IRawSearchQuery, token: CancellationToken): Thenable;
+ $provideFileSearchResults(handle: number, session: number, query: IRawQuery, token: CancellationToken): Thenable;
+ $provideTextSearchResults(handle: number, session: number, query: IRawTextQuery, token: CancellationToken): Thenable;
$clearCache(cacheKey: string): Thenable;
- $provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, query: IRawSearchQuery, token: CancellationToken): Thenable;
}
export interface ExtHostExtensionServiceShape {
diff --git a/src/vs/workbench/api/node/extHostComments.ts b/src/vs/workbench/api/node/extHostComments.ts
index 9d06aa6a57d..3970fd566ac 100644
--- a/src/vs/workbench/api/node/extHostComments.ts
+++ b/src/vs/workbench/api/node/extHostComments.ts
@@ -5,7 +5,6 @@
import { asThenable } from 'vs/base/common/async';
import { URI, UriComponents } from 'vs/base/common/uri';
-import { TPromise } from 'vs/base/common/winjs.base';
import * as modes from 'vs/editor/common/modes';
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
import * as extHostTypeConverter from 'vs/workbench/api/node/extHostTypeConverters';
@@ -68,7 +67,7 @@ export class ExtHostComments implements ExtHostCommentsShape {
const ran = extHostTypeConverter.Range.to(range);
if (!data || !data.document) {
- return TPromise.as(null);
+ return Promise.resolve(null);
}
const provider = this._documentProviders.get(handle);
@@ -82,7 +81,7 @@ export class ExtHostComments implements ExtHostCommentsShape {
const ran = extHostTypeConverter.Range.to(range);
if (!data || !data.document) {
- return TPromise.as(null);
+ return Promise.resolve(null);
}
const provider = this._documentProviders.get(handle);
@@ -120,7 +119,7 @@ export class ExtHostComments implements ExtHostCommentsShape {
$provideDocumentComments(handle: number, uri: UriComponents): Thenable {
const data = this._documents.getDocumentData(URI.revive(uri));
if (!data || !data.document) {
- return TPromise.as(null);
+ return Promise.resolve(null);
}
const provider = this._documentProviders.get(handle);
@@ -132,7 +131,7 @@ export class ExtHostComments implements ExtHostCommentsShape {
$provideWorkspaceComments(handle: number): Thenable {
const provider = this._workspaceProviders.get(handle);
if (!provider) {
- return TPromise.as(null);
+ return Promise.resolve(null);
}
return asThenable(() => {
diff --git a/src/vs/workbench/api/node/extHostDebugService.ts b/src/vs/workbench/api/node/extHostDebugService.ts
index 6552de5fc9e..5176cbe1602 100644
--- a/src/vs/workbench/api/node/extHostDebugService.ts
+++ b/src/vs/workbench/api/node/extHostDebugService.ts
@@ -6,7 +6,6 @@
import * as paths from 'vs/base/common/paths';
import { Schemas } from 'vs/base/common/network';
import { URI, UriComponents } from 'vs/base/common/uri';
-import { TPromise } from 'vs/base/common/winjs.base';
import { Event, Emitter } from 'vs/base/common/event';
import { asThenable } from 'vs/base/common/async';
import * as nls from 'vs/nls';
@@ -287,7 +286,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
// RPC methods (ExtHostDebugServiceShape)
- public $runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise {
+ public $runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): Thenable {
if (args.kind === 'integrated') {
@@ -300,7 +299,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
});
}
- return new TPromise(resolve => {
+ return new Promise(resolve => {
if (this._integratedTerminalInstance) {
this._integratedTerminalInstance.processId.then(pid => {
resolve(hasChildprocesses(pid));
@@ -318,7 +317,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
this._integratedTerminalInstance.show();
- return new TPromise((resolve, error) => {
+ return new Promise((resolve) => {
setTimeout(_ => {
const command = prepareCommand(args, config);
this._integratedTerminalInstance.sendText(command, true);
@@ -337,7 +336,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
return void 0;
}
- public $substituteVariables(folderUri: UriComponents | undefined, config: IConfig): TPromise {
+ public $substituteVariables(folderUri: UriComponents | undefined, config: IConfig): Promise {
if (!this._variableResolver) {
this._variableResolver = new ExtHostVariableResolverService(this._workspaceService, this._editorsService, this._configurationService);
}
@@ -353,10 +352,10 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
}
};
}
- return TPromise.wrap(this._variableResolver.resolveAny(ws, config));
+ return Promise.resolve(this._variableResolver.resolveAny(ws, config));
}
- public $startDASession(handle: number, sessionDto: IDebugSessionDto, folderUri: UriComponents | undefined, config: vscode.DebugConfiguration): TPromise {
+ public $startDASession(handle: number, sessionDto: IDebugSessionDto, folderUri: UriComponents | undefined, config: vscode.DebugConfiguration): Thenable {
const mythis = this;
return this.getAdapterDescriptor(this._providerByType.get(config.type), sessionDto, folderUri, config).then(adapter => {
@@ -429,7 +428,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
});
}
- public $sendDAMessage(handle: number, message: DebugProtocol.ProtocolMessage): TPromise {
+ public $sendDAMessage(handle: number, message: DebugProtocol.ProtocolMessage): Promise {
// VS Code -> DA
convertToDAPaths(message, source => uriToString(source));
@@ -445,7 +444,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
return void 0;
}
- public $stopDASession(handle: number): TPromise {
+ public $stopDASession(handle: number): Thenable {
const tracker = this._debugAdaptersTrackers.get(handle);
this._debugAdaptersTrackers.delete(handle);
@@ -526,10 +525,10 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
public $provideDebugConfigurations(handle: number, folderUri: UriComponents | undefined): Thenable {
let provider = this._providerByHandle.get(handle);
if (!provider) {
- return TPromise.wrapError(new Error('no handler found'));
+ return Promise.reject(new Error('no handler found'));
}
if (!provider.provideDebugConfigurations) {
- return TPromise.wrapError(new Error('handler has no method provideDebugConfigurations'));
+ return Promise.reject(new Error('handler has no method provideDebugConfigurations'));
}
return asThenable(() => provider.provideDebugConfigurations(this.getFolder(folderUri), CancellationToken.None));
}
@@ -537,10 +536,10 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
public $resolveDebugConfiguration(handle: number, folderUri: UriComponents | undefined, debugConfiguration: vscode.DebugConfiguration): Thenable {
let provider = this._providerByHandle.get(handle);
if (!provider) {
- return TPromise.wrapError(new Error('no handler found'));
+ return Promise.reject(new Error('no handler found'));
}
if (!provider.resolveDebugConfiguration) {
- return TPromise.wrapError(new Error('handler has no method resolveDebugConfiguration'));
+ return Promise.reject(new Error('handler has no method resolveDebugConfiguration'));
}
return asThenable(() => provider.resolveDebugConfiguration(this.getFolder(folderUri), debugConfiguration, CancellationToken.None));
}
@@ -548,10 +547,10 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
public $provideDebugAdapter(handle: number, sessionDto: IDebugSessionDto, folderUri: UriComponents | undefined, config: vscode.DebugConfiguration): Thenable {
let provider = this._providerByHandle.get(handle);
if (!provider) {
- return TPromise.wrapError(new Error('no handler found'));
+ return Promise.reject(new Error('no handler found'));
}
if (!provider.debugAdapterExecutable && !provider.provideDebugAdapter) {
- return TPromise.wrapError(new Error('handler has no methods provideDebugAdapter or debugAdapterExecutable'));
+ return Promise.reject(new Error('handler has no methods provideDebugAdapter or debugAdapterExecutable'));
}
return this.getAdapterDescriptor(provider, this.getSession(sessionDto), folderUri, config);
}
@@ -602,7 +601,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
return false;
}
- private getDebugAdapterTrackers(sessionDto: IDebugSessionDto, folderUri: UriComponents | undefined, config: vscode.DebugConfiguration): TPromise {
+ private getDebugAdapterTrackers(sessionDto: IDebugSessionDto, folderUri: UriComponents | undefined, config: vscode.DebugConfiguration): Promise {
const session = this.getSession(sessionDto);
const folder = this.getFolder(folderUri);
@@ -612,7 +611,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
.filter(pair => pair.provider.provideDebugAdapterTracker && (pair.type === type || pair.type === '*'))
.map(pair => pair.provider.provideDebugAdapterTracker(session, folder, config, CancellationToken.None));
- return TPromise.join(promises).then(trackers => {
+ return Promise.all(promises).then(trackers => {
if (trackers.length > 0) {
return new MultiTracker(trackers);
}
@@ -624,7 +623,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
// a "debugServer" attribute in the launch config takes precedence
if (typeof config.debugServer === 'number') {
- return TPromise.wrap(new DebugAdapterServer(config.debugServer));
+ return Promise.resolve(new DebugAdapterServer(config.debugServer));
}
if (debugConfigProvider) {
@@ -649,7 +648,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
}
// fallback: use executable information from package.json
- return TPromise.wrap(ExecutableDebugAdapter.platformAdapterExecutable(this._extensionService.getAllExtensionDescriptions(), config.type));
+ return Promise.resolve(ExecutableDebugAdapter.platformAdapterExecutable(this._extensionService.getAllExtensionDescriptions(), config.type));
}
private startBreakpoints() {
@@ -869,8 +868,8 @@ class DirectDebugAdapter extends AbstractDebugAdapter {
}
}
- startSession(): TPromise {
- return TPromise.wrap(void 0);
+ startSession(): Promise {
+ return Promise.resolve(void 0);
}
// VSCode -> DA
@@ -878,8 +877,8 @@ class DirectDebugAdapter extends AbstractDebugAdapter {
this.transport.sendUp(message);
}
- stopSession(): TPromise {
+ stopSession(): Promise {
this.transport.stop();
- return TPromise.wrap(void 0);
+ return Promise.resolve(void 0);
}
}
diff --git a/src/vs/workbench/api/node/extHostExtensionActivator.ts b/src/vs/workbench/api/node/extHostExtensionActivator.ts
index 05f10aa5768..0e078d1bf47 100644
--- a/src/vs/workbench/api/node/extHostExtensionActivator.ts
+++ b/src/vs/workbench/api/node/extHostExtensionActivator.ts
@@ -6,12 +6,11 @@
import * as nls from 'vs/nls';
import { IDisposable } from 'vs/base/common/lifecycle';
import Severity from 'vs/base/common/severity';
-import { TPromise } from 'vs/base/common/winjs.base';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
const hasOwnProperty = Object.hasOwnProperty;
-const NO_OP_VOID_PROMISE = TPromise.wrap(void 0);
+const NO_OP_VOID_PROMISE = Promise.resolve(void 0);
export interface IExtensionMemento {
get(key: string, defaultValue: T): T;
@@ -32,7 +31,7 @@ export interface IExtensionContext {
* Represents the source code (module) of an extension.
*/
export interface IExtensionModule {
- activate(ctx: IExtensionContext): TPromise;
+ activate(ctx: IExtensionContext): Promise;
deactivate(): void;
}
@@ -162,7 +161,7 @@ export class FailedExtension extends ActivatedExtension {
export interface IExtensionsActivatorHost {
showMessage(severity: Severity, message: string): void;
- actualActivateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): TPromise;
+ actualActivateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise;
}
export class ExtensionActivatedByEvent {
@@ -184,7 +183,7 @@ export class ExtensionsActivator {
private readonly _registry: ExtensionDescriptionRegistry;
private readonly _host: IExtensionsActivatorHost;
- private readonly _activatingExtensions: { [extensionId: string]: TPromise; };
+ private readonly _activatingExtensions: { [extensionId: string]: Promise; };
private readonly _activatedExtensions: { [extensionId: string]: ActivatedExtension; };
/**
* A map of already activated events to speed things up if the same activation event is triggered multiple times.
@@ -210,7 +209,7 @@ export class ExtensionsActivator {
return this._activatedExtensions[extensionId];
}
- public activateByEvent(activationEvent: string, reason: ExtensionActivationReason): TPromise {
+ public activateByEvent(activationEvent: string, reason: ExtensionActivationReason): Promise {
if (this._alreadyActivatedEvents[activationEvent]) {
return NO_OP_VOID_PROMISE;
}
@@ -220,7 +219,7 @@ export class ExtensionsActivator {
});
}
- public activateById(extensionId: string, reason: ExtensionActivationReason): TPromise {
+ public activateById(extensionId: string, reason: ExtensionActivationReason): Promise {
let desc = this._registry.getExtensionDescription(extensionId);
if (!desc) {
throw new Error('Extension `' + extensionId + '` is not known');
@@ -273,15 +272,15 @@ export class ExtensionsActivator {
}
}
- private _activateExtensions(extensionDescriptions: IExtensionDescription[], reason: ExtensionActivationReason, recursionLevel: number): TPromise {
+ private _activateExtensions(extensionDescriptions: IExtensionDescription[], reason: ExtensionActivationReason, recursionLevel: number): Promise {
// console.log(recursionLevel, '_activateExtensions: ', extensionDescriptions.map(p => p.id));
if (extensionDescriptions.length === 0) {
- return TPromise.as(void 0);
+ return Promise.resolve(void 0);
}
extensionDescriptions = extensionDescriptions.filter((p) => !hasOwnProperty.call(this._activatedExtensions, p.id));
if (extensionDescriptions.length === 0) {
- return TPromise.as(void 0);
+ return Promise.resolve(void 0);
}
if (recursionLevel > 10) {
@@ -292,7 +291,7 @@ export class ExtensionsActivator {
const error = new Error('More than 10 levels of dependencies (most likely a dependency loop)');
this._activatedExtensions[extensionDescriptions[i].id] = new FailedExtension(error);
}
- return TPromise.as(void 0);
+ return Promise.resolve(void 0);
}
let greenMap: { [id: string]: IExtensionDescription; } = Object.create(null),
@@ -316,7 +315,7 @@ export class ExtensionsActivator {
if (red.length === 0) {
// Finally reached only leafs!
- return TPromise.join(green.map((p) => this._activateExtension(p, reason))).then(_ => void 0);
+ return Promise.all(green.map((p) => this._activateExtension(p, reason))).then(_ => void 0);
}
return this._activateExtensions(green, reason, recursionLevel + 1).then(_ => {
@@ -324,9 +323,9 @@ export class ExtensionsActivator {
});
}
- private _activateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): TPromise {
+ private _activateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise {
if (hasOwnProperty.call(this._activatedExtensions, extensionDescription.id)) {
- return TPromise.as(void 0);
+ return Promise.resolve(void 0);
}
if (hasOwnProperty.call(this._activatingExtensions, extensionDescription.id)) {
diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts
index f1ff54df8a1..a2d339295f1 100644
--- a/src/vs/workbench/api/node/extHostExtensionService.ts
+++ b/src/vs/workbench/api/node/extHostExtensionService.ts
@@ -7,7 +7,6 @@ import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { join } from 'path';
import { realpath } from 'vs/base/node/pfs';
import Severity from 'vs/base/common/severity';
-import { TPromise } from 'vs/base/common/winjs.base';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { ExtHostStorage } from 'vs/workbench/api/node/extHostStorage';
@@ -83,7 +82,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
private readonly _proxy: MainThreadExtensionServiceShape;
private readonly _extHostLogService: ExtHostLogService;
private _activator: ExtensionsActivator;
- private _extensionPathIndex: TPromise>;
+ private _extensionPathIndex: Promise>;
/**
* This class is constructed manually because it is a service, so it doesn't use any ctor injection
*/
@@ -123,7 +122,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
}
},
- actualActivateExtension: (extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): TPromise => {
+ actualActivateExtension: (extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise => {
return this._activateExtension(extensionDescription, reason);
}
});
@@ -132,7 +131,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
});
}
- public onExtensionAPIReady(): TPromise {
+ public onExtensionAPIReady(): Thenable {
return this._barrier.wait();
}
@@ -143,7 +142,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
return false;
}
- public activateByEvent(activationEvent: string, startup: boolean): TPromise {
+ public activateByEvent(activationEvent: string, startup: boolean): Thenable {
const reason = new ExtensionActivatedByEvent(startup, activationEvent);
if (this._barrier.isOpen()) {
return this._activator.activateByEvent(activationEvent, reason);
@@ -152,7 +151,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
}
}
- public activateById(extensionId: string, reason: ExtensionActivationReason): TPromise {
+ public activateById(extensionId: string, reason: ExtensionActivationReason): Thenable {
if (this._barrier.isOpen()) {
return this._activator.activateById(extensionId, reason);
} else {
@@ -160,12 +159,12 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
}
}
- public activateByIdWithErrors(extensionId: string, reason: ExtensionActivationReason): TPromise {
+ public activateByIdWithErrors(extensionId: string, reason: ExtensionActivationReason): Thenable {
return this.activateById(extensionId, reason).then(() => {
const extension = this._activator.getActivatedExtension(extensionId);
if (extension.activationFailed) {
// activation failed => bubble up the error as the promise result
- return TPromise.wrapError(extension.activationFailedError);
+ return Promise.reject(extension.activationFailedError);
}
return void 0;
});
@@ -188,7 +187,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
}
// create trie to enable fast 'filename -> extension id' look up
- public getExtensionPathIndex(): TPromise> {
+ public getExtensionPathIndex(): Promise> {
if (!this._extensionPathIndex) {
const tree = TernarySearchTree.forPaths();
const extensions = this.getAllExtensionDescriptions().map(ext => {
@@ -197,14 +196,14 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
}
return realpath(ext.extensionLocation.fsPath).then(value => tree.set(URI.file(value).fsPath, ext));
});
- this._extensionPathIndex = TPromise.join(extensions).then(() => tree);
+ this._extensionPathIndex = Promise.all(extensions).then(() => tree);
}
return this._extensionPathIndex;
}
- public deactivate(extensionId: string): TPromise {
- let result: TPromise = TPromise.as(void 0);
+ public deactivate(extensionId: string): Thenable {
+ let result = Promise.resolve(void 0);
if (!this._barrier.isOpen()) {
return result;
@@ -222,9 +221,9 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
// call deactivate if available
try {
if (typeof extension.module.deactivate === 'function') {
- result = TPromise.wrap(extension.module.deactivate()).then(null, (err) => {
+ result = Promise.resolve(extension.module.deactivate()).then(null, (err) => {
// TODO: Do something with err if this is not the shutdown case
- return TPromise.as(void 0);
+ return Promise.resolve(void 0);
});
}
} catch (err) {
@@ -247,7 +246,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
// --- impl
- private _activateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): TPromise {
+ private _activateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise {
return this._doActivateExtension(extensionDescription, reason).then((activatedExtension) => {
const activationTimes = activatedExtension.activationTimes;
let activationEvent = (reason instanceof ExtensionActivatedByEvent ? reason.activationEvent : null);
@@ -259,7 +258,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
});
}
- private _doActivateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): TPromise {
+ private _doActivateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise {
let event = getTelemetryActivationEvent(extensionDescription, reason);
/* __GDPR__
"activatePlugin" : {
@@ -271,36 +270,27 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
this._mainThreadTelemetry.$publicLog('activatePlugin', event);
if (!extensionDescription.main) {
// Treat the extension as being empty => NOT AN ERROR CASE
- return TPromise.as(new EmptyExtension(ExtensionActivationTimes.NONE));
+ return Promise.resolve(new EmptyExtension(ExtensionActivationTimes.NONE));
}
this._extHostLogService.info(`ExtensionService#_doActivateExtension ${extensionDescription.id} ${JSON.stringify(reason)}`);
const activationTimesBuilder = new ExtensionActivationTimesBuilder(reason.startup);
- return TPromise.join([
+ return Promise.all([
loadCommonJSModule(this._extHostLogService, extensionDescription.main, activationTimesBuilder),
this._loadExtensionContext(extensionDescription)
]).then(values => {
return ExtHostExtensionService._callActivate(this._extHostLogService, extensionDescription.id, values[0], values[1], activationTimesBuilder);
- }, (errors: any[]) => {
- // Avoid failing with an array of errors, fail with a single error
- if (errors[0]) {
- return TPromise.wrapError(errors[0]);
- }
- if (errors[1]) {
- return TPromise.wrapError(errors[1]);
- }
- return undefined;
});
}
- private _loadExtensionContext(extensionDescription: IExtensionDescription): TPromise {
+ private _loadExtensionContext(extensionDescription: IExtensionDescription): Promise {
let globalState = new ExtensionMemento(extensionDescription.id, true, this._storage);
let workspaceState = new ExtensionMemento(extensionDescription.id, false, this._storage);
this._extHostLogService.trace(`ExtensionService#loadExtensionContext ${extensionDescription.id}`);
- return TPromise.join([
+ return Promise.all([
globalState.whenReady,
workspaceState.whenReady
]).then(() => {
@@ -334,20 +324,20 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
try {
activationTimesBuilder.activateCallStart();
logService.trace(`ExtensionService#_callActivateOptional ${extensionId}`);
- const activateResult: TPromise = extensionModule.activate.apply(global, [context]);
+ const activateResult: Thenable = extensionModule.activate.apply(global, [context]);
activationTimesBuilder.activateCallStop();
activationTimesBuilder.activateResolveStart();
- return TPromise.as(activateResult).then((value) => {
+ return Promise.resolve(activateResult).then((value) => {
activationTimesBuilder.activateResolveStop();
return value;
});
} catch (err) {
- return TPromise.wrapError(err);
+ return Promise.reject(err);
}
} else {
// No activate found => the module is the extension's exports
- return TPromise.as(extensionModule);
+ return Promise.resolve(extensionModule);
}
}
@@ -358,18 +348,18 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
}
}
-function loadCommonJSModule(logService: ILogService, modulePath: string, activationTimesBuilder: ExtensionActivationTimesBuilder): TPromise {
+function loadCommonJSModule(logService: ILogService, modulePath: string, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise {
let r: T | null = null;
activationTimesBuilder.codeLoadingStart();
logService.info(`ExtensionService#loadCommonJSModule ${modulePath}`);
try {
r = require.__$__nodeRequire(modulePath);
} catch (e) {
- return TPromise.wrapError(e);
+ return Promise.reject(e);
} finally {
activationTimesBuilder.codeLoadingStop();
}
- return TPromise.as(r);
+ return Promise.resolve(r);
}
function getTelemetryActivationEvent(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): any {
diff --git a/src/vs/workbench/api/node/extHostQuickOpen.ts b/src/vs/workbench/api/node/extHostQuickOpen.ts
index e7c92c50fd4..65e3e92a43c 100644
--- a/src/vs/workbench/api/node/extHostQuickOpen.ts
+++ b/src/vs/workbench/api/node/extHostQuickOpen.ts
@@ -7,7 +7,6 @@ import { asThenable } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Emitter } from 'vs/base/common/event';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
-import { TPromise } from 'vs/base/common/winjs.base';
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { InputBox, InputBoxOptions, QuickInput, QuickInputButton, QuickPick, QuickPickItem, QuickPickOptions, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode';
@@ -43,7 +42,7 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
// clear state from last invocation
this._onDidSelectItem = undefined;
- const itemsPromise = >TPromise.wrap(itemsOrItemsPromise);
+ const itemsPromise = >Promise.resolve(itemsOrItemsPromise);
const quickPickWidget = this._proxy.$show({
placeHolder: options && options.placeHolder,
@@ -120,7 +119,7 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
this._proxy.$setError(err);
- return TPromise.wrapError(err);
+ return Promise.reject(err);
});
}
@@ -145,7 +144,7 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
this._proxy.$setError(err);
- return TPromise.wrapError(err);
+ return Promise.reject(err);
});
}
diff --git a/src/vs/workbench/api/node/extHostSCM.ts b/src/vs/workbench/api/node/extHostSCM.ts
index a322633776e..e0bf0ca9a11 100644
--- a/src/vs/workbench/api/node/extHostSCM.ts
+++ b/src/vs/workbench/api/node/extHostSCM.ts
@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import { URI, UriComponents } from 'vs/base/common/uri';
-import { TPromise } from 'vs/base/common/winjs.base';
import { Event, Emitter, once } from 'vs/base/common/event';
import { debounce } from 'vs/base/common/decorators';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
@@ -604,23 +603,23 @@ export class ExtHostSCM implements ExtHostSCMShape {
const sourceControl = this._sourceControls.get(sourceControlHandle);
if (!sourceControl || !sourceControl.quickDiffProvider) {
- return TPromise.as(null);
+ return Promise.resolve(null);
}
return asThenable(() => sourceControl.quickDiffProvider.provideOriginalResource(uri, token));
}
- $onInputBoxValueChange(sourceControlHandle: number, value: string): TPromise {
+ $onInputBoxValueChange(sourceControlHandle: number, value: string): Promise