From 85c5b50ce7f600e7d621f1b817258a0fbddeecb1 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 1 May 2020 16:04:05 -0500 Subject: [PATCH 01/17] Distinguish a user removing a row from 'clear' in search Fix #91901 --- .../contrib/search/browser/searchActions.ts | 2 +- .../contrib/search/common/searchModel.ts | 37 ++++++++++--------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/searchActions.ts b/src/vs/workbench/contrib/search/browser/searchActions.ts index 96c16f7b7e397..034134ea9b42b 100644 --- a/src/vs/workbench/contrib/search/browser/searchActions.ts +++ b/src/vs/workbench/contrib/search/browser/searchActions.ts @@ -615,7 +615,7 @@ export class RemoveAction extends AbstractSearchAndReplaceAction { this.viewer.setFocus([nextFocusElement], getSelectionKeyboardEvent()); } - this.element.parent().remove(this.element); + this.element.parent().remove(this.element, true); this.viewer.domFocus(); return Promise.resolve(); diff --git a/src/vs/workbench/contrib/search/common/searchModel.ts b/src/vs/workbench/contrib/search/common/searchModel.ts index dca420558a9b4..cfe4f7c54ba51 100644 --- a/src/vs/workbench/contrib/search/common/searchModel.ts +++ b/src/vs/workbench/contrib/search/common/searchModel.ts @@ -192,8 +192,8 @@ export class FileMatch extends Disposable implements IFileMatch { return (selected ? FileMatch._CURRENT_FIND_MATCH : FileMatch._FIND_MATCH); } - private _onChange = this._register(new Emitter<{ didRemove?: boolean; forceUpdateModel?: boolean }>()); - readonly onChange: Event<{ didRemove?: boolean; forceUpdateModel?: boolean }> = this._onChange.event; + private _onChange = this._register(new Emitter<{ didRemove?: boolean; forceUpdateModel?: boolean; userRemoved?: boolean }>()); + readonly onChange: Event<{ didRemove?: boolean; forceUpdateModel?: boolean; userRemoved?: boolean }> = this._onChange.event; private _onDispose = this._register(new Emitter()); readonly onDispose: Event = this._onDispose.event; @@ -354,10 +354,10 @@ export class FileMatch extends Disposable implements IFileMatch { return values(this._matches); } - remove(match: Match): void { + remove(match: Match, userRemoved?: boolean): void { this.removeMatch(match); this._removedMatches.add(match.id()); - this._onChange.fire({ didRemove: true }); + this._onChange.fire({ didRemove: true, userRemoved }); } replace(toReplace: Match): Promise { @@ -447,6 +447,7 @@ export interface IChangeEvent { elements: FileMatch[]; added?: boolean; removed?: boolean; + userRemoved?: boolean; } export class FolderMatch extends Disposable { @@ -529,7 +530,7 @@ export class FolderMatch extends Disposable { const fileMatch = this.instantiationService.createInstance(FileMatch, this._query.contentPattern, this._query.previewOptions, this._query.maxResults, this, rawFileMatch); this.doAdd(fileMatch); added.push(fileMatch); - const disposable = fileMatch.onChange(({ didRemove }) => this.onFileChange(fileMatch, didRemove)); + const disposable = fileMatch.onChange(({ didRemove, userRemoved }) => this.onFileChange(fileMatch, didRemove, userRemoved)); fileMatch.onDispose(() => disposable.dispose()); } }); @@ -540,14 +541,14 @@ export class FolderMatch extends Disposable { } } - clear(): void { + clear(userRemoved?: boolean): void { const changed: FileMatch[] = this.matches(); this.disposeMatches(); - this._onChange.fire({ elements: changed, removed: true }); + this._onChange.fire({ elements: changed, removed: true, userRemoved }); } - remove(matches: FileMatch | FileMatch[]): void { - this.doRemove(matches); + remove(matches: FileMatch | FileMatch[], userRemoved?: boolean): void { + this.doRemove(matches, undefined, undefined, userRemoved); } replace(match: FileMatch): Promise { @@ -577,7 +578,7 @@ export class FolderMatch extends Disposable { return this.matches().reduce((prev, match) => prev + match.count(), 0); } - private onFileChange(fileMatch: FileMatch, removed = false): void { + private onFileChange(fileMatch: FileMatch, removed = false, userRemoved = false): void { let added = false; if (!this._fileMatches.has(fileMatch.resource)) { this.doAdd(fileMatch); @@ -589,7 +590,7 @@ export class FolderMatch extends Disposable { removed = true; } if (!this._replacingAll) { - this._onChange.fire({ elements: [fileMatch], added: added, removed: removed }); + this._onChange.fire({ elements: [fileMatch], added: added, removed: removed, userRemoved }); } } @@ -600,7 +601,7 @@ export class FolderMatch extends Disposable { } } - private doRemove(fileMatches: FileMatch | FileMatch[], dispose: boolean = true, trigger: boolean = true): void { + private doRemove(fileMatches: FileMatch | FileMatch[], dispose: boolean = true, trigger: boolean = true, userRemoved: boolean = false): void { if (!Array.isArray(fileMatches)) { fileMatches = [fileMatches]; } @@ -615,7 +616,7 @@ export class FolderMatch extends Disposable { } if (trigger) { - this._onChange.fire({ elements: fileMatches, removed: true }); + this._onChange.fire({ elements: fileMatches, removed: true, userRemoved }); } } @@ -717,7 +718,7 @@ export class SearchResult extends Disposable { this._register(this.modelService.onModelAdded(model => this.onModelAdded(model))); this._register(this.onChange(e => { - if (e.removed) { + if (e.userRemoved) { this._hasRemovedResults = true; } })); @@ -808,14 +809,14 @@ export class SearchResult extends Disposable { this._otherFilesMatch = null; } - remove(matches: FileMatch | FolderMatch | (FileMatch | FolderMatch)[]): void { + remove(matches: FileMatch | FolderMatch | (FileMatch | FolderMatch)[], userRemoved?: boolean): void { if (!Array.isArray(matches)) { matches = [matches]; } matches.forEach(m => { if (m instanceof FolderMatch) { - m.clear(); + m.clear(userRemoved); } }); @@ -827,11 +828,11 @@ export class SearchResult extends Disposable { return; } - this.getFolderMatch(matches[0].resource).remove(matches); + this.getFolderMatch(matches[0].resource).remove(matches, userRemoved); }); if (other.length) { - this.getFolderMatch(other[0].resource).remove(other); + this.getFolderMatch(other[0].resource).remove(other, userRemoved); } } From d07ffbccb997ac718fce41ed356d234001f410db Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 1 May 2020 16:52:56 -0500 Subject: [PATCH 02/17] Fix searchResult tests --- .../contrib/search/test/common/searchResult.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/search/test/common/searchResult.test.ts b/src/vs/workbench/contrib/search/test/common/searchResult.test.ts index f46f158ac2931..a82b823eb96c7 100644 --- a/src/vs/workbench/contrib/search/test/common/searchResult.test.ts +++ b/src/vs/workbench/contrib/search/test/common/searchResult.test.ts @@ -236,7 +236,7 @@ suite('SearchResult', () => { testObject.remove(objectToRemove); assert.ok(target.calledOnce); - assert.deepEqual([{ elements: [objectToRemove], removed: true }], target.args[0]); + assert.deepEqual([{ elements: [objectToRemove], removed: true, userRemoved: false }], target.args[0]); }); test('remove array triggers change event', function () { @@ -253,7 +253,7 @@ suite('SearchResult', () => { testObject.remove(arrayToRemove); assert.ok(target.calledOnce); - assert.deepEqual([{ elements: arrayToRemove, removed: true }], target.args[0]); + assert.deepEqual([{ elements: arrayToRemove, removed: true, userRemoved: false }], target.args[0]); }); test('remove triggers change event', function () { @@ -268,7 +268,7 @@ suite('SearchResult', () => { testObject.remove(objectToRemove); assert.ok(target.calledOnce); - assert.deepEqual([{ elements: [objectToRemove], removed: true }], target.args[0]); + assert.deepEqual([{ elements: [objectToRemove], removed: true, userRemoved: false }], target.args[0]); }); test('Removing all line matches and adding back will add file back to result', function () { @@ -315,7 +315,7 @@ suite('SearchResult', () => { return voidPromise.then(() => { assert.ok(target.calledOnce); - assert.deepEqual([{ elements: [objectToRemove], removed: true }], target.args[0]); + assert.deepEqual([{ elements: [objectToRemove], removed: true, userRemoved: false }], target.args[0]); }); }); From 69eb0320a1ec9dc987cad893bc1513c03167bf5b Mon Sep 17 00:00:00 2001 From: Robo Date: Fri, 1 May 2020 23:54:33 -0700 Subject: [PATCH 03/17] chore: bump electron@7.2.4 (#96819) --- .yarnrc | 2 +- cgmanifest.json | 4 ++-- package.json | 2 +- src/vs/platform/menubar/electron-main/menubar.ts | 3 ++- yarn.lock | 8 ++++---- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.yarnrc b/.yarnrc index c3c11fbeb9198..d86b284e83e63 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1,3 +1,3 @@ disturl "https://atom.io/download/electron" -target "7.2.2" +target "7.2.4" runtime "electron" diff --git a/cgmanifest.json b/cgmanifest.json index 2d5e8a2d66cb4..09478ca403e6a 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -60,12 +60,12 @@ "git": { "name": "electron", "repositoryUrl": "https://github.com/electron/electron", - "commitHash": "959e80cc53cbebf8eb1d62eb2d14fa8fd86b0394" + "commitHash": "0552e0d5de46ffa3b481d741f1db5c779e201565" } }, "isOnlyProductionDependency": true, "license": "MIT", - "version": "7.2.2" + "version": "7.2.4" }, { "component": { diff --git a/package.json b/package.json index 9b1f739894e2d..8836b634f38c6 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "css-loader": "^3.2.0", "debounce": "^1.0.0", "deemon": "^1.4.0", - "electron": "7.2.2", + "electron": "7.2.4", "eslint": "6.8.0", "eslint-plugin-jsdoc": "^19.1.0", "event-stream": "3.3.4", diff --git a/src/vs/platform/menubar/electron-main/menubar.ts b/src/vs/platform/menubar/electron-main/menubar.ts index 3f26d26785572..dd0251290f285 100644 --- a/src/vs/platform/menubar/electron-main/menubar.ts +++ b/src/vs/platform/menubar/electron-main/menubar.ts @@ -702,7 +702,8 @@ export class Menubar { } // DevTools focused - if (activeWindow.webContents.isDevToolsFocused()) { + if (activeWindow.webContents.isDevToolsFocused() && + activeWindow.webContents.devToolsWebContents) { return contextSpecificHandlers.inDevTools(activeWindow.webContents.devToolsWebContents); } diff --git a/yarn.lock b/yarn.lock index b9aa69f6d4026..19b82930df933 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2715,10 +2715,10 @@ electron-to-chromium@^1.2.7: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.27.tgz#78ecb8a399066187bb374eede35d9c70565a803d" integrity sha1-eOy4o5kGYYe7N07t412ccFZagD0= -electron@7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/electron/-/electron-7.2.2.tgz#92b159fa6e6c31dfcfe0c2818c7baacb81fa1c5f" - integrity sha512-8ppCjch2LRbi5JJ9D+gn+Q9erShNLDcN5ODRAPr/MAHqhTTlGBqCcvNMlCzRCEVV75PouKxVm7NjSKXBYlD9QA== +electron@7.2.4: + version "7.2.4" + resolved "https://registry.yarnpkg.com/electron/-/electron-7.2.4.tgz#9fc0446dae23ead897af8742470cb18da55c6ce9" + integrity sha512-Z+R692uTzXgP8AHrabE+kkrMlQJ6pnAYoINenwj9QSqaD2YbO8IuXU9DMCcUY0+VpA91ee09wFZJNUKYPMnCKg== dependencies: "@electron/get" "^1.0.1" "@types/node" "^12.0.12" From d40b8987aa16a70eaf0df5c8b83a01d95028ee94 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Sun, 3 May 2020 14:41:06 +0200 Subject: [PATCH 04/17] scope sync state per workspace in web --- .../services/environment/browser/environmentService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts index e92f3c1dbc07a..16da86c4af1f4 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts @@ -115,7 +115,7 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment get snippetsHome(): URI { return joinPath(this.userRoamingDataHome, 'snippets'); } @memoize - get userDataSyncHome(): URI { return joinPath(this.userRoamingDataHome, 'sync'); } + get userDataSyncHome(): URI { return joinPath(this.userRoamingDataHome, 'sync', this.options.workspaceId); } @memoize get userDataSyncLogResource(): URI { return joinPath(this.options.logsPath, 'userDataSync.log'); } From 8b2ee1bf53d056224d139f1baca017ccb573dd1b Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 4 May 2020 09:24:25 +0200 Subject: [PATCH 05/17] add comment why sync state should be scoped --- .../services/environment/browser/environmentService.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts index 16da86c4af1f4..5ef5e22577d8f 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts @@ -114,6 +114,11 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment @memoize get snippetsHome(): URI { return joinPath(this.userRoamingDataHome, 'snippets'); } + /* + * In Web every workspace can potentially have scoped user-data and/or extensions and if Sync state is shared then it can make + * Sync error prone - say removing extensions from another workspace. Hence scope Sync state per workspace. + * Sync scoped to a workspace is capable of handling even if workspaces/windows share same user data and extensions. + */ @memoize get userDataSyncHome(): URI { return joinPath(this.userRoamingDataHome, 'sync', this.options.workspaceId); } From c2873850fb3eba53888f41d1f2bbce7a4f832f8d Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 4 May 2020 09:37:57 +0200 Subject: [PATCH 06/17] update comment --- .../services/environment/browser/environmentService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts index 5ef5e22577d8f..7ed6e9e21ada2 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts @@ -117,7 +117,7 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment /* * In Web every workspace can potentially have scoped user-data and/or extensions and if Sync state is shared then it can make * Sync error prone - say removing extensions from another workspace. Hence scope Sync state per workspace. - * Sync scoped to a workspace is capable of handling even if workspaces/windows share same user data and extensions. + * Sync scoped to a workspace is capable of handling opening same workspace in multiple windows. */ @memoize get userDataSyncHome(): URI { return joinPath(this.userRoamingDataHome, 'sync', this.options.workspaceId); } From fd5d9a30259bb2bebab3e62dfd8315c2e1b27744 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 4 May 2020 10:22:49 +0200 Subject: [PATCH 07/17] editor groups - resolve #96725 (#96820) --- src/vs/workbench/common/editor/editorGroup.ts | 2 +- .../browser/parts/editor/editorGroups.test.ts | 44 +++++++++++++++++-- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/common/editor/editorGroup.ts b/src/vs/workbench/common/editor/editorGroup.ts index 78d6a8400bec6..4ab6ba247e3c6 100644 --- a/src/vs/workbench/common/editor/editorGroup.ts +++ b/src/vs/workbench/common/editor/editorGroup.ts @@ -662,7 +662,7 @@ export class EditorGroup extends Disposable { return null; })); - this.mru = data.mru.map(i => this.editors[i]); + this.mru = coalesce(data.mru.map(i => this.editors[i])); this.active = this.mru[0]; diff --git a/src/vs/workbench/test/browser/parts/editor/editorGroups.test.ts b/src/vs/workbench/test/browser/parts/editor/editorGroups.test.ts index f8e3f5e90a51b..9888760e450cd 100644 --- a/src/vs/workbench/test/browser/parts/editor/editorGroups.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editorGroups.test.ts @@ -145,11 +145,18 @@ interface ISerializedTestInput { class TestEditorInputFactory implements IEditorInputFactory { + static disableSerialize = false; + static disableDeserialize = false; + canSerialize(editorInput: EditorInput): boolean { return true; } - serialize(editorInput: EditorInput): string { + serialize(editorInput: EditorInput): string | undefined { + if (TestEditorInputFactory.disableSerialize) { + return undefined; + } + let testEditorInput = editorInput; let testInput: ISerializedTestInput = { id: testEditorInput.id @@ -158,7 +165,11 @@ class TestEditorInputFactory implements IEditorInputFactory { return JSON.stringify(testInput); } - deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): EditorInput { + deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): EditorInput | undefined { + if (TestEditorInputFactory.disableDeserialize) { + return undefined; + } + let testInput: ISerializedTestInput = JSON.parse(serializedEditorInput); return new TestEditorInput(testInput.id); @@ -170,6 +181,9 @@ suite('Workbench editor groups', () => { let disposables: IDisposable[] = []; setup(() => { + TestEditorInputFactory.disableSerialize = false; + TestEditorInputFactory.disableDeserialize = false; + disposables.push(Registry.as(EditorExtensions.EditorInputFactories).registerEditorInputFactory('testEditorInputForGroups', TestEditorInputFactory)); }); @@ -296,18 +310,40 @@ suite('Workbench editor groups', () => { const input2 = input(); const input3 = input(); - // Pinned and Active + // Case 1: inputs can be serialized and deserialized + group.openEditor(input1, { pinned: true, active: true }); group.openEditor(input2, { pinned: true, active: true }); group.openEditor(input3, { pinned: false, active: true }); - const deserialized = createGroup(group.serialize()); + let deserialized = createGroup(group.serialize()); assert.equal(group.id, deserialized.id); assert.equal(deserialized.count, 3); + assert.equal(deserialized.getEditors(EditorsOrder.SEQUENTIAL).length, 3); + assert.equal(deserialized.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 3); assert.equal(deserialized.isPinned(input1), true); assert.equal(deserialized.isPinned(input2), true); assert.equal(deserialized.isPinned(input3), false); assert.equal(deserialized.isActive(input3), true); + + // Case 2: inputs cannot be serialized + TestEditorInputFactory.disableSerialize = true; + + deserialized = createGroup(group.serialize()); + assert.equal(group.id, deserialized.id); + assert.equal(deserialized.count, 0); + assert.equal(deserialized.getEditors(EditorsOrder.SEQUENTIAL).length, 0); + assert.equal(deserialized.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 0); + + // Case 3: inputs cannot be deserialized + TestEditorInputFactory.disableSerialize = false; + TestEditorInputFactory.disableDeserialize = true; + + deserialized = createGroup(group.serialize()); + assert.equal(group.id, deserialized.id); + assert.equal(deserialized.count, 0); + assert.equal(deserialized.getEditors(EditorsOrder.SEQUENTIAL).length, 0); + assert.equal(deserialized.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 0); }); test('One Editor', function () { From 4229a3fc3f12d6252be2cd44fe63b95b6c34236e Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 4 May 2020 12:02:27 +0200 Subject: [PATCH 08/17] Fixes #96664: Accept `number[]` besides `Uint32Array` for semantic tokens --- .../api/common/extHostLanguageFeatures.ts | 48 ++++++++++++++++--- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 26084cfab8caa..35273ba1a37d4 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -7,7 +7,7 @@ import { URI, UriComponents } from 'vs/base/common/uri'; import { mixin } from 'vs/base/common/objects'; import type * as vscode from 'vscode'; import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters'; -import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, DocumentSymbol, SemanticTokensEdits } from 'vs/workbench/api/common/extHostTypes'; +import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, DocumentSymbol, SemanticTokensEdits, SemanticTokens, SemanticTokensEdit } from 'vs/workbench/api/common/extHostTypes'; import { ISingleEditOperation } from 'vs/editor/common/model'; import * as modes from 'vs/editor/common/modes'; import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments'; @@ -676,6 +676,13 @@ class SemanticTokensPreviousResult { ) { } } +type RelaxedSemanticTokens = { readonly resultId?: string; readonly data: number[]; }; +type RelaxedSemanticTokensEdit = { readonly start: number; readonly deleteCount: number; readonly data?: number[]; }; +type RelaxedSemanticTokensEdits = { readonly resultId?: string; readonly edits: RelaxedSemanticTokensEdit[]; }; + +type ProvidedSemanticTokens = vscode.SemanticTokens | RelaxedSemanticTokens; +type ProvidedSemanticTokensEdits = vscode.SemanticTokensEdits | RelaxedSemanticTokensEdits; + export class DocumentSemanticTokensAdapter { private readonly _previousResults: Map; @@ -696,13 +703,14 @@ export class DocumentSemanticTokensAdapter { return this._provider.provideDocumentSemanticTokensEdits(doc, previousResult.resultId, token); } return this._provider.provideDocumentSemanticTokens(doc, token); - }).then(value => { + }).then((value: ProvidedSemanticTokens | ProvidedSemanticTokensEdits | null | undefined) => { if (previousResult) { this._previousResults.delete(previousResultId); } if (!value) { return null; } + value = DocumentSemanticTokensAdapter._fixProvidedSemanticTokens(value); return this._send(DocumentSemanticTokensAdapter._convertToEdits(previousResult, value), value); }); } @@ -711,12 +719,40 @@ export class DocumentSemanticTokensAdapter { this._previousResults.delete(semanticColoringResultId); } - private static _isSemanticTokens(v: vscode.SemanticTokens | vscode.SemanticTokensEdits): v is vscode.SemanticTokens { - return v && !!((v as vscode.SemanticTokens).data); + private static _fixProvidedSemanticTokens(v: ProvidedSemanticTokens | ProvidedSemanticTokensEdits): vscode.SemanticTokens | vscode.SemanticTokensEdits { + if (DocumentSemanticTokensAdapter._isSemanticTokens(v)) { + if (DocumentSemanticTokensAdapter._isCorrectSemanticTokens(v)) { + return v; + } + return new SemanticTokens(new Uint32Array(v.data), v.resultId); + } else if (DocumentSemanticTokensAdapter._isSemanticTokensEdits(v)) { + if (DocumentSemanticTokensAdapter._isCorrectSemanticTokensEdits(v)) { + return v; + } + return new SemanticTokensEdits(v.edits.map(edit => new SemanticTokensEdit(edit.start, edit.deleteCount, edit.data ? new Uint32Array(edit.data) : edit.data)), v.resultId); + } + return v; + } + + private static _isSemanticTokens(v: ProvidedSemanticTokens | ProvidedSemanticTokensEdits): v is ProvidedSemanticTokens { + return v && !!((v as ProvidedSemanticTokens).data); } - private static _isSemanticTokensEdits(v: vscode.SemanticTokens | vscode.SemanticTokensEdits): v is vscode.SemanticTokensEdits { - return v && Array.isArray((v as vscode.SemanticTokensEdits).edits); + private static _isCorrectSemanticTokens(v: ProvidedSemanticTokens): v is vscode.SemanticTokens { + return (v.data instanceof Uint32Array); + } + + private static _isSemanticTokensEdits(v: ProvidedSemanticTokens | ProvidedSemanticTokensEdits): v is ProvidedSemanticTokensEdits { + return v && Array.isArray((v as ProvidedSemanticTokensEdits).edits); + } + + private static _isCorrectSemanticTokensEdits(v: ProvidedSemanticTokensEdits): v is vscode.SemanticTokensEdits { + for (const edit of v.edits) { + if (!(edit.data instanceof Uint32Array)) { + return false; + } + } + return true; } private static _convertToEdits(previousResult: SemanticTokensPreviousResult | null | undefined, newResult: vscode.SemanticTokens | vscode.SemanticTokensEdits): vscode.SemanticTokens | vscode.SemanticTokensEdits { From 56d9340d285aad4f8b0a10dbb9c40b734277cfb0 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Mon, 4 May 2020 12:10:18 -0700 Subject: [PATCH 09/17] Update onDidChangeTreeData event type, fixes #96932 (#96933) --- src/vs/vscode.d.ts | 2 +- src/vs/workbench/api/common/extHostTreeViews.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index fbec8b1f552f4..479a28c599005 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -7897,7 +7897,7 @@ declare module 'vscode' { * This will trigger the view to update the changed element/root and its children recursively (if shown). * To signal that root has changed, do not pass any argument or pass `undefined` or `null`. */ - onDidChangeTreeData?: Event; + onDidChangeTreeData?: Event; /** * Get [TreeItem](#TreeItem) representation of the `element` diff --git a/src/vs/workbench/api/common/extHostTreeViews.ts b/src/vs/workbench/api/common/extHostTreeViews.ts index f3b43d63036fc..a2e117ad7e515 100644 --- a/src/vs/workbench/api/common/extHostTreeViews.ts +++ b/src/vs/workbench/api/common/extHostTreeViews.ts @@ -153,7 +153,7 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape { } } -type Root = null | undefined; +type Root = null | undefined | void; type TreeData = { message: boolean, element: T | Root | false }; interface TreeNode extends IDisposable { From d4b8ec9da3bf1061a948fbb1b0d9d3db750cc79f Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Mon, 4 May 2020 16:25:35 +0200 Subject: [PATCH 10/17] Make image/dockerfile/dockerComposeFile optional --- .../schemas/devContainer.schema.json | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/extensions/configuration-editing/schemas/devContainer.schema.json b/extensions/configuration-editing/schemas/devContainer.schema.json index 9cb171915fc62..5a69d57057b02 100644 --- a/extensions/configuration-editing/schemas/devContainer.schema.json +++ b/extensions/configuration-editing/schemas/devContainer.schema.json @@ -282,33 +282,42 @@ ] } }, - "allOf": [ + "oneOf": [ { - "oneOf": [ + "allOf": [ { - "allOf": [ + "oneOf": [ { - "oneOf": [ + "allOf": [ { - "$ref": "#/definitions/dockerfileContainer" + "oneOf": [ + { + "$ref": "#/definitions/dockerfileContainer" + }, + { + "$ref": "#/definitions/imageContainer" + } + ] }, { - "$ref": "#/definitions/imageContainer" + "$ref": "#/definitions/nonComposeBase" } ] }, { - "$ref": "#/definitions/nonComposeBase" + "$ref": "#/definitions/composeContainer" } ] }, { - "$ref": "#/definitions/composeContainer" + "$ref": "#/definitions/devContainerCommon" } ] }, { - "$ref": "#/definitions/devContainerCommon" + "type": "object", + "$ref": "#/definitions/devContainerCommon", + "additionalProperties": false } ] } From 96b89dd69c1e77af04c5726f96def177ed7adabf Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 5 May 2020 18:10:06 +0200 Subject: [PATCH 11/17] Fix task instance limit (#97011) Fixes https://github.com/microsoft/vscode/issues/96999 --- .../contrib/tasks/browser/terminalTaskSystem.ts | 1 + src/vs/workbench/contrib/tasks/common/tasks.ts | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts index 7724568c0ff8c..c301d2fdb1108 100644 --- a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts @@ -229,6 +229,7 @@ export class TerminalTaskSystem implements ITaskSystem { } public run(task: Task, resolver: ITaskResolver, trigger: string = Triggers.command): ITaskExecuteResult { + task = task.clone(); // A small amount of task state is stored in the task (instance) and tasks passed in to run may have that set already. const recentTaskKey = task.getRecentlyUsedKey() ?? ''; let validInstance = task.runOptions && task.runOptions.instanceLimit && this.instances[recentTaskKey] && this.instances[recentTaskKey].instances < task.runOptions.instanceLimit; let instance = this.instances[recentTaskKey] ? this.instances[recentTaskKey].instances : 0; diff --git a/src/vs/workbench/contrib/tasks/common/tasks.ts b/src/vs/workbench/contrib/tasks/common/tasks.ts index 71b65beff27dd..754c69442c750 100644 --- a/src/vs/workbench/contrib/tasks/common/tasks.ts +++ b/src/vs/workbench/contrib/tasks/common/tasks.ts @@ -688,6 +688,10 @@ export class CustomTask extends CommonTask { } } + public clone(): CustomTask { + return new CustomTask(this._id, this._source, this._label, this.type, this.command, this.hasDefinedMatchers, this.runOptions, this.configurationProperties); + } + public customizes(): KeyedTaskIdentifier | undefined { if (this._source && this._source.customizes) { return this._source.customizes; @@ -874,6 +878,10 @@ export class ContributedTask extends CommonTask { this.command = command; } + public clone(): ContributedTask { + return new ContributedTask(this._id, this._source, this._label, this.type, this.defines, this.command, this.hasDefinedMatchers, this.runOptions, this.configurationProperties); + } + public getDefinition(): KeyedTaskIdentifier { return this.defines; } @@ -938,6 +946,10 @@ export class InMemoryTask extends CommonTask { this._source = source; } + public clone(): InMemoryTask { + return new InMemoryTask(this._id, this._source, this._label, this.type, this.runOptions, this.configurationProperties); + } + public static is(value: any): value is InMemoryTask { return value instanceof InMemoryTask; } From c56ec34934970db84df4f38500ba79377d5f5e8f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 5 May 2020 11:45:14 -0700 Subject: [PATCH 12/17] Apply scroll area to hover content, not status bar Part of #97016 --- .../workbench/contrib/terminal/browser/widgets/hoverWidget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminal/browser/widgets/hoverWidget.ts b/src/vs/workbench/contrib/terminal/browser/widgets/hoverWidget.ts index 40a9a34ee0bff..004d554f843e5 100644 --- a/src/vs/workbench/contrib/terminal/browser/widgets/hoverWidget.ts +++ b/src/vs/workbench/contrib/terminal/browser/widgets/hoverWidget.ts @@ -93,7 +93,7 @@ export class HoverWidget extends Widget { const actionsElement = $('div.actions'); this._actions.forEach(action => this._renderAction(actionsElement, action)); statusBarElement.appendChild(actionsElement); - this._domNode.appendChild(statusBarElement); + this._containerDomNode.appendChild(statusBarElement); } this._mouseTracker = new CompositeMouseTracker([this._containerDomNode, ..._target.targetElements]); From d69a79b73808559a91206d73d7717ff5f798f23c Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 5 May 2020 14:48:19 -0700 Subject: [PATCH 13/17] Force custom editors in diff view to have 100% height wrappers (#96969) Fix for #96968 This is a scoped fix for #96968. The cause of the issue is the following: 1. Webview must be rendered outside of the main editor DOM. We do this by absolutely positioning them over some element in the DOM. 1. In split views, we try to lay the webview out over an element that has 0 height. 1. Due to my workaround in ea07e9bbdc598480dadfd1297e9e817e40802bce, this causes the webview to either not show at all (because it also will have zero height) or partially show This fix forces the webivew's parent in the split view to have 100%. That actually seems like a reasonable default but I've scoped my fix to just webviews --- .../contrib/webview/browser/dynamicWebviewEditorOverlay.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts b/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts index c8396d281d749..27d56ce2dc55f 100644 --- a/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts +++ b/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts @@ -97,6 +97,12 @@ export class DynamicWebviewEditorOverlay extends Disposable implements WebviewOv if (!this.container || !this.container.parentElement) { return; } + + // Workaround for #94805 + if ((element.classList.contains('details-editor-container') || element.classList.contains('master-editor-container')) && !element.style.height) { + element.style.height = '100%'; + } + const frameRect = element.getBoundingClientRect(); const containerRect = this.container.parentElement.getBoundingClientRect(); this.container.style.position = 'absolute'; From a480e4304acc2180e5f2e07833880ffc532c7425 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 8 May 2020 08:54:37 -0500 Subject: [PATCH 14/17] Fix #97192 - delete bad setting validation --- .../services/preferences/common/preferencesValidation.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/services/preferences/common/preferencesValidation.ts b/src/vs/workbench/services/preferences/common/preferencesValidation.ts index 9a1080649a6aa..56edf974a3b91 100644 --- a/src/vs/workbench/services/preferences/common/preferencesValidation.ts +++ b/src/vs/workbench/services/preferences/common/preferencesValidation.ts @@ -69,7 +69,6 @@ export function getInvalidTypeError(value: any, type: undefined | string | strin (valueType === 'boolean' && !canBeType(typeArr, 'boolean')) || (valueType === 'object' && !canBeType(typeArr, 'object', 'null', 'array')) || (valueType === 'string' && !canBeType(typeArr, 'string', 'number', 'integer')) || - (typeof parseFloat(value) === 'number' && !isNaN(parseFloat(value)) && !canBeType(typeArr, 'number', 'integer')) || (Array.isArray(value) && !canBeType(typeArr, 'array')) ) { if (typeof type !== 'undefined') { From 01a97826ce166e36d9648209c9837ffcc350e6c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 11 May 2020 13:53:57 +0100 Subject: [PATCH 15/17] fixes #97199 (#97487) --- src/vs/code/electron-browser/proxy/auth.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/code/electron-browser/proxy/auth.html b/src/vs/code/electron-browser/proxy/auth.html index 5ef195878cafc..76d22eb491a57 100644 --- a/src/vs/code/electron-browser/proxy/auth.html +++ b/src/vs/code/electron-browser/proxy/auth.html @@ -5,7 +5,7 @@ + content="default-src 'none'; img-src 'self' https: data:; media-src 'none'; child-src 'self'; object-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; connect-src 'self' https:; font-src 'self' https:;">