Merge from vscode 3c6f6af7347d38e87bc6406024e8dcf9e9bce229 (#8962)

* Merge from vscode 3c6f6af7347d38e87bc6406024e8dcf9e9bce229

* skip failing tests

* update mac build image
This commit is contained in:
Anthony Dresser
2020-01-27 15:28:17 -08:00
committed by Karl Burtram
parent 0eaee18dc4
commit fefe1454de
481 changed files with 12764 additions and 7836 deletions

View File

@@ -7,14 +7,13 @@ import { URI } from 'vs/base/common/uri';
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { TextDocumentSaveReason, TextEdit, Position, EndOfLine } from 'vs/workbench/api/common/extHostTypes';
import { MainThreadTextEditorsShape, IWorkspaceEditDto } from 'vs/workbench/api/common/extHost.protocol';
import { MainThreadTextEditorsShape, IWorkspaceEditDto, IWorkspaceTextEditDto } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostDocumentSaveParticipant } from 'vs/workbench/api/common/extHostDocumentSaveParticipant';
import { SingleProxyRPCProtocol } from './testRPCProtocol';
import { SaveReason } from 'vs/workbench/common/editor';
import type * as vscode from 'vscode';
import { mock } from 'vs/workbench/test/electron-browser/api/mock';
import { NullLogService } from 'vs/platform/log/common/log';
import { WorkspaceTextEdit } from 'vs/editor/common/modes';
import { timeout } from 'vs/base/common/async';
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
@@ -278,9 +277,9 @@ suite('ExtHostDocumentSaveParticipant', () => {
return participant.$participateInSave(resource, SaveReason.EXPLICIT).then(() => {
sub.dispose();
assert.equal(dto.edits.length, 1);
assert.ok(WorkspaceTextEdit.is(dto.edits[0]));
assert.equal((<WorkspaceTextEdit>dto.edits[0]).edits.length, 2);
assert.equal(dto.edits.length, 2);
assert.ok((<IWorkspaceTextEditDto>dto.edits[0]).edit);
assert.ok((<IWorkspaceTextEditDto>dto.edits[1]).edit);
});
});
@@ -326,23 +325,20 @@ suite('ExtHostDocumentSaveParticipant', () => {
$tryApplyWorkspaceEdit(dto: IWorkspaceEditDto) {
for (const edit of dto.edits) {
if (!WorkspaceTextEdit.is(edit)) {
continue;
}
const { resource, edits } = edit;
const uri = URI.revive(resource);
for (const { text, range } of edits) {
documents.$acceptModelChanged(uri, {
changes: [{
range,
text,
rangeOffset: undefined!,
rangeLength: undefined!,
}],
eol: undefined!,
versionId: documents.getDocumentData(uri)!.version + 1
}, true);
}
const uri = URI.revive((<IWorkspaceTextEditDto>edit).resource);
const { text, range } = (<IWorkspaceTextEditDto>edit).edit;
documents.$acceptModelChanged(uri, {
changes: [{
range,
text,
rangeOffset: undefined!,
rangeLength: undefined!,
}],
eol: undefined!,
versionId: documents.getDocumentData(uri)!.version + 1
}, true);
// }
}
return Promise.resolve(true);

View File

@@ -759,8 +759,6 @@ suite('ExtHostLanguageFeatures', function () {
const value = await rename(model, new EditorPosition(1, 1), 'newName');
// least relevant rename provider
assert.equal(value.edits.length, 2);
assert.equal((<modes.WorkspaceTextEdit>value.edits[0]).edits.length, 1);
assert.equal((<modes.WorkspaceTextEdit>value.edits[1]).edits.length, 1);
});
// --- parameter hints
@@ -881,7 +879,7 @@ suite('ExtHostLanguageFeatures', function () {
await rpcProtocol.sync();
const value = await provideSuggestionItems(model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<modes.CompletionItemKind>().add(modes.CompletionItemKind.Snippet)));
assert.equal(value[0].container.incomplete, undefined);
assert.equal(value[0].container.incomplete, false);
});
test('Suggest, CompletionList', async () => {

View File

@@ -18,6 +18,7 @@ import { mock } from 'vs/workbench/test/electron-browser/api/mock';
import { TreeItemCollapsibleState, ITreeItem } from 'vs/workbench/common/views';
import { NullLogService } from 'vs/platform/log/common/log';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import type { IDisposable } from 'vs/base/common/lifecycle';
suite('ExtHostTreeView', function () {
@@ -29,7 +30,9 @@ suite('ExtHostTreeView', function () {
}
$refresh(viewId: string, itemsToRefresh: { [treeItemHandle: string]: ITreeItem }): Promise<void> {
return Promise.resolve(null).then(() => this.onRefresh.fire(itemsToRefresh));
return Promise.resolve(null).then(() => {
this.onRefresh.fire(itemsToRefresh);
});
}
$reveal(): Promise<void> {
@@ -243,46 +246,62 @@ suite('ExtHostTreeView', function () {
onDidChangeTreeNode.fire(getNode('bb'));
});
test('refresh parent and child node trigger refresh only on parent - scenario 1', function (done) {
target.onRefresh.event(actuals => {
assert.deepEqual(['0/0:b', '0/0:a/0:aa'], Object.keys(actuals));
assert.deepEqual(removeUnsetKeys(actuals['0/0:b']), {
handle: '0/0:b',
label: { label: 'b' },
collapsibleState: TreeItemCollapsibleState.Collapsed
async function runWithEventMerging(action: (resolve: () => void) => void) {
await new Promise((resolve) => {
let subscription: IDisposable | undefined = undefined;
subscription = target.onRefresh.event(() => {
subscription!.dispose();
resolve();
});
assert.deepEqual(removeUnsetKeys(actuals['0/0:a/0:aa']), {
handle: '0/0:a/0:aa',
parentHandle: '0/0:a',
label: { label: 'aa' },
collapsibleState: TreeItemCollapsibleState.None
});
done();
onDidChangeTreeNode.fire(getNode('b'));
});
await new Promise(action);
}
test('refresh parent and child node trigger refresh only on parent - scenario 1', async () => {
return runWithEventMerging((resolve) => {
target.onRefresh.event(actuals => {
assert.deepEqual(['0/0:b', '0/0:a/0:aa'], Object.keys(actuals));
assert.deepEqual(removeUnsetKeys(actuals['0/0:b']), {
handle: '0/0:b',
label: { label: 'b' },
collapsibleState: TreeItemCollapsibleState.Collapsed
});
assert.deepEqual(removeUnsetKeys(actuals['0/0:a/0:aa']), {
handle: '0/0:a/0:aa',
parentHandle: '0/0:a',
label: { label: 'aa' },
collapsibleState: TreeItemCollapsibleState.None
});
resolve();
});
onDidChangeTreeNode.fire(getNode('b'));
onDidChangeTreeNode.fire(getNode('aa'));
onDidChangeTreeNode.fire(getNode('bb'));
});
onDidChangeTreeNode.fire(getNode('b'));
onDidChangeTreeNode.fire(getNode('aa'));
onDidChangeTreeNode.fire(getNode('bb'));
});
test('refresh parent and child node trigger refresh only on parent - scenario 2', function (done) {
target.onRefresh.event(actuals => {
assert.deepEqual(['0/0:a/0:aa', '0/0:b'], Object.keys(actuals));
assert.deepEqual(removeUnsetKeys(actuals['0/0:b']), {
handle: '0/0:b',
label: { label: 'b' },
collapsibleState: TreeItemCollapsibleState.Collapsed
test('refresh parent and child node trigger refresh only on parent - scenario 2', async () => {
return runWithEventMerging((resolve) => {
target.onRefresh.event(actuals => {
assert.deepEqual(['0/0:a/0:aa', '0/0:b'], Object.keys(actuals));
assert.deepEqual(removeUnsetKeys(actuals['0/0:b']), {
handle: '0/0:b',
label: { label: 'b' },
collapsibleState: TreeItemCollapsibleState.Collapsed
});
assert.deepEqual(removeUnsetKeys(actuals['0/0:a/0:aa']), {
handle: '0/0:a/0:aa',
parentHandle: '0/0:a',
label: { label: 'aa' },
collapsibleState: TreeItemCollapsibleState.None
});
resolve();
});
assert.deepEqual(removeUnsetKeys(actuals['0/0:a/0:aa']), {
handle: '0/0:a/0:aa',
parentHandle: '0/0:a',
label: { label: 'aa' },
collapsibleState: TreeItemCollapsibleState.None
});
done();
onDidChangeTreeNode.fire(getNode('bb'));
onDidChangeTreeNode.fire(getNode('aa'));
onDidChangeTreeNode.fire(getNode('b'));
});
onDidChangeTreeNode.fire(getNode('bb'));
onDidChangeTreeNode.fire(getNode('aa'));
onDidChangeTreeNode.fire(getNode('b'));
});
test('refresh an element for label change', function (done) {
@@ -299,63 +318,73 @@ suite('ExtHostTreeView', function () {
onDidChangeTreeNode.fire(getNode('a'));
});
test('refresh calls are throttled on roots', function (done) {
target.onRefresh.event(actuals => {
assert.equal(undefined, actuals);
done();
test('refresh calls are throttled on roots', () => {
return runWithEventMerging((resolve) => {
target.onRefresh.event(actuals => {
assert.equal(undefined, actuals);
resolve();
});
onDidChangeTreeNode.fire(undefined);
onDidChangeTreeNode.fire(undefined);
onDidChangeTreeNode.fire(undefined);
onDidChangeTreeNode.fire(undefined);
});
onDidChangeTreeNode.fire(undefined);
onDidChangeTreeNode.fire(undefined);
onDidChangeTreeNode.fire(undefined);
onDidChangeTreeNode.fire(undefined);
});
test('refresh calls are throttled on elements', function (done) {
target.onRefresh.event(actuals => {
assert.deepEqual(['0/0:a', '0/0:b'], Object.keys(actuals));
done();
});
test('refresh calls are throttled on elements', () => {
return runWithEventMerging((resolve) => {
target.onRefresh.event(actuals => {
assert.deepEqual(['0/0:a', '0/0:b'], Object.keys(actuals));
resolve();
});
onDidChangeTreeNode.fire(getNode('a'));
onDidChangeTreeNode.fire(getNode('b'));
onDidChangeTreeNode.fire(getNode('b'));
onDidChangeTreeNode.fire(getNode('a'));
onDidChangeTreeNode.fire(getNode('a'));
onDidChangeTreeNode.fire(getNode('b'));
onDidChangeTreeNode.fire(getNode('b'));
onDidChangeTreeNode.fire(getNode('a'));
});
});
test('refresh calls are throttled on unknown elements', function (done) {
target.onRefresh.event(actuals => {
assert.deepEqual(['0/0:a', '0/0:b'], Object.keys(actuals));
done();
});
test('refresh calls are throttled on unknown elements', () => {
return runWithEventMerging((resolve) => {
target.onRefresh.event(actuals => {
assert.deepEqual(['0/0:a', '0/0:b'], Object.keys(actuals));
resolve();
});
onDidChangeTreeNode.fire(getNode('a'));
onDidChangeTreeNode.fire(getNode('b'));
onDidChangeTreeNode.fire(getNode('g'));
onDidChangeTreeNode.fire(getNode('a'));
onDidChangeTreeNode.fire(getNode('a'));
onDidChangeTreeNode.fire(getNode('b'));
onDidChangeTreeNode.fire(getNode('g'));
onDidChangeTreeNode.fire(getNode('a'));
});
});
test('refresh calls are throttled on unknown elements and root', function (done) {
target.onRefresh.event(actuals => {
assert.equal(undefined, actuals);
done();
});
test('refresh calls are throttled on unknown elements and root', () => {
return runWithEventMerging((resolve) => {
target.onRefresh.event(actuals => {
assert.equal(undefined, actuals);
resolve();
});
onDidChangeTreeNode.fire(getNode('a'));
onDidChangeTreeNode.fire(getNode('b'));
onDidChangeTreeNode.fire(getNode('g'));
onDidChangeTreeNode.fire(undefined);
onDidChangeTreeNode.fire(getNode('a'));
onDidChangeTreeNode.fire(getNode('b'));
onDidChangeTreeNode.fire(getNode('g'));
onDidChangeTreeNode.fire(undefined);
});
});
test('refresh calls are throttled on elements and root', function (done) {
target.onRefresh.event(actuals => {
assert.equal(undefined, actuals);
done();
});
test('refresh calls are throttled on elements and root', () => {
return runWithEventMerging((resolve) => {
target.onRefresh.event(actuals => {
assert.equal(undefined, actuals);
resolve();
});
onDidChangeTreeNode.fire(getNode('a'));
onDidChangeTreeNode.fire(getNode('b'));
onDidChangeTreeNode.fire(undefined);
onDidChangeTreeNode.fire(getNode('a'));
onDidChangeTreeNode.fire(getNode('a'));
onDidChangeTreeNode.fire(getNode('b'));
onDidChangeTreeNode.fire(undefined);
onDidChangeTreeNode.fire(getNode('a'));
});
});
test('generate unique handles from labels by escaping them', (done) => {
@@ -552,37 +581,40 @@ suite('ExtHostTreeView', function () {
const treeView = testObject.createTreeView('treeDataProvider', { treeDataProvider: aCompleteNodeTreeDataProvider() }, { enableProposedApi: true } as IExtensionDescription);
return loadCompleteTree('treeDataProvider')
.then(() => {
tree = {
'a': {
'aa': {},
'ac': {}
},
'b': {
'ba': {},
'bb': {}
}
};
onDidChangeTreeNode.fire(getNode('a'));
tree = {
'a': {
'aa': {},
'ac': {}
},
'b': {
'ba': {},
'bc': {}
}
};
onDidChangeTreeNode.fire(getNode('b'));
return treeView.reveal({ key: 'bc' })
.then(() => {
assert.ok(revealTarget.calledOnce);
assert.deepEqual('treeDataProvider', revealTarget.args[0][0]);
assert.deepEqual({ handle: '0/0:b/0:bc', label: { label: 'bc' }, collapsibleState: TreeItemCollapsibleState.None, parentHandle: '0/0:b' }, removeUnsetKeys(revealTarget.args[0][1]));
assert.deepEqual([{ handle: '0/0:b', label: { label: 'b' }, collapsibleState: TreeItemCollapsibleState.Collapsed }], (<Array<any>>revealTarget.args[0][2]).map(arg => removeUnsetKeys(arg)));
assert.deepEqual({ select: true, focus: false, expand: false }, revealTarget.args[0][3]);
});
runWithEventMerging((resolve) => {
tree = {
'a': {
'aa': {},
'ac': {}
},
'b': {
'ba': {},
'bb': {}
}
};
onDidChangeTreeNode.fire(getNode('a'));
tree = {
'a': {
'aa': {},
'ac': {}
},
'b': {
'ba': {},
'bc': {}
}
};
onDidChangeTreeNode.fire(getNode('b'));
resolve();
}).then(() => {
return treeView.reveal({ key: 'bc' })
.then(() => {
assert.ok(revealTarget.calledOnce);
assert.deepEqual('treeDataProvider', revealTarget.args[0][0]);
assert.deepEqual({ handle: '0/0:b/0:bc', label: { label: 'bc' }, collapsibleState: TreeItemCollapsibleState.None, parentHandle: '0/0:b' }, removeUnsetKeys(revealTarget.args[0][1]));
assert.deepEqual([{ handle: '0/0:b', label: { label: 'b' }, collapsibleState: TreeItemCollapsibleState.Collapsed }], (<Array<any>>revealTarget.args[0][2]).map(arg => removeUnsetKeys(arg)));
assert.deepEqual({ select: true, focus: false, expand: false }, revealTarget.args[0][3]);
});
});
});
});

View File

@@ -7,6 +7,7 @@ import * as assert from 'assert';
import { URI } from 'vs/base/common/uri';
import * as types from 'vs/workbench/api/common/extHostTypes';
import { isWindows } from 'vs/base/common/platform';
import { assertType } from 'vs/base/common/types';
function assertToJSON(a: any, expected: any) {
const raw = JSON.stringify(a);
@@ -383,33 +384,22 @@ suite('ExtHostTypes', function () {
edit.replace(URI.parse('foo:a'), new types.Range(2, 1, 2, 1), 'bar');
edit.replace(URI.parse('foo:b'), new types.Range(3, 1, 3, 1), 'bazz');
const all = edit._allEntries();
const all = edit.allEntries();
assert.equal(all.length, 4);
function isFileChange(thing: [URI, types.TextEdit[]] | [URI?, URI?, { overwrite?: boolean }?]): thing is [URI?, URI?, { overwrite?: boolean }?] {
const [f, s] = thing;
return URI.isUri(f) && URI.isUri(s);
}
function isTextChange(thing: [URI, types.TextEdit[]] | [URI?, URI?, { overwrite?: boolean }?]): thing is [URI, types.TextEdit[]] {
const [f, s] = thing;
return URI.isUri(f) && Array.isArray(s);
}
const [first, second, third, fourth] = all;
assert.equal(first[0]!.toString(), 'foo:a');
assert.ok(!isFileChange(first));
assert.ok(isTextChange(first) && first[1].length === 1);
assertType(first._type === 2);
assert.equal(first.uri.toString(), 'foo:a');
assert.equal(second[0]!.toString(), 'foo:a');
assert.ok(isFileChange(second));
assertType(second._type === 1);
assert.equal(second.from!.toString(), 'foo:a');
assert.equal(second.to!.toString(), 'foo:b');
assert.equal(third[0]!.toString(), 'foo:a');
assert.ok(isTextChange(third) && third[1].length === 1);
assertType(third._type === 2);
assert.equal(third.uri.toString(), 'foo:a');
assert.equal(fourth[0]!.toString(), 'foo:b');
assert.ok(!isFileChange(fourth));
assert.ok(isTextChange(fourth) && fourth[1].length === 1);
assertType(fourth._type === 2);
assert.equal(fourth.uri.toString(), 'foo:b');
});
test('WorkspaceEdit - two edits for one resource', function () {
@@ -418,10 +408,13 @@ suite('ExtHostTypes', function () {
edit.insert(uri, new types.Position(0, 0), 'Hello');
edit.insert(uri, new types.Position(0, 0), 'Foo');
assert.equal(edit._allEntries().length, 2);
let [first, second] = edit._allEntries();
assert.equal((first as [URI, types.TextEdit[]])[1][0].newText, 'Hello');
assert.equal((second as [URI, types.TextEdit[]])[1][0].newText, 'Foo');
assert.equal(edit.allEntries().length, 2);
let [first, second] = edit.allEntries();
assertType(first._type === 2);
assertType(second._type === 2);
assert.equal(first.edit.newText, 'Hello');
assert.equal(second.edit.newText, 'Foo');
});
test('DocumentLink', () => {

View File

@@ -10,7 +10,7 @@ import { TestConfigurationService } from 'vs/platform/configuration/test/common/
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
import { TestCodeEditorService } from 'vs/editor/test/browser/editorTestServices';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { ExtHostDocumentsAndEditorsShape, ExtHostContext, ExtHostDocumentsShape } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostDocumentsAndEditorsShape, ExtHostContext, ExtHostDocumentsShape, IWorkspaceTextEditDto } from 'vs/workbench/api/common/extHost.protocol';
import { mock } from 'vs/workbench/test/electron-browser/api/mock';
import { Event } from 'vs/base/common/event';
import { MainThreadTextEditors } from 'vs/workbench/api/browser/mainThreadEditors';
@@ -20,7 +20,6 @@ import { Position } from 'vs/editor/common/core/position';
import { IModelService } from 'vs/editor/common/services/modelService';
import { EditOperation } from 'vs/editor/common/core/editOperation';
import { TestFileService, TestEditorService, TestEditorGroupsService, TestEnvironmentService, TestContextService, TestTextResourcePropertiesService } from 'vs/workbench/test/workbenchTestServices';
import { WorkspaceTextEdit } from 'vs/editor/common/modes';
import { BulkEditService } from 'vs/workbench/services/bulkEdit/browser/bulkEditService';
import { NullLogService } from 'vs/platform/log/common/log';
import { ITextModelService, IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService';
@@ -141,13 +140,13 @@ suite('MainThreadEditors', () => {
let model = modelService.createModel('something', null, resource);
let workspaceResourceEdit: WorkspaceTextEdit = {
let workspaceResourceEdit: IWorkspaceTextEditDto = {
resource: resource,
modelVersionId: model.getVersionId(),
edits: [{
edit: {
text: 'asdfg',
range: new Range(1, 1, 1, 1)
}]
}
};
// Act as if the user edited the model
@@ -162,21 +161,21 @@ suite('MainThreadEditors', () => {
let model = modelService.createModel('something', null, resource);
let workspaceResourceEdit1: WorkspaceTextEdit = {
let workspaceResourceEdit1: IWorkspaceTextEditDto = {
resource: resource,
modelVersionId: model.getVersionId(),
edits: [{
edit: {
text: 'asdfg',
range: new Range(1, 1, 1, 1)
}]
}
};
let workspaceResourceEdit2: WorkspaceTextEdit = {
let workspaceResourceEdit2: IWorkspaceTextEditDto = {
resource: resource,
modelVersionId: model.getVersionId(),
edits: [{
edit: {
text: 'asdfg',
range: new Range(1, 1, 1, 1)
}]
}
};
let p1 = editors.$tryApplyWorkspaceEdit({ edits: [workspaceResourceEdit1] }).then((result) => {