merge master

This commit is contained in:
isidor
2018-12-28 15:30:48 +01:00
122 changed files with 1425 additions and 1635 deletions
+3 -1
View File
@@ -48,5 +48,7 @@
}, {
"fileMatch": [ "cglicenses.json" ],
"url": "./.vscode/cglicenses.schema.json"
}]
}
],
"git.ignoreLimitWarning": true
}
@@ -2,7 +2,7 @@ steps:
- script: |
set -e
sudo apt-get update
sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 libgconf-2-4 dbus xvfb libgtk-3-0
sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0
sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb
sudo chmod +x /etc/init.d/xvfb
sudo update-rc.d xvfb defaults
+1 -1
View File
@@ -100,7 +100,7 @@ gulp.task('optimize-vscode', ['clean-optimized-vscode', 'compile-build', 'compil
gulp.task('optimize-index-js', ['optimize-vscode'], () => {
const fullpath = path.join(process.cwd(), 'out-vscode/vs/code/electron-browser/workbench/workbench.js');
const fullpath = path.join(process.cwd(), 'out-vscode/bootstrap-window.js');
const contents = fs.readFileSync(fullpath).toString();
const newContents = contents.replace('[/*BUILD->INSERT_NODE_MODULES*/]', JSON.stringify(nodeModules));
fs.writeFileSync(fullpath, newContents);
+1 -1
View File
@@ -53,7 +53,7 @@
"vscode-ripgrep": "^1.2.5",
"vscode-sqlite3": "4.0.5",
"vscode-textmate": "^4.0.1",
"vscode-xterm": "3.10.0-beta7",
"vscode-xterm": "3.10.0-beta9",
"winreg": "^1.2.4",
"yauzl": "^2.9.1",
"yazl": "^2.4.3"
+1 -1
View File
@@ -1,7 +1,7 @@
Package: @@NAME@@
Version: @@VERSION@@
Section: devel
Depends: libnotify4, libnss3 (>= 2:3.26), gnupg, apt, libxkbfile1, libgconf-2-4, libsecret-1-0, libgtk-3-0 (>= 3.10.0), libxss1
Depends: libnotify4, libnss3 (>= 2:3.26), gnupg, apt, libxkbfile1, libsecret-1-0, libgtk-3-0 (>= 3.10.0), libxss1
Priority: optional
Architecture: @@ARCHITECTURE@@
Maintainer: Microsoft Corporation <vscode-linux@microsoft.com>
-2
View File
@@ -27,7 +27,6 @@
"libX11.so.6()(64bit)",
"libXss.so.1()(64bit)",
"libXtst.so.6()(64bit)",
"libgconf-2.so.4()(64bit)",
"libgmodule-2.0.so.0()(64bit)",
"librt.so.1()(64bit)",
"libglib-2.0.so.0()(64bit)",
@@ -107,7 +106,6 @@
"libgcc_s.so.1",
"libgcc_s.so.1(GCC_4.0.0)",
"libgcc_s.so.1(GLIBC_2.0)",
"libgconf-2.so.4",
"libgdk-x11-2.0.so.0",
"libgdk_pixbuf-2.0.so.0",
"libgio-2.0.so.0",
-1
View File
@@ -16,7 +16,6 @@ parts:
stage-packages:
- libasound2
- libc++1
- libgconf2-4
- libnotify4
- libnspr4
- libnss3
+1 -3
View File
@@ -319,7 +319,6 @@
"./vs/nls.mock.ts",
"./vs/platform/actions/browser/menuItemActionItem.ts",
"./vs/platform/actions/common/actions.ts",
"./vs/platform/actions/common/menu.ts",
"./vs/platform/actions/common/menuService.ts",
"./vs/platform/actions/test/common/menuService.test.ts",
"./vs/platform/backup/common/backup.ts",
@@ -607,7 +606,6 @@
"./vs/workbench/parts/output/common/output.ts",
"./vs/workbench/parts/output/common/outputLinkComputer.ts",
"./vs/workbench/parts/output/common/outputLinkProvider.ts",
"./vs/workbench/parts/performance/electron-browser/stats.ts",
"./vs/workbench/parts/preferences/browser/settingsWidgets.ts",
"./vs/workbench/parts/preferences/common/smartSnippetInserter.ts",
"./vs/workbench/parts/preferences/test/common/smartSnippetInserter.test.ts",
@@ -812,4 +810,4 @@
"exclude": [
"./typings/require-monaco.d.ts"
]
}
}
@@ -38,11 +38,11 @@ suite('QuickOpen', () => {
model.addEntries([entry1, entry2, entry3]);
const ds = new DataSource(model);
assert.equal(entry1.getId(), ds.getId(null, entry1));
assert.equal(true, ds.hasChildren(null, model));
assert.equal(false, ds.hasChildren(null, entry1));
assert.equal(entry1.getId(), ds.getId(null!, entry1));
assert.equal(true, ds.hasChildren(null!, model));
assert.equal(false, ds.hasChildren(null!, entry1));
ds.getChildren(null, model).then((children: any[]) => {
ds.getChildren(null!, model).then((children: any[]) => {
assert.equal(3, children.length);
});
});
@@ -36,7 +36,7 @@ export class FakeRenderer {
class TreeContext implements _.ITreeContext {
public tree: _.ITree = null;
public tree: _.ITree = null!;
public options: _.ITreeOptions = { autoExpandSingleChildren: true };
public dataSource: _.IDataSource;
public renderer: _.IRenderer;
@@ -17,7 +17,7 @@ function makeItem(id, height): any {
}
function makeItems(...args: any[]) {
var r = [];
var r: any[] = [];
for (var i = 0; i < args.length; i += 2) {
r.push(makeItem(args[i], args[i + 1]));
@@ -59,7 +59,7 @@ suite('TreeView - HeightMap', () => {
teardown(() => {
rangeMap.dispose();
rangeMap = null;
rangeMap = null!;
});
test('simple', () => {
@@ -96,7 +96,7 @@ function attachTo(item: ProcessItem) {
config.port = parseInt(matches[2]);
}
ipcRenderer.send('vscode:workbenchCommand', { id: 'workbench.action.debug.start', from: 'processExplorer', args: [config] });
ipcRenderer.send('vscode:workbenchCommand', { id: 'debug.startFromConfig', from: 'processExplorer', args: [config] });
}
function getProcessIdWithHighestProperty(processList, propertyName: string) {
@@ -299,4 +299,4 @@ export function startup(data: ProcessExplorerData): void {
applyZoom(webFrame.getZoomLevel() - 1);
}
};
}
}
+10 -1
View File
@@ -455,7 +455,10 @@ export class CodeApplication extends Disposable {
const appInstantiationService = this.instantiationService.createChild(services);
return appInstantiationService.invokeFunction(accessor => this.initStorageService(accessor)).then(() => appInstantiationService);
return appInstantiationService.invokeFunction(accessor => Promise.all([
this.initStorageService(accessor),
this.initBackupService(accessor)
])).then(() => appInstantiationService);
}
private initStorageService(accessor: ServicesAccessor): Promise<void> {
@@ -495,6 +498,12 @@ export class CodeApplication extends Disposable {
});
}
private initBackupService(accessor: ServicesAccessor): Promise<void> {
const backupMainService = accessor.get(IBackupMainService) as BackupMainService;
return backupMainService.initialize();
}
private openFirstWindow(accessor: ServicesAccessor): ICodeWindow[] {
const appInstantiationService = accessor.get(IInstantiationService);
@@ -82,16 +82,16 @@ suite('OutlineModel', function () {
}
function fakeMarker(range: Range): IMarker {
return { ...range, owner: 'ffff', message: 'test', severity: MarkerSeverity.Error, resource: null };
return { ...range, owner: 'ffff', message: 'test', severity: MarkerSeverity.Error, resource: null! };
}
test('OutlineElement - updateMarker', function () {
let e0 = new OutlineElement('foo1', null, fakeSymbolInformation(new Range(1, 1, 1, 10)));
let e1 = new OutlineElement('foo2', null, fakeSymbolInformation(new Range(2, 1, 5, 1)));
let e2 = new OutlineElement('foo3', null, fakeSymbolInformation(new Range(6, 1, 10, 10)));
let e0 = new OutlineElement('foo1', null!, fakeSymbolInformation(new Range(1, 1, 1, 10)));
let e1 = new OutlineElement('foo2', null!, fakeSymbolInformation(new Range(2, 1, 5, 1)));
let e2 = new OutlineElement('foo3', null!, fakeSymbolInformation(new Range(6, 1, 10, 10)));
let group = new OutlineGroup('group', null, null, 1);
let group = new OutlineGroup('group', null!, null!, 1);
group.children[e0.id] = e0;
group.children[e1.id] = e1;
group.children[e2.id] = e2;
@@ -113,11 +113,11 @@ suite('OutlineModel', function () {
test('OutlineElement - updateMarker, 2', function () {
let p = new OutlineElement('A', null, fakeSymbolInformation(new Range(1, 1, 11, 1)));
let c1 = new OutlineElement('A/B', null, fakeSymbolInformation(new Range(2, 4, 5, 4)));
let c2 = new OutlineElement('A/C', null, fakeSymbolInformation(new Range(6, 4, 9, 4)));
let p = new OutlineElement('A', null!, fakeSymbolInformation(new Range(1, 1, 11, 1)));
let c1 = new OutlineElement('A/B', null!, fakeSymbolInformation(new Range(2, 4, 5, 4)));
let c2 = new OutlineElement('A/C', null!, fakeSymbolInformation(new Range(6, 4, 9, 4)));
let group = new OutlineGroup('group', null, null, 1);
let group = new OutlineGroup('group', null!, null!, 1);
group.children[p.id] = p;
p.children[c1.id] = c1;
p.children[c2.id] = c2;
@@ -155,16 +155,16 @@ suite('OutlineModel', function () {
let model = new class extends OutlineModel {
constructor() {
super(null);
super(null!);
}
readyForTesting() {
this._groups = this.children as any;
}
};
model.children['g1'] = new OutlineGroup('g1', model, null, 1);
model.children['g1'] = new OutlineGroup('g1', model, null!, 1);
model.children['g1'].children['c1'] = new OutlineElement('c1', model.children['g1'], fakeSymbolInformation(new Range(1, 1, 11, 1)));
model.children['g2'] = new OutlineGroup('g2', model, null, 1);
model.children['g2'] = new OutlineGroup('g2', model, null!, 1);
model.children['g2'].children['c2'] = new OutlineElement('c2', model.children['g2'], fakeSymbolInformation(new Range(1, 1, 7, 1)));
model.children['g2'].children['c2'].children['c2.1'] = new OutlineElement('c2.1', model.children['g2'].children['c2'], fakeSymbolInformation(new Range(1, 3, 2, 19)));
model.children['g2'].children['c2'].children['c2.2'] = new OutlineElement('c2.2', model.children['g2'].children['c2'], fakeSymbolInformation(new Range(4, 1, 6, 10)));
@@ -22,7 +22,7 @@ class TestSnippetController extends SnippetController2 {
}
isInSnippetMode(): boolean {
return SnippetController2.InSnippetMode.getValue(this._contextKeyService);
return SnippetController2.InSnippetMode.getValue(this._contextKeyService)!;
}
}
@@ -42,7 +42,7 @@ suite('SnippetController', () => {
}
withTestCodeEditor(lines, {}, (editor, cursor) => {
editor.getModel().updateOptions({
editor.getModel()!.updateOptions({
insertSpaces: false
});
let snippetController = editor.registerAndInstantiateContribution<TestSnippetController>(TestSnippetController);
@@ -63,30 +63,30 @@ suite('SnippetController', () => {
editor.setPosition({ lineNumber: 4, column: 2 });
snippetController.insert(template, 0, 0);
assert.equal(editor.getModel().getLineContent(4), '\tfor (var index; index < array.length; index++) {');
assert.equal(editor.getModel().getLineContent(5), '\t\tvar element = array[index];');
assert.equal(editor.getModel().getLineContent(6), '\t\t');
assert.equal(editor.getModel().getLineContent(7), '\t}');
assert.equal(editor.getModel()!.getLineContent(4), '\tfor (var index; index < array.length; index++) {');
assert.equal(editor.getModel()!.getLineContent(5), '\t\tvar element = array[index];');
assert.equal(editor.getModel()!.getLineContent(6), '\t\t');
assert.equal(editor.getModel()!.getLineContent(7), '\t}');
editor.trigger('test', 'type', { text: 'i' });
assert.equal(editor.getModel().getLineContent(4), '\tfor (var i; i < array.length; i++) {');
assert.equal(editor.getModel().getLineContent(5), '\t\tvar element = array[i];');
assert.equal(editor.getModel().getLineContent(6), '\t\t');
assert.equal(editor.getModel().getLineContent(7), '\t}');
assert.equal(editor.getModel()!.getLineContent(4), '\tfor (var i; i < array.length; i++) {');
assert.equal(editor.getModel()!.getLineContent(5), '\t\tvar element = array[i];');
assert.equal(editor.getModel()!.getLineContent(6), '\t\t');
assert.equal(editor.getModel()!.getLineContent(7), '\t}');
snippetController.next();
editor.trigger('test', 'type', { text: 'arr' });
assert.equal(editor.getModel().getLineContent(4), '\tfor (var i; i < arr.length; i++) {');
assert.equal(editor.getModel().getLineContent(5), '\t\tvar element = arr[i];');
assert.equal(editor.getModel().getLineContent(6), '\t\t');
assert.equal(editor.getModel().getLineContent(7), '\t}');
assert.equal(editor.getModel()!.getLineContent(4), '\tfor (var i; i < arr.length; i++) {');
assert.equal(editor.getModel()!.getLineContent(5), '\t\tvar element = arr[i];');
assert.equal(editor.getModel()!.getLineContent(6), '\t\t');
assert.equal(editor.getModel()!.getLineContent(7), '\t}');
snippetController.prev();
editor.trigger('test', 'type', { text: 'j' });
assert.equal(editor.getModel().getLineContent(4), '\tfor (var j; j < arr.length; j++) {');
assert.equal(editor.getModel().getLineContent(5), '\t\tvar element = arr[j];');
assert.equal(editor.getModel().getLineContent(6), '\t\t');
assert.equal(editor.getModel().getLineContent(7), '\t}');
assert.equal(editor.getModel()!.getLineContent(4), '\tfor (var j; j < arr.length; j++) {');
assert.equal(editor.getModel()!.getLineContent(5), '\t\tvar element = arr[j];');
assert.equal(editor.getModel()!.getLineContent(6), '\t\t');
assert.equal(editor.getModel()!.getLineContent(7), '\t}');
snippetController.next();
snippetController.next();
@@ -99,10 +99,10 @@ suite('SnippetController', () => {
editor.setPosition({ lineNumber: 4, column: 2 });
snippetController.insert(template, 0, 0);
assert.equal(editor.getModel().getLineContent(4), '\tfor (var index; index < array.length; index++) {');
assert.equal(editor.getModel().getLineContent(5), '\t\tvar element = array[index];');
assert.equal(editor.getModel().getLineContent(6), '\t\t');
assert.equal(editor.getModel().getLineContent(7), '\t}');
assert.equal(editor.getModel()!.getLineContent(4), '\tfor (var index; index < array.length; index++) {');
assert.equal(editor.getModel()!.getLineContent(5), '\t\tvar element = array[index];');
assert.equal(editor.getModel()!.getLineContent(6), '\t\t');
assert.equal(editor.getModel()!.getLineContent(7), '\t}');
snippetController.cancel();
assert.deepEqual(editor.getPosition(), new Position(4, 16));
@@ -114,7 +114,7 @@ suite('SnippetController', () => {
// editor.setPosition({ lineNumber: 4, column: 2 });
// snippetController.insert(codeSnippet, 0, 0);
// editor.getModel().applyEdits([{
// editor.getModel()!.applyEdits([{
// forceMoveMarkers: false,
// identifier: null,
// isAutoWhitespaceEdit: false,
@@ -131,7 +131,7 @@ suite('SnippetController', () => {
// editor.setPosition({ lineNumber: 4, column: 2 });
// snippetController.run(codeSnippet, 0, 0);
// editor.getModel().applyEdits([{
// editor.getModel()!.applyEdits([{
// forceMoveMarkers: false,
// identifier: null,
// isAutoWhitespaceEdit: false,
@@ -148,7 +148,7 @@ suite('SnippetController', () => {
// editor.setPosition({ lineNumber: 4, column: 2 });
// snippetController.run(codeSnippet, 0, 0);
// editor.getModel().applyEdits([{
// editor.getModel()!.applyEdits([{
// forceMoveMarkers: false,
// identifier: null,
// isAutoWhitespaceEdit: false,
@@ -165,7 +165,7 @@ suite('SnippetController', () => {
// editor.setPosition({ lineNumber: 4, column: 2 });
// snippetController.run(codeSnippet, 0, 0);
// editor.getModel().applyEdits([{
// editor.getModel()!.applyEdits([{
// forceMoveMarkers: false,
// identifier: null,
// isAutoWhitespaceEdit: false,
@@ -182,7 +182,7 @@ suite('SnippetController', () => {
editor.setPosition({ lineNumber: 4, column: 2 });
snippetController.insert(codeSnippet, 0, 0);
editor.getModel().setValue('goodbye');
editor.getModel()!.setValue('goodbye');
assert.equal(snippetController.isInSnippetMode(), false);
});
@@ -193,7 +193,7 @@ suite('SnippetController', () => {
editor.setPosition({ lineNumber: 4, column: 2 });
snippetController.insert(codeSnippet, 0, 0);
editor.getModel().undo();
editor.getModel()!.undo();
assert.equal(snippetController.isInSnippetMode(), false);
});
@@ -242,8 +242,8 @@ suite('SnippetController', () => {
codeSnippet = 'foo$0';
snippetController.insert(codeSnippet, 0, 0);
assert.equal(editor.getSelections().length, 2);
const [first, second] = editor.getSelections();
assert.equal(editor.getSelections()!.length, 2);
const [first, second] = editor.getSelections()!;
assert.ok(first.equalsRange({ startLineNumber: 1, startColumn: 4, endLineNumber: 1, endColumn: 4 }), first.toString());
assert.ok(second.equalsRange({ startLineNumber: 2, startColumn: 4, endLineNumber: 2, endColumn: 4 }), second.toString());
});
@@ -257,8 +257,8 @@ suite('SnippetController', () => {
codeSnippet = 'foo$0bar';
snippetController.insert(codeSnippet, 0, 0);
assert.equal(editor.getSelections().length, 2);
const [first, second] = editor.getSelections();
assert.equal(editor.getSelections()!.length, 2);
const [first, second] = editor.getSelections()!;
assert.ok(first.equalsRange({ startLineNumber: 1, startColumn: 4, endLineNumber: 1, endColumn: 4 }), first.toString());
assert.ok(second.equalsRange({ startLineNumber: 2, startColumn: 4, endLineNumber: 2, endColumn: 4 }), second.toString());
});
@@ -272,8 +272,8 @@ suite('SnippetController', () => {
codeSnippet = 'foo$0bar';
snippetController.insert(codeSnippet, 0, 0);
assert.equal(editor.getSelections().length, 2);
const [first, second] = editor.getSelections();
assert.equal(editor.getSelections()!.length, 2);
const [first, second] = editor.getSelections()!;
assert.ok(first.equalsRange({ startLineNumber: 1, startColumn: 4, endLineNumber: 1, endColumn: 4 }), first.toString());
assert.ok(second.equalsRange({ startLineNumber: 1, startColumn: 14, endLineNumber: 1, endColumn: 14 }), second.toString());
});
@@ -287,8 +287,8 @@ suite('SnippetController', () => {
codeSnippet = 'foo\n$0\nbar';
snippetController.insert(codeSnippet, 0, 0);
assert.equal(editor.getSelections().length, 2);
const [first, second] = editor.getSelections();
assert.equal(editor.getSelections()!.length, 2);
const [first, second] = editor.getSelections()!;
assert.ok(first.equalsRange({ startLineNumber: 2, startColumn: 1, endLineNumber: 2, endColumn: 1 }), first.toString());
assert.ok(second.equalsRange({ startLineNumber: 4, startColumn: 1, endLineNumber: 4, endColumn: 1 }), second.toString());
});
@@ -302,8 +302,8 @@ suite('SnippetController', () => {
codeSnippet = 'foo\n$0\nbar';
snippetController.insert(codeSnippet, 0, 0);
assert.equal(editor.getSelections().length, 2);
const [first, second] = editor.getSelections();
assert.equal(editor.getSelections()!.length, 2);
const [first, second] = editor.getSelections()!;
assert.ok(first.equalsRange({ startLineNumber: 2, startColumn: 1, endLineNumber: 2, endColumn: 1 }), first.toString());
assert.ok(second.equalsRange({ startLineNumber: 4, startColumn: 1, endLineNumber: 4, endColumn: 1 }), second.toString());
});
@@ -316,8 +316,8 @@ suite('SnippetController', () => {
codeSnippet = 'xo$0r';
snippetController.insert(codeSnippet, 1, 0);
assert.equal(editor.getSelections().length, 1);
assert.ok(editor.getSelection().equalsRange({ startLineNumber: 2, startColumn: 8, endColumn: 8, endLineNumber: 2 }));
assert.equal(editor.getSelections()!.length, 1);
assert.ok(editor.getSelection()!.equalsRange({ startLineNumber: 2, startColumn: 8, endColumn: 8, endLineNumber: 2 }));
});
});
@@ -329,9 +329,9 @@ suite('SnippetController', () => {
codeSnippet = '{{% url_**$1** %}}';
controller.insert(codeSnippet, 2, 0);
assert.equal(editor.getSelections().length, 1);
assert.ok(editor.getSelection().equalsRange({ startLineNumber: 1, startColumn: 27, endLineNumber: 1, endColumn: 27 }));
assert.equal(editor.getModel().getValue(), 'example example {{% url_**** %}}');
assert.equal(editor.getSelections()!.length, 1);
assert.ok(editor.getSelection()!.equalsRange({ startLineNumber: 1, startColumn: 27, endLineNumber: 1, endColumn: 27 }));
assert.equal(editor.getModel()!.getValue(), 'example example {{% url_**** %}}');
}, ['example example sc']);
@@ -347,9 +347,9 @@ suite('SnippetController', () => {
controller.insert(codeSnippet, 2, 0);
assert.equal(editor.getSelections().length, 1);
assert.ok(editor.getSelection().equalsRange({ startLineNumber: 2, startColumn: 2, endLineNumber: 2, endColumn: 2 }), editor.getSelection().toString());
assert.equal(editor.getModel().getValue(), 'afterEach((done) => {\n\ttest\n});');
assert.equal(editor.getSelections()!.length, 1);
assert.ok(editor.getSelection()!.equalsRange({ startLineNumber: 2, startColumn: 2, endLineNumber: 2, endColumn: 2 }), editor.getSelection()!.toString());
assert.equal(editor.getModel()!.getValue(), 'afterEach((done) => {\n\ttest\n});');
}, ['af']);
@@ -365,9 +365,9 @@ suite('SnippetController', () => {
controller.insert(codeSnippet, 2, 0);
assert.equal(editor.getSelections().length, 1);
assert.ok(editor.getSelection().equalsRange({ startLineNumber: 2, startColumn: 1, endLineNumber: 2, endColumn: 1 }), editor.getSelection().toString());
assert.equal(editor.getModel().getValue(), 'afterEach((done) => {\n\ttest\n});');
assert.equal(editor.getSelections()!.length, 1);
assert.ok(editor.getSelection()!.equalsRange({ startLineNumber: 2, startColumn: 1, endLineNumber: 2, endColumn: 1 }), editor.getSelection()!.toString());
assert.equal(editor.getModel()!.getValue(), 'afterEach((done) => {\n\ttest\n});');
}, ['af']);
@@ -381,9 +381,9 @@ suite('SnippetController', () => {
controller.insert(codeSnippet, 8, 0);
assert.equal(editor.getModel().getValue(), 'after');
assert.equal(editor.getSelections().length, 1);
assert.ok(editor.getSelection().equalsRange({ startLineNumber: 1, startColumn: 4, endLineNumber: 1, endColumn: 4 }), editor.getSelection().toString());
assert.equal(editor.getModel()!.getValue(), 'after');
assert.equal(editor.getSelections()!.length, 1);
assert.ok(editor.getSelection()!.equalsRange({ startLineNumber: 1, startColumn: 4, endLineNumber: 1, endColumn: 4 }), editor.getSelection()!.toString());
}, ['afterone']);
});
@@ -405,8 +405,8 @@ suite('SnippetController', () => {
controller.insert(codeSnippet, 2, 0);
assert.equal(editor.getSelections().length, 2);
const [first, second] = editor.getSelections();
assert.equal(editor.getSelections()!.length, 2);
const [first, second] = editor.getSelections()!;
assert.ok(first.equalsRange({ startLineNumber: 5, startColumn: 3, endLineNumber: 5, endColumn: 3 }), first.toString());
assert.ok(second.equalsRange({ startLineNumber: 2, startColumn: 2, endLineNumber: 2, endColumn: 2 }), second.toString());
@@ -430,8 +430,8 @@ suite('SnippetController', () => {
controller.insert(codeSnippet, 2, 0);
assert.equal(editor.getSelections().length, 1);
const [first] = editor.getSelections();
assert.equal(editor.getSelections()!.length, 1);
const [first] = editor.getSelections()!;
assert.ok(first.equalsRange({ startLineNumber: 2, startColumn: 3, endLineNumber: 2, endColumn: 3 }), first.toString());
@@ -450,7 +450,7 @@ suite('SnippetController', () => {
controller.insert(codeSnippet, 2, 0);
assert.ok(editor.getSelection().equalsRange({ startLineNumber: 1, startColumn: 10, endLineNumber: 1, endColumn: 10 }));
assert.ok(editor.getSelection()!.equalsRange({ startLineNumber: 1, startColumn: 10, endLineNumber: 1, endColumn: 10 }));
}, ['af', '\taf']);
});
@@ -466,7 +466,7 @@ suite('SnippetController', () => {
codeSnippet = '_foo';
controller.insert(codeSnippet, 1, 0);
assert.equal(editor.getModel().getValue(), 'this._foo\nabc_foo');
assert.equal(editor.getModel()!.getValue(), 'this._foo\nabc_foo');
}, ['this._', 'abc']);
@@ -479,7 +479,7 @@ suite('SnippetController', () => {
codeSnippet = 'XX';
controller.insert(codeSnippet, 1, 0);
assert.equal(editor.getModel().getValue(), 'this.XX\nabcXX');
assert.equal(editor.getModel()!.getValue(), 'this.XX\nabcXX');
}, ['this._', 'abc']);
@@ -493,7 +493,7 @@ suite('SnippetController', () => {
codeSnippet = '_foo';
controller.insert(codeSnippet, 1, 0);
assert.equal(editor.getModel().getValue(), 'this._foo\nabc_foo\ndef_foo');
assert.equal(editor.getModel()!.getValue(), 'this._foo\nabc_foo\ndef_foo');
}, ['this._', 'abc', 'def_']);
@@ -507,7 +507,7 @@ suite('SnippetController', () => {
codeSnippet = '._foo';
controller.insert(codeSnippet, 2, 0);
assert.equal(editor.getModel().getValue(), 'this._foo\nabc._foo\ndef._foo');
assert.equal(editor.getModel()!.getValue(), 'this._foo\nabc._foo\ndef._foo');
}, ['this._', 'abc', 'def._']);
@@ -521,7 +521,7 @@ suite('SnippetController', () => {
codeSnippet = '._foo';
controller.insert(codeSnippet, 2, 0);
assert.equal(editor.getModel().getValue(), 'this._foo\nabc._foo\ndef._foo');
assert.equal(editor.getModel()!.getValue(), 'this._foo\nabc._foo\ndef._foo');
}, ['this._', 'abc', 'def._']);
@@ -535,7 +535,7 @@ suite('SnippetController', () => {
codeSnippet = '._foo';
controller.insert(codeSnippet, 2, 0);
assert.equal(editor.getModel().getValue(), 'this._._foo\na._foo\ndef._._foo');
assert.equal(editor.getModel()!.getValue(), 'this._._foo\na._foo\ndef._._foo');
}, ['this._', 'abc', 'def._']);
@@ -551,7 +551,7 @@ suite('SnippetController', () => {
codeSnippet = 'document';
controller.insert(codeSnippet, 3, 0);
assert.equal(editor.getModel().getValue(), '{document}\n{document && true}');
assert.equal(editor.getModel()!.getValue(), '{document}\n{document && true}');
}, ['{foo}', '{foo && true}']);
});
@@ -566,7 +566,7 @@ suite('SnippetController', () => {
codeSnippet = 'for (var ${1:i}=0; ${1:i}<len; ${1:i}++) { $0 }';
controller.insert(codeSnippet, 0, 0);
assert.equal(editor.getModel().getValue(), 'for (var i=0; i<len; i++) { }for (var i=0; i<len; i++) { }');
assert.equal(editor.getModel()!.getValue(), 'for (var i=0; i<len; i++) { }for (var i=0; i<len; i++) { }');
}, ['for (var i=0; i<len; i++) { }']);
@@ -579,7 +579,7 @@ suite('SnippetController', () => {
codeSnippet = 'for (let ${1:i}=0; ${1:i}<len; ${1:i}++) { $0 }';
controller.insert(codeSnippet, 0, 0);
assert.equal(editor.getModel().getValue(), 'for (let i=0; i<len; i++) { }for (var i=0; i<len; i++) { }');
assert.equal(editor.getModel()!.getValue(), 'for (let i=0; i<len; i++) { }for (var i=0; i<len; i++) { }');
}, ['for (var i=0; i<len; i++) { }']);
@@ -15,8 +15,8 @@ import { Handler } from 'vs/editor/common/editorCommon';
suite('SnippetController2', function () {
function assertSelections(editor: ICodeEditor, ...s: Selection[]) {
for (const selection of editor.getSelections()) {
const actual = s.shift();
for (const selection of editor.getSelections()!) {
const actual = s.shift()!;
assert.ok(selection.equalsSelection(actual), `actual=${selection.toString()} <> expected=${actual.toString()}`);
}
assert.equal(s.length, 0);
@@ -74,7 +74,7 @@ suite('SuggestMemories', function () {
assert.equal(mem.select(buffer, pos, []), 0);
mem.memorize(buffer, pos, items[0]);
mem.memorize(buffer, pos, null);
mem.memorize(buffer, pos, null!);
});
test('LRUMemory', () => {
@@ -71,7 +71,7 @@ suite('SuggestModel - Context', function () {
this._register(TokenizationRegistry.register(this.getLanguageIdentifier().language, {
getInitialState: (): IState => NULL_STATE,
tokenize: undefined,
tokenize: undefined!,
tokenize2: (line: string, state: IState): TokenizationResult2 => {
const tokensArr: number[] = [];
let prevLanguageId: LanguageIdentifier | undefined = undefined;
@@ -418,7 +418,7 @@ suite('SuggestModel - TriggerAndCancelOracle', function () {
return withOracle((model, editor) => {
editor.getModel().setValue('fo');
editor.getModel()!.setValue('fo');
editor.setPosition({ lineNumber: 1, column: 3 });
return assertEvent(model.onDidSuggest, () => {
@@ -443,7 +443,7 @@ suite('SuggestModel - TriggerAndCancelOracle', function () {
return withOracle((model, editor) => {
editor.getModel().setValue('fo');
editor.getModel()!.setValue('fo');
editor.setPosition({ lineNumber: 1, column: 3 });
return assertEvent(model.onDidSuggest, () => {
@@ -480,7 +480,7 @@ suite('SuggestModel - TriggerAndCancelOracle', function () {
return withOracle((model, editor) => {
editor.getModel().setValue('foo');
editor.getModel()!.setValue('foo');
editor.setPosition({ lineNumber: 1, column: 4 });
return assertEvent(model.onDidSuggest, () => {
@@ -517,7 +517,7 @@ suite('SuggestModel - TriggerAndCancelOracle', function () {
return withOracle((model, editor) => {
editor.getModel().setValue('foo');
editor.getModel()!.setValue('foo');
editor.setPosition({ lineNumber: 1, column: 4 });
return assertEvent(model.onDidSuggest, () => {
@@ -548,7 +548,7 @@ suite('SuggestModel - TriggerAndCancelOracle', function () {
triggerCharacters: ['.'],
provideCompletionItems(doc, pos, context): CompletionList {
assert.equal(context.triggerKind, CompletionTriggerKind.TriggerCharacter);
triggerCharacter = context.triggerCharacter;
triggerCharacter = context.triggerCharacter!;
return {
incomplete: false,
suggestions: [
@@ -22,7 +22,7 @@ suite('TokenizationSupport2Adapter', () => {
class MockTokenTheme extends TokenTheme {
private counter = 0;
constructor() {
super(null, null);
super(null!, null!);
}
public match(languageId: LanguageId, token: string): number {
return (
-159
View File
@@ -1,159 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Event, Emitter } from 'vs/base/common/event';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { MenuId, MenuRegistry, MenuItemAction, IMenu, IMenuItem, IMenuActionOptions, ISubmenuItem, SubmenuItemAction, isIMenuItem } from 'vs/platform/actions/common/actions';
import { ICommandService } from 'vs/platform/commands/common/commands';
type MenuItemGroup = [string, Array<IMenuItem | ISubmenuItem>];
export class Menu implements IMenu {
private readonly _onDidChange = new Emitter<IMenu>();
private readonly _disposables: IDisposable[] = [];
private _menuGroups: MenuItemGroup[];
private _contextKeys: Set<string>;
constructor(
private readonly _id: MenuId,
@ICommandService private readonly _commandService: ICommandService,
@IContextKeyService private readonly _contextKeyService: IContextKeyService
) {
this._build();
// rebuild this menu whenever the menu registry reports an
// event for this MenuId
Event.debounce(
Event.filter(MenuRegistry.onDidChangeMenu, menuId => menuId === this._id),
() => { },
50
)(this._build, this, this._disposables);
// when context keys change we need to check if the menu also
// has changed
Event.debounce(
this._contextKeyService.onDidChangeContext,
(last, event) => last || event.affectsSome(this._contextKeys),
50
)(e => e && this._onDidChange.fire(), this, this._disposables);
}
private _build(): void {
// reset
this._menuGroups = [];
this._contextKeys = new Set();
const menuItems = MenuRegistry.getMenuItems(this._id);
let group: MenuItemGroup | undefined;
menuItems.sort(Menu._compareMenuItems);
for (let item of menuItems) {
// group by groupId
const groupName = item.group || '';
if (!group || group[0] !== groupName) {
group = [groupName, []];
this._menuGroups.push(group);
}
group![1].push(item);
// keep keys for eventing
Menu._fillInKbExprKeys(item.when, this._contextKeys);
// keep precondition keys for event if applicable
if (isIMenuItem(item) && item.command.precondition) {
Menu._fillInKbExprKeys(item.command.precondition, this._contextKeys);
}
// keep toggled keys for event if applicable
if (isIMenuItem(item) && item.command.toggled) {
Menu._fillInKbExprKeys(item.command.toggled, this._contextKeys);
}
}
this._onDidChange.fire(this);
}
dispose() {
dispose(this._disposables);
this._onDidChange.dispose();
}
get onDidChange(): Event<IMenu> {
return this._onDidChange.event;
}
getActions(options: IMenuActionOptions): [string, Array<MenuItemAction | SubmenuItemAction>][] {
const result: [string, Array<MenuItemAction | SubmenuItemAction>][] = [];
for (let group of this._menuGroups) {
const [id, items] = group;
const activeActions: Array<MenuItemAction | SubmenuItemAction> = [];
for (const item of items) {
if (this._contextKeyService.contextMatchesRules(item.when || null)) {
const action = isIMenuItem(item) ? new MenuItemAction(item.command, item.alt, options, this._contextKeyService, this._commandService) : new SubmenuItemAction(item);
activeActions.push(action);
}
}
if (activeActions.length > 0) {
result.push([id, activeActions]);
}
}
return result;
}
private static _fillInKbExprKeys(exp: ContextKeyExpr | undefined, set: Set<string>): void {
if (exp) {
for (let key of exp.keys()) {
set.add(key);
}
}
}
private static _compareMenuItems(a: IMenuItem, b: IMenuItem): number {
let aGroup = a.group;
let bGroup = b.group;
if (aGroup !== bGroup) {
// Falsy groups come last
if (!aGroup) {
return 1;
} else if (!bGroup) {
return -1;
}
// 'navigation' group comes first
if (aGroup === 'navigation') {
return -1;
} else if (bGroup === 'navigation') {
return 1;
}
// lexical sort for groups
let value = aGroup.localeCompare(bGroup);
if (value !== 0) {
return value;
}
}
// sort on priority - default is 0
let aPrio = a.order || 0;
let bPrio = b.order || 0;
if (aPrio < bPrio) {
return -1;
} else if (aPrio > bPrio) {
return 1;
}
// sort on titles
const aTitle = typeof a.command.title === 'string' ? a.command.title : a.command.title.value;
const bTitle = typeof b.command.title === 'string' ? b.command.title : b.command.title.value;
return aTitle.localeCompare(bTitle);
}
}
+154 -3
View File
@@ -3,10 +3,11 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { MenuId, IMenu, IMenuService } from 'vs/platform/actions/common/actions';
import { Menu } from 'vs/platform/actions/common/menu';
import { Emitter, Event } from 'vs/base/common/event';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { IMenu, IMenuActionOptions, IMenuItem, IMenuService, isIMenuItem, ISubmenuItem, MenuId, MenuItemAction, MenuRegistry, SubmenuItemAction } from 'vs/platform/actions/common/actions';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
export class MenuService implements IMenuService {
@@ -22,3 +23,153 @@ export class MenuService implements IMenuService {
return new Menu(id, this._commandService, contextKeyService);
}
}
type MenuItemGroup = [string, Array<IMenuItem | ISubmenuItem>];
class Menu implements IMenu {
private readonly _onDidChange = new Emitter<IMenu>();
private readonly _disposables: IDisposable[] = [];
private _menuGroups: MenuItemGroup[];
private _contextKeys: Set<string>;
constructor(
private readonly _id: MenuId,
@ICommandService private readonly _commandService: ICommandService,
@IContextKeyService private readonly _contextKeyService: IContextKeyService
) {
this._build();
// rebuild this menu whenever the menu registry reports an
// event for this MenuId
Event.debounce(
Event.filter(MenuRegistry.onDidChangeMenu, menuId => menuId === this._id),
() => { },
50
)(this._build, this, this._disposables);
// when context keys change we need to check if the menu also
// has changed
Event.debounce(
this._contextKeyService.onDidChangeContext,
(last, event) => last || event.affectsSome(this._contextKeys),
50
)(e => e && this._onDidChange.fire(), this, this._disposables);
}
private _build(): void {
// reset
this._menuGroups = [];
this._contextKeys = new Set();
const menuItems = MenuRegistry.getMenuItems(this._id);
let group: MenuItemGroup | undefined;
menuItems.sort(Menu._compareMenuItems);
for (let item of menuItems) {
// group by groupId
const groupName = item.group || '';
if (!group || group[0] !== groupName) {
group = [groupName, []];
this._menuGroups.push(group);
}
group![1].push(item);
// keep keys for eventing
Menu._fillInKbExprKeys(item.when, this._contextKeys);
// keep precondition keys for event if applicable
if (isIMenuItem(item) && item.command.precondition) {
Menu._fillInKbExprKeys(item.command.precondition, this._contextKeys);
}
// keep toggled keys for event if applicable
if (isIMenuItem(item) && item.command.toggled) {
Menu._fillInKbExprKeys(item.command.toggled, this._contextKeys);
}
}
this._onDidChange.fire(this);
}
dispose() {
dispose(this._disposables);
this._onDidChange.dispose();
}
get onDidChange(): Event<IMenu> {
return this._onDidChange.event;
}
getActions(options: IMenuActionOptions): [string, Array<MenuItemAction | SubmenuItemAction>][] {
const result: [string, Array<MenuItemAction | SubmenuItemAction>][] = [];
for (let group of this._menuGroups) {
const [id, items] = group;
const activeActions: Array<MenuItemAction | SubmenuItemAction> = [];
for (const item of items) {
if (this._contextKeyService.contextMatchesRules(item.when || null)) {
const action = isIMenuItem(item) ? new MenuItemAction(item.command, item.alt, options, this._contextKeyService, this._commandService) : new SubmenuItemAction(item);
activeActions.push(action);
}
}
if (activeActions.length > 0) {
result.push([id, activeActions]);
}
}
return result;
}
private static _fillInKbExprKeys(exp: ContextKeyExpr | undefined, set: Set<string>): void {
if (exp) {
for (let key of exp.keys()) {
set.add(key);
}
}
}
private static _compareMenuItems(a: IMenuItem, b: IMenuItem): number {
let aGroup = a.group;
let bGroup = b.group;
if (aGroup !== bGroup) {
// Falsy groups come last
if (!aGroup) {
return 1;
} else if (!bGroup) {
return -1;
}
// 'navigation' group comes first
if (aGroup === 'navigation') {
return -1;
} else if (bGroup === 'navigation') {
return 1;
}
// lexical sort for groups
let value = aGroup.localeCompare(bGroup);
if (value !== 0) {
return value;
}
}
// sort on priority - default is 0
let aPrio = a.order || 0;
let bPrio = b.order || 0;
if (aPrio < bPrio) {
return -1;
} else if (aPrio > bPrio) {
return 1;
}
// sort on titles
const aTitle = typeof a.command.title === 'string' ? a.command.title : a.command.title.value;
const bTitle = typeof b.command.title === 'string' ? b.command.title : b.command.title.value;
return aTitle.localeCompare(bTitle);
}
}
@@ -7,19 +7,19 @@ import * as fs from 'fs';
import * as path from 'path';
import * as crypto from 'crypto';
import * as platform from 'vs/base/common/platform';
import { writeFileAndFlushSync, readdirSync, delSync } from 'vs/base/node/extfs';
import { writeFileAndFlushSync } from 'vs/base/node/extfs';
import * as arrays from 'vs/base/common/arrays';
import { IBackupMainService, IBackupWorkspacesFormat, IEmptyWindowBackupInfo } from 'vs/platform/backup/common/backup';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IFilesConfiguration, HotExitConfiguration } from 'vs/platform/files/common/files';
import { ILogService } from 'vs/platform/log/common/log';
import { IWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { URI } from 'vs/base/common/uri';
import { isEqual as areResourcesEquals, getComparisonKey, hasToIgnoreCase } from 'vs/base/common/resources';
import { isEqual } from 'vs/base/common/paths';
import { Schemas } from 'vs/base/common/network';
import { writeFile, readFile, readdir, exists, del, rename } from 'vs/base/node/pfs';
export class BackupMainService implements IBackupMainService {
@@ -39,8 +39,55 @@ export class BackupMainService implements IBackupMainService {
) {
this.backupHome = environmentService.backupHome;
this.workspacesJsonPath = environmentService.backupWorkspacesPath;
}
this.loadSync();
async initialize(): Promise<void> {
let backups: IBackupWorkspacesFormat;
try {
backups = JSON.parse(await readFile(this.workspacesJsonPath, 'utf8')); // invalid JSON or permission issue can happen here
} catch (error) {
backups = Object.create(null);
}
// read empty workspaces backups first
if (backups.emptyWorkspaceInfos) {
this.emptyWorkspaces = await this.validateEmptyWorkspaces(backups.emptyWorkspaceInfos);
} else if (Array.isArray(backups.emptyWorkspaces)) {
// read legacy entries
this.emptyWorkspaces = await this.validateEmptyWorkspaces(backups.emptyWorkspaces.map(backupFolder => ({ backupFolder })));
} else {
this.emptyWorkspaces = [];
}
// read workspace backups
this.rootWorkspaces = await this.validateWorkspaces(backups.rootWorkspaces);
// read folder backups
let workspaceFolders: URI[] = [];
try {
if (Array.isArray(backups.folderURIWorkspaces)) {
workspaceFolders = backups.folderURIWorkspaces.map(f => URI.parse(f));
} else if (Array.isArray(backups.folderWorkspaces)) {
// migrate legacy folder paths
workspaceFolders = [];
for (const folderPath of backups.folderWorkspaces) {
const oldFolderHash = this.getLegacyFolderHash(folderPath);
const folderUri = URI.file(folderPath);
const newFolderHash = this.getFolderHash(folderUri);
if (newFolderHash !== oldFolderHash) {
await this.moveBackupFolder(this.getBackupPath(newFolderHash), this.getBackupPath(oldFolderHash));
}
workspaceFolders.push(folderUri);
}
}
} catch (e) {
// ignore URI parsing exceptions
}
this.folderWorkspaces = await this.validateFolders(workspaceFolders);
// save again in case some workspaces or folders have been removed
await this.save();
}
getWorkspaceBackups(): IWorkspaceIdentifier[] {
@@ -100,7 +147,7 @@ export class BackupMainService implements IBackupMainService {
// Target exists: make sure to convert existing backups to empty window backups
if (fs.existsSync(backupPath)) {
this.convertToEmptyWindowBackup(backupPath);
this.convertToEmptyWindowBackupSync(backupPath);
}
// When we have data to migrate from, move it over to the target location
@@ -113,6 +160,23 @@ export class BackupMainService implements IBackupMainService {
}
}
private async moveBackupFolder(backupPath: string, moveFromPath: string): Promise<void> {
// Target exists: make sure to convert existing backups to empty window backups
if (await exists(backupPath)) {
await this.convertToEmptyWindowBackup(backupPath);
}
// When we have data to migrate from, move it over to the target location
if (await exists(moveFromPath)) {
try {
await rename(moveFromPath, backupPath);
} catch (ex) {
this.logService.error(`Backup: Could not move backup folder to new location: ${ex.toString()}`);
}
}
}
unregisterWorkspaceBackupSync(workspace: IWorkspaceIdentifier): void {
let index = arrays.firstIndex(this.rootWorkspaces, w => w.id === workspace.id);
if (index !== -1) {
@@ -163,60 +227,11 @@ export class BackupMainService implements IBackupMainService {
}
}
protected loadSync(): void {
let backups: IBackupWorkspacesFormat;
try {
backups = JSON.parse(fs.readFileSync(this.workspacesJsonPath, 'utf8').toString()); // invalid JSON or permission issue can happen here
} catch (error) {
backups = Object.create(null);
}
// read empty workspaces backups first
if (backups.emptyWorkspaceInfos) {
this.emptyWorkspaces = this.validateEmptyWorkspaces(backups.emptyWorkspaceInfos);
} else if (Array.isArray(backups.emptyWorkspaces)) {
// read legacy entries
this.emptyWorkspaces = this.validateEmptyWorkspaces(backups.emptyWorkspaces.map(backupFolder => ({ backupFolder })));
} else {
this.emptyWorkspaces = [];
}
// read workspace backups
this.rootWorkspaces = this.validateWorkspaces(backups.rootWorkspaces);
// read folder backups
let workspaceFolders: URI[] = [];
try {
if (Array.isArray(backups.folderURIWorkspaces)) {
workspaceFolders = backups.folderURIWorkspaces.map(f => URI.parse(f));
} else if (Array.isArray(backups.folderWorkspaces)) {
// migrate legacy folder paths
workspaceFolders = [];
for (const folderPath of backups.folderWorkspaces) {
const oldFolderHash = this.getLegacyFolderHash(folderPath);
const folderUri = URI.file(folderPath);
const newFolderHash = this.getFolderHash(folderUri);
if (newFolderHash !== oldFolderHash) {
this.moveBackupFolderSync(this.getBackupPath(newFolderHash), this.getBackupPath(oldFolderHash));
}
workspaceFolders.push(folderUri);
}
}
} catch (e) {
// ignore URI parsing exceptions
}
this.folderWorkspaces = this.validateFolders(workspaceFolders);
// save again in case some workspaces or folders have been removed
this.saveSync();
}
private getBackupPath(oldFolderHash: string): string {
return path.join(this.backupHome, oldFolderHash);
}
private validateWorkspaces(rootWorkspaces: IWorkspaceIdentifier[]): IWorkspaceIdentifier[] {
private async validateWorkspaces(rootWorkspaces: IWorkspaceIdentifier[]): Promise<IWorkspaceIdentifier[]> {
if (!Array.isArray(rootWorkspaces)) {
return [];
}
@@ -234,18 +249,18 @@ export class BackupMainService implements IBackupMainService {
seenIds[workspace.id] = true;
const backupPath = this.getBackupPath(workspace.id);
const hasBackups = this.hasBackupsSync(backupPath);
const hasBackups = await this.hasBackups(backupPath);
// If the workspace has no backups, ignore it
if (hasBackups) {
if (fs.existsSync(workspace.configPath)) {
if (await exists(workspace.configPath)) {
result.push(workspace);
} else {
// If the workspace has backups, but the target workspace is missing, convert backups to empty ones
this.convertToEmptyWindowBackup(backupPath);
await this.convertToEmptyWindowBackup(backupPath);
}
} else {
this.deleteStaleBackup(backupPath);
await this.deleteStaleBackup(backupPath);
}
}
}
@@ -253,7 +268,7 @@ export class BackupMainService implements IBackupMainService {
return result;
}
private validateFolders(folderWorkspaces: URI[]): URI[] {
private async validateFolders(folderWorkspaces: URI[]): Promise<URI[]> {
if (!Array.isArray(folderWorkspaces)) {
return [];
}
@@ -266,18 +281,18 @@ export class BackupMainService implements IBackupMainService {
seen[key] = true;
const backupPath = this.getBackupPath(this.getFolderHash(folderURI));
const hasBackups = this.hasBackupsSync(backupPath);
const hasBackups = await this.hasBackups(backupPath);
// If the folder has no backups, ignore it
if (hasBackups) {
if (folderURI.scheme !== Schemas.file || fs.existsSync(folderURI.fsPath)) {
if (folderURI.scheme !== Schemas.file || await exists(folderURI.fsPath)) {
result.push(folderURI);
} else {
// If the folder has backups, but the target workspace is missing, convert backups to empty ones
this.convertToEmptyWindowBackup(backupPath);
await this.convertToEmptyWindowBackup(backupPath);
}
} else {
this.deleteStaleBackup(backupPath);
await this.deleteStaleBackup(backupPath);
}
}
}
@@ -285,7 +300,7 @@ export class BackupMainService implements IBackupMainService {
return result;
}
private validateEmptyWorkspaces(emptyWorkspaces: IEmptyWindowBackupInfo[]): IEmptyWindowBackupInfo[] {
private async validateEmptyWorkspaces(emptyWorkspaces: IEmptyWindowBackupInfo[]): Promise<IEmptyWindowBackupInfo[]> {
if (!Array.isArray(emptyWorkspaces)) {
return [];
}
@@ -304,10 +319,10 @@ export class BackupMainService implements IBackupMainService {
seen[backupFolder] = true;
const backupPath = this.getBackupPath(backupFolder);
if (this.hasBackupsSync(backupPath)) {
if (await this.hasBackups(backupPath)) {
result.push(backupInfo);
} else {
this.deleteStaleBackup(backupPath);
await this.deleteStaleBackup(backupPath);
}
}
}
@@ -315,17 +330,38 @@ export class BackupMainService implements IBackupMainService {
return result;
}
private deleteStaleBackup(backupPath: string) {
private async deleteStaleBackup(backupPath: string): Promise<void> {
try {
if (fs.existsSync(backupPath)) {
delSync(backupPath);
if (await exists(backupPath)) {
await del(backupPath);
}
} catch (ex) {
this.logService.error(`Backup: Could not delete stale backup: ${ex.toString()}`);
}
}
private convertToEmptyWindowBackup(backupPath: string): boolean {
private async convertToEmptyWindowBackup(backupPath: string): Promise<boolean> {
// New empty window backup
let newBackupFolder = this.getRandomEmptyWindowId();
while (this.emptyWorkspaces.some(w => isEqual(w.backupFolder, newBackupFolder, platform.isLinux))) {
newBackupFolder = this.getRandomEmptyWindowId();
}
// Rename backupPath to new empty window backup path
const newEmptyWindowBackupPath = this.getBackupPath(newBackupFolder);
try {
await rename(backupPath, newEmptyWindowBackupPath);
} catch (ex) {
this.logService.error(`Backup: Could not rename backup folder: ${ex.toString()}`);
return false;
}
this.emptyWorkspaces.push({ backupFolder: newBackupFolder });
return true;
}
private convertToEmptyWindowBackupSync(backupPath: string): boolean {
// New empty window backup
let newBackupFolder = this.getRandomEmptyWindowId();
@@ -346,40 +382,53 @@ export class BackupMainService implements IBackupMainService {
return true;
}
private hasBackupsSync(backupPath: string): boolean {
private async hasBackups(backupPath: string): Promise<boolean> {
try {
const backupSchemas = readdirSync(backupPath);
if (backupSchemas.length === 0) {
return false; // empty backups
}
const backupSchemas = await readdir(backupPath);
return backupSchemas.some(backupSchema => {
for (let i = 0; i < backupSchemas.length; i++) {
const backupSchema = backupSchemas[i];
try {
return readdirSync(path.join(backupPath, backupSchema)).length > 0;
const backupSchemaChildren = await readdir(path.join(backupPath, backupSchema));
if (backupSchemaChildren.length > 0) {
return true;
}
} catch (error) {
return false; // invalid folder
// invalid folder
}
});
}
} catch (error) {
return false; // backup path does not exist
// backup path does not exist
}
return false;
}
private saveSync(): void {
try {
const backups: IBackupWorkspacesFormat = {
rootWorkspaces: this.rootWorkspaces,
folderURIWorkspaces: this.folderWorkspaces.map(f => f.toString()),
emptyWorkspaceInfos: this.emptyWorkspaces,
emptyWorkspaces: this.emptyWorkspaces.map(info => info.backupFolder)
};
writeFileAndFlushSync(this.workspacesJsonPath, JSON.stringify(backups));
writeFileAndFlushSync(this.workspacesJsonPath, JSON.stringify(this.serializeBackups()));
} catch (ex) {
this.logService.error(`Backup: Could not save workspaces.json: ${ex.toString()}`);
}
}
private async save(): Promise<void> {
try {
await writeFile(this.workspacesJsonPath, JSON.stringify(this.serializeBackups()));
} catch (ex) {
this.logService.error(`Backup: Could not save workspaces.json: ${ex.toString()}`);
}
}
private serializeBackups(): IBackupWorkspacesFormat {
return {
rootWorkspaces: this.rootWorkspaces,
folderURIWorkspaces: this.folderWorkspaces.map(f => f.toString()),
emptyWorkspaceInfos: this.emptyWorkspaces,
emptyWorkspaces: this.emptyWorkspaces.map(info => info.backupFolder)
} as IBackupWorkspacesFormat;
}
private getRandomEmptyWindowId(): string {
return (Date.now() + Math.round(Math.random() * 1000)).toString();
}
@@ -41,13 +41,6 @@ suite('BackupMainService', () => {
this.backupHome = backupHome;
this.workspacesJsonPath = backupWorkspacesPath;
// Force a reload with the new paths
this.loadSync();
}
public loadSync(): void {
super.loadSync();
}
public toBackupPath(arg: Uri | string): string {
@@ -116,6 +109,8 @@ suite('BackupMainService', () => {
}).then(() => {
configService = new TestConfigurationService();
service = new TestBackupMainService(backupHome, backupWorkspacesPath, configService);
return service.initialize();
});
});
@@ -123,13 +118,13 @@ suite('BackupMainService', () => {
return pfs.del(backupHome, os.tmpdir());
});
test('service validates backup workspaces on startup and cleans up (folder workspaces)', function () {
test('service validates backup workspaces on startup and cleans up (folder workspaces)', async function () {
this.timeout(1000 * 10); // increase timeout for this test
// 1) backup workspace path does not exist
service.registerFolderBackupSync(fooFile);
service.registerFolderBackupSync(barFile);
service.loadSync();
await service.initialize();
assertEqualUris(service.getFolderBackupPaths(), []);
// 2) backup workspace path exists with empty contents within
@@ -137,7 +132,7 @@ suite('BackupMainService', () => {
fs.mkdirSync(service.toBackupPath(barFile));
service.registerFolderBackupSync(fooFile);
service.registerFolderBackupSync(barFile);
service.loadSync();
await service.initialize();
assertEqualUris(service.getFolderBackupPaths(), []);
assert.ok(!fs.existsSync(service.toBackupPath(fooFile)));
assert.ok(!fs.existsSync(service.toBackupPath(barFile)));
@@ -149,7 +144,7 @@ suite('BackupMainService', () => {
fs.mkdirSync(path.join(service.toBackupPath(barFile), Schemas.untitled));
service.registerFolderBackupSync(fooFile);
service.registerFolderBackupSync(barFile);
service.loadSync();
await service.initialize();
assertEqualUris(service.getFolderBackupPaths(), []);
assert.ok(!fs.existsSync(service.toBackupPath(fooFile)));
assert.ok(!fs.existsSync(service.toBackupPath(barFile)));
@@ -164,18 +159,18 @@ suite('BackupMainService', () => {
assert.equal(service.getFolderBackupPaths().length, 1);
assert.equal(service.getEmptyWindowBackupPaths().length, 0);
fs.writeFileSync(path.join(fileBackups, 'backup.txt'), '');
service.loadSync();
await service.initialize();
assert.equal(service.getFolderBackupPaths().length, 0);
assert.equal(service.getEmptyWindowBackupPaths().length, 1);
});
test('service validates backup workspaces on startup and cleans up (root workspaces)', function () {
test('service validates backup workspaces on startup and cleans up (root workspaces)', async function () {
this.timeout(1000 * 10); // increase timeout for this test
// 1) backup workspace path does not exist
service.registerWorkspaceBackupSync(toWorkspace(fooFile.fsPath));
service.registerWorkspaceBackupSync(toWorkspace(barFile.fsPath));
service.loadSync();
await service.initialize();
assert.deepEqual(service.getWorkspaceBackups(), []);
// 2) backup workspace path exists with empty contents within
@@ -183,7 +178,7 @@ suite('BackupMainService', () => {
fs.mkdirSync(service.toBackupPath(barFile));
service.registerWorkspaceBackupSync(toWorkspace(fooFile.fsPath));
service.registerWorkspaceBackupSync(toWorkspace(barFile.fsPath));
service.loadSync();
await service.initialize();
assert.deepEqual(service.getWorkspaceBackups(), []);
assert.ok(!fs.existsSync(service.toBackupPath(fooFile)));
assert.ok(!fs.existsSync(service.toBackupPath(barFile)));
@@ -195,7 +190,7 @@ suite('BackupMainService', () => {
fs.mkdirSync(path.join(service.toBackupPath(barFile), Schemas.untitled));
service.registerWorkspaceBackupSync(toWorkspace(fooFile.fsPath));
service.registerWorkspaceBackupSync(toWorkspace(barFile.fsPath));
service.loadSync();
await service.initialize();
assert.deepEqual(service.getWorkspaceBackups(), []);
assert.ok(!fs.existsSync(service.toBackupPath(fooFile)));
assert.ok(!fs.existsSync(service.toBackupPath(barFile)));
@@ -210,7 +205,7 @@ suite('BackupMainService', () => {
assert.equal(service.getWorkspaceBackups().length, 1);
assert.equal(service.getEmptyWindowBackupPaths().length, 0);
fs.writeFileSync(path.join(fileBackups, 'backup.txt'), '');
service.loadSync();
await service.initialize();
assert.equal(service.getWorkspaceBackups().length, 0);
assert.equal(service.getEmptyWindowBackupPaths().length, 1);
});
@@ -285,17 +280,15 @@ suite('BackupMainService', () => {
}
const workspacesJson = { rootWorkspaces: [], folderWorkspaces: [path1, path2], emptyWorkspaces: [] };
await pfs.writeFile(backupWorkspacesPath, JSON.stringify(workspacesJson)).then(() => {
service.loadSync();
return pfs.readFile(backupWorkspacesPath, 'utf-8').then(content => {
const json = <IBackupWorkspacesFormat>JSON.parse(content);
assert.deepEqual(json.folderURIWorkspaces, [uri1.toString(), uri2.toString()]);
const newBackupFolder1 = service.toBackupPath(uri1);
assert.ok(fs.existsSync(path.join(newBackupFolder1, Schemas.file, 'unsaved1.txt')));
const newBackupFolder2 = service.toBackupPath(uri2);
assert.ok(fs.existsSync(path.join(newBackupFolder2, Schemas.file, 'unsaved2.txt')));
});
});
await pfs.writeFile(backupWorkspacesPath, JSON.stringify(workspacesJson));
await service.initialize();
const content = await pfs.readFile(backupWorkspacesPath, 'utf-8');
const json = (<IBackupWorkspacesFormat>JSON.parse(content));
assert.deepEqual(json.folderURIWorkspaces, [uri1.toString(), uri2.toString()]);
const newBackupFolder1 = service.toBackupPath(uri1);
assert.ok(fs.existsSync(path.join(newBackupFolder1, Schemas.file, 'unsaved1.txt')));
const newBackupFolder2 = service.toBackupPath(uri2);
assert.ok(fs.existsSync(path.join(newBackupFolder2, Schemas.file, 'unsaved2.txt')));
});
});
@@ -304,50 +297,50 @@ suite('BackupMainService', () => {
assertEqualUris(service.getFolderBackupPaths(), []);
});
test('getFolderBackupPaths() should return [] when workspaces.json is not properly formed JSON', () => {
test('getFolderBackupPaths() should return [] when workspaces.json is not properly formed JSON', async () => {
fs.writeFileSync(backupWorkspacesPath, '');
service.loadSync();
await service.initialize();
assertEqualUris(service.getFolderBackupPaths(), []);
fs.writeFileSync(backupWorkspacesPath, '{]');
service.loadSync();
await service.initialize();
assertEqualUris(service.getFolderBackupPaths(), []);
fs.writeFileSync(backupWorkspacesPath, 'foo');
service.loadSync();
await service.initialize();
assertEqualUris(service.getFolderBackupPaths(), []);
});
test('getFolderBackupPaths() should return [] when folderWorkspaces in workspaces.json is absent', () => {
test('getFolderBackupPaths() should return [] when folderWorkspaces in workspaces.json is absent', async () => {
fs.writeFileSync(backupWorkspacesPath, '{}');
service.loadSync();
await service.initialize();
assertEqualUris(service.getFolderBackupPaths(), []);
});
test('getFolderBackupPaths() should return [] when folderWorkspaces in workspaces.json is not a string array', () => {
test('getFolderBackupPaths() should return [] when folderWorkspaces in workspaces.json is not a string array', async () => {
fs.writeFileSync(backupWorkspacesPath, '{"folderWorkspaces":{}}');
service.loadSync();
await service.initialize();
assertEqualUris(service.getFolderBackupPaths(), []);
fs.writeFileSync(backupWorkspacesPath, '{"folderWorkspaces":{"foo": ["bar"]}}');
service.loadSync();
await service.initialize();
assertEqualUris(service.getFolderBackupPaths(), []);
fs.writeFileSync(backupWorkspacesPath, '{"folderWorkspaces":{"foo": []}}');
service.loadSync();
await service.initialize();
assertEqualUris(service.getFolderBackupPaths(), []);
fs.writeFileSync(backupWorkspacesPath, '{"folderWorkspaces":{"foo": "bar"}}');
service.loadSync();
await service.initialize();
assertEqualUris(service.getFolderBackupPaths(), []);
fs.writeFileSync(backupWorkspacesPath, '{"folderWorkspaces":"foo"}');
service.loadSync();
await service.initialize();
assertEqualUris(service.getFolderBackupPaths(), []);
fs.writeFileSync(backupWorkspacesPath, '{"folderWorkspaces":1}');
service.loadSync();
await service.initialize();
assertEqualUris(service.getFolderBackupPaths(), []);
});
test('getFolderBackupPaths() should return [] when files.hotExit = "onExitAndWindowClose"', () => {
test('getFolderBackupPaths() should return [] when files.hotExit = "onExitAndWindowClose"', async () => {
service.registerFolderBackupSync(Uri.file(fooFile.fsPath.toUpperCase()));
assertEqualUris(service.getFolderBackupPaths(), [Uri.file(fooFile.fsPath.toUpperCase())]);
configService.setUserConfiguration('files.hotExit', HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE);
service.loadSync();
await service.initialize();
assertEqualUris(service.getFolderBackupPaths(), []);
});
@@ -355,51 +348,51 @@ suite('BackupMainService', () => {
assert.deepEqual(service.getWorkspaceBackups(), []);
});
test('getWorkspaceBackups() should return [] when workspaces.json is not properly formed JSON', () => {
test('getWorkspaceBackups() should return [] when workspaces.json is not properly formed JSON', async () => {
fs.writeFileSync(backupWorkspacesPath, '');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getWorkspaceBackups(), []);
fs.writeFileSync(backupWorkspacesPath, '{]');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getWorkspaceBackups(), []);
fs.writeFileSync(backupWorkspacesPath, 'foo');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getWorkspaceBackups(), []);
});
test('getWorkspaceBackups() should return [] when folderWorkspaces in workspaces.json is absent', () => {
test('getWorkspaceBackups() should return [] when folderWorkspaces in workspaces.json is absent', async () => {
fs.writeFileSync(backupWorkspacesPath, '{}');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getWorkspaceBackups(), []);
});
test('getWorkspaceBackups() should return [] when rootWorkspaces in workspaces.json is not a object array', () => {
test('getWorkspaceBackups() should return [] when rootWorkspaces in workspaces.json is not a object array', async () => {
fs.writeFileSync(backupWorkspacesPath, '{"rootWorkspaces":{}}');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getWorkspaceBackups(), []);
fs.writeFileSync(backupWorkspacesPath, '{"rootWorkspaces":{"foo": ["bar"]}}');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getWorkspaceBackups(), []);
fs.writeFileSync(backupWorkspacesPath, '{"rootWorkspaces":{"foo": []}}');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getWorkspaceBackups(), []);
fs.writeFileSync(backupWorkspacesPath, '{"rootWorkspaces":{"foo": "bar"}}');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getWorkspaceBackups(), []);
fs.writeFileSync(backupWorkspacesPath, '{"rootWorkspaces":"foo"}');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getWorkspaceBackups(), []);
fs.writeFileSync(backupWorkspacesPath, '{"rootWorkspaces":1}');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getWorkspaceBackups(), []);
});
test('getWorkspaceBackups() should return [] when files.hotExit = "onExitAndWindowClose"', () => {
test('getWorkspaceBackups() should return [] when files.hotExit = "onExitAndWindowClose"', async () => {
service.registerWorkspaceBackupSync(toWorkspace(fooFile.fsPath.toUpperCase()));
assert.equal(service.getWorkspaceBackups().length, 1);
assert.deepEqual(service.getWorkspaceBackups().map(r => r.configPath), [fooFile.fsPath.toUpperCase()]);
configService.setUserConfiguration('files.hotExit', HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE);
service.loadSync();
await service.initialize();
assert.deepEqual(service.getWorkspaceBackups(), []);
});
@@ -407,43 +400,43 @@ suite('BackupMainService', () => {
assert.deepEqual(service.getEmptyWindowBackupPaths(), []);
});
test('getEmptyWorkspaceBackupPaths() should return [] when workspaces.json is not properly formed JSON', () => {
test('getEmptyWorkspaceBackupPaths() should return [] when workspaces.json is not properly formed JSON', async () => {
fs.writeFileSync(backupWorkspacesPath, '');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getEmptyWindowBackupPaths(), []);
fs.writeFileSync(backupWorkspacesPath, '{]');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getEmptyWindowBackupPaths(), []);
fs.writeFileSync(backupWorkspacesPath, 'foo');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getEmptyWindowBackupPaths(), []);
});
test('getEmptyWorkspaceBackupPaths() should return [] when folderWorkspaces in workspaces.json is absent', () => {
test('getEmptyWorkspaceBackupPaths() should return [] when folderWorkspaces in workspaces.json is absent', async () => {
fs.writeFileSync(backupWorkspacesPath, '{}');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getEmptyWindowBackupPaths(), []);
});
test('getEmptyWorkspaceBackupPaths() should return [] when folderWorkspaces in workspaces.json is not a string array', function () {
test('getEmptyWorkspaceBackupPaths() should return [] when folderWorkspaces in workspaces.json is not a string array', async function () {
this.timeout(5000);
fs.writeFileSync(backupWorkspacesPath, '{"emptyWorkspaces":{}}');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getEmptyWindowBackupPaths(), []);
fs.writeFileSync(backupWorkspacesPath, '{"emptyWorkspaces":{"foo": ["bar"]}}');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getEmptyWindowBackupPaths(), []);
fs.writeFileSync(backupWorkspacesPath, '{"emptyWorkspaces":{"foo": []}}');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getEmptyWindowBackupPaths(), []);
fs.writeFileSync(backupWorkspacesPath, '{"emptyWorkspaces":{"foo": "bar"}}');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getEmptyWindowBackupPaths(), []);
fs.writeFileSync(backupWorkspacesPath, '{"emptyWorkspaces":"foo"}');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getEmptyWindowBackupPaths(), []);
fs.writeFileSync(backupWorkspacesPath, '{"emptyWorkspaces":1}');
service.loadSync();
await service.initialize();
assert.deepEqual(service.getEmptyWindowBackupPaths(), []);
});
});
@@ -458,13 +451,12 @@ suite('BackupMainService', () => {
folderURIWorkspaces: [existingTestFolder1.toString(), existingTestFolder1.toString()],
emptyWorkspaceInfos: []
};
return pfs.writeFile(backupWorkspacesPath, JSON.stringify(workspacesJson)).then(() => {
service.loadSync();
return pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => {
const json = <IBackupWorkspacesFormat>JSON.parse(buffer);
assert.deepEqual(json.folderURIWorkspaces, [existingTestFolder1.toString()]);
});
});
await pfs.writeFile(backupWorkspacesPath, JSON.stringify(workspacesJson));
await service.initialize();
const buffer = await pfs.readFile(backupWorkspacesPath, 'utf-8');
const json = <IBackupWorkspacesFormat>JSON.parse(buffer);
assert.deepEqual(json.folderURIWorkspaces, [existingTestFolder1.toString()]);
});
test('should ignore duplicates on Windows and Mac (folder workspace)', async () => {
@@ -476,13 +468,11 @@ suite('BackupMainService', () => {
folderURIWorkspaces: [existingTestFolder1.toString(), existingTestFolder1.toString().toLowerCase()],
emptyWorkspaceInfos: []
};
return pfs.writeFile(backupWorkspacesPath, JSON.stringify(workspacesJson)).then(() => {
service.loadSync();
return pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => {
const json = <IBackupWorkspacesFormat>JSON.parse(buffer);
assert.deepEqual(json.folderURIWorkspaces, [existingTestFolder1.toString()]);
});
});
await pfs.writeFile(backupWorkspacesPath, JSON.stringify(workspacesJson));
await service.initialize();
const buffer = await pfs.readFile(backupWorkspacesPath, 'utf-8');
const json = <IBackupWorkspacesFormat>JSON.parse(buffer);
assert.deepEqual(json.folderURIWorkspaces, [existingTestFolder1.toString()]);
});
test('should ignore duplicates on Windows and Mac (root workspace)', async () => {
@@ -501,34 +491,31 @@ suite('BackupMainService', () => {
folderURIWorkspaces: [],
emptyWorkspaceInfos: []
};
return pfs.writeFile(backupWorkspacesPath, JSON.stringify(workspacesJson)).then(() => {
service.loadSync();
return pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => {
const json = <IBackupWorkspacesFormat>JSON.parse(buffer);
assert.equal(json.rootWorkspaces.length, platform.isLinux ? 3 : 1);
if (platform.isLinux) {
assert.deepEqual(json.rootWorkspaces.map(r => r.configPath), [workspacePath, workspacePath.toUpperCase(), workspacePath.toLowerCase()]);
} else {
assert.deepEqual(json.rootWorkspaces.map(r => r.configPath), [workspacePath], 'should return the first duplicated entry');
}
});
});
await pfs.writeFile(backupWorkspacesPath, JSON.stringify(workspacesJson));
await service.initialize();
const buffer = await pfs.readFile(backupWorkspacesPath, 'utf-8');
const json = <IBackupWorkspacesFormat>JSON.parse(buffer);
assert.equal(json.rootWorkspaces.length, platform.isLinux ? 3 : 1);
if (platform.isLinux) {
assert.deepEqual(json.rootWorkspaces.map(r => r.configPath), [workspacePath, workspacePath.toUpperCase(), workspacePath.toLowerCase()]);
} else {
assert.deepEqual(json.rootWorkspaces.map(r => r.configPath), [workspacePath], 'should return the first duplicated entry');
}
});
});
suite('registerWindowForBackups', () => {
test('should persist paths to workspaces.json (folder workspace)', () => {
test('should persist paths to workspaces.json (folder workspace)', async () => {
service.registerFolderBackupSync(fooFile);
service.registerFolderBackupSync(barFile);
assertEqualUris(service.getFolderBackupPaths(), [fooFile, barFile]);
return pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => {
const json = <IBackupWorkspacesFormat>JSON.parse(buffer);
assert.deepEqual(json.folderURIWorkspaces, [fooFile.toString(), barFile.toString()]);
});
const buffer = await pfs.readFile(backupWorkspacesPath, 'utf-8');
const json = <IBackupWorkspacesFormat>JSON.parse(buffer);
assert.deepEqual(json.folderURIWorkspaces, [fooFile.toString(), barFile.toString()]);
});
test('should persist paths to workspaces.json (root workspace)', () => {
test('should persist paths to workspaces.json (root workspace)', async () => {
const ws1 = toWorkspace(fooFile.fsPath);
service.registerWorkspaceBackupSync(ws1);
const ws2 = toWorkspace(barFile.fsPath);
@@ -538,31 +525,30 @@ suite('BackupMainService', () => {
assert.equal(ws1.id, service.getWorkspaceBackups()[0].id);
assert.equal(ws2.id, service.getWorkspaceBackups()[1].id);
return pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => {
const json = <IBackupWorkspacesFormat>JSON.parse(buffer);
const buffer = await pfs.readFile(backupWorkspacesPath, 'utf-8');
const json = <IBackupWorkspacesFormat>JSON.parse(buffer);
assert.deepEqual(json.rootWorkspaces.map(b => b.configPath), [fooFile.fsPath, barFile.fsPath]);
assert.equal(ws1.id, json.rootWorkspaces[0].id);
assert.equal(ws2.id, json.rootWorkspaces[1].id);
});
assert.deepEqual(json.rootWorkspaces.map(b => b.configPath), [fooFile.fsPath, barFile.fsPath]);
assert.equal(ws1.id, json.rootWorkspaces[0].id);
assert.equal(ws2.id, json.rootWorkspaces[1].id);
});
});
test('should always store the workspace path in workspaces.json using the case given, regardless of whether the file system is case-sensitive (folder workspace)', () => {
service.registerFolderBackupSync(Uri.file(fooFile.fsPath.toUpperCase()));
assertEqualUris(service.getFolderBackupPaths(), [Uri.file(fooFile.fsPath.toUpperCase())]);
return pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => {
const json = <IBackupWorkspacesFormat>JSON.parse(buffer);
assert.deepEqual(json.folderURIWorkspaces, [Uri.file(fooFile.fsPath.toUpperCase()).toString()]);
});
test('should always store the workspace path in workspaces.json using the case given, regardless of whether the file system is case-sensitive (folder workspace)', () => {
service.registerFolderBackupSync(Uri.file(fooFile.fsPath.toUpperCase()));
assertEqualUris(service.getFolderBackupPaths(), [Uri.file(fooFile.fsPath.toUpperCase())]);
return pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => {
const json = <IBackupWorkspacesFormat>JSON.parse(buffer);
assert.deepEqual(json.folderURIWorkspaces, [Uri.file(fooFile.fsPath.toUpperCase()).toString()]);
});
});
test('should always store the workspace path in workspaces.json using the case given, regardless of whether the file system is case-sensitive (root workspace)', () => {
service.registerWorkspaceBackupSync(toWorkspace(fooFile.fsPath.toUpperCase()));
assert.deepEqual(service.getWorkspaceBackups().map(b => b.configPath), [fooFile.fsPath.toUpperCase()]);
return pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => {
const json = <IBackupWorkspacesFormat>JSON.parse(buffer);
assert.deepEqual(json.rootWorkspaces.map(b => b.configPath), [fooFile.fsPath.toUpperCase()]);
});
test('should always store the workspace path in workspaces.json using the case given, regardless of whether the file system is case-sensitive (root workspace)', () => {
service.registerWorkspaceBackupSync(toWorkspace(fooFile.fsPath.toUpperCase()));
assert.deepEqual(service.getWorkspaceBackups().map(b => b.configPath), [fooFile.fsPath.toUpperCase()]);
return pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => {
const json = <IBackupWorkspacesFormat>JSON.parse(buffer);
assert.deepEqual(json.rootWorkspaces.map(b => b.configPath), [fooFile.fsPath.toUpperCase()]);
});
});
@@ -619,15 +605,13 @@ suite('BackupMainService', () => {
await ensureFolderExists(existingTestFolder1); // make sure backup folder exists, so the folder is not removed on loadSync
const workspacesJson: IBackupWorkspacesFormat = { rootWorkspaces: [], folderURIWorkspaces: [existingTestFolder1.toString()], emptyWorkspaceInfos: [] };
return pfs.writeFile(backupWorkspacesPath, JSON.stringify(workspacesJson)).then(() => {
service.loadSync();
service.unregisterFolderBackupSync(barFile);
service.unregisterEmptyWindowBackupSync('test');
return pfs.readFile(backupWorkspacesPath, 'utf-8').then(content => {
const json = <IBackupWorkspacesFormat>JSON.parse(content);
assert.deepEqual(json.folderURIWorkspaces, [existingTestFolder1.toString()]);
});
});
await pfs.writeFile(backupWorkspacesPath, JSON.stringify(workspacesJson));
await service.initialize();
service.unregisterFolderBackupSync(barFile);
service.unregisterEmptyWindowBackupSync('test');
const content = await pfs.readFile(backupWorkspacesPath, 'utf-8');
const json = (<IBackupWorkspacesFormat>JSON.parse(content));
assert.deepEqual(json.folderURIWorkspaces, [existingTestFolder1.toString()]);
});
});
+11 -11
View File
@@ -8,13 +8,13 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands';
suite('Command Tests', function () {
test('register command - no handler', function () {
assert.throws(() => CommandsRegistry.registerCommand('foo', null));
assert.throws(() => CommandsRegistry.registerCommand('foo', null!));
});
test('register/dispose', () => {
const command = function () { };
const reg = CommandsRegistry.registerCommand('foo', command);
assert.ok(CommandsRegistry.getCommand('foo').handler === command);
assert.ok(CommandsRegistry.getCommand('foo')!.handler === command);
reg.dispose();
assert.ok(CommandsRegistry.getCommand('foo') === undefined);
});
@@ -25,23 +25,23 @@ suite('Command Tests', function () {
// dispose overriding command
let reg1 = CommandsRegistry.registerCommand('foo', command1);
assert.ok(CommandsRegistry.getCommand('foo').handler === command1);
assert.ok(CommandsRegistry.getCommand('foo')!.handler === command1);
let reg2 = CommandsRegistry.registerCommand('foo', command2);
assert.ok(CommandsRegistry.getCommand('foo').handler === command2);
assert.ok(CommandsRegistry.getCommand('foo')!.handler === command2);
reg2.dispose();
assert.ok(CommandsRegistry.getCommand('foo').handler === command1);
assert.ok(CommandsRegistry.getCommand('foo')!.handler === command1);
reg1.dispose();
assert.ok(CommandsRegistry.getCommand('foo') === void 0);
// dispose override command first
reg1 = CommandsRegistry.registerCommand('foo', command1);
reg2 = CommandsRegistry.registerCommand('foo', command2);
assert.ok(CommandsRegistry.getCommand('foo').handler === command2);
assert.ok(CommandsRegistry.getCommand('foo')!.handler === command2);
reg1.dispose();
assert.ok(CommandsRegistry.getCommand('foo').handler === command2);
assert.ok(CommandsRegistry.getCommand('foo')!.handler === command2);
reg2.dispose();
assert.ok(CommandsRegistry.getCommand('foo') === void 0);
@@ -68,10 +68,10 @@ suite('Command Tests', function () {
}
});
CommandsRegistry.getCommands()['test'].handler.apply(undefined, [undefined, 'string']);
CommandsRegistry.getCommands()['test2'].handler.apply(undefined, [undefined, 'string']);
assert.throws(() => CommandsRegistry.getCommands()['test3'].handler.apply(undefined, [undefined, 'string']));
assert.equal(CommandsRegistry.getCommands()['test3'].handler.apply(undefined, [undefined, 1]), true);
CommandsRegistry.getCommands()['test'].handler.apply(undefined, [undefined!, 'string']);
CommandsRegistry.getCommands()['test2'].handler.apply(undefined, [undefined!, 'string']);
assert.throws(() => CommandsRegistry.getCommands()['test3'].handler.apply(undefined, [undefined!, 'string']));
assert.equal(CommandsRegistry.getCommands()['test3'].handler.apply(undefined, [undefined!, 1]), true);
});
});
@@ -25,10 +25,10 @@ export interface ParsedArgs {
'reuse-window'?: boolean;
locale?: string;
'user-data-dir'?: string;
performance?: boolean;
'prof-startup'?: string;
'prof-startup-prefix'?: string;
'prof-append-timers'?: string;
'prof-modules'?: string;
verbose?: boolean;
trace?: boolean;
'trace-category-filter'?: string;
@@ -126,7 +126,6 @@ export interface IEnvironmentService {
isBuilt: boolean;
wait: boolean;
status: boolean;
performance: boolean;
// logging
log?: string;
+4 -4
View File
@@ -51,8 +51,8 @@ const options: minimist.Opts = {
'unity-launch',
'reuse-window',
'open-url',
'performance',
'prof-startup',
'prof-code-loading',
'verbose',
'logExtensionHostCommunication',
'disable-extensions',
@@ -175,8 +175,8 @@ const troubleshootingHelp: { [name: string]: string; } = {
'--verbose': localize('verbose', "Print verbose output (implies --wait)."),
'--log <level>': localize('log', "Log level to use. Default is 'info'. Allowed values are 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'."),
'-s, --status': localize('status', "Print process usage and diagnostics information."),
'-p, --performance': localize('performance', "Start with the 'Developer: Startup Performance' command enabled."),
'--prof-startup': localize('prof-startup', "Run CPU profiler during startup"),
'--prof-startup': localize('prof-startup', "Run CPU profilers during startup."),
'--prof-modules': localize('prof-modules', "Capture performance markers while loading JS modules and print them with 'F1 > Developer: Startup Performance'"),
'--disable-extensions': localize('disableExtensions', "Disable all installed extensions."),
'--disable-extension <extension-id>': localize('disableExtension', "Disable an extension."),
'--inspect-extensions': localize('inspect-extensions', "Allow debugging and profiling of extensions. Check the developer tools for the connection URI."),
@@ -265,4 +265,4 @@ export function hasArgs(arg: string | string[] | undefined): boolean {
return true;
}
return false;
}
}
@@ -222,7 +222,6 @@ export class EnvironmentService implements IEnvironmentService {
get logExtensionHostCommunication(): boolean { return !!this._args.logExtensionHostCommunication; }
get performance(): boolean { return !!this._args.performance; }
get status(): boolean { return !!this._args.status; }
@memoize
@@ -50,7 +50,7 @@ suite('ExtensionEnablementService Test', () => {
setup(() => {
instantiationService = new TestInstantiationService();
instantiationService.stub(IExtensionManagementService, { onDidUninstallExtension: didUninstallEvent.event, onDidInstallExtension: didInstallEvent.event, getInstalled: () => Promise.resolve([]) } as IExtensionManagementService);
instantiationService.stub(IExtensionManagementService, { onDidUninstallExtension: didUninstallEvent.event, onDidInstallExtension: didInstallEvent.event, getInstalled: () => Promise.resolve([] as ILocalExtension[]) } as IExtensionManagementService);
testObject = new TestExtensionEnablementService(instantiationService);
});
@@ -77,15 +77,15 @@ suite('AbstractKeybindingService', () => {
altKey: keybinding.altKey,
metaKey: keybinding.metaKey,
keyCode: keybinding.keyCode,
code: null
}, null);
code: null!
}, null!);
}
}
let createTestKeybindingService: (items: ResolvedKeybindingItem[], contextValue?: any) => TestKeybindingService = null;
let createTestKeybindingService: (items: ResolvedKeybindingItem[], contextValue?: any) => TestKeybindingService = null!;
let currentContextValue: IContext | null = null;
let executeCommandCalls: { commandId: string; args: any[]; }[] = null;
let showMessageCalls: { sev: Severity, message: any; }[] = null;
let executeCommandCalls: { commandId: string; args: any[]; }[] = null!;
let showMessageCalls: { sev: Severity, message: any; }[] = null!;
let statusMessageCalls: string[] | null = null;
let statusMessageCallsDisposed: string[] | null = null;
@@ -99,12 +99,12 @@ suite('AbstractKeybindingService', () => {
let contextKeyService: IContextKeyService = {
_serviceBrand: undefined,
dispose: undefined,
onDidChangeContext: undefined,
createKey: undefined,
contextMatchesRules: undefined,
getContextKeyValue: undefined,
createScoped: undefined,
dispose: undefined!,
onDidChangeContext: undefined!,
createKey: undefined!,
contextMatchesRules: undefined!,
getContextKeyValue: undefined!,
createScoped: undefined!,
getContext: (target: IContextKeyServiceTarget): any => {
return currentContextValue;
}
@@ -147,12 +147,12 @@ suite('AbstractKeybindingService', () => {
let statusbarService: IStatusbarService = {
_serviceBrand: undefined,
addEntry: undefined,
addEntry: undefined!,
setStatusMessage: (message: string, autoDisposeAfter?: number, delayBy?: number): IDisposable => {
statusMessageCalls.push(message);
statusMessageCalls!.push(message);
return {
dispose: () => {
statusMessageCallsDisposed.push(message);
statusMessageCallsDisposed!.push(message);
}
};
}
@@ -166,15 +166,15 @@ suite('AbstractKeybindingService', () => {
teardown(() => {
currentContextValue = null;
executeCommandCalls = null;
showMessageCalls = null;
createTestKeybindingService = null;
executeCommandCalls = null!;
showMessageCalls = null!;
createTestKeybindingService = null!;
statusMessageCalls = null;
statusMessageCallsDisposed = null;
});
function kbItem(keybinding: number, command: string, when: ContextKeyExpr | null = null): ResolvedKeybindingItem {
const resolvedKeybinding = (keybinding !== 0 ? new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS), OS) : null);
const resolvedKeybinding = (keybinding !== 0 ? new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS)!, OS) : null);
return new ResolvedKeybindingItem(
resolvedKeybinding,
command,
@@ -185,8 +185,8 @@ suite('AbstractKeybindingService', () => {
}
function toUsLabel(keybinding: number): string {
const usResolvedKeybinding = new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS), OS);
return usResolvedKeybinding.getLabel();
const usResolvedKeybinding = new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS)!, OS);
return usResolvedKeybinding.getLabel()!;
}
test('issue #16498: chord mode is quit for invalid chords', () => {
@@ -30,10 +30,10 @@ suite('StorageService', () => {
const storage = new TestStorageService();
storage.store('Monaco.IDE.Core.Storage.Test.remove', 'foobar', scope);
strictEqual('foobar', storage.get('Monaco.IDE.Core.Storage.Test.remove', scope, void 0));
strictEqual('foobar', storage.get('Monaco.IDE.Core.Storage.Test.remove', scope, (void 0)!));
storage.remove('Monaco.IDE.Core.Storage.Test.remove', scope);
ok(!storage.get('Monaco.IDE.Core.Storage.Test.remove', scope, void 0));
ok(!storage.get('Monaco.IDE.Core.Storage.Test.remove', scope, (void 0)!));
}
test('Get Data, Integer, Boolean (global, in-memory)', () => {
@@ -55,22 +55,22 @@ suite('StorageService', () => {
strictEqual(storage.getBoolean('Monaco.IDE.Core.Storage.Test.getBoolean', scope, false), false);
storage.store('Monaco.IDE.Core.Storage.Test.get', 'foobar', scope);
strictEqual(storage.get('Monaco.IDE.Core.Storage.Test.get', scope, void 0), 'foobar');
strictEqual(storage.get('Monaco.IDE.Core.Storage.Test.get', scope, (void 0)!), 'foobar');
storage.store('Monaco.IDE.Core.Storage.Test.get', '', scope);
strictEqual(storage.get('Monaco.IDE.Core.Storage.Test.get', scope, void 0), '');
strictEqual(storage.get('Monaco.IDE.Core.Storage.Test.get', scope, (void 0)!), '');
storage.store('Monaco.IDE.Core.Storage.Test.getInteger', 5, scope);
strictEqual(storage.getInteger('Monaco.IDE.Core.Storage.Test.getInteger', scope, void 0), 5);
strictEqual(storage.getInteger('Monaco.IDE.Core.Storage.Test.getInteger', scope, (void 0)!), 5);
storage.store('Monaco.IDE.Core.Storage.Test.getInteger', 0, scope);
strictEqual(storage.getInteger('Monaco.IDE.Core.Storage.Test.getInteger', scope, void 0), 0);
strictEqual(storage.getInteger('Monaco.IDE.Core.Storage.Test.getInteger', scope, (void 0)!), 0);
storage.store('Monaco.IDE.Core.Storage.Test.getBoolean', true, scope);
strictEqual(storage.getBoolean('Monaco.IDE.Core.Storage.Test.getBoolean', scope, void 0), true);
strictEqual(storage.getBoolean('Monaco.IDE.Core.Storage.Test.getBoolean', scope, (void 0)!), true);
storage.store('Monaco.IDE.Core.Storage.Test.getBoolean', false, scope);
strictEqual(storage.getBoolean('Monaco.IDE.Core.Storage.Test.getBoolean', scope, void 0), false);
strictEqual(storage.getBoolean('Monaco.IDE.Core.Storage.Test.getBoolean', scope, (void 0)!), false);
strictEqual(storage.get('Monaco.IDE.Core.Storage.Test.getDefault', scope, 'getDefault'), 'getDefault');
strictEqual(storage.getInteger('Monaco.IDE.Core.Storage.Test.getIntegerDefault', scope, 5), 5);
@@ -17,8 +17,8 @@ suite('Telemetry - common properties', function () {
const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'telemetryservice');
const installSource = path.join(parentDir, 'installSource');
const commit: string = void 0;
const version: string = void 0;
const commit: string = (void 0)!;
const version: string = (void 0)!;
let testStorageService: IStorageService;
setup(() => {
@@ -41,7 +41,7 @@ suite('Color Registry', function () {
test('all colors documented', async function () {
const reqContext = await request({ url: 'https://raw.githubusercontent.com/Microsoft/vscode-docs/vnext/docs/getstarted/theme-color-reference.md' }, CancellationToken.None);
const content = await asText(reqContext);
const content = (await asText(reqContext))!;
const expression = /\-\s*\`([\w\.]+)\`: (.*)/g;
@@ -177,9 +177,9 @@ suite('WorkspacesMainService', () => {
workspace.configPath = newPath;
const resolved = service.resolveWorkspaceSync(workspace.configPath);
assert.equal(2, resolved.folders.length);
assert.equal(resolved.configPath, workspace.configPath);
assert.ok(resolved.id);
assert.equal(2, resolved!.folders.length);
assert.equal(resolved!.configPath, workspace.configPath);
assert.ok(resolved!.id);
fs.writeFileSync(workspace.configPath, JSON.stringify({ something: 'something' })); // invalid workspace
const resolvedInvalid = service.resolveWorkspaceSync(workspace.configPath);
@@ -192,7 +192,7 @@ suite('WorkspacesMainService', () => {
fs.writeFileSync(workspace.configPath, JSON.stringify({ folders: [{ path: './ticino-playground/lib' }] }));
const resolved = service.resolveWorkspaceSync(workspace.configPath);
assert.equal(resolved.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'lib')).fsPath);
assert.equal(resolved!.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'lib')).fsPath);
});
});
@@ -201,7 +201,7 @@ suite('WorkspacesMainService', () => {
fs.writeFileSync(workspace.configPath, JSON.stringify({ folders: [{ path: './ticino-playground/lib/../other' }] }));
const resolved = service.resolveWorkspaceSync(workspace.configPath);
assert.equal(resolved.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'other')).fsPath);
assert.equal(resolved!.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'other')).fsPath);
});
});
@@ -210,7 +210,7 @@ suite('WorkspacesMainService', () => {
fs.writeFileSync(workspace.configPath, JSON.stringify({ folders: [{ path: 'ticino-playground/lib' }] }));
const resolved = service.resolveWorkspaceSync(workspace.configPath);
assert.equal(resolved.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'lib')).fsPath);
assert.equal(resolved!.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'lib')).fsPath);
});
});
@@ -219,7 +219,7 @@ suite('WorkspacesMainService', () => {
fs.writeFileSync(workspace.configPath, '{ "folders": [ { "path": "./ticino-playground/lib" } , ] }'); // trailing comma
const resolved = service.resolveWorkspaceSync(workspace.configPath);
assert.equal(resolved.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'lib')).fsPath);
assert.equal(resolved!.folders[0].uri.fsPath, URI.file(path.join(path.dirname(workspace.configPath), 'ticino-playground', 'lib')).fsPath);
});
});
+1 -1
View File
@@ -7929,7 +7929,7 @@ declare module 'vscode' {
export function registerReferenceProvider(selector: DocumentSelector, provider: ReferenceProvider): Disposable;
/**
* Register a reference provider.
* Register a rename provider.
*
* Multiple providers can be registered for a language. In that case providers are sorted
* by their [score](#languages.match) and the best-matching provider is used. Failure
+1 -1
View File
@@ -47,7 +47,7 @@ declare module 'vscode' {
export class SelectionRange {
kind: SelectionRangeKind;
range: Range;
constructor(kind: SelectionRangeKind, range: Range);
constructor(range: Range, kind: SelectionRangeKind);
}
export interface SelectionRangeProvider {
@@ -855,7 +855,7 @@ export namespace SelectionRange {
}
export function to(obj: modes.SelectionRange): vscode.SelectionRange {
return new types.SelectionRange(SelectionRangeKind.to(obj.kind), Range.to(obj.range));
return new types.SelectionRange(Range.to(obj.range), SelectionRangeKind.to(obj.kind));
}
}
+3 -3
View File
@@ -491,7 +491,7 @@ export class TextEdit {
constructor(range: Range, newText: string) {
this.range = range;
this.newText = newText || '';
this.newText = newText;
}
toJSON(): any {
@@ -1060,9 +1060,9 @@ export class SelectionRange {
kind: SelectionRangeKind;
range: Range;
constructor(kind: SelectionRangeKind, range: Range) {
this.kind = kind;
constructor(range: Range, kind: SelectionRangeKind, ) {
this.range = range;
this.kind = kind;
}
}
@@ -1059,7 +1059,7 @@ export class TabsTitleControl extends TitleControl {
element = (e as GestureEvent).initialTarget as HTMLElement;
}
return !!findParentWithClass(element, 'monaco-action-bar', 'tab');
return !!findParentWithClass(element, 'action-item', 'tab');
}
private onDrop(e: DragEvent, targetIndex: number): void {
@@ -886,6 +886,11 @@ configurationRegistry.registerConfiguration({
'default': true,
'description': nls.localize('zenMode.hideActivityBar', "Controls whether turning on Zen Mode also hides the activity bar at the left of the workbench.")
},
'zenMode.hideLineNumbers': {
'type': 'boolean',
'default': true,
'description': nls.localize('zenMode.hideLineNumbers', "Controls whether turning on Zen Mode also hides the editor line numbers.")
},
'zenMode.restore': {
'type': 'boolean',
'default': false,
@@ -113,6 +113,7 @@ import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/work
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
import { FileDialogService } from 'vs/workbench/services/dialogs/electron-browser/dialogService';
import { LogStorageAction } from 'vs/platform/storage/node/storageService';
import { IEditor } from 'vs/editor/common/editorCommon';
interface WorkbenchParams {
configuration: IWindowConfiguration;
@@ -125,6 +126,7 @@ interface IZenModeSettings {
hideTabs: boolean;
hideActivityBar: boolean;
hideStatusBar: boolean;
hideLineNumbers: boolean;
restore: boolean;
}
@@ -1236,6 +1238,14 @@ export class Workbench extends Disposable implements IPartService {
// Check if zen mode transitioned to full screen and if now we are out of zen mode
// -> we need to go out of full screen (same goes for the centered editor layout)
let toggleFullScreen = false;
const setLineNumbers = (lineNumbers: any) => {
this.editorService.visibleControls.forEach(editor => {
const control = <IEditor>editor.getControl();
if (control) {
control.updateOptions({ lineNumbers });
}
});
};
// Zen Mode Active
if (this.zenMode.active) {
@@ -1258,6 +1268,11 @@ export class Workbench extends Disposable implements IPartService {
this.setStatusBarHidden(true, true);
}
if (config.hideLineNumbers) {
setLineNumbers('off');
this.zenMode.transitionDisposeables.push(this.editorService.onDidVisibleEditorsChange(() => setLineNumbers('off')));
}
if (config.hideTabs && this.editorPart.partOptions.showTabs) {
this.zenMode.transitionDisposeables.push(this.editorPart.enforcePartOptions({ showTabs: false }));
}
@@ -1280,6 +1295,7 @@ export class Workbench extends Disposable implements IPartService {
if (this.zenMode.transitionedToCenteredEditorLayout) {
this.centerEditorLayout(false, true);
}
setLineNumbers(this.configurationService.getValue('editor.lineNumbers'));
// Status bar and activity bar visibility come from settings -> update their visibility.
this.onDidUpdateConfiguration(true);
@@ -190,6 +190,11 @@ export abstract class AbstractExpressionsRenderer
data.toDispose.push(dom.addDisposableListener(inputBox.inputElement, 'blur', () => {
wrapUp(true);
}));
data.toDispose.push(dom.addDisposableListener(inputBox.inputElement, 'click', e => {
// Do not expand / collapse selected elements
e.preventDefault();
e.stopPropagation();
}));
};
return data;
@@ -10,7 +10,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IFileService } from 'vs/platform/files/common/files';
import { IDebugService, State, IDebugSession, IThread, IEnablement, IBreakpoint, IStackFrame, REPL_ID, IConfig }
import { IDebugService, State, IDebugSession, IThread, IEnablement, IBreakpoint, IStackFrame, REPL_ID }
from 'vs/workbench/parts/debug/common/debug';
import { Variable, Expression, Thread, Breakpoint } from 'vs/workbench/parts/debug/common/debugModel';
import { IPartService } from 'vs/workbench/services/part/common/partService';
@@ -135,11 +135,7 @@ export class StartAction extends AbstractDebugAction {
// Note: When this action is executed from the process explorer, a config is passed. For all
// other cases it is run with no arguments.
public run(config?: IConfig): Promise<any> {
if (config && 'type' in config && 'request' in config) {
return this.debugService.startDebugging(undefined, config, this.isNoDebug());
}
public run(): Promise<any> {
const configurationManager = this.debugService.getConfigurationManager();
let launch = configurationManager.selectedConfiguration.launch;
if (!launch || launch.getConfigurationNames().length === 0) {
@@ -9,7 +9,7 @@ import { List } from 'vs/base/browser/ui/list/listWidget';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IListService } from 'vs/platform/list/browser/listService';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IDebugService, IEnablement, CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_VARIABLES_FOCUSED, EDITOR_CONTRIBUTION_ID, IDebugEditorContribution, CONTEXT_IN_DEBUG_MODE, CONTEXT_EXPRESSION_SELECTED, CONTEXT_BREAKPOINT_SELECTED } from 'vs/workbench/parts/debug/common/debug';
import { IDebugService, IEnablement, CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_VARIABLES_FOCUSED, EDITOR_CONTRIBUTION_ID, IDebugEditorContribution, CONTEXT_IN_DEBUG_MODE, CONTEXT_EXPRESSION_SELECTED, CONTEXT_BREAKPOINT_SELECTED, IConfig } from 'vs/workbench/parts/debug/common/debug';
import { Expression, Variable, Breakpoint, FunctionBreakpoint } from 'vs/workbench/parts/debug/common/debugModel';
import { IExtensionsViewlet, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/parts/extensions/common/extensions';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
@@ -23,12 +23,22 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
import { InputFocusedContext } from 'vs/platform/workbench/common/contextkeys';
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { PanelFocusContext } from 'vs/workbench/browser/parts/panel/panelPart';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { onUnexpectedError } from 'vs/base/common/errors';
export const ADD_CONFIGURATION_ID = 'debug.addConfiguration';
export const TOGGLE_INLINE_BREAKPOINT_ID = 'editor.debug.action.toggleInlineBreakpoint';
export function registerCommands(): void {
CommandsRegistry.registerCommand({
id: 'debug.startFromConfig',
handler: (accessor, config: IConfig) => {
const debugService = accessor.get(IDebugService);
debugService.startDebugging(undefined, config).then(undefined, onUnexpectedError);
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'debug.toggleBreakpoint',
weight: KeybindingWeight.WorkbenchContrib + 5,
@@ -155,15 +155,21 @@
margin-left: 6px;
}
.monaco-workbench .monaco-list-row:not(.selected) .expression .name {
/* White color when element is selected and list is focused. White looks better on blue selection background. */
.monaco-workbench .monaco-list:focus .monaco-list-row.selected .expression .name,
.monaco-workbench .monaco-list:focus .monaco-list-row.selected .expression .value {
color: white;
}
.monaco-workbench .monaco-list-row .expression .name {
color: #9B46B0;
}
.monaco-workbench .monaco-list-row:not(.selected) .expression .name.virtual {
.monaco-workbench .monaco-list-row .expression .name.virtual {
opacity: 0.5;
}
.monaco-workbench > .monaco-list-row:not(.selected) .expression .value {
.monaco-workbench > .monaco-list-row .expression .value {
color: rgba(108, 108, 108, 0.8);
}
@@ -171,67 +177,67 @@
font-style: italic;
}
.monaco-workbench .monaco-list-row:not(.selected) .expression .error {
.monaco-workbench .monaco-list-row .expression .error {
color: #E51400;
}
.monaco-workbench .monaco-list-row:not(.selected) .expression .value.number {
.monaco-workbench .monaco-list-row .expression .value.number {
color: #09885A;
}
.monaco-workbench .monaco-list-row:not(.selected) .expression .value.boolean {
.monaco-workbench .monaco-list-row .expression .value.boolean {
color: #0000FF;
}
.monaco-workbench .monaco-list-row:not(.selected) .expression .value.string {
.monaco-workbench .monaco-list-row .expression .value.string {
color: #A31515;
}
.vs-dark .monaco-workbench > .monaco-list-row:not(.selected) .expression .value {
.vs-dark .monaco-workbench > .monaco-list-row .expression .value {
color: rgba(204, 204, 204, 0.6);
}
.vs-dark .monaco-workbench .monaco-list-row:not(.selected) .expression .error {
.vs-dark .monaco-workbench .monaco-list-row .expression .error {
color: #F48771;
}
.vs-dark .monaco-workbench .monaco-list-row:not(.selected) .expression .value.number {
.vs-dark .monaco-workbench .monaco-list-row .expression .value.number {
color: #B5CEA8;
}
.hc-black .monaco-workbench .monaco-list-row:not(.selected) .expression .value.number {
.hc-black .monaco-workbench .monaco-list-row .expression .value.number {
color: #89d185;
}
.hc-black .monaco-workbench .monaco-list-row:not(.selected) .expression .value.boolean {
.hc-black .monaco-workbench .monaco-list-row .expression .value.boolean {
color: #75bdfe;
}
.hc-black .monaco-workbench .monaco-list-row:not(.selected) .expression .value.string {
.hc-black .monaco-workbench .monaco-list-row .expression .value.string {
color: #f48771;
}
.vs-dark .monaco-workbench .monaco-list-row:not(.selected) .expression .value.boolean {
.vs-dark .monaco-workbench .monaco-list-row .expression .value.boolean {
color: #4E94CE;
}
.vs-dark .monaco-workbench .monaco-list-row:not(.selected) .expression .value.string {
.vs-dark .monaco-workbench .monaco-list-row .expression .value.string {
color: #CE9178;
}
.hc-black .monaco-workbench .monaco-list-row:not(.selected) .expression .error {
.hc-black .monaco-workbench .monaco-list-row .expression .error {
color: #F48771;
}
/* Dark theme */
.vs-dark .monaco-workbench .monaco-list-row:not(.selected) .expression .name {
.vs-dark .monaco-workbench .monaco-list-row .expression .name {
color: #C586C0;
}
/* High Contrast Theming */
.hc-black .monaco-workbench .monaco-list-row:not(.selected) .expression .name {
.hc-black .monaco-workbench .monaco-list-row .expression .name {
color: inherit;
}
@@ -5,7 +5,7 @@
/* Debug repl */
.repl {
.composite.panel .repl {
height: 100%;
box-sizing: border-box;
overflow: hidden;
+1 -1
View File
@@ -393,7 +393,7 @@ export interface IDebugModel extends ITreeElement {
getWatchExpressions(): ReadonlyArray<IExpression & IEvaluate>;
onDidChangeBreakpoints: Event<IBreakpointsChangeEvent>;
onDidChangeCallStack: Event<void>;
onDidChangeCallStack: Event<IThread | undefined>;
onDidChangeWatchExpressions: Event<IExpression>;
}
@@ -644,6 +644,13 @@ export class Breakpoint extends BaseBreakpoint implements IBreakpoint {
return data ? data.endColumn : undefined;
}
setSessionData(sessionId: string, data: DebugProtocol.Breakpoint): void {
super.setSessionData(sessionId, data);
if (!this._adapterData) {
this._adapterData = this.adapterData;
}
}
toJSON(): any {
const result = super.toJSON();
result.uri = this.uri;
@@ -737,7 +744,7 @@ export class DebugModel implements IDebugModel {
private schedulers = new Map<string, RunOnceScheduler>();
private breakpointsSessionId: string;
private readonly _onDidChangeBreakpoints: Emitter<IBreakpointsChangeEvent>;
private readonly _onDidChangeCallStack: Emitter<void>;
private readonly _onDidChangeCallStack: Emitter<IThread | undefined>;
private readonly _onDidChangeWatchExpressions: Emitter<IExpression>;
constructor(
@@ -751,7 +758,7 @@ export class DebugModel implements IDebugModel {
this.sessions = [];
this.toDispose = [];
this._onDidChangeBreakpoints = new Emitter<IBreakpointsChangeEvent>();
this._onDidChangeCallStack = new Emitter<void>();
this._onDidChangeCallStack = new Emitter<IThread | undefined>();
this._onDidChangeWatchExpressions = new Emitter<IExpression>();
}
@@ -786,7 +793,7 @@ export class DebugModel implements IDebugModel {
return this._onDidChangeBreakpoints.event;
}
get onDidChangeCallStack(): Event<void> {
get onDidChangeCallStack(): Event<IThread | undefined> {
return this._onDidChangeCallStack.event;
}
@@ -819,12 +826,12 @@ export class DebugModel implements IDebugModel {
return thread.fetchCallStack(1).then(() => {
if (!this.schedulers.has(thread.getId())) {
this.schedulers.set(thread.getId(), new RunOnceScheduler(() => {
thread.fetchCallStack(19).then(() => this._onDidChangeCallStack.fire());
thread.fetchCallStack(19).then(() => this._onDidChangeCallStack.fire(thread));
}, 420));
}
this.schedulers.get(thread.getId()).schedule();
this._onDidChangeCallStack.fire();
this._onDidChangeCallStack.fire(thread);
});
}
@@ -10,7 +10,7 @@ import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { Registry } from 'vs/platform/registry/common/platform';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { KeybindingWeight, IKeybindings, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { KeybindingWeight, IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import { IWorkbenchActionRegistry, Extensions as WorkbenchActionRegistryExtensions } from 'vs/workbench/common/actions';
import { ShowViewletAction, Extensions as ViewletExtensions, ViewletRegistry, ViewletDescriptor } from 'vs/workbench/browser/viewlet';
@@ -49,13 +49,11 @@ import { DebugViewlet } from 'vs/workbench/parts/debug/browser/debugViewlet';
import { Repl, ClearReplAction } from 'vs/workbench/parts/debug/electron-browser/repl';
import { DebugQuickOpenHandler } from 'vs/workbench/parts/debug/browser/debugQuickOpen';
import { DebugStatus } from 'vs/workbench/parts/debug/browser/debugStatus';
import { LifecyclePhase, ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { launchSchemaId } from 'vs/workbench/services/configuration/common/configuration';
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
import { LoadedScriptsView } from 'vs/workbench/parts/debug/browser/loadedScriptsView';
import { TOGGLE_LOG_POINT_ID, TOGGLE_CONDITIONAL_BREAKPOINT_ID, TOGGLE_BREAKPOINT_ID } from 'vs/workbench/parts/debug/browser/debugEditorActions';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
class OpenDebugViewletAction extends ShowViewletAction {
public static readonly ID = VIEWLET_ID;
@@ -132,58 +130,7 @@ Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).regi
const debugCategory = nls.localize('debugCategory', "Debug");
const startDebugDescriptor = new SyncActionDescriptor(StartAction, StartAction.ID, StartAction.LABEL, { primary: KeyCode.F5 }, CONTEXT_IN_DEBUG_MODE.toNegated());
function startDebugHandler(accessor, args): Promise<void> {
const notificationService = accessor.get(INotificationService);
const instantiationService = accessor.get(IInstantiationService);
const lifecycleService = accessor.get(ILifecycleService);
return Promise.resolve(lifecycleService.when(LifecyclePhase.Ready).then(() => {
const actionInstance = instantiationService.createInstance(startDebugDescriptor.syncDescriptor);
try {
// don't run the action when not enabled
if (!actionInstance.enabled) {
actionInstance.dispose();
return void 0;
}
const from = args && args.from || 'keybinding';
if (args) {
delete args.from;
}
return Promise.resolve(actionInstance.run(args, { from })).then(() => {
actionInstance.dispose();
}, err => {
actionInstance.dispose();
return Promise.reject(err);
});
} catch (err) {
actionInstance.dispose();
return Promise.reject(err);
}
})).then(void 0, err => notificationService.error(err));
}
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: StartAction.ID,
weight: KeybindingWeight.WorkbenchContrib,
when: CONTEXT_IN_DEBUG_MODE.toNegated(),
primary: KeyCode.F5,
handler: startDebugHandler
});
MenuRegistry.addCommand({
id: StartAction.ID,
title: StartAction.LABEL,
category: debugCategory
});
registry.registerWorkbenchAction(new SyncActionDescriptor(StartAction, StartAction.ID, StartAction.LABEL, { primary: KeyCode.F5 }), 'Debug: Start Debugging', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(StepOverAction, StepOverAction.ID, StepOverAction.LABEL, { primary: KeyCode.F10 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Step Over', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(StepIntoAction, StepIntoAction.ID, StepIntoAction.LABEL, { primary: KeyCode.F11 }, CONTEXT_IN_DEBUG_MODE, KeybindingWeight.WorkbenchContrib + 1), 'Debug: Step Into', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(StepOutAction, StepOutAction.ID, StepOutAction.LABEL, { primary: KeyMod.Shift | KeyCode.F11 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Step Out', debugCategory);
@@ -778,7 +778,7 @@ export class DebugService implements IDebugService {
if (!stackFrame) {
if (thread) {
const callStack = thread.getCallStack();
stackFrame = first(callStack, sf => sf.source && sf.source.available, undefined);
stackFrame = first(callStack, sf => sf.source && sf.source.available && sf.source.presentationHint !== 'deemphasize', undefined);
}
}
@@ -611,6 +611,16 @@ export class DebugSession implements IDebugSession {
this.model.fetchCallStack(<Thread>thread).then(() => {
if (!event.body.preserveFocusHint && thread.getCallStack().length) {
this.debugService.focusStackFrame(undefined, thread);
if (!this.debugService.getViewModel().focusedStackFrame) {
// There were no appropriate stack frames to focus.
// We need to listen on additional stack frame fetching and try to refocus #65012
const listener = this.model.onDidChangeCallStack(t => {
if (t && t.getId() === thread.getId()) {
dispose(listener);
this.debugService.focusStackFrame(undefined, thread);
}
});
}
if (thread.stoppedDetails) {
if (this.configurationService.getValue<IDebugConfiguration>('debug').openDebug === 'openOnDebugBreak') {
this.viewletService.openViewlet(VIEWLET_ID);
@@ -118,7 +118,7 @@ export class WatchExpressionsView extends ViewletPanel {
const element = e.element;
// double click on primitive value: open input box to be able to select and copy value.
if (element instanceof Expression) {
if (element instanceof Expression && element !== this.debugService.getViewModel().getSelectedExpression()) {
this.debugService.getViewModel().setSelectedExpression(element);
} else if (!element) {
// Double click in watch panel triggers to add a new watch expression
@@ -34,7 +34,7 @@ suite('Debug - ANSI Handling', () => {
assert.equal(2, root.children.length);
child = root.firstChild;
child = root.firstChild!;
if (child instanceof HTMLSpanElement) {
assert.equal('content1', child.textContent);
assert(dom.hasClass(child, 'class1'));
@@ -43,7 +43,7 @@ suite('Debug - ANSI Handling', () => {
assert.fail('Unexpected assertion error');
}
child = root.lastChild;
child = root.lastChild!;
if (child instanceof HTMLSpanElement) {
assert.equal('content2', child.textContent);
assert(dom.hasClass(child, 'class2'));
@@ -62,12 +62,12 @@ suite('Debug - ANSI Handling', () => {
function getSequenceOutput(sequence: string): HTMLSpanElement {
const root: HTMLSpanElement = handleANSIOutput(sequence, linkDetector);
assert.equal(1, root.children.length);
const child: Node = root.lastChild;
const child: Node = root.lastChild!;
if (child instanceof HTMLSpanElement) {
return child;
} else {
assert.fail('Unexpected assertion error');
return null;
return null!;
}
}
@@ -37,7 +37,7 @@ suite('Debug - Debugger', () => {
}
}
},
variables: null,
variables: null!,
initialConfigurations: [
{
name: 'Mock-Debug',
@@ -57,7 +57,7 @@ suite('Debug - Debugger', () => {
extensionLocation: URI.file(extensionFolderPath),
isBuiltin: false,
isUnderDevelopment: false,
engines: null,
engines: null!,
contributes: {
'debuggers': [
debuggerContribution
@@ -74,7 +74,7 @@ suite('Debug - Debugger', () => {
extensionLocation: URI.file('/e1/b/c/'),
isBuiltin: false,
isUnderDevelopment: false,
engines: null,
engines: null!,
contributes: {
'debuggers': [
{
@@ -97,7 +97,7 @@ suite('Debug - Debugger', () => {
extensionLocation: URI.file('/e2/b/c/'),
isBuiltin: false,
isUnderDevelopment: false,
engines: null,
engines: null!,
contributes: {
'debuggers': [
{
@@ -130,11 +130,11 @@ suite('Debug - Debugger', () => {
const testResourcePropertiesService = new TestTextResourcePropertiesService(configurationService);
setup(() => {
_debugger = new Debugger(configurationManager, debuggerContribution, extensionDescriptor0, configurationService, testResourcePropertiesService, undefined, undefined, undefined);
_debugger = new Debugger(configurationManager, debuggerContribution, extensionDescriptor0, configurationService, testResourcePropertiesService, undefined!, undefined!, undefined!);
});
teardown(() => {
_debugger = null;
_debugger = null!;
});
test('attributes', () => {
@@ -143,8 +143,8 @@ suite('Debug - Debugger', () => {
const ae = ExecutableDebugAdapter.platformAdapterExecutable([extensionDescriptor0], 'mock');
assert.equal(ae.command, paths.join(extensionFolderPath, debuggerContribution.program));
assert.deepEqual(ae.args, debuggerContribution.args);
assert.equal(ae!.command, paths.join(extensionFolderPath, debuggerContribution.program));
assert.deepEqual(ae!.args, debuggerContribution.args);
});
test('schema attributes', () => {
@@ -155,14 +155,14 @@ suite('Debug - Debugger', () => {
});
assert.equal(schemaAttribute['additionalProperties'], false);
assert.equal(!!schemaAttribute['properties']['request'], true);
assert.equal(!!schemaAttribute['properties']['name'], true);
assert.equal(!!schemaAttribute['properties']['type'], true);
assert.equal(!!schemaAttribute['properties']['preLaunchTask'], true);
assert.equal(!!schemaAttribute['properties']!['request'], true);
assert.equal(!!schemaAttribute['properties']!['name'], true);
assert.equal(!!schemaAttribute['properties']!['type'], true);
assert.equal(!!schemaAttribute['properties']!['preLaunchTask'], true);
});
test('merge platform specific attributes', () => {
const ae = ExecutableDebugAdapter.platformAdapterExecutable([extensionDescriptor1, extensionDescriptor2], 'mock');
const ae = ExecutableDebugAdapter.platformAdapterExecutable([extensionDescriptor1, extensionDescriptor2], 'mock')!;
assert.equal(ae.command, platform.isLinux ? 'linuxRuntime' : (platform.isMacintosh ? 'osxRuntime' : 'winRuntime'));
const xprogram = platform.isLinux ? 'linuxProgram' : (platform.isMacintosh ? 'osxProgram' : 'winProgram');
assert.deepEqual(ae.args, ['rarg', '/e2/b/c/' + xprogram, 'parg']);
@@ -27,7 +27,13 @@ import { URI } from 'vs/base/common/uri';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { lastSessionDateStorageKey } from 'vs/platform/telemetry/node/workbenchCommonProperties';
let experimentData = {
interface ExperimentSettings {
enabled?: boolean;
id?: string;
state?: ExperimentState;
}
let experimentData: { [i: string]: any } = {
experiments: []
};
@@ -495,9 +501,9 @@ suite('Experiment Service', () => {
]
};
let storageDataExperiment1 = { enabled: false };
let storageDataExperiment2 = { enabled: false };
let storageDataAllExperiments = ['experiment1', 'experiment2', 'experiment3'];
let storageDataExperiment1: ExperimentSettings | null = { enabled: false };
let storageDataExperiment2: ExperimentSettings | null = { enabled: false };
let storageDataAllExperiments: string[] | null = ['experiment1', 'experiment2', 'experiment3'];
instantiationService.stub(IStorageService, {
get: (a, b, c) => {
switch (a) {
@@ -554,8 +560,8 @@ suite('Experiment Service', () => {
assert.equal(!!storageDataExperiment2, false);
});
return Promise.all([disabledExperiment, deletedExperiment]).then(() => {
assert.equal(storageDataAllExperiments.length, 1);
assert.equal(storageDataAllExperiments[0], 'experiment3');
assert.equal(storageDataAllExperiments!.length, 1);
assert.equal(storageDataAllExperiments![0], 'experiment3');
});
});
@@ -565,11 +571,11 @@ suite('Experiment Service', () => {
experiments: null
};
let storageDataExperiment1 = { enabled: true, state: ExperimentState.Run };
let storageDataExperiment2 = { enabled: true, state: ExperimentState.NoRun };
let storageDataExperiment3 = { enabled: true, state: ExperimentState.Evaluating };
let storageDataExperiment4 = { enabled: true, state: ExperimentState.Complete };
let storageDataAllExperiments = ['experiment1', 'experiment2', 'experiment3', 'experiment4'];
let storageDataExperiment1: ExperimentSettings | null = { enabled: true, state: ExperimentState.Run };
let storageDataExperiment2: ExperimentSettings | null = { enabled: true, state: ExperimentState.NoRun };
let storageDataExperiment3: ExperimentSettings | null = { enabled: true, state: ExperimentState.Evaluating };
let storageDataExperiment4: ExperimentSettings | null = { enabled: true, state: ExperimentState.Complete };
let storageDataAllExperiments: string[] | null = ['experiment1', 'experiment2', 'experiment3', 'experiment4'];
instantiationService.stub(IStorageService, {
get: (a, b, c) => {
switch (a) {
@@ -718,9 +724,9 @@ suite('Experiment Service', () => {
assert.equal(result.length, 3);
assert.equal(result[0].id, 'simple-experiment');
assert.equal(result[1].id, 'custom-experiment');
assert.equal(result[1].action.properties, customProperties);
assert.equal(result[1].action!.properties, customProperties);
assert.equal(result[2].id, 'custom-experiment-no-properties');
assert.equal(!!result[2].action.properties, true);
assert.equal(!!result[2].action!.properties, true);
});
const prompt = testObject.getExperimentsByType(ExperimentActionType.Prompt).then(result => {
assert.equal(result.length, 2);
@@ -1285,7 +1285,7 @@ suite('ExtensionsActions Test', () => {
}
function aPage<T>(...objects: T[]): IPager<T> {
return { firstPage: objects, total: objects.length, pageSize: objects.length, getPage: () => null };
return { firstPage: objects, total: objects.length, pageSize: objects.length, getPage: () => null! };
}
});
@@ -139,18 +139,18 @@ const mockTestData = {
};
function aPage<T>(...objects: T[]): IPager<T> {
return { firstPage: objects, total: objects.length, pageSize: objects.length, getPage: () => null };
return { firstPage: objects, total: objects.length, pageSize: objects.length, getPage: () => null! };
}
const noAssets: IGalleryExtensionAssets = {
changelog: null,
download: null,
icon: null,
download: null!,
icon: null!,
license: null,
manifest: null,
readme: null,
repository: null,
coreTranslations: null
coreTranslations: null!
};
function aGalleryExtension(name: string, properties: any = {}, galleryExtensionProperties: any = {}, assets: IGalleryExtensionAssets = noAssets): IGalleryExtension {
@@ -235,7 +235,7 @@ suite('ExtensionsTipsService Test', () => {
class TestNotificationService2 extends TestNotificationService {
public prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions) {
prompted = true;
return null;
return null!;
}
}
@@ -324,10 +324,10 @@ suite('ExtensionsListView Tests', () => {
return testableView.show('@recommended:workspace').then(result => {
assert.ok(target.calledOnce);
const options: IQueryOptions = target.args[0][0];
assert.equal(options.names.length, workspaceRecommendedExtensions.length);
assert.equal(options.names!.length, workspaceRecommendedExtensions.length);
assert.equal(result.length, workspaceRecommendedExtensions.length);
for (let i = 0; i < workspaceRecommendedExtensions.length; i++) {
assert.equal(options.names[i], workspaceRecommendedExtensions[i].identifier.id);
assert.equal(options.names![i], workspaceRecommendedExtensions[i].identifier.id);
assert.equal(result.get(i).identifier.id, workspaceRecommendedExtensions[i].identifier.id);
}
});
@@ -345,10 +345,10 @@ suite('ExtensionsListView Tests', () => {
const options: IQueryOptions = target.args[0][0];
assert.ok(target.calledOnce);
assert.equal(options.names.length, allRecommendedExtensions.length);
assert.equal(options.names!.length, allRecommendedExtensions.length);
assert.equal(result.length, allRecommendedExtensions.length);
for (let i = 0; i < allRecommendedExtensions.length; i++) {
assert.equal(options.names[i], allRecommendedExtensions[i].identifier.id);
assert.equal(options.names![i], allRecommendedExtensions[i].identifier.id);
assert.equal(result.get(i).identifier.id, allRecommendedExtensions[i].identifier.id);
}
});
@@ -369,10 +369,10 @@ suite('ExtensionsListView Tests', () => {
const options: IQueryOptions = target.args[0][0];
assert.ok(target.calledOnce);
assert.equal(options.names.length, allRecommendedExtensions.length);
assert.equal(options.names!.length, allRecommendedExtensions.length);
assert.equal(result.length, allRecommendedExtensions.length);
for (let i = 0; i < allRecommendedExtensions.length; i++) {
assert.equal(options.names[i], allRecommendedExtensions[i].identifier.id);
assert.equal(options.names![i], allRecommendedExtensions[i].identifier.id);
assert.equal(result.get(i).identifier.id, allRecommendedExtensions[i].identifier.id);
}
});
@@ -392,10 +392,10 @@ suite('ExtensionsListView Tests', () => {
assert.ok(experimentTarget.calledOnce);
assert.ok(queryTarget.calledOnce);
assert.equal(options.names.length, curatedList.length);
assert.equal(options.names!.length, curatedList.length);
assert.equal(result.length, curatedList.length);
for (let i = 0; i < curatedList.length; i++) {
assert.equal(options.names[i], curatedList[i].identifier.id);
assert.equal(options.names![i], curatedList[i].identifier.id);
assert.equal(result.get(i).identifier.id, curatedList[i].identifier.id);
}
assert.equal(curatedKey, 'mykey');
@@ -518,7 +518,7 @@ suite('ExtensionsListView Tests', () => {
}
function aPage<T>(...objects: T[]): IPager<T> {
return { firstPage: objects, total: objects.length, pageSize: objects.length, getPage: () => null };
return { firstPage: objects, total: objects.length, pageSize: objects.length, getPage: () => null! };
}
});
@@ -488,28 +488,28 @@ suite('ExtensionsWorkbenchServiceTest', () => {
return testObject.queryGallery().then(page => {
const extension = page.firstPage[0];
return testObject.loadDependencies(extension, CancellationToken.None).then(actual => {
assert.ok(actual.hasDependencies);
assert.equal(extension, actual.extension);
assert.equal(null, actual.dependent);
assert.equal(3, actual.dependencies.length);
assert.equal('pub.a', actual.identifier);
assert.ok(actual!.hasDependencies);
assert.equal(extension, actual!.extension);
assert.equal(null, actual!.dependent);
assert.equal(3, actual!.dependencies.length);
assert.equal('pub.a', actual!.identifier);
let dependent = actual;
actual = dependent.dependencies[0];
actual = dependent!.dependencies[0];
assert.ok(!actual.hasDependencies);
assert.equal('pub.b', actual.extension.identifier.id);
assert.equal('pub.b', actual.identifier);
assert.equal(dependent, actual.dependent);
assert.equal(0, actual.dependencies.length);
actual = dependent.dependencies[1];
actual = dependent!.dependencies[1];
assert.ok(!actual.hasDependencies);
assert.equal('pub.c', actual.extension.identifier.id);
assert.equal('pub.c', actual.identifier);
assert.equal(dependent, actual.dependent);
assert.equal(0, actual.dependencies.length);
actual = dependent.dependencies[2];
actual = dependent!.dependencies[2];
assert.ok(!actual.hasDependencies);
assert.equal('pub.d', actual.extension.identifier.id);
assert.equal('pub.d', actual.identifier);
@@ -527,21 +527,21 @@ suite('ExtensionsWorkbenchServiceTest', () => {
return testObject.queryGallery().then(page => {
const extension = page.firstPage[0];
return testObject.loadDependencies(extension, CancellationToken.None).then(actual => {
assert.ok(actual.hasDependencies);
assert.equal(extension, actual.extension);
assert.equal(null, actual.dependent);
assert.equal(2, actual.dependencies.length);
assert.equal('pub.a', actual.identifier);
assert.ok(actual!.hasDependencies);
assert.equal(extension, actual!.extension);
assert.equal(null, actual!.dependent);
assert.equal(2, actual!.dependencies.length);
assert.equal('pub.a', actual!.identifier);
let dependent = actual;
actual = dependent.dependencies[0];
actual = dependent!.dependencies[0]!;
assert.ok(!actual.hasDependencies);
assert.equal('pub.b', actual.extension.identifier.id);
assert.equal('pub.b', actual.identifier);
assert.equal(dependent, actual.dependent);
assert.equal(0, actual.dependencies.length);
actual = dependent.dependencies[1];
actual = dependent!.dependencies[1]!;
assert.ok(!actual.hasDependencies);
assert.equal('pub.a', actual.extension.identifier.id);
assert.equal('pub.a', actual.identifier);
@@ -559,21 +559,21 @@ suite('ExtensionsWorkbenchServiceTest', () => {
return testObject.queryGallery().then(page => {
const extension = page.firstPage[0];
return testObject.loadDependencies(extension, CancellationToken.None).then(actual => {
assert.ok(actual.hasDependencies);
assert.equal(extension, actual.extension);
assert.equal(null, actual.dependent);
assert.equal(2, actual.dependencies.length);
assert.equal('pub.a', actual.identifier);
assert.ok(actual!.hasDependencies);
assert.equal(extension, actual!.extension);
assert.equal(null, actual!.dependent);
assert.equal(2, actual!.dependencies.length);
assert.equal('pub.a', actual!.identifier);
let dependent = actual;
actual = dependent.dependencies[0];
actual = dependent!.dependencies[0]!;
assert.ok(!actual.hasDependencies);
assert.equal(null, actual.extension);
assert.equal('pub.b', actual.identifier);
assert.equal(dependent, actual.dependent);
assert.equal(0, actual.dependencies.length);
actual = dependent.dependencies[1];
actual = dependent!.dependencies[1]!;
assert.ok(!actual.hasDependencies);
assert.equal('pub.a', actual.extension.identifier.id);
assert.equal('pub.a', actual.identifier);
@@ -593,14 +593,14 @@ suite('ExtensionsWorkbenchServiceTest', () => {
return testObject.queryGallery().then(page => {
const extension = page.firstPage[0];
return testObject.loadDependencies(extension, CancellationToken.None).then(actual => {
assert.ok(actual.hasDependencies);
assert.equal(extension, actual.extension);
assert.equal(null, actual.dependent);
assert.equal(2, actual.dependencies.length);
assert.equal('pub.a', actual.identifier);
assert.ok(actual!.hasDependencies);
assert.equal(extension, actual!.extension);
assert.equal(null, actual!.dependent);
assert.equal(2, actual!.dependencies.length);
assert.equal('pub.a', actual!.identifier);
let dependent = actual;
actual = dependent.dependencies[0];
actual = dependent!.dependencies[0]!;
assert.ok(!actual.hasDependencies);
assert.equal('pub.inbuilt', actual.extension.identifier.id);
assert.equal('pub.inbuilt', actual.identifier);
@@ -608,7 +608,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
assert.equal(0, actual.dependencies.length);
actual = dependent.dependencies[1];
actual = dependent!.dependencies[1]!;
assert.ok(!actual.hasDependencies);
assert.equal('pub.a', actual.extension.identifier.id);
assert.equal('pub.a', actual.identifier);
@@ -631,20 +631,20 @@ suite('ExtensionsWorkbenchServiceTest', () => {
return testObject.queryGallery().then(page => {
const extension = page.firstPage[0];
return testObject.loadDependencies(extension, CancellationToken.None).then(a => {
assert.ok(a.hasDependencies);
assert.equal(extension, a.extension);
assert.equal(null, a.dependent);
assert.equal(2, a.dependencies.length);
assert.equal('pub.a', a.identifier);
assert.ok(a!.hasDependencies);
assert.equal(extension, a!.extension);
assert.equal(null, a!.dependent);
assert.equal(2, a!.dependencies.length);
assert.equal('pub.a', a!.identifier);
let b = a.dependencies[0];
let b = a!.dependencies[0];
assert.ok(b.hasDependencies);
assert.equal('pub.b', b.extension.identifier.id);
assert.equal('pub.b', b.identifier);
assert.equal(a, b.dependent);
assert.equal(2, b.dependencies.length);
let c = a.dependencies[1];
let c = a!.dependencies[1];
assert.ok(c.hasDependencies);
assert.equal('pub.c', c.extension.identifier.id);
assert.equal('pub.c', c.identifier);
@@ -686,7 +686,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
assert.equal(c, d.dependent);
assert.equal(0, d.dependencies.length);
c = a.dependencies[1];
c = a!.dependencies[1];
d = c.dependencies[0];
assert.ok(d.hasDependencies);
assert.equal('pub.d', d.extension.identifier.id);
@@ -1192,13 +1192,13 @@ suite('ExtensionsWorkbenchServiceTest', () => {
const noAssets: IGalleryExtensionAssets = {
changelog: null,
download: null,
icon: null,
download: null!,
icon: null!,
license: null,
manifest: null,
readme: null,
repository: null,
coreTranslations: null
coreTranslations: null!
};
function aGalleryExtension(name: string, properties: any = {}, galleryExtensionProperties: any = {}, assets: IGalleryExtensionAssets = noAssets): IGalleryExtension {
@@ -1211,7 +1211,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
}
function aPage<T>(...objects: T[]): IPager<T> {
return { firstPage: objects, total: objects.length, pageSize: objects.length, getPage: () => null };
return { firstPage: objects, total: objects.length, pageSize: objects.length, getPage: () => null! };
}
function eventToPromise(event: Event<any>, count: number = 1): Promise<void> {
@@ -277,7 +277,7 @@ export class OpenEditorsView extends ViewletPanel {
const element = focused.length ? focused[0] : undefined;
if (element instanceof OpenEditor) {
this.openEditor(element, { preserveFocus: isSingleClick, pinned: isDoubleClick, sideBySide: openToSide });
} else {
} else if (element) {
this.editorGroupService.activateGroup(element);
}
}));
@@ -189,7 +189,7 @@ suite('Files - View Model', () => {
const sChild = createStat('/path/to/stat/alles.klar', 'alles.klar', true, true, 8096, d);
s.addChild(sChild);
assert(validateFileName(s, null) !== null);
assert(validateFileName(s, null!) !== null);
assert(validateFileName(s, '') !== null);
assert(validateFileName(s, ' ') !== null);
assert(validateFileName(s, 'Read Me') === null, 'name containing space');
@@ -282,6 +282,6 @@ suite('Files - View Model', () => {
// Verify that merge does not replace existing children, but updates properties in that case
const existingChild = merge1.getChild('foo.html');
ExplorerItem.mergeLocalWithDisk(merge2, merge1);
assert.ok(existingChild === merge1.getChild(existingChild.name));
assert.ok(existingChild === merge1.getChild(existingChild!.name));
});
});
@@ -1,311 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Action } from 'vs/base/common/actions';
import { IWindowService } from 'vs/platform/windows/common/windows';
import * as nls from 'vs/nls';
import product from 'vs/platform/node/product';
import pkg from 'vs/platform/node/package';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IIntegrityService } from 'vs/platform/integrity/common/integrity';
import { ITimerService, IStartupMetrics } from 'vs/workbench/services/timer/electron-browser/timerService';
import * as os from 'os';
import { IExtensionService, ActivationTimes } from 'vs/workbench/services/extensions/common/extensions';
import { getEntries } from 'vs/base/common/performance';
import { timeout } from 'vs/base/common/async';
import { StartupKindToString } from 'vs/platform/lifecycle/common/lifecycle';
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { forEach } from 'vs/base/common/collections';
import { mergeSort } from 'vs/base/common/arrays';
class Info {
static getTimerInfo(metrics: IStartupMetrics, nodeModuleLoadTime?: number): { [name: string]: Info } {
const table: { [name: string]: Info } = Object.create(null);
table['start => app.isReady'] = new Info(metrics.timers.ellapsedAppReady, '[main]', `initial startup: ${metrics.initialStartup}`);
table['nls:start => nls:end'] = new Info(metrics.timers.ellapsedNlsGeneration, '[main]', `initial startup: ${metrics.initialStartup}`);
table['app.isReady => window.loadUrl()'] = new Info(metrics.timers.ellapsedWindowLoad, '[main]', `initial startup: ${metrics.initialStartup}`);
table['require & init global storage'] = new Info(metrics.timers.ellapsedGlobalStorageInitMain, '[main]', `initial startup: ${metrics.initialStartup}`);
table['window.loadUrl() => begin to require(workbench.main.js)'] = new Info(metrics.timers.ellapsedWindowLoadToRequire, '[main->renderer]', StartupKindToString(metrics.windowKind));
table['require(workbench.main.js)'] = new Info(metrics.timers.ellapsedRequire, '[renderer]', `cached data: ${(metrics.didUseCachedData ? 'YES' : 'NO')}${nodeModuleLoadTime ? `, node_modules took ${nodeModuleLoadTime}ms` : ''}`);
table['init global storage'] = new Info(metrics.timers.ellapsedGlobalStorageInitRenderer, '[renderer]');
table['require workspace storage'] = new Info(metrics.timers.ellapsedWorkspaceStorageRequire, '[renderer]');
table['require & init workspace storage'] = new Info(metrics.timers.ellapsedWorkspaceStorageInit, '[renderer]');
table['init workspace service'] = new Info(metrics.timers.ellapsedWorkspaceServiceInit, '[renderer]');
table['register extensions & spawn extension host'] = new Info(metrics.timers.ellapsedExtensions, '[renderer]');
table['restore viewlet'] = new Info(metrics.timers.ellapsedViewletRestore, '[renderer]', metrics.viewletId);
table['restore panel'] = new Info(metrics.timers.ellapsedPanelRestore, '[renderer]', metrics.panelId);
table['restore editors'] = new Info(metrics.timers.ellapsedEditorRestore, '[renderer]', `${metrics.editorIds.length}: ${metrics.editorIds.join(', ')}`);
table['overall workbench load'] = new Info(metrics.timers.ellapsedWorkbench, '[renderer]');
table['workbench ready'] = new Info(metrics.ellapsed, '[main->renderer]');
table['extensions registered'] = new Info(metrics.timers.ellapsedExtensionsReady, '[renderer]');
return table;
}
private constructor(readonly duration: number, readonly process: string, readonly info: string | boolean = '') { }
}
class LoaderStat {
static getLoaderStats() {
let seq = 1;
const amdLoad = new Map<string, LoaderStat>();
const amdInvoke = new Map<string, LoaderStat>();
const nodeRequire = new Map<string, LoaderStat>();
const nodeEval = new Map<string, LoaderStat>();
function mark(map: Map<string, LoaderStat>, stat: LoaderEvent) {
if (map.has(stat.detail)) {
// console.warn('BAD events, DOUBLE start', stat);
// map.delete(stat.detail);
return;
}
map.set(stat.detail, new LoaderStat(-stat.timestamp, seq++));
}
function diff(map: Map<string, LoaderStat>, stat: LoaderEvent) {
let obj = map.get(stat.detail);
if (!obj) {
// console.warn('BAD events, end WITHOUT start', stat);
// map.delete(stat.detail);
return;
}
if (obj.duration >= 0) {
// console.warn('BAD events, DOUBLE end', stat);
// map.delete(stat.detail);
return;
}
obj.duration = (obj.duration + stat.timestamp);
}
const stats = mergeSort(require.getStats().slice(0), (a, b) => a.timestamp - b.timestamp);
for (const stat of stats) {
switch (stat.type) {
case LoaderEventType.BeginLoadingScript:
mark(amdLoad, stat);
break;
case LoaderEventType.EndLoadingScriptOK:
case LoaderEventType.EndLoadingScriptError:
diff(amdLoad, stat);
break;
case LoaderEventType.BeginInvokeFactory:
mark(amdInvoke, stat);
break;
case LoaderEventType.EndInvokeFactory:
diff(amdInvoke, stat);
break;
case LoaderEventType.NodeBeginNativeRequire:
mark(nodeRequire, stat);
break;
case LoaderEventType.NodeEndNativeRequire:
diff(nodeRequire, stat);
break;
case LoaderEventType.NodeBeginEvaluatingScript:
mark(nodeEval, stat);
break;
case LoaderEventType.NodeEndEvaluatingScript:
diff(nodeEval, stat);
break;
}
}
function toObject(map: Map<string, any>): { [name: string]: any } {
const result = Object.create(null);
map.forEach((value, index) => result[index] = value);
return result;
}
let nodeRequireTotal = 0;
nodeRequire.forEach(value => nodeRequireTotal += value.duration);
return {
amdLoad: toObject(amdLoad),
amdInvoke: toObject(amdInvoke),
nodeRequire: toObject(nodeRequire),
nodeEval: toObject(nodeEval),
nodeRequireTotal
};
}
constructor(public duration: number, public seq: number) { }
}
export class ShowStartupPerformance extends Action {
static readonly ID = 'workbench.action.appPerf';
static readonly LABEL = nls.localize('appPerf', "Startup Performance");
constructor(
id: string,
label: string,
@IWindowService private windowService: IWindowService,
@ITimerService private timerService: ITimerService,
@IEnvironmentService private environmentService: IEnvironmentService,
@IExtensionService private extensionService: IExtensionService
) {
super(id, label);
}
run(): Promise<boolean> {
// Show dev tools
this.windowService.openDevTools();
Promise.all([
timeout(1000), // needed to print a table
this.timerService.startupMetrics
]).then(([, metrics]) => {
console.group('Startup Performance Measurement');
console.log(`OS: ${metrics.platform}(${metrics.release})`);
console.log(`CPUs: ${metrics.cpus.model}(${metrics.cpus.count} x ${metrics.cpus.speed})`);
console.log(`Memory(System): ${(metrics.totalmem / (1024 * 1024 * 1024)).toFixed(2)} GB(${(metrics.freemem / (1024 * 1024 * 1024)).toFixed(2)}GB free)`);
console.log(`Memory(Process): ${(metrics.meminfo.workingSetSize / 1024).toFixed(2)} MB working set(${(metrics.meminfo.peakWorkingSetSize / 1024).toFixed(2)}MB peak, ${(metrics.meminfo.privateBytes / 1024).toFixed(2)}MB private, ${(metrics.meminfo.sharedBytes / 1024).toFixed(2)}MB shared)`);
console.log(`VM(likelyhood): ${metrics.isVMLikelyhood}% `);
console.log(`Initial Startup: ${metrics.initialStartup} `);
console.log(`Has ${metrics.windowCount - 1} other windows`);
console.log(`Screen Reader Active: ${metrics.hasAccessibilitySupport} `);
console.log(`Empty Workspace: ${metrics.emptyWorkbench} `);
const loaderStats = this.environmentService.performance && LoaderStat.getLoaderStats();
console.table(Info.getTimerInfo(metrics, loaderStats && loaderStats.nodeRequireTotal));
if (loaderStats) {
for (const key in loaderStats) {
console.groupCollapsed(`Loader: ${key} `);
console.table(loaderStats[key]);
console.groupEnd();
}
}
console.groupEnd();
console.group('Extension Activation Stats');
let extensionsActivationTimes: { [id: string]: ActivationTimes; } = {};
let extensionsStatus = this.extensionService.getExtensionsStatus();
for (let id in extensionsStatus) {
const status = extensionsStatus[id];
if (status.activationTimes) {
extensionsActivationTimes[id] = status.activationTimes;
}
}
console.table(extensionsActivationTimes);
console.groupEnd();
console.group('Raw Startup Timers (CSV)');
let value = `Name\tStart\n`;
let entries = getEntries('mark');
for (const entry of entries) {
value += `${entry.name} \t${entry.startTime} \n`;
}
console.log(value);
console.groupEnd();
});
return Promise.resolve(true);
}
}
// NOTE: This is still used when running --prof-startup, which already opens a dialog, so the reporter is not used.
export class ReportPerformanceIssueAction extends Action {
static readonly ID = 'workbench.action.reportPerformanceIssue';
static readonly LABEL = nls.localize('reportPerformanceIssue', "Report Performance Issue");
constructor(
id: string,
label: string,
@IIntegrityService private integrityService: IIntegrityService,
@IEnvironmentService private environmentService: IEnvironmentService,
@ITimerService private timerService: ITimerService
) {
super(id, label);
}
run(appendix?: string): Promise<boolean> {
Promise.all([
this.timerService.startupMetrics,
this.integrityService.isPure()
]).then(([metrics, integrity]) => {
const issueUrl = this.generatePerformanceIssueUrl(metrics, product.reportIssueUrl, pkg.name, pkg.version, product.commit, product.date, integrity.isPure, appendix);
window.open(issueUrl);
});
return Promise.resolve(true);
}
private generatePerformanceIssueUrl(metrics: IStartupMetrics, baseUrl: string, name: string, version: string, _commit: string, _date: string, isPure: boolean, appendix?: string): string {
if (!appendix) {
appendix = `Additional Steps to Reproduce(if any):
1.
2.`;
}
let nodeModuleLoadTime: number;
if (this.environmentService.performance) {
nodeModuleLoadTime = LoaderStat.getLoaderStats().nodeRequireTotal;
}
const osVersion = `${os.type()} ${os.arch()} ${os.release()}`;
const queryStringPrefix = baseUrl.indexOf('?') === -1 ? '?' : '&';
const body = encodeURIComponent(
`- VSCode Version: <code>${name} ${version} ${isPure ? '' : ' **[Unsupported]**'} (${product.commit || 'Commit unknown'}, ${product.date || 'Date unknown'})</code>
- OS Version: <code>${ osVersion} </code>
- CPUs: <code>${ metrics.cpus.model} (${metrics.cpus.count} x ${metrics.cpus.speed})</code>
- Memory(System): <code>${ (metrics.totalmem / (1024 * 1024 * 1024)).toFixed(2)} GB(${(metrics.freemem / (1024 * 1024 * 1024)).toFixed(2)}GB free) </code>
- Memory(Process): <code>${ (metrics.meminfo.workingSetSize / 1024).toFixed(2)} MB working set(${(metrics.meminfo.peakWorkingSetSize / 1024).toFixed(2)}MB peak, ${(metrics.meminfo.privateBytes / 1024).toFixed(2)}MB private, ${(metrics.meminfo.sharedBytes / 1024).toFixed(2)}MB shared) </code>
- Load(avg): <code>${ metrics.loadavg.map(l => Math.round(l)).join(', ')} </code>
- VM: <code>${ metrics.isVMLikelyhood}% </code>
- Initial Startup: <code>${ metrics.initialStartup ? 'yes' : 'no'} </code>
- Screen Reader: <code>${ metrics.hasAccessibilitySupport ? 'yes' : 'no'} </code>
- Empty Workspace: <code>${ metrics.emptyWorkbench ? 'yes' : 'no'} </code>
- Timings:
${this.generatePerformanceTable(metrics, nodeModuleLoadTime)}
---
${appendix}`);
return `${baseUrl}${queryStringPrefix}body=${body}`;
}
private generatePerformanceTable(metrics: IStartupMetrics, nodeModuleLoadTime?: number): string {
let tableHeader = `| Component | Task | Duration(ms) | Info |
| ---| ---| ---| ---| `;
let table = '';
forEach(Info.getTimerInfo(metrics, nodeModuleLoadTime), e => {
table += `| ${e.value.process}| ${e.key}| ${e.value.duration}| ${e.value.info}|\n`;
});
return `${tableHeader} \n${table} `;
}
}
Registry
.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions)
.registerWorkbenchAction(new SyncActionDescriptor(ShowStartupPerformance, ShowStartupPerformance.ID, ShowStartupPerformance.LABEL), 'Developer: Startup Performance', nls.localize('developer', "Developer"));
@@ -7,13 +7,21 @@ import { localize } from 'vs/nls';
import { MenuRegistry } from 'vs/platform/actions/common/actions';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { Registry } from 'vs/platform/registry/common/platform';
import { Extensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import { Extensions as Input, IEditorInputFactory, IEditorInputFactoryRegistry } from 'vs/workbench/common/editor';
import { PerfviewInput } from 'vs/workbench/parts/performance/electron-browser/perfviewEditor';
import { PerfviewContrib, PerfviewInput } from 'vs/workbench/parts/performance/electron-browser/perfviewEditor';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import './startupProfiler';
import './startupTimings';
import './stats';
import { StartupProfiler } from './startupProfiler';
import { StartupTimings } from './startupTimings';
// -- startup performance view
Registry.as<IWorkbenchContributionsRegistry>(Extensions.Workbench).registerWorkbenchContribution(
PerfviewContrib,
LifecyclePhase.Ready
);
Registry.as<IEditorInputFactoryRegistry>(Input.EditorInputFactories).registerEditorInputFactory(
PerfviewInput.Id,
@@ -28,7 +36,6 @@ Registry.as<IEditorInputFactoryRegistry>(Input.EditorInputFactories).registerEdi
);
CommandsRegistry.registerCommand('perfview.show', accessor => {
const editorService = accessor.get(IEditorService);
const instaService = accessor.get(IInstantiationService);
return editorService.openEditor(instaService.createInstance(PerfviewInput));
@@ -37,5 +44,20 @@ CommandsRegistry.registerCommand('perfview.show', accessor => {
MenuRegistry.addCommand({
id: 'perfview.show',
category: localize('show.cat', "Developer"),
title: localize('show.label', "Startup Performance (2)")
title: localize('show.label', "Startup Performance")
});
// -- startup profiler
Registry.as<IWorkbenchContributionsRegistry>(Extensions.Workbench).registerWorkbenchContribution(
StartupProfiler,
LifecyclePhase.Restored
);
// -- startup timings
Registry.as<IWorkbenchContributionsRegistry>(Extensions.Workbench).registerWorkbenchContribution(
StartupTimings,
LifecyclePhase.Eventually
);
@@ -9,7 +9,6 @@ import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorIn
import { ITextModelService, ITextModelContentProvider } from 'vs/editor/common/services/resolverService';
import { IHashService } from 'vs/workbench/services/hash/common/hashService';
import { ITextModel } from 'vs/editor/common/model';
import { ITextEditorModel } from 'vs/workbench/common/editor';
import { ILifecycleService, LifecyclePhase, StartupKindToString } from 'vs/platform/lifecycle/common/lifecycle';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -21,6 +20,26 @@ import * as perf from 'vs/base/common/performance';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { writeTransientState } from 'vs/workbench/parts/codeEditor/electron-browser/toggleWordWrap';
import { mergeSort } from 'vs/base/common/arrays';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import product from 'vs/platform/node/product';
import pkg from 'vs/platform/node/package';
export class PerfviewContrib {
private readonly _registration: IDisposable;
constructor(
@IInstantiationService instaService: IInstantiationService,
@ITextModelService textModelResolverService: ITextModelService
) {
this._registration = textModelResolverService.registerTextModelContentProvider('perf', instaService.createInstance(PerfModelContentProvider));
}
dispose(): void {
this._registration.dispose();
}
}
export class PerfviewInput extends ResourceEditorInput {
@@ -28,28 +47,20 @@ export class PerfviewInput extends ResourceEditorInput {
static readonly Uri = URI.from({ scheme: 'perf', path: 'Startup Performance' });
constructor(
@IInstantiationService private readonly _instaService: IInstantiationService,
@ITextModelService private _textModelResolverService: ITextModelService,
@ITextModelService textModelResolverService: ITextModelService,
@IHashService hashService: IHashService
) {
super(
localize('name', "Startup Performance"),
undefined,
PerfviewInput.Uri,
_textModelResolverService, hashService
textModelResolverService, hashService
);
}
getTypeId(): string {
return PerfviewInput.Id;
}
resolve(): Promise<ITextEditorModel> {
if (!this._textModelResolverService.hasTextModelContentProvider(PerfviewInput.Uri.scheme)) {
this._textModelResolverService.registerTextModelContentProvider(PerfviewInput.Uri.scheme, this._instaService.createInstance(PerfModelContentProvider));
}
return super.resolve();
}
}
class PerfModelContentProvider implements ITextModelContentProvider {
@@ -63,12 +74,13 @@ class PerfModelContentProvider implements ITextModelContentProvider {
@ICodeEditorService private readonly _editorService: ICodeEditorService,
@ILifecycleService private readonly _lifecycleService: ILifecycleService,
@ITimerService private readonly _timerService: ITimerService,
@IEnvironmentService private readonly _envService: IEnvironmentService,
@IExtensionService private readonly _extensionService: IExtensionService,
) { }
provideTextContent(resource: URI): Promise<ITextModel> {
if (!this._model) {
if (!this._model || this._model.isDisposed()) {
dispose(this._modelDisposables);
const langId = this._modeService.create('markdown');
this._model = this._modelService.getModel(resource) || this._modelService.createModel('Loading...', langId, resource);
@@ -85,21 +97,25 @@ class PerfModelContentProvider implements ITextModelContentProvider {
private _updateModel(): void {
Promise.all([
this._timerService.startupMetrics,
this._lifecycleService.when(LifecyclePhase.Eventually),
this._extensionService.whenInstalledExtensionsRegistered()
]).then(([metrics]) => {
if (!this._model.isDisposed()) {
let stats = this._envService.args['prof-modules'] ? LoaderStats.get() : undefined;
let md = new MarkdownBuilder();
this._addSummary(md, metrics);
md.blank();
this._addSummaryTable(md, metrics);
this._addSummaryTable(md, metrics, stats);
md.blank();
this._addExtensionsTable(md);
md.blank();
this._addRawPerfMarks(md);
md.blank();
this._addLoaderStats(md, stats);
this._model.setValue(md.value);
}
});
@@ -108,6 +124,7 @@ class PerfModelContentProvider implements ITextModelContentProvider {
private _addSummary(md: MarkdownBuilder, metrics: IStartupMetrics): void {
md.heading(2, 'System Info');
md.li(`${product.nameShort}: ${pkg.version} (${product.commit || '0000000'})`);
md.li(`OS: ${metrics.platform}(${metrics.release})`);
md.li(`CPUs: ${metrics.cpus.model}(${metrics.cpus.count} x ${metrics.cpus.speed})`);
md.li(`Memory(System): ${(metrics.totalmem / (1024 * 1024 * 1024)).toFixed(2)} GB(${(metrics.freemem / (1024 * 1024 * 1024)).toFixed(2)}GB free)`);
@@ -119,7 +136,7 @@ class PerfModelContentProvider implements ITextModelContentProvider {
md.li(`Empty Workspace: ${metrics.emptyWorkbench}`);
}
private _addSummaryTable(md: MarkdownBuilder, metrics: IStartupMetrics, nodeModuleLoadTime?: number): void {
private _addSummaryTable(md: MarkdownBuilder, metrics: IStartupMetrics, stats?: LoaderStats): void {
const table: (string | number)[][] = [];
table.push(['start => app.isReady', metrics.timers.ellapsedAppReady, '[main]', `initial startup: ${metrics.initialStartup}`]);
@@ -127,7 +144,7 @@ class PerfModelContentProvider implements ITextModelContentProvider {
table.push(['app.isReady => window.loadUrl()', metrics.timers.ellapsedWindowLoad, '[main]', `initial startup: ${metrics.initialStartup}`]);
table.push(['require & init global storage', metrics.timers.ellapsedGlobalStorageInitMain, '[main]', `initial startup: ${metrics.initialStartup}`]);
table.push(['window.loadUrl() => begin to require(workbench.main.js)', metrics.timers.ellapsedWindowLoadToRequire, '[main->renderer]', StartupKindToString(metrics.windowKind)]);
table.push(['require(workbench.main.js)', metrics.timers.ellapsedRequire, '[renderer]', `cached data: ${(metrics.didUseCachedData ? 'YES' : 'NO')}${nodeModuleLoadTime ? `, node_modules took ${nodeModuleLoadTime}ms` : ''}`]);
table.push(['require(workbench.main.js)', metrics.timers.ellapsedRequire, '[renderer]', `cached data: ${(metrics.didUseCachedData ? 'YES' : 'NO')}${stats ? `, node_modules took ${stats.nodeRequireTotal}ms` : ''}`]);
table.push(['init global storage', metrics.timers.ellapsedGlobalStorageInitRenderer, '[renderer]', undefined]);
table.push(['require workspace storage', metrics.timers.ellapsedWorkspaceStorageRequire, '[renderer]', undefined]);
table.push(['require & init workspace storage', metrics.timers.ellapsedWorkspaceStorageInit, '[renderer]', undefined]);
@@ -146,15 +163,22 @@ class PerfModelContentProvider implements ITextModelContentProvider {
private _addExtensionsTable(md: MarkdownBuilder): void {
const table: ({ toString(): string })[][] = [];
const eager: ({ toString(): string })[][] = [];
const normal: ({ toString(): string })[][] = [];
let extensionsStatus = this._extensionService.getExtensionsStatus();
for (let id in extensionsStatus) {
const { activationTimes: times } = extensionsStatus[id];
if (!times) {
continue;
}
table.push([id, times.startup, times.codeLoadingTime, times.activateCallTime, times.activateResolvedTime, times.activationEvent]);
if (times.startup) {
eager.push([id, times.startup, times.codeLoadingTime, times.activateCallTime, times.activateResolvedTime, times.activationEvent]);
} else {
normal.push([id, times.startup, times.codeLoadingTime, times.activateCallTime, times.activateResolvedTime, times.activationEvent]);
}
}
const table = eager.concat(normal);
if (table.length > 0) {
md.heading(2, 'Extension Activation Stats');
md.table(
@@ -167,11 +191,125 @@ class PerfModelContentProvider implements ITextModelContentProvider {
private _addRawPerfMarks(md: MarkdownBuilder): void {
md.heading(2, 'Raw Perf Marks');
md.value += '```\n';
md.value += `Name\tTimestamp\tDelta\n`;
let lastStartTime = -1;
for (const { name, startTime } of perf.getEntries('mark')) {
md.value += `${name}\t${startTime}\n`;
md.value += `${name}\t${startTime}\t${lastStartTime !== -1 ? startTime - lastStartTime : 0}\n`;
lastStartTime = startTime;
}
md.value += '```\n';
}
private _addLoaderStats(md: MarkdownBuilder, stats?: LoaderStats): void {
if (stats) {
md.heading(2, 'Loader Stats');
md.heading(3, 'Load AMD-module');
md.table(['Module', 'Duration'], stats.amdLoad);
md.blank();
md.heading(3, 'Load commonjs-module');
md.table(['Module', 'Duration'], stats.nodeRequire);
md.blank();
md.heading(3, 'Invoke AMD-module factory');
md.table(['Module', 'Duration'], stats.amdInvoke);
md.blank();
md.heading(3, 'Invoke commonjs-module');
md.table(['Module', 'Duration'], stats.nodeEval);
}
}
}
abstract class LoaderStats {
readonly amdLoad: (string | number)[][];
readonly amdInvoke: (string | number)[][];
readonly nodeRequire: (string | number)[][];
readonly nodeEval: (string | number)[][];
readonly nodeRequireTotal: number;
static get(): LoaderStats {
const amdLoadScript = new Map<string, number>();
const amdInvokeFactory = new Map<string, number>();
const nodeRequire = new Map<string, number>();
const nodeEval = new Map<string, number>();
function mark(map: Map<string, number>, stat: LoaderEvent) {
if (map.has(stat.detail)) {
// console.warn('BAD events, DOUBLE start', stat);
// map.delete(stat.detail);
return;
}
map.set(stat.detail, -stat.timestamp);
}
function diff(map: Map<string, number>, stat: LoaderEvent) {
let duration = map.get(stat.detail);
if (!duration) {
// console.warn('BAD events, end WITHOUT start', stat);
// map.delete(stat.detail);
return;
}
if (duration >= 0) {
// console.warn('BAD events, DOUBLE end', stat);
// map.delete(stat.detail);
return;
}
map.set(stat.detail, duration + stat.timestamp);
}
const stats = mergeSort(require.getStats().slice(0), (a, b) => a.timestamp - b.timestamp);
for (const stat of stats) {
switch (stat.type) {
case LoaderEventType.BeginLoadingScript:
mark(amdLoadScript, stat);
break;
case LoaderEventType.EndLoadingScriptOK:
case LoaderEventType.EndLoadingScriptError:
diff(amdLoadScript, stat);
break;
case LoaderEventType.BeginInvokeFactory:
mark(amdInvokeFactory, stat);
break;
case LoaderEventType.EndInvokeFactory:
diff(amdInvokeFactory, stat);
break;
case LoaderEventType.NodeBeginNativeRequire:
mark(nodeRequire, stat);
break;
case LoaderEventType.NodeEndNativeRequire:
diff(nodeRequire, stat);
break;
case LoaderEventType.NodeBeginEvaluatingScript:
mark(nodeEval, stat);
break;
case LoaderEventType.NodeEndEvaluatingScript:
diff(nodeEval, stat);
break;
}
}
let nodeRequireTotal = 0;
nodeRequire.forEach(value => nodeRequireTotal += value);
function to2dArray(map: Map<string, number>): (string | number)[][] {
let res: (string | number)[][] = [];
map.forEach((value, index) => res.push([index, value]));
return res;
}
return {
amdLoad: to2dArray(amdLoadScript),
amdInvoke: to2dArray(amdInvokeFactory),
nodeRequire: to2dArray(nodeRequire),
nodeEval: to2dArray(nodeEval),
nodeRequireTotal
};
}
}
class MarkdownBuilder {
@@ -200,7 +338,7 @@ class MarkdownBuilder {
});
rows.forEach(row => {
row.forEach((cell, ci) => {
if (!cell) {
if (typeof cell === 'undefined') {
cell = row[ci] = '-';
}
const len = cell.toString().length;
@@ -6,24 +6,26 @@
import { dirname, join } from 'path';
import { basename } from 'vs/base/common/paths';
import { del, exists, readdir, readFile } from 'vs/base/node/pfs';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { localize } from 'vs/nls';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { Registry } from 'vs/platform/registry/common/platform';
import product from 'vs/platform/node/product';
import { IWindowsService } from 'vs/platform/windows/common/windows';
import { Extensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import { ReportPerformanceIssueAction } from 'vs/workbench/parts/performance/electron-browser/actions';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { PerfviewInput } from 'vs/workbench/parts/performance/electron-browser/perfviewEditor';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
class StartupProfiler implements IWorkbenchContribution {
export class StartupProfiler implements IWorkbenchContribution {
constructor(
@IWindowsService private readonly _windowsService: IWindowsService,
@IDialogService private readonly _dialogService: IDialogService,
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@ITextModelService private readonly _textModelResolverService: ITextModelService,
@IClipboardService private readonly _clipboardService: IClipboardService,
@ILifecycleService lifecycleService: ILifecycleService,
@IExtensionService extensionService: IExtensionService,
) {
@@ -76,10 +78,9 @@ class StartupProfiler implements IWorkbenchContribution {
secondaryButton: localize('prof.restart', "Restart")
}).then(res => {
if (res.confirmed) {
const action = this._instantiationService.createInstance(ReportPerformanceIssueAction, ReportPerformanceIssueAction.ID, ReportPerformanceIssueAction.LABEL);
Promise.all<any>([
this._windowsService.showItemInFolder(join(dir, files[0])),
action.run(`:warning: Make sure to **attach** these files from your *home*-directory: :warning:\n${files.map(file => `-\`${file}\``).join('\n')}`)
this._createPerfIssue(files)
]).then(() => {
// keep window stable until restart is selected
return this._dialogService.confirm({
@@ -101,7 +102,22 @@ class StartupProfiler implements IWorkbenchContribution {
});
});
}
}
const registry = Registry.as<IWorkbenchContributionsRegistry>(Extensions.Workbench);
registry.registerWorkbenchContribution(StartupProfiler, LifecyclePhase.Restored);
private _createPerfIssue(files: string[]): Promise<void> {
return this._textModelResolverService.createModelReference(PerfviewInput.Uri).then(ref => {
this._clipboardService.writeText(ref.object.textEditorModel.getValue());
ref.dispose();
const body = `
1. :warning: We have copied additional data to your clipboard. Make sure to **paste** here. :warning:
1. :warning: Make sure to **attach** these files from your *home*-directory: :warning:\n${files.map(file => `-\`${file}\``).join('\n')}
`;
const baseUrl = product.reportIssueUrl;
const queryStringPrefix = baseUrl.indexOf('?') === -1 ? '?' : '&';
window.open(`${baseUrl}${queryStringPrefix}body=${encodeURIComponent(body)}`);
});
}
}
@@ -3,26 +3,25 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { appendFile } from 'fs';
import { nfcall, timeout } from 'vs/base/common/async';
import { onUnexpectedError } from 'vs/base/common/errors';
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
import { ILifecycleService, LifecyclePhase, StartupKind } from 'vs/platform/lifecycle/common/lifecycle';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { ILifecycleService, StartupKind } from 'vs/platform/lifecycle/common/lifecycle';
import { ILogService } from 'vs/platform/log/common/log';
import { Registry } from 'vs/platform/registry/common/platform';
import product from 'vs/platform/node/product';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IUpdateService } from 'vs/platform/update/common/update';
import { IWindowsService } from 'vs/platform/windows/common/windows';
import { Extensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import * as files from 'vs/workbench/parts/files/common/files';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { ITimerService, didUseCachedData } from 'vs/workbench/services/timer/electron-browser/timerService';
import { didUseCachedData, ITimerService } from 'vs/workbench/services/timer/electron-browser/timerService';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import product from 'vs/platform/node/product';
import { timeout, nfcall } from 'vs/base/common/async';
import { appendFile } from 'fs';
class StartupTimings implements IWorkbenchContribution {
export class StartupTimings implements IWorkbenchContribution {
constructor(
@ILogService private readonly _logService: ILogService,
@@ -138,5 +137,3 @@ class StartupTimings implements IWorkbenchContribution {
}
}
const registry = Registry.as<IWorkbenchContributionsRegistry>(Extensions.Workbench);
registry.registerWorkbenchContribution(StartupTimings, LifecyclePhase.Eventually);
@@ -1,117 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
interface IRequire {
(...a: any[]): any;
getStats(): ILoaderEvent[];
}
declare var require: IRequire;
/* Copied from loader.ts */
enum LoaderEventType {
LoaderAvailable = 1,
BeginLoadingScript = 10,
EndLoadingScriptOK = 11,
EndLoadingScriptError = 12,
BeginInvokeFactory = 21,
EndInvokeFactory = 22,
NodeBeginEvaluatingScript = 31,
NodeEndEvaluatingScript = 32,
NodeBeginNativeRequire = 33,
NodeEndNativeRequire = 34
}
interface ILoaderEvent {
type: LoaderEventType;
timestamp: number;
detail: string;
}
class Tick {
public readonly duration: number;
public readonly detail: string;
constructor(public readonly start: ILoaderEvent, public readonly end: ILoaderEvent) {
console.assert(start.detail === end.detail);
this.duration = this.end.timestamp - this.start.timestamp;
this.detail = start.detail;
}
static compareUsingStartTimestamp(a: Tick, b: Tick): number {
if (a.start.timestamp < b.start.timestamp) {
return -1;
} else if (a.start.timestamp > b.start.timestamp) {
return 1;
} else {
return 0;
}
}
}
function getStats(): Map<LoaderEventType, Tick[]> {
const stats = require.getStats().slice(0).sort((a: ILoaderEvent, b: ILoaderEvent) => {
if (a.detail < b.detail) {
return -1;
} else if (a.detail > b.detail) {
return 1;
} else if (a.type < b.type) {
return -1;
} else if (a.type > b.type) {
return 1;
} else {
return 0;
}
});
const ticks = new Map<LoaderEventType, Tick[]>();
ticks.set(LoaderEventType.BeginLoadingScript, []);
ticks.set(LoaderEventType.BeginInvokeFactory, []);
ticks.set(LoaderEventType.NodeBeginEvaluatingScript, []);
ticks.set(LoaderEventType.NodeBeginNativeRequire, []);
for (let i = 1; i < stats.length - 1; i++) {
const stat = stats[i];
const nextStat = stats[i + 1];
if (nextStat.type - stat.type > 2) {
//bad?!
break;
}
i += 1;
ticks.get(stat.type).push(new Tick(stat, nextStat));
}
ticks.get(LoaderEventType.BeginLoadingScript).sort(Tick.compareUsingStartTimestamp);
ticks.get(LoaderEventType.BeginInvokeFactory).sort(Tick.compareUsingStartTimestamp);
ticks.get(LoaderEventType.NodeBeginEvaluatingScript).sort(Tick.compareUsingStartTimestamp);
ticks.get(LoaderEventType.NodeBeginNativeRequire).sort(Tick.compareUsingStartTimestamp);
return ticks;
}
CommandsRegistry.registerCommand('dev.stats.loader', accessor => {
const clipboard = accessor.get(IClipboardService);
let value = `Name\tDuration\n`;
for (let tick of getStats().get(LoaderEventType.BeginInvokeFactory)) {
value += `${tick.detail}\t${tick.duration.toPrecision(2)}\n`;
}
console.log(value);
clipboard.writeText(value);
});
@@ -167,7 +167,7 @@ suite('CacheState', () => {
cacheKey => cache.query(cacheKey),
query => cache.load(query),
cacheKey => cache.dispose(cacheKey),
previous
previous!
);
}
@@ -191,7 +191,7 @@ suite('CacheState', () => {
public load(query: IFileQuery): Promise<any> {
const promise = new DeferredPromise<any>();
this.loading[query.cacheKey] = promise;
this.loading[query.cacheKey!] = promise;
return promise.p;
}
@@ -67,8 +67,8 @@ suite('Search - Viewlet', () => {
const resultIterator = createIterator(result, 'auto');
const first = resultIterator.next();
assert(!!first.value.children);
assert.equal((<Iterator<ITreeElement<RenderableMatch>>>first.value.children).next().value.element.id(), 'file:///c%3A/foo>[2,1 -> 2,2]b');
assert(!!first.value!.children);
assert.equal((<Iterator<ITreeElement<RenderableMatch>>>first.value!.children).next().value!.element.id(), 'file:///c%3A/foo>[2,1 -> 2,2]b');
});
test('Comparer', () => {
@@ -817,7 +817,7 @@ function assertEqualQueries(actual: ITextQuery | IFileQuery, expected: ITextQuer
}
if (expected.extraFileResources) {
assert.deepEqual(actual.extraFileResources.map(extraFile => extraFile.fsPath), expected.extraFileResources.map(extraFile => extraFile.fsPath));
assert.deepEqual(actual.extraFileResources!.map(extraFile => extraFile.fsPath), expected.extraFileResources.map(extraFile => extraFile.fsPath));
delete expected.extraFileResources;
delete actual.extraFileResources;
}
@@ -837,7 +837,7 @@ function assertEqualSearchPathResults(actual: ISearchPathsResult, expected: ISea
assert.equal(actual.searchPaths && actual.searchPaths.length, expected.searchPaths && expected.searchPaths.length);
if (actual.searchPaths) {
actual.searchPaths.forEach((searchPath, i) => {
const expectedSearchPath = expected.searchPaths[i];
const expectedSearchPath = expected.searchPaths![i];
assert.equal(searchPath.pattern, expectedSearchPath.pattern);
assert.equal(searchPath.searchPath.toString(), expectedSearchPath.searchPath.toString());
});
@@ -885,7 +885,7 @@ function fixPath(...slashPathParts: string[]): string {
return paths.join(...slashPathParts);
}
function normalizeExpression(expression: IExpression): IExpression {
function normalizeExpression(expression: IExpression | undefined): IExpression | undefined {
if (!expression) {
return expression;
}
@@ -84,8 +84,8 @@ suite('SearchModel', () => {
textSearch(query: ISearchQuery, token?: CancellationToken, onProgress?: (result: ISearchProgressItem) => void): Promise<ISearchComplete> {
return new Promise(resolve => {
process.nextTick(() => {
results.forEach(onProgress);
resolve(complete);
results.forEach(onProgress!);
resolve(complete!);
});
});
}
@@ -32,7 +32,7 @@ suite('SearchResult', () => {
});
test('Line Match', function () {
let fileMatch = aFileMatch('folder/file.txt', null);
let fileMatch = aFileMatch('folder/file.txt', null!);
let lineMatch = new Match(fileMatch, ['foo bar'], new OneLineRange(0, 0, 3), new OneLineRange(1, 0, 3));
assert.equal(lineMatch.text(), 'foo bar');
assert.equal(lineMatch.range().startLineNumber, 2);
@@ -307,7 +307,7 @@ suite('SearchResult', () => {
aRawMatch('file://c:/2',
new TextSearchMatch('preview 2', lineOneRange))]);
testObject.replaceAll(null);
testObject.replaceAll(null!);
return voidPromise.then(() => assert.ok(testObject.isEmpty()));
});
@@ -169,7 +169,7 @@ class CommandConfigurationBuilder {
}
public done(taskName: string): void {
this.result.args = this.result.args.map(arg => arg === '$name' ? taskName : arg);
this.result.args = this.result.args!.map(arg => arg === '$name' ? taskName : arg);
this.presentationBuilder.done();
}
}
@@ -227,7 +227,7 @@ class CustomTaskBuilder {
public problemMatcher(): ProblemMatcherBuilder {
let builder = new ProblemMatcherBuilder(this);
this.result.configurationProperties.problemMatchers.push(builder.result);
this.result.configurationProperties.problemMatchers!.push(builder.result);
return builder;
}
@@ -236,7 +236,7 @@ class CustomTaskBuilder {
}
public done(): void {
this.commandBuilder.done(this.result.configurationProperties.name);
this.commandBuilder.done(this.result.configurationProperties.name!);
}
}
@@ -253,7 +253,7 @@ class ProblemMatcherBuilder {
severity: undefined,
fileLocation: FileLocationKind.Relative,
filePrefix: '${workspaceFolder}',
pattern: undefined
pattern: undefined!
};
}
@@ -362,7 +362,7 @@ function testDefaultProblemMatcher(external: ExternalTaskRunnerConfiguration, re
assert.strictEqual(result.custom.length, 1);
let task = result.custom[0];
assert.ok(task);
assert.strictEqual(task.configurationProperties.problemMatchers.length, resolved);
assert.strictEqual(task.configurationProperties.problemMatchers!.length, resolved);
}
function testConfiguration(external: ExternalTaskRunnerConfiguration, builder: ConfiguationBuilder): void {
@@ -409,8 +409,8 @@ class TaskGroupMap {
return;
}
let expectedTaskMap: { [key: string]: boolean } = Object.create(null);
expectedTasks.forEach(task => expectedTaskMap[task.configurationProperties.name] = true);
actualTasks.forEach(task => delete expectedTaskMap[task.configurationProperties.name]);
expectedTasks.forEach(task => expectedTaskMap[task.configurationProperties.name!] = true);
actualTasks.forEach(task => delete expectedTaskMap[task.configurationProperties.name!]);
assert.strictEqual(Object.keys(expectedTaskMap).length, 0);
});
}
@@ -430,9 +430,9 @@ function assertConfiguration(result: ParseResult, expected: Tasks.Task[]): void
let actualId2Name: { [key: string]: string; } = Object.create(null);
let actualTaskGroups = new TaskGroupMap();
actual.forEach(task => {
assert.ok(!actualTasks[task.configurationProperties.name]);
actualTasks[task.configurationProperties.name] = task;
actualId2Name[task._id] = task.configurationProperties.name;
assert.ok(!actualTasks[task.configurationProperties.name!]);
actualTasks[task.configurationProperties.name!] = task;
actualId2Name[task._id] = task.configurationProperties.name!;
if (task.configurationProperties.group) {
actualTaskGroups.add(task.configurationProperties.group, task);
}
@@ -440,8 +440,8 @@ function assertConfiguration(result: ParseResult, expected: Tasks.Task[]): void
let expectedTasks: { [key: string]: Tasks.Task; } = Object.create(null);
let expectedTaskGroup = new TaskGroupMap();
expected.forEach(task => {
assert.ok(!expectedTasks[task.configurationProperties.name]);
expectedTasks[task.configurationProperties.name] = task;
assert.ok(!expectedTasks[task.configurationProperties.name!]);
expectedTasks[task.configurationProperties.name!] = task;
if (task.configurationProperties.group) {
expectedTaskGroup.add(task.configurationProperties.group, task);
}
@@ -479,7 +479,7 @@ function assertTask(actual: Tasks.Task, expected: Tasks.Task) {
function assertCommandConfiguration(actual: Tasks.CommandConfiguration, expected: Tasks.CommandConfiguration) {
assert.strictEqual(typeof actual, typeof expected);
if (actual && expected) {
assertPresentation(actual.presentation, expected.presentation);
assertPresentation(actual.presentation!, expected.presentation!);
assert.strictEqual(actual.name, expected.name, 'name');
assert.strictEqual(actual.runtime, expected.runtime, 'runtime type');
assert.strictEqual(actual.suppressTaskName, expected.suppressTaskName, 'suppressTaskName');
@@ -1070,7 +1070,7 @@ suite('Tasks version 0.1.0', () => {
applyTo(ApplyToKind.closedDocuments).
severity(Severity.Warning).
fileLocation(FileLocationKind.Absolute).
filePrefix(undefined).
filePrefix(undefined!).
pattern(/abc/);
testConfiguration(external, builder);
});
@@ -226,6 +226,11 @@ export class TerminalConfigHelper implements ITerminalConfigHelper {
shell.executable = path.join(process.env.windir, 'System32', shell.executable.substr(sysnativePath.length));
}
}
// Convert / to \ on Windows for convenience
if (platform.isWindows) {
shell.executable = shell.executable.replace(/\//g, '\\');
}
}
private _toInteger(source: any, minimum: number, maximum: number, fallback: number): number {
@@ -688,6 +688,8 @@ export class TerminalInstance implements ITerminalInstance {
c(this._escapeNonWindowsPath(stdout.trim()));
});
return;
} else if (hasSpace && (exe.indexOf('powershell') !== -1)) {
c('& \'' + path + '\'');
} else if (hasSpace) {
c('"' + path + '"');
} else {
@@ -65,9 +65,10 @@ export function sanitizeEnvironment(env: ITerminalEnvironment): void {
'VSCODE_IPC_HOOK',
'VSCODE_LOGS',
'VSCODE_NLS_CONFIG',
'VSCODE_NODE_CACHED_DATA_DIR',
'VSCODE_PORTABLE',
'VSCODE_PID',
'VSCODE_NODE_CACHED_DATA_DIR'
'VSCODE_PREVENT_FOREIGN_INSPECT'
];
keysToRemove.forEach((key) => {
if (env[key]) {
@@ -92,7 +92,7 @@ suite('BackupFileService', () => {
service = new TestBackupFileService(workspaceResource, backupHome, workspacesJsonPath);
return service.loadBackupResource(fooFile).then(resource => {
assert.ok(resource);
assert.equal(path.basename(resource.fsPath), path.basename(fooBackupPath));
assert.equal(path.basename(resource!.fsPath), path.basename(fooBackupPath));
return service.hasBackups().then(hasBackups => {
assert.ok(hasBackups);
});
@@ -122,7 +122,7 @@ suite('ConfigurationEditingService', () => {
if (configuraitonService) {
configuraitonService.dispose();
}
instantiationService = null;
instantiationService = null!;
}
}
@@ -133,7 +133,7 @@ suite('ConfigurationEditingService', () => {
} else {
c(void 0);
}
}).then(() => parentDir = null);
}).then(() => parentDir = null!);
}
test('errors cases - invalid key', () => {
@@ -178,7 +178,7 @@ suite('ConfigurationEditingService', () => {
test('do not notify error', () => {
instantiationService.stub(ITextFileService, 'isDirty', true);
const target = sinon.stub();
instantiationService.stub(INotificationService, <INotificationService>{ prompt: target, _serviceBrand: null, notify: null, error: null, info: null, warn: null });
instantiationService.stub(INotificationService, <INotificationService>{ prompt: target, _serviceBrand: null, notify: null!, error: null!, info: null!, warn: null! });
return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }, { donotNotifyError: true })
.then(() => assert.fail('Should fail with ERROR_CONFIGURATION_FILE_DIRTY error.'),
(error: ConfigurationEditingError) => {
@@ -293,7 +293,7 @@ suite('WorkspaceContextService - Workspace', () => {
done();
});
const workspace = { folders: [{ path: folders[0].uri.fsPath }, { path: folders[1].uri.fsPath }] };
fs.writeFileSync(testObject.getWorkspace().configuration.fsPath, JSON.stringify(workspace, null, '\t'));
fs.writeFileSync(testObject.getWorkspace().configuration!.fsPath, JSON.stringify(workspace, null, '\t'));
}, done);
});
@@ -350,7 +350,7 @@ suite('WorkspaceContextService - Workspace', () => {
const target = sinon.spy();
testObject.onDidChangeWorkspaceFolders(target);
const workspace = { folders: [{ path: testObject.getWorkspace().folders[1].uri.fsPath }, { path: testObject.getWorkspace().folders[0].uri.fsPath }] };
fs.writeFileSync(testObject.getWorkspace().configuration.fsPath, JSON.stringify(workspace, null, '\t'));
fs.writeFileSync(testObject.getWorkspace().configuration!.fsPath, JSON.stringify(workspace, null, '\t'));
return testObject.reloadConfiguration()
.then(() => {
assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`);
@@ -365,7 +365,7 @@ suite('WorkspaceContextService - Workspace', () => {
const target = sinon.spy();
testObject.onDidChangeWorkspaceFolders(target);
const workspace = { folders: [{ path: testObject.getWorkspace().folders[0].uri.fsPath, name: '1' }, { path: testObject.getWorkspace().folders[1].uri.fsPath }] };
fs.writeFileSync(testObject.getWorkspace().configuration.fsPath, JSON.stringify(workspace, null, '\t'));
fs.writeFileSync(testObject.getWorkspace().configuration!.fsPath, JSON.stringify(workspace, null, '\t'));
return testObject.reloadConfiguration()
.then(() => {
assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`);
@@ -977,14 +977,14 @@ suite('WorkspaceConfigurationService-Multiroot', () => {
test('application settings are not read from workspace', () => {
fs.writeFileSync(environmentService.appSettingsPath, '{ "configurationService.workspace.applicationSetting": "userValue" }');
return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration, { key: 'settings', value: { 'configurationService.workspace.applicationSetting': 'workspaceValue' } }, true)
return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, { key: 'settings', value: { 'configurationService.workspace.applicationSetting': 'workspaceValue' } }, true)
.then(() => testObject.reloadConfiguration())
.then(() => assert.equal(testObject.getValue('configurationService.workspace.applicationSetting'), 'userValue'));
});
test('workspace settings override user settings after defaults are registered ', () => {
fs.writeFileSync(environmentService.appSettingsPath, '{ "configurationService.workspace.newSetting": "userValue" }');
return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration, { key: 'settings', value: { 'configurationService.workspace.newSetting': 'workspaceValue' } }, true)
return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, { key: 'settings', value: { 'configurationService.workspace.newSetting': 'workspaceValue' } }, true)
.then(() => testObject.reloadConfiguration())
.then(() => {
configurationRegistry.registerConfiguration({
@@ -1030,7 +1030,7 @@ suite('WorkspaceConfigurationService-Multiroot', () => {
test('resource setting in folder is read after it is registered later', () => {
fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.testNewResourceSetting2": "workspaceFolderValue" }');
return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration, { key: 'settings', value: { 'configurationService.workspace.testNewResourceSetting2': 'workspaceValue' } }, true)
return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, { key: 'settings', value: { 'configurationService.workspace.testNewResourceSetting2': 'workspaceValue' } }, true)
.then(() => testObject.reloadConfiguration())
.then(() => {
configurationRegistry.registerConfiguration({
@@ -1073,7 +1073,7 @@ suite('WorkspaceConfigurationService-Multiroot', () => {
assert.equal(actual.workspaceFolder, void 0);
assert.equal(actual.value, 'userValue');
return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration, { key: 'settings', value: { 'configurationService.workspace.testResourceSetting': 'workspaceValue' } }, true)
return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, { key: 'settings', value: { 'configurationService.workspace.testResourceSetting': 'workspaceValue' } }, true)
.then(() => testObject.reloadConfiguration())
.then(() => {
actual = testObject.inspect('configurationService.workspace.testResourceSetting');
@@ -1115,7 +1115,7 @@ suite('WorkspaceConfigurationService-Multiroot', () => {
}
]
};
return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration, { key: 'launch', value: expectedLaunchConfiguration }, true)
return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, { key: 'launch', value: expectedLaunchConfiguration }, true)
.then(() => testObject.reloadConfiguration())
.then(() => {
const actual = testObject.getValue('launch');
@@ -1140,7 +1140,7 @@ suite('WorkspaceConfigurationService-Multiroot', () => {
}
]
};
return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration, { key: 'launch', value: expectedLaunchConfiguration }, true)
return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, { key: 'launch', value: expectedLaunchConfiguration }, true)
.then(() => testObject.reloadConfiguration())
.then(() => {
const actual = testObject.inspect('launch').workspace;
@@ -1221,7 +1221,7 @@ suite('WorkspaceConfigurationService-Multiroot', () => {
});
test('task configurations are not read from workspace', () => {
return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration, { key: 'tasks', value: { 'version': '1.0' } }, true)
return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, { key: 'tasks', value: { 'version': '1.0' } }, true)
.then(() => testObject.reloadConfiguration())
.then(() => {
const actual = testObject.inspect('tasks.version');
@@ -16,7 +16,7 @@ import { Delayer } from 'vs/base/common/async';
import { IRawFileChange } from 'vs/workbench/services/files/node/watcher/common';
import { FileChangeType } from 'vs/platform/files/common/files';
function newRequest(basePath: string, ignored = []): IWatcherRequest {
function newRequest(basePath: string, ignored: string[] = []): IWatcherRequest {
return { basePath, ignored };
}
@@ -127,7 +127,7 @@ suite.skip('Chockidar watching', () => {
const service = new ChokidarWatcherService();
const result: IRawFileChange[] = [];
let error = null;
let error: string | null = null;
suiteSetup(async () => {
await pfs.mkdirp(testDir);
@@ -58,7 +58,7 @@ suite('FileService', () => {
assert.ok(event);
assert.equal(event.resource.fsPath, resource.fsPath);
assert.equal(event.operation, FileOperation.CREATE);
assert.equal(event.target.resource.fsPath, resource.fsPath);
assert.equal(event.target!.resource.fsPath, resource.fsPath);
toDispose.dispose();
});
});
@@ -93,7 +93,7 @@ suite('FileService', () => {
assert.ok(event);
assert.equal(event.resource.fsPath, resource.fsPath);
assert.equal(event.operation, FileOperation.CREATE);
assert.equal(event.target.resource.fsPath, resource.fsPath);
assert.equal(event.target!.resource.fsPath, resource.fsPath);
toDispose.dispose();
});
});
@@ -114,8 +114,8 @@ suite('FileService', () => {
assert.ok(event);
assert.equal(event.resource.fsPath, resource.fsPath);
assert.equal(event.operation, FileOperation.CREATE);
assert.equal(event.target.resource.fsPath, resource.fsPath);
assert.equal(event.target.isDirectory, true);
assert.equal(event.target!.resource.fsPath, resource.fsPath);
assert.equal(event.target!.isDirectory, true);
toDispose.dispose();
});
});
@@ -139,8 +139,8 @@ suite('FileService', () => {
assert.ok(event);
assert.equal(event.resource.fsPath, resource.fsPath);
assert.equal(event.operation, FileOperation.CREATE);
assert.equal(event.target.resource.fsPath, resource.fsPath);
assert.equal(event.target.isDirectory, true);
assert.equal(event.target!.resource.fsPath, resource.fsPath);
assert.equal(event.target!.isDirectory, true);
toDispose.dispose();
});
});
@@ -161,7 +161,7 @@ suite('FileService', () => {
assert.ok(event);
assert.equal(event.resource.fsPath, resource.fsPath);
assert.equal(event.operation, FileOperation.MOVE);
assert.equal(event.target.resource.fsPath, renamed.resource.fsPath);
assert.equal(event.target!.resource.fsPath, renamed.resource.fsPath);
toDispose.dispose();
});
});
@@ -185,7 +185,7 @@ suite('FileService', () => {
assert.ok(event);
assert.equal(event.resource.fsPath, resource.fsPath);
assert.equal(event.operation, FileOperation.MOVE);
assert.equal(event.target.resource.fsPath, renamed.resource.fsPath);
assert.equal(event.target!.resource.fsPath, renamed.resource.fsPath);
toDispose.dispose();
});
});
@@ -206,7 +206,7 @@ suite('FileService', () => {
assert.ok(event);
assert.equal(event.resource.fsPath, resource.fsPath);
assert.equal(event.operation, FileOperation.MOVE);
assert.equal(event.target.resource.fsPath, renamed.resource.fsPath);
assert.equal(event.target!.resource.fsPath, renamed.resource.fsPath);
toDispose.dispose();
});
});
@@ -230,7 +230,7 @@ suite('FileService', () => {
assert.ok(event);
assert.equal(event.resource.fsPath, resource.fsPath);
assert.equal(event.operation, FileOperation.MOVE);
assert.equal(event.target.resource.fsPath, renamed.resource.fsPath);
assert.equal(event.target!.resource.fsPath, renamed.resource.fsPath);
toDispose.dispose();
});
});
@@ -250,7 +250,7 @@ suite('FileService', () => {
assert.ok(event);
assert.equal(event.resource.fsPath, resource.fsPath);
assert.equal(event.operation, FileOperation.MOVE);
assert.equal(event.target.resource.fsPath, renamed.resource.fsPath);
assert.equal(event.target!.resource.fsPath, renamed.resource.fsPath);
toDispose.dispose();
});
});
@@ -271,7 +271,7 @@ suite('FileService', () => {
assert.ok(event);
assert.equal(event.resource.fsPath, resource.fsPath);
assert.equal(event.operation, FileOperation.MOVE);
assert.equal(event.target.resource.fsPath, renamed.resource.fsPath);
assert.equal(event.target!.resource.fsPath, renamed.resource.fsPath);
toDispose.dispose();
});
});
@@ -324,7 +324,7 @@ suite('FileService', () => {
assert.ok(event);
assert.equal(event.resource.fsPath, resource.fsPath);
assert.equal(event.operation, FileOperation.MOVE);
assert.equal(event.target.resource.fsPath, renamed.resource.fsPath);
assert.equal(event.target!.resource.fsPath, renamed.resource.fsPath);
toDispose.dispose();
});
});
@@ -357,7 +357,7 @@ suite('FileService', () => {
assert.ok(moveEvent);
assert.equal(moveEvent.resource.fsPath, resource.fsPath);
assert.equal(moveEvent.target.resource.fsPath, moved.resource.fsPath);
assert.equal(moveEvent!.target!.resource.fsPath, moved.resource.fsPath);
assert.equal(deleteEvent.resource.fsPath, folderResource.fsPath);
@@ -382,7 +382,7 @@ suite('FileService', () => {
assert.ok(event);
assert.equal(event.resource.fsPath, source.resource.fsPath);
assert.equal(event.operation, FileOperation.COPY);
assert.equal(event.target.resource.fsPath, copied.resource.fsPath);
assert.equal(event.target!.resource.fsPath, copied.resource.fsPath);
toDispose.dispose();
});
});
@@ -415,7 +415,7 @@ suite('FileService', () => {
assert.ok(copyEvent);
assert.equal(copyEvent.resource.fsPath, resource.fsPath);
assert.equal(copyEvent.target.resource.fsPath, copied.resource.fsPath);
assert.equal(copyEvent.target!.resource.fsPath, copied.resource.fsPath);
assert.equal(deleteEvent.resource.fsPath, folderResource.fsPath);
@@ -505,10 +505,10 @@ suite('FileService', () => {
test('resolveFile', () => {
return service.resolveFile(uri.file(testDir), { resolveTo: [uri.file(path.join(testDir, 'deep'))] }).then(r => {
assert.equal(r.children.length, 8);
assert.equal(r.children!.length, 8);
const deep = utils.getByName(r, 'deep');
assert.equal(deep.children.length, 4);
const deep = utils.getByName(r, 'deep')!;
assert.equal(deep.children!.length, 4);
});
});
@@ -519,13 +519,13 @@ suite('FileService', () => {
]).then(res => {
const r1 = res[0].stat;
assert.equal(r1.children.length, 8);
assert.equal(r1.children!.length, 8);
const deep = utils.getByName(r1, 'deep');
assert.equal(deep.children.length, 4);
const deep = utils.getByName(r1, 'deep')!;
assert.equal(deep.children!.length, 4);
const r2 = res[1].stat;
assert.equal(r2.children.length, 4);
assert.equal(r2.children!.length, 4);
assert.equal(r2.name, 'deep');
});
});
@@ -45,7 +45,7 @@ export class TestEditorInput extends EditorInput implements IFileEditorInput {
resolve(): Promise<IEditorModel> { return Promise.resolve(); }
matches(other: TestEditorInput): boolean { return other && this.resource.toString() === other.resource.toString() && other instanceof TestEditorInput; }
setEncoding(encoding: string) { }
getEncoding(): string { return null; }
getEncoding(): string { return null!; }
setPreferredEncoding(encoding: string) { }
getResource(): URI { return this.resource; }
setForceOpenAsBinary(): void { }
@@ -225,12 +225,12 @@ suite('Editor groups service', () => {
assert.equal(mru[0], rightGroup);
assert.equal(mru[1], rootGroup);
let rightGroupInstantiator: IInstantiationService;
let rightGroupInstantiator!: IInstantiationService;
part.activeGroup.invokeWithinContext(accessor => {
rightGroupInstantiator = accessor.get(IInstantiationService);
});
let rootGroupInstantiator: IInstantiationService;
let rootGroupInstantiator!: IInstantiationService;
rootGroup.invokeWithinContext(accessor => {
rootGroupInstantiator = accessor.get(IInstantiationService);
});
@@ -353,8 +353,8 @@ suite('Editor groups service', () => {
test('options', () => {
const part = createPart();
let oldOptions: IEditorPartOptions;
let newOptions: IEditorPartOptions;
let oldOptions!: IEditorPartOptions;
let newOptions!: IEditorPartOptions;
part.onDidEditorPartOptionsChange(event => {
oldOptions = event.oldPartOptions;
newOptions = event.newPartOptions;
@@ -476,7 +476,7 @@ export class HistoryService extends Disposable implements IHistoryService {
private clearOnEditorDispose(editor: IEditorInput | IResourceInput | FileChangesEvent, mapEditorToDispose: Map<EditorInput, IDisposable[]>): void {
if (editor instanceof EditorInput) {
const disposables = this.editorHistoryListeners.get(editor);
const disposables = mapEditorToDispose.get(editor);
if (disposables) {
dispose(disposables);
mapEditorToDispose.delete(editor);
@@ -115,7 +115,7 @@ suite('KeybindingsEditing', () => {
} else {
c(void 0);
}
}).then(() => testDir = null);
}).then(() => testDir = null!);
});
test('errors cases - parse errors', () => {
@@ -247,7 +247,7 @@ suite('KeybindingsEditing', () => {
function aResolvedKeybindingItem({ command, when, isDefault, firstPart, chordPart }: { command?: string, when?: string, isDefault?: boolean, firstPart?: { keyCode: KeyCode, modifiers?: Modifiers }, chordPart?: { keyCode: KeyCode, modifiers?: Modifiers } }): ResolvedKeybindingItem {
const aSimpleKeybinding = function (part: { keyCode: KeyCode, modifiers?: Modifiers }): SimpleKeybinding {
const { ctrlKey, shiftKey, altKey, metaKey } = part.modifiers || { ctrlKey: false, shiftKey: false, altKey: false, metaKey: false };
return new SimpleKeybinding(ctrlKey, shiftKey, altKey, metaKey, part.keyCode);
return new SimpleKeybinding(ctrlKey!, shiftKey!, altKey!, metaKey!, part.keyCode);
};
const keybinding = firstPart ? chordPart ? new ChordKeybinding(aSimpleKeybinding(firstPart), aSimpleKeybinding(chordPart)) : aSimpleKeybinding(firstPart) : null;
return new ResolvedKeybindingItem(keybinding ? new USLayoutResolvedKeybinding(keybinding, OS) : null, command || 'some command', null, when ? ContextKeyExpr.deserialize(when) : null, isDefault === void 0 ? true : isDefault);
@@ -37,7 +37,7 @@ suite('keyboardMapper - MAC de_ch', () => {
}
function _assertResolveKeybinding(k: number, expected: IResolvedKeybinding[]): void {
assertResolveKeybinding(mapper, createKeybinding(k, OperatingSystem.Macintosh), expected);
assertResolveKeybinding(mapper, createKeybinding(k, OperatingSystem.Macintosh)!, expected);
}
test('kb => hw', () => {
@@ -463,7 +463,7 @@ suite('keyboardMapper - LINUX de_ch', () => {
}
function _assertResolveKeybinding(k: number, expected: IResolvedKeybinding[]): void {
assertResolveKeybinding(mapper, createKeybinding(k, OperatingSystem.Linux), expected);
assertResolveKeybinding(mapper, createKeybinding(k, OperatingSystem.Linux)!, expected);
}
test('kb => hw', () => {
@@ -808,7 +808,7 @@ suite('keyboardMapper - LINUX en_us', () => {
});
function _assertResolveKeybinding(k: number, expected: IResolvedKeybinding[]): void {
assertResolveKeybinding(mapper, createKeybinding(k, OperatingSystem.Linux), expected);
assertResolveKeybinding(mapper, createKeybinding(k, OperatingSystem.Linux)!, expected);
}
test('resolveKeybinding Ctrl+A', () => {
@@ -1251,7 +1251,7 @@ suite('keyboardMapper', () => {
assertNumpadKeyboardEvent(KeyCode.DownArrow, 'Numpad2', 'DownArrow', 'Down', 'down', '[ArrowDown]');
assertNumpadKeyboardEvent(KeyCode.PageDown, 'Numpad3', 'PageDown', 'PageDown', 'pagedown', '[PageDown]');
assertNumpadKeyboardEvent(KeyCode.LeftArrow, 'Numpad4', 'LeftArrow', 'Left', 'left', '[ArrowLeft]');
assertNumpadKeyboardEvent(KeyCode.Unknown, 'Numpad5', 'NumPad5', null, 'numpad5', '[Numpad5]');
assertNumpadKeyboardEvent(KeyCode.Unknown, 'Numpad5', 'NumPad5', null!, 'numpad5', '[Numpad5]');
assertNumpadKeyboardEvent(KeyCode.RightArrow, 'Numpad6', 'RightArrow', 'Right', 'right', '[ArrowRight]');
assertNumpadKeyboardEvent(KeyCode.Home, 'Numpad7', 'Home', 'Home', 'home', '[Home]');
assertNumpadKeyboardEvent(KeyCode.UpArrow, 'Numpad8', 'UpArrow', 'Up', 'up', '[ArrowUp]');
@@ -1326,7 +1326,7 @@ suite('keyboardMapper - LINUX ru', () => {
});
function _assertResolveKeybinding(k: number, expected: IResolvedKeybinding[]): void {
assertResolveKeybinding(mapper, createKeybinding(k, OperatingSystem.Linux), expected);
assertResolveKeybinding(mapper, createKeybinding(k, OperatingSystem.Linux)!, expected);
}
test('resolveKeybinding Ctrl+S', () => {
@@ -1396,7 +1396,7 @@ suite('keyboardMapper - MAC zh_hant', () => {
});
function _assertResolveKeybinding(k: number, expected: IResolvedKeybinding[]): void {
assertResolveKeybinding(mapper, createKeybinding(k, OperatingSystem.Macintosh), expected);
assertResolveKeybinding(mapper, createKeybinding(k, OperatingSystem.Macintosh)!, expected);
}
test('issue #28237 resolveKeybinding Cmd+C', () => {
@@ -1427,7 +1427,7 @@ function _assertKeybindingTranslation(mapper: MacLinuxKeyboardMapper, OS: Operat
const runtimeKeybinding = createKeybinding(kb, OS);
const keybindingLabel = new USLayoutResolvedKeybinding(runtimeKeybinding, OS).getUserSettingsLabel();
const keybindingLabel = new USLayoutResolvedKeybinding(runtimeKeybinding!, OS).getUserSettingsLabel();
const actualHardwareKeypresses = mapper.simpleKeybindingToScanCodeBinding(<SimpleKeybinding>runtimeKeybinding);
if (actualHardwareKeypresses.length === 0) {
@@ -106,8 +106,8 @@ suite('KeybindingsEditorModel test', () => {
aResolvedKeybindingItem({ command: 'd' + uuid.generateUuid(), firstPart: { keyCode: KeyCode.Escape }, chordPart: { keyCode: KeyCode.Escape } })
);
registerCommandWithTitle(keybindings[1].command, 'B Title');
registerCommandWithTitle(keybindings[3].command, 'A Title');
registerCommandWithTitle(keybindings[1].command!, 'B Title');
registerCommandWithTitle(keybindings[3].command!, 'A Title');
const expected = [keybindings[3], keybindings[1], keybindings[0], keybindings[2]];
instantiationService.stub(IKeybindingService, 'getKeybindings', () => keybindings);
@@ -127,8 +127,8 @@ suite('KeybindingsEditorModel test', () => {
aResolvedKeybindingItem({ command: sameId, firstPart: { keyCode: KeyCode.Escape }, isDefault: false })
);
registerCommandWithTitle(keybindings[1].command, 'Same Title');
registerCommandWithTitle(keybindings[3].command, 'Same Title');
registerCommandWithTitle(keybindings[1].command!, 'Same Title');
registerCommandWithTitle(keybindings[3].command!, 'Same Title');
const expected = [keybindings[3], keybindings[1], keybindings[0], keybindings[2]];
await testObject.resolve({});
@@ -157,22 +157,22 @@ suite('KeybindingsEditorModel test', () => {
assert.equal(actual.keybindingItem.command, expected.command);
assert.equal(actual.keybindingItem.commandLabel, '');
assert.equal(actual.keybindingItem.commandDefaultLabel, null);
assert.equal(actual.keybindingItem.keybinding.getAriaLabel(), expected.resolvedKeybinding.getAriaLabel());
assert.equal(actual.keybindingItem.when, expected.when.serialize());
assert.equal(actual.keybindingItem.keybinding.getAriaLabel(), expected.resolvedKeybinding!.getAriaLabel());
assert.equal(actual.keybindingItem.when, expected.when!.serialize());
});
test('convert keybinding with title to entry', async () => {
const expected = aResolvedKeybindingItem({ command: 'a' + uuid.generateUuid(), firstPart: { keyCode: KeyCode.Escape }, when: 'context1 && context2' });
prepareKeybindingService(expected);
registerCommandWithTitle(expected.command, 'Some Title');
registerCommandWithTitle(expected.command!, 'Some Title');
await testObject.resolve({});
const actual = testObject.fetch('')[0];
assert.equal(actual.keybindingItem.command, expected.command);
assert.equal(actual.keybindingItem.commandLabel, 'Some Title');
assert.equal(actual.keybindingItem.commandDefaultLabel, null);
assert.equal(actual.keybindingItem.keybinding.getAriaLabel(), expected.resolvedKeybinding.getAriaLabel());
assert.equal(actual.keybindingItem.when, expected.when.serialize());
assert.equal(actual.keybindingItem.keybinding.getAriaLabel(), expected.resolvedKeybinding!.getAriaLabel());
assert.equal(actual.keybindingItem.when, expected.when!.serialize());
});
test('convert without title and binding to entry', async () => {
@@ -282,8 +282,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('cmd').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { metaKey: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, {});
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { metaKey: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, {});
});
test('filter by meta key', async () => {
@@ -296,8 +296,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('meta').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { metaKey: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, {});
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { metaKey: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, {});
});
test('filter by command key', async () => {
@@ -310,8 +310,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('command').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { metaKey: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, {});
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { metaKey: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, {});
});
test('filter by windows key', async () => {
@@ -324,8 +324,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('windows').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { metaKey: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, {});
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { metaKey: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, {});
});
test('filter by alt key', async () => {
@@ -336,8 +336,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('alt').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { altKey: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, {});
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { altKey: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, {});
});
test('filter by option key', async () => {
@@ -348,8 +348,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('option').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { altKey: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, {});
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { altKey: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, {});
});
test('filter by ctrl key', async () => {
@@ -360,8 +360,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('ctrl').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { ctrlKey: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, {});
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { ctrlKey: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, {});
});
test('filter by control key', async () => {
@@ -372,8 +372,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('control').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { ctrlKey: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, {});
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { ctrlKey: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, {});
});
test('filter by shift key', async () => {
@@ -384,8 +384,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('shift').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { shiftKey: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, {});
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { shiftKey: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, {});
});
test('filter by arrow', async () => {
@@ -396,8 +396,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('arrow').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { keyCode: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, {});
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { keyCode: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, {});
});
test('filter by modifier and key', async () => {
@@ -408,8 +408,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('alt right').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { altKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, {});
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { altKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, {});
});
test('filter by key and modifier', async () => {
@@ -431,8 +431,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('alt cmd esc').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { altKey: true, metaKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, {});
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { altKey: true, metaKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, {});
});
test('filter by modifiers in random order and key', async () => {
@@ -444,8 +444,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('cmd shift esc').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { metaKey: true, shiftKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, {});
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { metaKey: true, shiftKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, {});
});
test('filter by first part', async () => {
@@ -457,8 +457,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('cmd shift esc').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { metaKey: true, shiftKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, {});
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { metaKey: true, shiftKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, {});
});
test('filter matches in chord part', async () => {
@@ -470,8 +470,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('cmd del').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { metaKey: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, { keyCode: true });
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { metaKey: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, { keyCode: true });
});
test('filter matches first part and in chord part', async () => {
@@ -483,8 +483,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('cmd shift esc del').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { shiftKey: true, metaKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, { keyCode: true });
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { shiftKey: true, metaKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, { keyCode: true });
});
test('filter exact matches', async () => {
@@ -495,8 +495,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('"ctrl c"').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { ctrlKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, {});
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { ctrlKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, {});
});
test('filter exact matches with first and chord part', async () => {
@@ -507,8 +507,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('"shift meta escape ctrl c"').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { shiftKey: true, metaKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, { ctrlKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { shiftKey: true, metaKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, { ctrlKey: true, keyCode: true });
});
test('filter exact matches with first and chord part no results', async () => {
@@ -530,8 +530,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('"control+c"').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { ctrlKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, {});
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { ctrlKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, {});
});
test('filter matches with + separator in first and chord parts', async () => {
@@ -542,8 +542,8 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('"shift+meta+escape ctrl+c"').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { shiftKey: true, metaKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches.chordPart, { keyCode: true, ctrlKey: true });
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { shiftKey: true, metaKey: true, keyCode: true });
assert.deepEqual(actual[0].keybindingMatches!.chordPart, { keyCode: true, ctrlKey: true });
});
test('filter exact matches with space #32993', async () => {
@@ -565,7 +565,7 @@ suite('KeybindingsEditorModel test', () => {
await testObject.resolve({});
const actual = testObject.fetch('"down"').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches.firstPart, { keyCode: true });
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { keyCode: true });
});
function prepareKeybindingService(...keybindingItems: ResolvedKeybindingItem[]): ResolvedKeybindingItem[] {
@@ -591,7 +591,7 @@ suite('KeybindingsEditorModel test', () => {
assert.equal(actual.command, expected.command);
if (actual.when) {
assert.ok(!!expected.when);
assert.equal(actual.when.serialize(), expected.when.serialize());
assert.equal(actual.when.serialize(), expected.when!.serialize());
} else {
assert.ok(!expected.when);
}
@@ -599,7 +599,7 @@ suite('KeybindingsEditorModel test', () => {
if (actual.resolvedKeybinding) {
assert.ok(!!expected.resolvedKeybinding);
assert.equal(actual.resolvedKeybinding.getLabel(), expected.resolvedKeybinding.getLabel());
assert.equal(actual.resolvedKeybinding.getLabel(), expected.resolvedKeybinding!.getLabel());
} else {
assert.ok(!expected.resolvedKeybinding);
}
@@ -608,7 +608,7 @@ suite('KeybindingsEditorModel test', () => {
function aResolvedKeybindingItem({ command, when, isDefault, firstPart, chordPart }: { command?: string, when?: string, isDefault?: boolean, firstPart?: { keyCode: KeyCode, modifiers?: Modifiers }, chordPart?: { keyCode: KeyCode, modifiers?: Modifiers } }): ResolvedKeybindingItem {
const aSimpleKeybinding = function (part: { keyCode: KeyCode, modifiers?: Modifiers }): SimpleKeybinding {
const { ctrlKey, shiftKey, altKey, metaKey } = part.modifiers || { ctrlKey: false, shiftKey: false, altKey: false, metaKey: false };
return new SimpleKeybinding(ctrlKey, shiftKey, altKey, metaKey, part.keyCode);
return new SimpleKeybinding(ctrlKey!, shiftKey!, altKey!, metaKey!, part.keyCode);
};
const keybinding = firstPart ? chordPart ? new ChordKeybinding(aSimpleKeybinding(firstPart), aSimpleKeybinding(chordPart)) : aSimpleKeybinding(firstPart) : null;
return new ResolvedKeybindingItem(keybinding ? new USLayoutResolvedKeybinding(keybinding, OS) : null, command || 'some command', null, when ? ContextKeyExpr.deserialize(when) : null, isDefault === void 0 ? true : isDefault);
@@ -13,7 +13,7 @@ suite('Preferences Model test', () => {
private validator: (value: any) => string;
constructor(private settings: IConfigurationPropertySchema) {
this.validator = createValidator(settings);
this.validator = createValidator(settings)!;
}
public accepts(input) {
@@ -29,8 +29,8 @@ class TestViewletService implements IViewletService {
onDidViewletClose = this.onDidViewletCloseEmitter.event;
onDidViewletEnablementChange = this.onDidViewletEnableEmitter.event;
public openViewlet(id: string, focus?: boolean): Promise<IViewlet | null> {
return Promise.resolve(null);
public openViewlet(id: string, focus?: boolean): Promise<IViewlet> {
return Promise.resolve(null!);
}
public getViewlets(): ViewletDescriptor[] {
@@ -54,11 +54,11 @@ class TestViewletService implements IViewletService {
}
public getViewlet(id: string): ViewletDescriptor {
return null;
return null!;
}
public getProgressIndicator(id: string) {
return null;
return null!;
}
}
@@ -69,7 +69,7 @@ class TestPanelService implements IPanelService {
onDidPanelClose = new Emitter<IPanel>().event;
public openPanel(id: string, focus?: boolean): IPanel {
return null;
return null!;
}
public getPanels(): any[] {
@@ -130,14 +130,14 @@ class TestViewlet implements IViewlet {
* Returns the action item for a specific action.
*/
getActionItem(action: IAction): IActionItem {
return null;
return null!;
}
/**
* Returns the underlying control of this composite.
*/
getControl(): IEditorControl {
return null;
return null!;
}
/**
@@ -176,14 +176,14 @@ class TestProgressBar {
}
public infinite() {
this.fDone = null;
this.fDone = null!;
this.fInfinite = true;
return this;
}
public total(total: number) {
this.fDone = null;
this.fDone = null!;
this.fTotal = total;
return this;
@@ -194,7 +194,7 @@ class TestProgressBar {
}
public worked(worked: number) {
this.fDone = null;
this.fDone = null!;
if (this.fWorked) {
this.fWorked += worked;
@@ -208,9 +208,9 @@ class TestProgressBar {
public done() {
this.fDone = true;
this.fInfinite = null;
this.fWorked = null;
this.fTotal = null;
this.fInfinite = null!;
this.fWorked = null!;
this.fTotal = null!;
return this;
}
@@ -47,7 +47,7 @@ class TestSearchEngine implements ISearchEngine<IRawFileMatch> {
(function next() {
process.nextTick(() => {
if (self.isCanceled) {
done(null, {
done(null!, {
limitHit: false,
stats: stats
});
@@ -55,7 +55,7 @@ class TestSearchEngine implements ISearchEngine<IRawFileMatch> {
}
const result = self.result();
if (!result) {
done(null, {
done(null!, {
limitHit: false,
stats: stats
});
@@ -109,7 +109,7 @@ suite('RawSearchService', () => {
}
};
await service.doFileSearchWithEngine(Engine, rawSearch, cb, null, 0);
await service.doFileSearchWithEngine(Engine, rawSearch, cb, null!, 0);
return assert.strictEqual(results, 5);
});
@@ -119,7 +119,7 @@ suite('RawSearchService', () => {
const Engine = TestSearchEngine.bind(null, () => i-- && rawMatch);
const service = new RawSearchService();
const results = [];
const results: number[] = [];
const cb: (p: ISerializedSearchProgressItem) => void = value => {
if (Array.isArray(value)) {
value.forEach(m => {
@@ -158,7 +158,7 @@ suite('RawSearchService', () => {
return emitter.event;
}
const progressResults = [];
const progressResults: any[] = [];
const onProgress = match => {
assert.strictEqual(match.resource.path, uriPath);
progressResults.push(match);
@@ -218,7 +218,7 @@ suite('RawSearchService', () => {
const Engine = TestSearchEngine.bind(null, () => matches.shift());
const service = new RawSearchService();
const results = [];
const results: any[] = [];
const cb = value => {
if (Array.isArray(value)) {
results.push(...value.map(v => v.path));
@@ -234,7 +234,7 @@ suite('RawSearchService', () => {
sortByScore: true,
maxResults: 2
}, cb, undefined, 1);
assert.notStrictEqual(typeof TestSearchEngine.last.config.maxResults, 'number');
assert.notStrictEqual(typeof TestSearchEngine.last.config!.maxResults, 'number');
assert.deepStrictEqual(results, [path.normalize('/some/where/bbc'), path.normalize('/some/where/bab')]);
});
@@ -244,7 +244,7 @@ suite('RawSearchService', () => {
const Engine = TestSearchEngine.bind(null, () => i-- && rawMatch);
const service = new RawSearchService();
const results = [];
const results: number[] = [];
const cb = value => {
if (Array.isArray(value)) {
value.forEach(m => {
@@ -277,7 +277,7 @@ suite('RawSearchService', () => {
const Engine = TestSearchEngine.bind(null, () => matches.shift());
const service = new RawSearchService();
const results = [];
const results: any[] = [];
const cb = value => {
if (Array.isArray(value)) {
results.push(...value.map(v => v.path));
@@ -295,7 +295,7 @@ suite('RawSearchService', () => {
assert.strictEqual((<IFileSearchStats>complete.stats).fromCache, false);
assert.deepStrictEqual(results, [path.normalize('/some/where/bcb'), path.normalize('/some/where/bbc'), path.normalize('/some/where/aab')]);
}).then(async () => {
const results = [];
const results: any[] = [];
const cb = value => {
if (Array.isArray(value)) {
results.push(...value.map(v => v.path));
@@ -324,7 +324,7 @@ suite('RawSearchService', () => {
basename: 'bc',
size: 3
});
const results = [];
const results: any[] = [];
const cb = value => {
if (Array.isArray(value)) {
results.push(...value.map(v => v.path));
@@ -779,8 +779,8 @@ suite('FileWalker', () => {
const cmd1 = walker.spawnFindCmd(TEST_ROOT_FOLDER);
walker.readStdout(cmd1, 'utf8', /*isRipgrep=*/false, (err1, stdout1) => {
assert.equal(err1, null);
assert.notStrictEqual(stdout1.split('\n').indexOf(file0), -1, stdout1);
assert.notStrictEqual(stdout1.split('\n').indexOf(file1), -1, stdout1);
assert.notStrictEqual(stdout1!.split('\n').indexOf(file0), -1, stdout1);
assert.notStrictEqual(stdout1!.split('\n').indexOf(file1), -1, stdout1);
const walker = new FileWalker({
type: QueryType.File,
@@ -790,8 +790,8 @@ suite('FileWalker', () => {
const cmd2 = walker.spawnFindCmd(TEST_ROOT_FOLDER);
walker.readStdout(cmd2, 'utf8', /*isRipgrep=*/false, (err2, stdout2) => {
assert.equal(err2, null);
assert.notStrictEqual(stdout1.split('\n').indexOf(file0), -1, stdout1);
assert.strictEqual(stdout2.split('\n').indexOf(file1), -1, stdout2);
assert.notStrictEqual(stdout1!.split('\n').indexOf(file0), -1, stdout1);
assert.strictEqual(stdout2!.split('\n').indexOf(file1), -1, stdout2);
done();
});
});
@@ -818,8 +818,8 @@ suite('FileWalker', () => {
const cmd1 = walker.spawnFindCmd(folderQueries[0]);
walker.readStdout(cmd1, 'utf8', /*isRipgrep=*/false, (err1, stdout1) => {
assert.equal(err1, null);
assert(outputContains(stdout1, file0), stdout1);
assert(!outputContains(stdout1, file1), stdout1);
assert(outputContains(stdout1!, file0), stdout1);
assert(!outputContains(stdout1!, file1), stdout1);
done();
});
});
@@ -839,17 +839,17 @@ suite('FileWalker', () => {
const cmd1 = walker.spawnFindCmd(TEST_ROOT_FOLDER);
walker.readStdout(cmd1, 'utf8', /*isRipgrep=*/false, (err1, stdout1) => {
assert.equal(err1, null);
assert.notStrictEqual(stdout1.split('\n').indexOf(file0), -1, stdout1);
assert.notStrictEqual(stdout1.split('\n').indexOf(file1), -1, stdout1);
assert.notStrictEqual(stdout1.split('\n').indexOf(file2), -1, stdout1);
assert.notStrictEqual(stdout1!.split('\n').indexOf(file0), -1, stdout1);
assert.notStrictEqual(stdout1!.split('\n').indexOf(file1), -1, stdout1);
assert.notStrictEqual(stdout1!.split('\n').indexOf(file2), -1, stdout1);
const walker = new FileWalker({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, excludePattern: { '{**/examples,**/more}': true } });
const cmd2 = walker.spawnFindCmd(TEST_ROOT_FOLDER);
walker.readStdout(cmd2, 'utf8', /*isRipgrep=*/false, (err2, stdout2) => {
assert.equal(err2, null);
assert.notStrictEqual(stdout1.split('\n').indexOf(file0), -1, stdout1);
assert.strictEqual(stdout2.split('\n').indexOf(file1), -1, stdout2);
assert.strictEqual(stdout2.split('\n').indexOf(file2), -1, stdout2);
assert.notStrictEqual(stdout1!.split('\n').indexOf(file0), -1, stdout1);
assert.strictEqual(stdout2!.split('\n').indexOf(file1), -1, stdout2);
assert.strictEqual(stdout2!.split('\n').indexOf(file2), -1, stdout2);
done();
});
});
@@ -869,15 +869,15 @@ suite('FileWalker', () => {
const cmd1 = walker.spawnFindCmd(TEST_ROOT_FOLDER);
walker.readStdout(cmd1, 'utf8', /*isRipgrep=*/false, (err1, stdout1) => {
assert.equal(err1, null);
assert.notStrictEqual(stdout1.split('\n').indexOf(file0), -1, stdout1);
assert.notStrictEqual(stdout1.split('\n').indexOf(file1), -1, stdout1);
assert.notStrictEqual(stdout1!.split('\n').indexOf(file0), -1, stdout1);
assert.notStrictEqual(stdout1!.split('\n').indexOf(file1), -1, stdout1);
const walker = new FileWalker({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, excludePattern: { '**/examples/subfolder': true } });
const cmd2 = walker.spawnFindCmd(TEST_ROOT_FOLDER);
walker.readStdout(cmd2, 'utf8', /*isRipgrep=*/false, (err2, stdout2) => {
assert.equal(err2, null);
assert.notStrictEqual(stdout1.split('\n').indexOf(file0), -1, stdout1);
assert.strictEqual(stdout2.split('\n').indexOf(file1), -1, stdout2);
assert.notStrictEqual(stdout1!.split('\n').indexOf(file0), -1, stdout1);
assert.strictEqual(stdout2!.split('\n').indexOf(file1), -1, stdout2);
done();
});
});
@@ -897,15 +897,15 @@ suite('FileWalker', () => {
const cmd1 = walker.spawnFindCmd(TEST_ROOT_FOLDER);
walker.readStdout(cmd1, 'utf8', /*isRipgrep=*/false, (err1, stdout1) => {
assert.equal(err1, null);
assert.notStrictEqual(stdout1.split('\n').indexOf(file0), -1, stdout1);
assert.notStrictEqual(stdout1.split('\n').indexOf(file1), -1, stdout1);
assert.notStrictEqual(stdout1!.split('\n').indexOf(file0), -1, stdout1);
assert.notStrictEqual(stdout1!.split('\n').indexOf(file1), -1, stdout1);
const walker = new FileWalker({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, excludePattern: { '**/subfolder/anotherfolder': true } });
const cmd2 = walker.spawnFindCmd(TEST_ROOT_FOLDER);
walker.readStdout(cmd2, 'utf8', /*isRipgrep=*/false, (err2, stdout2) => {
assert.equal(err2, null);
assert.notStrictEqual(stdout1.split('\n').indexOf(file0), -1, stdout1);
assert.strictEqual(stdout2.split('\n').indexOf(file1), -1, stdout2);
assert.notStrictEqual(stdout1!.split('\n').indexOf(file0), -1, stdout1);
assert.strictEqual(stdout2!.split('\n').indexOf(file1), -1, stdout2);
done();
});
});
@@ -925,15 +925,15 @@ suite('FileWalker', () => {
const cmd1 = walker.spawnFindCmd(TEST_ROOT_FOLDER);
walker.readStdout(cmd1, 'utf8', /*isRipgrep=*/false, (err1, stdout1) => {
assert.equal(err1, null);
assert.notStrictEqual(stdout1.split('\n').indexOf(file0), -1, stdout1);
assert.notStrictEqual(stdout1.split('\n').indexOf(file1), -1, stdout1);
assert.notStrictEqual(stdout1!.split('\n').indexOf(file0), -1, stdout1);
assert.notStrictEqual(stdout1!.split('\n').indexOf(file1), -1, stdout1);
const walker = new FileWalker({ type: QueryType.File, folderQueries: ROOT_FOLDER_QUERY, excludePattern: { 'examples/subfolder': true } });
const cmd2 = walker.spawnFindCmd(TEST_ROOT_FOLDER);
walker.readStdout(cmd2, 'utf8', /*isRipgrep=*/false, (err2, stdout2) => {
assert.equal(err2, null);
assert.notStrictEqual(stdout1.split('\n').indexOf(file0), -1, stdout1);
assert.strictEqual(stdout2.split('\n').indexOf(file1), -1, stdout2);
assert.notStrictEqual(stdout1!.split('\n').indexOf(file0), -1, stdout1);
assert.strictEqual(stdout2!.split('\n').indexOf(file1), -1, stdout2);
done();
});
});
@@ -970,10 +970,10 @@ suite('FileWalker', () => {
walker.readStdout(cmd1, 'utf8', /*isRipgrep=*/false, (err1, stdout1) => {
assert.equal(err1, null);
for (const fileIn of filesIn) {
assert.notStrictEqual(stdout1.split('\n').indexOf(fileIn), -1, stdout1);
assert.notStrictEqual(stdout1!.split('\n').indexOf(fileIn), -1, stdout1);
}
for (const fileOut of filesOut) {
assert.strictEqual(stdout1.split('\n').indexOf(fileOut), -1, stdout1);
assert.strictEqual(stdout1!.split('\n').indexOf(fileOut), -1, stdout1);
}
done();
});
@@ -15,7 +15,7 @@ import { ISerializedFileMatch } from 'vs/workbench/services/search/node/search';
import { TextSearchEngineAdapter } from 'vs/workbench/services/search/node/textSearchAdapter';
function countAll(matches: ISerializedFileMatch[]): number {
return matches.reduce((acc, m) => acc + m.numMatches, 0);
return matches.reduce((acc, m) => acc + m.numMatches!, 0);
}
const TEST_FIXTURES = path.normalize(getPathFromAmdModule(require, './fixtures'));
@@ -39,7 +39,7 @@ function doLegacySearchTest(config: ITextQuery, expectedResultCount: number | Fu
if (result && Array.isArray(result)) {
c += countAll(result);
}
}, null).then(() => {
}, null!).then(() => {
if (typeof expectedResultCount === 'function') {
assert(expectedResultCount(c));
} else {
@@ -55,7 +55,7 @@ function doRipgrepSearchTest(query: ITextQuery, expectedResultCount: number | Fu
const results: ISerializedFileMatch[] = [];
return engine.search(new CancellationTokenSource().token, _results => {
if (_results) {
c += _results.reduce((acc, cur) => acc + cur.numMatches, 0);
c += _results.reduce((acc, cur) => acc + cur.numMatches!, 0);
results.push(..._results);
}
}, () => { }).then(() => {
@@ -319,7 +319,7 @@ suite('Search-integration', function () {
};
return doRipgrepSearchTest(config, 1).then(results => {
const matchRange = (<ITextSearchMatch>results[0].results[0]).ranges;
const matchRange = (<ITextSearchMatch>results[0].results![0]).ranges;
assert.deepEqual(matchRange, [{
startLineNumber: 0,
startColumn: 1,
@@ -338,8 +338,8 @@ suite('Search-integration', function () {
return doRipgrepSearchTest(config, 15).then(results => {
assert.equal(results.length, 3);
assert.equal(results[0].results.length, 1);
const match = <ITextSearchMatch>results[0].results[0];
assert.equal(results[0].results!.length, 1);
const match = <ITextSearchMatch>results[0].results![0];
assert.equal((<ISearchRange[]>match.ranges).length, 5);
});
});
@@ -355,13 +355,13 @@ suite('Search-integration', function () {
return doRipgrepSearchTest(config, 4).then(results => {
assert.equal(results.length, 4);
assert.equal((<ITextSearchContext>results[0].results[0]).lineNumber, 25);
assert.equal((<ITextSearchContext>results[0].results[0]).text, ' compiler.addUnit(prog,"input.ts");');
assert.equal((<ITextSearchContext>results[0].results![0]).lineNumber, 25);
assert.equal((<ITextSearchContext>results[0].results![0]).text, ' compiler.addUnit(prog,"input.ts");');
// assert.equal((<ITextSearchMatch>results[1].results[0]).preview.text, ' compiler.typeCheck();\n'); // See https://github.com/BurntSushi/ripgrep/issues/1095
assert.equal((<ITextSearchContext>results[2].results[0]).lineNumber, 27);
assert.equal((<ITextSearchContext>results[2].results[0]).text, ' compiler.emit();');
assert.equal((<ITextSearchContext>results[3].results[0]).lineNumber, 28);
assert.equal((<ITextSearchContext>results[3].results[0]).text, '');
assert.equal((<ITextSearchContext>results[2].results![0]).lineNumber, 27);
assert.equal((<ITextSearchContext>results[2].results![0]).text, ' compiler.emit();');
assert.equal((<ITextSearchContext>results[3].results![0]).lineNumber, 28);
assert.equal((<ITextSearchContext>results[3].results![0]).text, '');
});
});
@@ -219,9 +219,9 @@ suite('Files - TextFileService', () => {
assert.equal(res.results.length, 1);
assert.ok(res.results[0].success);
assert.equal(res.results[0].target.scheme, Schemas.file);
assert.equal(res.results[0].target.authority, untitledUncUri.authority);
assert.equal(res.results[0].target.path, untitledUncUri.path);
assert.equal(res.results[0].target!.scheme, Schemas.file);
assert.equal(res.results[0].target!.authority, untitledUncUri.authority);
assert.equal(res.results[0].target!.path, untitledUncUri.path);
});
});
});
@@ -47,7 +47,7 @@ suite('Workbench - TextModelResolverService', () => {
teardown(() => {
if (model) {
model.dispose();
model = void 0;
model = (void 0)!;
}
(<TextFileEditorModelManager>accessor.textFileService.models).clear();
(<TextFileEditorModelManager>accessor.textFileService.models).dispose();
@@ -63,11 +63,11 @@ suite('Workbench - TextModelResolverService', () => {
return Promise.resolve(accessor.modelService.createModel(modelContent, languageSelection, resource));
}
return Promise.resolve(null);
return Promise.resolve(null!);
}
});
let resource = URI.from({ scheme: 'test', authority: null, path: 'thePath' });
let resource = URI.from({ scheme: 'test', authority: null!, path: 'thePath' });
let input: ResourceEditorInput = instantiationService.createInstance(ResourceEditorInput, 'The Name', 'The Description', resource);
return input.resolve().then(async model => {
@@ -132,7 +132,7 @@ suite('Workbench - TextModelResolverService', () => {
});
test('even loading documents should be refcounted', async () => {
let resolveModel: Function;
let resolveModel!: Function;
let waitForIt = new Promise(c => resolveModel = c);
const disposable = accessor.textModelResolverService.registerTextModelContentProvider('test', {
@@ -145,7 +145,7 @@ suite('Workbench - TextModelResolverService', () => {
}
});
const uri = URI.from({ scheme: 'test', authority: null, path: 'thePath' });
const uri = URI.from({ scheme: 'test', authority: null!, path: 'thePath' });
const modelRefPromise1 = accessor.textModelResolverService.createModelReference(uri);
const modelRefPromise2 = accessor.textModelResolverService.createModelReference(uri);
+6 -6
View File
@@ -19,12 +19,12 @@ class MyPart extends Part {
createTitleArea(parent: HTMLElement): HTMLElement {
assert.strictEqual(parent, this.expectedParent);
return super.createTitleArea(parent);
return super.createTitleArea(parent)!;
}
createContentArea(parent: HTMLElement): HTMLElement {
assert.strictEqual(parent, this.expectedParent);
return super.createContentArea(parent);
return super.createContentArea(parent)!;
}
getMemento(scope: StorageScope) {
@@ -68,7 +68,7 @@ class MyPart3 extends Part {
}
createTitleArea(parent: HTMLElement): HTMLElement {
return null;
return null!;
}
createContentArea(parent: HTMLElement): HTMLElement {
@@ -97,7 +97,7 @@ suite('Workbench parts', () => {
test('Creation', () => {
let b = document.createElement('div');
document.getElementById(fixtureId).appendChild(b);
document.getElementById(fixtureId)!.appendChild(b);
hide(b);
let part = new MyPart(b);
@@ -134,7 +134,7 @@ suite('Workbench parts', () => {
test('Part Layout with Title and Content', function () {
let b = document.createElement('div');
document.getElementById(fixtureId).appendChild(b);
document.getElementById(fixtureId)!.appendChild(b);
hide(b);
let part = new MyPart2();
@@ -146,7 +146,7 @@ suite('Workbench parts', () => {
test('Part Layout with Content only', function () {
let b = document.createElement('div');
document.getElementById(fixtureId).appendChild(b);
document.getElementById(fixtureId)!.appendChild(b);
hide(b);
let part = new MyPart3();
@@ -267,7 +267,7 @@ suite('Workbench base editor', () => {
super();
}
public getTypeId() { return 'testEditorInput'; }
public resolve(): Promise<IEditorModel> { return Promise.resolve(null); }
public resolve(): Promise<IEditorModel> { return Promise.resolve(null!); }
public matches(other: TestEditorInput): boolean {
return other && this.id === other.id && other instanceof TestEditorInput;
@@ -40,7 +40,7 @@ suite('Editor - Range decorations', () => {
model = aModel(URI.file('some_file'));
codeEditor = createTestCodeEditor({ model: model });
instantiationService.stub(IEditorService, 'activeEditor', { getResource: () => { return codeEditor.getModel().uri; } });
instantiationService.stub(IEditorService, 'activeEditor', { getResource: () => { return codeEditor.getModel()!.uri; } });
instantiationService.stub(IEditorService, 'activeTextEditorWidget', codeEditor);
testObject = instantiationService.createInstance(RangeHighlightDecorations);
@@ -13,9 +13,9 @@ import { QuickOpenHandlerDescriptor, IQuickOpenRegistry, Extensions as QuickOpen
export class TestQuickOpenService implements IQuickOpenService {
public _serviceBrand: any;
private callback: (prefix: string) => void;
private callback?: (prefix?: string) => void;
constructor(callback?: (prefix: string) => void) {
constructor(callback?: (prefix?: string) => void) {
this.callback = callback;
}
@@ -37,11 +37,11 @@ export class TestQuickOpenService implements IQuickOpenService {
}
get onShow(): Event<void> {
return null;
return null!;
}
get onHide(): Event<void> {
return null;
return null!;
}
public dispose() { }
@@ -59,7 +59,7 @@ suite('QuickOpen', () => {
'testhandler',
',',
'Handler',
null
null!
);
registry.registerQuickOpenHandler(handler);
@@ -71,7 +71,7 @@ suite('QuickOpen', () => {
});
test('QuickOpen Action', () => {
let defaultAction = new QuickOpenAction('id', 'label', void 0, new TestQuickOpenService((prefix: string) => assert(!prefix)));
let defaultAction = new QuickOpenAction('id', 'label', (void 0)!, new TestQuickOpenService((prefix: string) => assert(!prefix)));
let prefixAction = new QuickOpenAction('id', 'label', ',', new TestQuickOpenService((prefix: string) => assert(!!prefix)));
defaultAction.run();
@@ -13,7 +13,7 @@ suite('Viewlets', () => {
class TestViewlet extends Viewlet {
constructor() {
super('id', null, null, null, null, null);
super('id', null!, null!, null!, null!, null!);
}
public layout(dimension: any): void {
@@ -44,12 +44,12 @@ suite('Workbench editor model', () => {
return Promise.resolve(accessor.modelService.createModel(modelContent, languageSelection, resource));
}
return Promise.resolve(null);
return Promise.resolve(null!);
}
});
let input = instantiationService.createInstance(ResourceEditorInput, 'name', 'description', URI.from({ scheme: 'test', authority: null, path: 'thePath' }));
let otherInput = instantiationService.createInstance(ResourceEditorInput, 'name2', 'description', URI.from({ scheme: 'test', authority: null, path: 'thePath' }));
let input = instantiationService.createInstance(ResourceEditorInput, 'name', 'description', URI.from({ scheme: 'test', authority: null!, path: 'thePath' }));
let otherInput = instantiationService.createInstance(ResourceEditorInput, 'name2', 'description', URI.from({ scheme: 'test', authority: null!, path: 'thePath' }));
let diffInput = new DiffEditorInput('name', 'description', input, otherInput);
return diffInput.resolve().then((model: any) => {
@@ -77,7 +77,7 @@ class TestEditorInput extends EditorInput {
super();
}
getTypeId() { return 'testEditorInputForGroups'; }
resolve(): Promise<IEditorModel> { return Promise.resolve(null); }
resolve(): Promise<IEditorModel> { return Promise.resolve(null!); }
matches(other: TestEditorInput): boolean {
return other && this.id === other.id && other instanceof TestEditorInput;
@@ -97,7 +97,7 @@ class NonSerializableTestEditorInput extends EditorInput {
super();
}
getTypeId() { return 'testEditorInputForGroups-nonSerializable'; }
resolve(): Promise<IEditorModel> { return Promise.resolve(null); }
resolve(): Promise<IEditorModel> { return Promise.resolve(null!); }
matches(other: NonSerializableTestEditorInput): boolean {
return other && this.id === other.id && other instanceof NonSerializableTestEditorInput;
@@ -110,7 +110,7 @@ class TestFileEditorInput extends EditorInput implements IFileEditorInput {
super();
}
getTypeId() { return 'testFileEditorInputForGroups'; }
resolve(): Promise<IEditorModel> { return Promise.resolve(null); }
resolve(): Promise<IEditorModel> { return Promise.resolve(null!); }
matches(other: TestFileEditorInput): boolean {
return other && this.id === other.id && other instanceof TestFileEditorInput;
@@ -120,7 +120,7 @@ class TestFileEditorInput extends EditorInput implements IFileEditorInput {
}
getEncoding(): string {
return null;
return null!;
}
setPreferredEncoding(encoding: string) {
@@ -781,7 +781,7 @@ suite('Workbench editor groups', () => {
group.openEditor(input5, { active: true, pinned: true });
// Close Others
group.closeEditors(group.activeEditor);
group.closeEditors(group.activeEditor!);
assert.equal(group.activeEditor, input5);
assert.equal(group.count, 1);
@@ -795,7 +795,7 @@ suite('Workbench editor groups', () => {
// Close Left
assert.equal(group.activeEditor, input3);
group.closeEditors(group.activeEditor, CloseDirection.LEFT);
group.closeEditors(group.activeEditor!, CloseDirection.LEFT);
assert.equal(group.activeEditor, input3);
assert.equal(group.count, 3);
assert.equal(group.getEditors()[0], input3);
@@ -812,7 +812,7 @@ suite('Workbench editor groups', () => {
// Close Right
assert.equal(group.activeEditor, input3);
group.closeEditors(group.activeEditor, CloseDirection.RIGHT);
group.closeEditors(group.activeEditor!, CloseDirection.RIGHT);
assert.equal(group.activeEditor, input3);
assert.equal(group.count, 3);
assert.equal(group.getEditors()[0], input1);
@@ -953,16 +953,16 @@ suite('Workbench editor groups', () => {
group.openEditor(input1);
assert.equal(group.count, 1);
assert.equal(group.activeEditor.matches(input1), true);
assert.equal(group.previewEditor.matches(input1), true);
assert.equal(group.activeEditor!.matches(input1), true);
assert.equal(group.previewEditor!.matches(input1), true);
assert.equal(group.isActive(input1), true);
// Create model again - should load from storage
group = inst.createInstance(EditorGroup, group.serialize());
assert.equal(group.count, 1);
assert.equal(group.activeEditor.matches(input1), true);
assert.equal(group.previewEditor.matches(input1), true);
assert.equal(group.activeEditor!.matches(input1), true);
assert.equal(group.previewEditor!.matches(input1), true);
assert.equal(group.isActive(input1), true);
});
@@ -1003,10 +1003,10 @@ suite('Workbench editor groups', () => {
assert.equal(group1.count, 3);
assert.equal(group2.count, 3);
assert.equal(group1.activeEditor.matches(g1_input2), true);
assert.equal(group2.activeEditor.matches(g2_input1), true);
assert.equal(group1.previewEditor.matches(g1_input2), true);
assert.equal(group2.previewEditor.matches(g2_input2), true);
assert.equal(group1.activeEditor!.matches(g1_input2), true);
assert.equal(group2.activeEditor!.matches(g2_input1), true);
assert.equal(group1.previewEditor!.matches(g1_input2), true);
assert.equal(group2.previewEditor!.matches(g2_input2), true);
assert.equal(group1.getEditors(true)[0].matches(g1_input2), true);
assert.equal(group1.getEditors(true)[1].matches(g1_input1), true);
@@ -1022,10 +1022,10 @@ suite('Workbench editor groups', () => {
assert.equal(group1.count, 3);
assert.equal(group2.count, 3);
assert.equal(group1.activeEditor.matches(g1_input2), true);
assert.equal(group2.activeEditor.matches(g2_input1), true);
assert.equal(group1.previewEditor.matches(g1_input2), true);
assert.equal(group2.previewEditor.matches(g2_input2), true);
assert.equal(group1.activeEditor!.matches(g1_input2), true);
assert.equal(group2.activeEditor!.matches(g2_input1), true);
assert.equal(group1.previewEditor!.matches(g1_input2), true);
assert.equal(group2.previewEditor!.matches(g2_input2), true);
assert.equal(group1.getEditors(true)[0].matches(g1_input2), true);
assert.equal(group1.getEditors(true)[1].matches(g1_input1), true);
@@ -1062,8 +1062,8 @@ suite('Workbench editor groups', () => {
group.openEditor(serializableInput2, { active: false, pinned: true });
assert.equal(group.count, 3);
assert.equal(group.activeEditor.matches(nonSerializableInput2), true);
assert.equal(group.previewEditor.matches(nonSerializableInput2), true);
assert.equal(group.activeEditor!.matches(nonSerializableInput2), true);
assert.equal(group.previewEditor!.matches(nonSerializableInput2), true);
assert.equal(group.getEditors(true)[0].matches(nonSerializableInput2), true);
assert.equal(group.getEditors(true)[1].matches(serializableInput1), true);
@@ -1073,7 +1073,7 @@ suite('Workbench editor groups', () => {
group = inst.createInstance(EditorGroup, group.serialize());
assert.equal(group.count, 2);
assert.equal(group.activeEditor.matches(serializableInput1), true);
assert.equal(group.activeEditor!.matches(serializableInput1), true);
assert.equal(group.previewEditor, null);
assert.equal(group.getEditors(true)[0].matches(serializableInput1), true);
@@ -64,7 +64,7 @@ suite('Workbench editor model', () => {
let m = new MyTextEditorModel(modelService, modeService);
return m.load().then((model: MyTextEditorModel) => {
assert(model === m);
model.createTextEditorModel(createTextBufferFactory('foo'), null, 'text/plain');
model.createTextEditorModel(createTextBufferFactory('foo'), null!, 'text/plain');
assert.strictEqual(m.isResolved(), true);
}).then(() => {
m.dispose();

Some files were not shown because too many files have changed in this diff Show More