From 669e5c578c94842a423bb72bc04c018fa71afa5e Mon Sep 17 00:00:00 2001 From: weartist Date: Thu, 1 Jun 2023 09:40:34 +0800 Subject: [PATCH 001/128] adjust to correct link --- extensions/npm/src/tasks.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/npm/src/tasks.ts b/extensions/npm/src/tasks.ts index 7bd6b1a2b14..17bb815f962 100644 --- a/extensions/npm/src/tasks.ts +++ b/extensions/npm/src/tasks.ts @@ -140,7 +140,7 @@ export async function getPackageManager(extensionContext: ExtensionContext, fold window.showInformationMessage(multiplePMWarning, learnMore, neverShowAgain).then(result => { switch (result) { case neverShowAgain: extensionContext.globalState.update(neverShowWarning, true); break; - case learnMore: env.openExternal(Uri.parse('https://nodejs.dev/learn/the-package-lock-json-file')); + case learnMore: env.openExternal(Uri.parse('https://docs.npmjs.com/cli/v9/configuring-npm/package-lock-json')); } }); } From 7ab2d5169aa771b1ddf8858ff897a0994afdcdfe Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Wed, 7 Jun 2023 09:42:01 +0200 Subject: [PATCH 002/128] initial code --- .../interactiveEditor/browser/interactiveEditorWidget.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorWidget.ts b/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorWidget.ts index d89df5c9d9e..7f0e5458b51 100644 --- a/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorWidget.ts +++ b/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorWidget.ts @@ -763,6 +763,10 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { protected override _doLayout(heightInPixel: number): void { const info = this.editor.getLayoutInfo(); + if (this.position) { + const lineIndentColumn = this.editor._getViewModel()?.getLineIndentColumn(this.position.lineNumber); + console.log('lineIndentColumn', lineIndentColumn); + } const spaceLeft = info.lineNumbersWidth + info.glyphMarginWidth + info.decorationsWidth; const spaceRight = info.minimap.minimapWidth + info.verticalScrollbarWidth; From d25a4bff9eab0309e890a0cdd47b2ad20e376d2c Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Wed, 7 Jun 2023 12:19:54 +0200 Subject: [PATCH 003/128] cleaning the code, using only an approximate indentation width --- .../browser/interactiveEditorWidget.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorWidget.ts b/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorWidget.ts index 7f0e5458b51..bc75cfc582b 100644 --- a/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorWidget.ts +++ b/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorWidget.ts @@ -763,11 +763,7 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { protected override _doLayout(heightInPixel: number): void { const info = this.editor.getLayoutInfo(); - if (this.position) { - const lineIndentColumn = this.editor._getViewModel()?.getLineIndentColumn(this.position.lineNumber); - console.log('lineIndentColumn', lineIndentColumn); - } - const spaceLeft = info.lineNumbersWidth + info.glyphMarginWidth + info.decorationsWidth; + const spaceLeft = info.lineNumbersWidth + info.glyphMarginWidth + info.decorationsWidth + (this._findApproximateIndentationWidth() ?? 0); const spaceRight = info.minimap.minimapWidth + info.verticalScrollbarWidth; const maxWidth = !this.widget.showsAnyPreview() ? 640 : Number.MAX_SAFE_INTEGER; @@ -779,6 +775,17 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { this.widget.layout(this._dimension); } + private _findApproximateIndentationWidth(): number | undefined { + if (!this.position) { + return; + } + const lineIndentColumn = this.editor._getViewModel()?.getLineIndentColumn(this.position.lineNumber); + if (!lineIndentColumn) { + return; + } + return (lineIndentColumn - 1) * this.editor.getOption(EditorOption.fontSize); + } + private _computeHeightInLines(): number { const lineHeight = this.editor.getOption(EditorOption.lineHeight); return this.widget.getHeight() / lineHeight; From 1c22e0e8c55c6b06904822e2befae5b026821bb7 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Wed, 7 Jun 2023 17:12:08 +0200 Subject: [PATCH 004/128] code after review --- .../browser/inlineChatController.ts | 4 +- .../inlineChat/browser/inlineChatWidget.ts | 42 ++++++++++--------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 8b41fc56def..d883e5170a6 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -269,7 +269,7 @@ export class InteractiveEditorController implements IEditorContribution { this._zone.value.widget.placeholder = this._getPlaceholderText(); this._zone.value.widget.value = this._activeSession.lastInput ?? ''; this._zone.value.widget.updateInfo(this._activeSession.session.message ?? localize('welcome.1', "AI-generated code may be incorrect")); - this._zone.value.show(this._activeSession.wholeRange.value.getEndPosition()); + this._zone.value.show(this._activeSession.wholeRange.value); this._zone.value.widget.preferredExpansionState = this._activeSession.lastExpansionState; this._sessionStore.add(this._editor.onDidChangeModel((e) => { @@ -359,7 +359,7 @@ export class InteractiveEditorController implements IEditorContribution { assertType(this._activeSession); this._zone.value.widget.placeholder = this._getPlaceholderText(); - this._zone.value.show(this._activeSession.wholeRange.value.getEndPosition()); + this._zone.value.show(this._activeSession.wholeRange.value); if (options?.message) { this._zone.value.widget.value = options?.message; diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index 4ac76d56350..0a4770fc338 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -26,7 +26,7 @@ import { EmbeddedCodeEditorWidget, EmbeddedDiffEditorWidget } from 'vs/editor/br import { HiddenItemStrategy, MenuWorkbenchToolBar } from 'vs/platform/actions/browser/toolbar'; import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; import { SuggestController } from 'vs/editor/contrib/suggest/browser/suggestController'; -import { IPosition, Position } from 'vs/editor/common/core/position'; +import { Position } from 'vs/editor/common/core/position'; import { DEFAULT_FONT_FAMILY } from 'vs/workbench/browser/style'; import { DropdownWithDefaultActionViewItem, IMenuEntryActionViewItemOptions, MenuEntryActionViewItem, createActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { CompletionItem, CompletionItemInsertTextRule, CompletionItemKind, CompletionItemProvider, CompletionList, ProviderResult, TextEdit } from 'vs/editor/common/languages'; @@ -763,29 +763,13 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { protected override _doLayout(heightInPixel: number): void { const info = this.editor.getLayoutInfo(); - const spaceLeft = info.lineNumbersWidth + info.glyphMarginWidth + info.decorationsWidth + (this._findApproximateIndentationWidth() ?? 0); - const spaceRight = info.minimap.minimapWidth + info.verticalScrollbarWidth; - const maxWidth = !this.widget.showsAnyPreview() ? 640 : Number.MAX_SAFE_INTEGER; const width = Math.min(maxWidth, info.contentWidth - (info.glyphMarginWidth + info.decorationsWidth)); this._dimension = new Dimension(width, heightInPixel); - this.widget.domNode.style.marginLeft = `${spaceLeft}px`; - this.widget.domNode.style.marginRight = `${spaceRight}px`; this.widget.domNode.style.width = `${width}px`; this.widget.layout(this._dimension); } - private _findApproximateIndentationWidth(): number | undefined { - if (!this.position) { - return; - } - const lineIndentColumn = this.editor._getViewModel()?.getLineIndentColumn(this.position.lineNumber); - if (!lineIndentColumn) { - return; - } - return (lineIndentColumn - 1) * this.editor.getOption(EditorOption.fontSize); - } - private _computeHeightInLines(): number { const lineHeight = this.editor.getOption(EditorOption.lineHeight); return this.widget.getHeight() / lineHeight; @@ -798,10 +782,30 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { super._relayout(this._computeHeightInLines()); } - override show(where: IPosition): void { - super.show(where, this._computeHeightInLines()); + override show(selectionRange: Range): void { + super.show(selectionRange.getEndPosition(), this._computeHeightInLines()); this.widget.focus(); this._ctxVisible.set(true); + this._setMargins(selectionRange); + } + + private _setMargins(selectionRange: Range): void { + const info = this.editor.getLayoutInfo(); + const startLineNumber = selectionRange.getStartPosition().lineNumber; + const endLineNumber = selectionRange.getEndPosition().lineNumber; + let lineNumberForIndentation = endLineNumber; + for (let lineNumber = endLineNumber; lineNumber >= startLineNumber; lineNumber--) { + const lineContent = this.editor.getModel()?.getLineContent(lineNumber); + if (lineContent !== '') { + lineNumberForIndentation = lineNumber; + break; + } + } + const indentationLevel = this.editor._getViewModel()?.getLineFirstNonWhitespaceColumn(lineNumberForIndentation); + const spaceLeft = info.lineNumbersWidth + info.glyphMarginWidth + info.decorationsWidth + (indentationLevel ? this.editor.getOffsetForColumn(lineNumberForIndentation, indentationLevel) : 0); + const spaceRight = info.minimap.minimapWidth + info.verticalScrollbarWidth; + this.widget.domNode.style.marginLeft = `${spaceLeft}px`; + this.widget.domNode.style.marginRight = `${spaceRight}px`; } override hide(): void { From a4505ae392a5fa74830a3041923b34e81c6df67c Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Wed, 7 Jun 2023 17:16:20 +0200 Subject: [PATCH 005/128] checking that lineContent is defined first --- src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index 0a4770fc338..7eab018b327 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -796,7 +796,7 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { let lineNumberForIndentation = endLineNumber; for (let lineNumber = endLineNumber; lineNumber >= startLineNumber; lineNumber--) { const lineContent = this.editor.getModel()?.getLineContent(lineNumber); - if (lineContent !== '') { + if (lineContent && lineContent !== '') { lineNumberForIndentation = lineNumber; break; } From 09b41bea74c9aaa1b899755bac147488cee5e69e Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Thu, 8 Jun 2023 12:19:51 +0200 Subject: [PATCH 006/128] review changes --- .../inlineChat/browser/inlineChatWidget.ts | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index 7eab018b327..c08a9849965 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -183,6 +183,7 @@ export class InteractiveEditorWidget { private _isLayouting: boolean = false; private _preferredExpansionState: ExpansionState | undefined; private _expansionState: ExpansionState = ExpansionState.NOT_CROPPED; + private _indentationWidth: number = 0; constructor( private readonly parentEditor: ICodeEditor, @@ -464,6 +465,14 @@ export class InteractiveEditorWidget { this._preferredExpansionState = expansionState; } + set indentationWidth(indentationWidth: number) { + this._indentationWidth = indentationWidth; + } + + get indentationWidth(): number { + return this._indentationWidth; + } + updateMarkdownMessage(message: Node | undefined) { this._elements.markdownMessage.classList.toggle('hidden', !message); let expansionState: ExpansionState; @@ -764,7 +773,7 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { const info = this.editor.getLayoutInfo(); const maxWidth = !this.widget.showsAnyPreview() ? 640 : Number.MAX_SAFE_INTEGER; - const width = Math.min(maxWidth, info.contentWidth - (info.glyphMarginWidth + info.decorationsWidth)); + const width = Math.min(maxWidth, info.contentWidth - (info.glyphMarginWidth + info.decorationsWidth + this.widget.indentationWidth)); this._dimension = new Dimension(width, heightInPixel); this.widget.domNode.style.width = `${width}px`; this.widget.layout(this._dimension); @@ -793,16 +802,19 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { const info = this.editor.getLayoutInfo(); const startLineNumber = selectionRange.getStartPosition().lineNumber; const endLineNumber = selectionRange.getEndPosition().lineNumber; - let lineNumberForIndentation = endLineNumber; + const viewModel = this.editor._getViewModel(); + let indentationLineNumber = endLineNumber; + let indentationLevel = viewModel?.getLineFirstNonWhitespaceColumn(endLineNumber); for (let lineNumber = endLineNumber; lineNumber >= startLineNumber; lineNumber--) { - const lineContent = this.editor.getModel()?.getLineContent(lineNumber); - if (lineContent && lineContent !== '') { - lineNumberForIndentation = lineNumber; + const currentIndentationLevel = viewModel?.getLineFirstNonWhitespaceColumn(lineNumber); + if (currentIndentationLevel && currentIndentationLevel !== 0) { + indentationLineNumber = lineNumber; + indentationLevel = currentIndentationLevel; break; } } - const indentationLevel = this.editor._getViewModel()?.getLineFirstNonWhitespaceColumn(lineNumberForIndentation); - const spaceLeft = info.lineNumbersWidth + info.glyphMarginWidth + info.decorationsWidth + (indentationLevel ? this.editor.getOffsetForColumn(lineNumberForIndentation, indentationLevel) : 0); + this.widget.indentationWidth = (indentationLevel ? this.editor.getOffsetForColumn(indentationLineNumber, indentationLevel) : 0); + const spaceLeft = info.lineNumbersWidth + info.glyphMarginWidth + info.decorationsWidth + this.widget.indentationWidth; const spaceRight = info.minimap.minimapWidth + info.verticalScrollbarWidth; this.widget.domNode.style.marginLeft = `${spaceLeft}px`; this.widget.domNode.style.marginRight = `${spaceRight}px`; From 094052c1e22a58f6ae0311a8b3f72043b2618e86 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Thu, 8 Jun 2023 14:23:51 +0200 Subject: [PATCH 007/128] initial commit --- .../inlineChat/browser/inlineChatStrategies.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts index c4da4e2090d..d57c6e7d862 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts @@ -40,6 +40,8 @@ export abstract class EditModeStrategy { abstract renderChanges(response: EditResponse): Promise; abstract toggleDiff(): void; + + abstract getWidgetPosition(range: Range): Position; } export class PreviewStrategy extends EditModeStrategy { @@ -126,6 +128,10 @@ export class PreviewStrategy extends EditModeStrategy { toggleDiff(): void { // nothing to do } + + getWidgetPosition(range: Range): Position { + throw new Error('not supported'); + } } class InlineDiffDecorations { @@ -318,6 +324,10 @@ export class LiveStrategy extends EditModeStrategy { } this._widget.updateStatus(message); } + + getWidgetPosition(range: Range): Position { + throw new Error('not supported'); + } } export class LivePreviewStrategy extends LiveStrategy { @@ -372,6 +382,10 @@ export class LivePreviewStrategy extends LiveStrategy { } scrollState.restore(this._editor); } + + override getWidgetPosition(range: Range): Position { + throw new Error('not supported'); + } } function showSingleCreateFile(accessor: ServicesAccessor, edit: EditResponse) { From 169c0ed296e45eb47e0d8d4977a77be9a5709c90 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Thu, 8 Jun 2023 15:02:14 +0200 Subject: [PATCH 008/128] extracting the showing into a separate code --- .../inlineChat/browser/inlineChatController.ts | 14 ++++++++++++-- .../contrib/inlineChat/browser/inlineChatWidget.ts | 7 +++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index d883e5170a6..9be2c6c6b23 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -249,6 +249,13 @@ export class InteractiveEditorController implements IEditorContribution { return State.INIT_UI; } + private _showWidget(): void { + assertType(this._activeSession); + const selectionRange = this._activeSession.wholeRange.value; + const position = this._strategy?.getWidgetPosition(selectionRange); + this._zone.value.showWidget(selectionRange, position); + } + private async [State.INIT_UI](options: InteractiveEditorRunOptions | undefined): Promise { assertType(this._activeSession); @@ -269,8 +276,9 @@ export class InteractiveEditorController implements IEditorContribution { this._zone.value.widget.placeholder = this._getPlaceholderText(); this._zone.value.widget.value = this._activeSession.lastInput ?? ''; this._zone.value.widget.updateInfo(this._activeSession.session.message ?? localize('welcome.1', "AI-generated code may be incorrect")); - this._zone.value.show(this._activeSession.wholeRange.value); this._zone.value.widget.preferredExpansionState = this._activeSession.lastExpansionState; + console.log('before show of the init ui'); + this._showWidget(); this._sessionStore.add(this._editor.onDidChangeModel((e) => { const msg = this._activeSession?.lastExchange @@ -359,7 +367,9 @@ export class InteractiveEditorController implements IEditorContribution { assertType(this._activeSession); this._zone.value.widget.placeholder = this._getPlaceholderText(); - this._zone.value.show(this._activeSession.wholeRange.value); + + console.log('before show of wait_for_input'); + this._showWidget(); if (options?.message) { this._zone.value.widget.value = options?.message; diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index c08a9849965..026eb1f478a 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -791,8 +791,11 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { super._relayout(this._computeHeightInLines()); } - override show(selectionRange: Range): void { - super.show(selectionRange.getEndPosition(), this._computeHeightInLines()); + showWidget(selectionRange: Range, position: Position | undefined): void { + console.log('selectionRange : ', selectionRange); + console.log('position : ', position); + + super.show(position ?? selectionRange.getEndPosition(), this._computeHeightInLines()); this.widget.focus(); this._ctxVisible.set(true); this._setMargins(selectionRange); From d3692b2a98f8c41b001c89a3bed3459a4b6fafa0 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Thu, 8 Jun 2023 15:14:19 +0200 Subject: [PATCH 009/128] changes from review --- .../inlineChat/browser/inlineChatWidget.ts | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index c08a9849965..e55ab286449 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -183,7 +183,6 @@ export class InteractiveEditorWidget { private _isLayouting: boolean = false; private _preferredExpansionState: ExpansionState | undefined; private _expansionState: ExpansionState = ExpansionState.NOT_CROPPED; - private _indentationWidth: number = 0; constructor( private readonly parentEditor: ICodeEditor, @@ -465,14 +464,6 @@ export class InteractiveEditorWidget { this._preferredExpansionState = expansionState; } - set indentationWidth(indentationWidth: number) { - this._indentationWidth = indentationWidth; - } - - get indentationWidth(): number { - return this._indentationWidth; - } - updateMarkdownMessage(message: Node | undefined) { this._elements.markdownMessage.classList.toggle('hidden', !message); let expansionState: ExpansionState; @@ -725,6 +716,7 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { private readonly _ctxVisible: IContextKey; private readonly _ctxCursorPosition: IContextKey<'above' | 'below' | ''>; private _dimension?: Dimension; + private _indentationWidth: number = 0; constructor( editor: ICodeEditor, @@ -773,7 +765,7 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { const info = this.editor.getLayoutInfo(); const maxWidth = !this.widget.showsAnyPreview() ? 640 : Number.MAX_SAFE_INTEGER; - const width = Math.min(maxWidth, info.contentWidth - (info.glyphMarginWidth + info.decorationsWidth + this.widget.indentationWidth)); + const width = Math.min(maxWidth, info.contentWidth - (info.glyphMarginWidth + info.decorationsWidth + this._indentationWidth)); this._dimension = new Dimension(width, heightInPixel); this.widget.domNode.style.width = `${width}px`; this.widget.layout(this._dimension); @@ -803,18 +795,21 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { const startLineNumber = selectionRange.getStartPosition().lineNumber; const endLineNumber = selectionRange.getEndPosition().lineNumber; const viewModel = this.editor._getViewModel(); - let indentationLineNumber = endLineNumber; - let indentationLevel = viewModel?.getLineFirstNonWhitespaceColumn(endLineNumber); + if (!viewModel) { + return; + } + let indentationLineNumber; + let indentationLevel; for (let lineNumber = endLineNumber; lineNumber >= startLineNumber; lineNumber--) { - const currentIndentationLevel = viewModel?.getLineFirstNonWhitespaceColumn(lineNumber); - if (currentIndentationLevel && currentIndentationLevel !== 0) { + const currentIndentationLevel = viewModel.getLineFirstNonWhitespaceColumn(lineNumber); + if (currentIndentationLevel !== 0) { indentationLineNumber = lineNumber; indentationLevel = currentIndentationLevel; break; } } - this.widget.indentationWidth = (indentationLevel ? this.editor.getOffsetForColumn(indentationLineNumber, indentationLevel) : 0); - const spaceLeft = info.lineNumbersWidth + info.glyphMarginWidth + info.decorationsWidth + this.widget.indentationWidth; + this._indentationWidth = this.editor.getOffsetForColumn(indentationLineNumber ?? endLineNumber, indentationLevel ?? viewModel.getLineFirstNonWhitespaceColumn(endLineNumber)); + const spaceLeft = info.lineNumbersWidth + info.glyphMarginWidth + info.decorationsWidth + this._indentationWidth; const spaceRight = info.minimap.minimapWidth + info.verticalScrollbarWidth; this.widget.domNode.style.marginLeft = `${spaceLeft}px`; this.widget.domNode.style.marginRight = `${spaceRight}px`; From c3bd33203d341fcc4081ae2b239c05dca5d66093 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Thu, 8 Jun 2023 16:33:38 +0200 Subject: [PATCH 010/128] checking that there is enough available space before doing the indentation --- .../contrib/inlineChat/browser/inlineChatWidget.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index e55ab286449..f24a7ba797c 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -763,14 +763,18 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { protected override _doLayout(heightInPixel: number): void { - const info = this.editor.getLayoutInfo(); const maxWidth = !this.widget.showsAnyPreview() ? 640 : Number.MAX_SAFE_INTEGER; - const width = Math.min(maxWidth, info.contentWidth - (info.glyphMarginWidth + info.decorationsWidth + this._indentationWidth)); + const width = Math.min(maxWidth, this._availableSpaceWithIndentation()); this._dimension = new Dimension(width, heightInPixel); this.widget.domNode.style.width = `${width}px`; this.widget.layout(this._dimension); } + private _availableSpaceWithIndentation(): number { + const info = this.editor.getLayoutInfo(); + return info.contentWidth - (info.glyphMarginWidth + info.decorationsWidth + this._indentationWidth); + } + private _computeHeightInLines(): number { const lineHeight = this.editor.getOption(EditorOption.lineHeight); return this.widget.getHeight() / lineHeight; @@ -809,7 +813,11 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { } } this._indentationWidth = this.editor.getOffsetForColumn(indentationLineNumber ?? endLineNumber, indentationLevel ?? viewModel.getLineFirstNonWhitespaceColumn(endLineNumber)); - const spaceLeft = info.lineNumbersWidth + info.glyphMarginWidth + info.decorationsWidth + this._indentationWidth; + const marginWithoutIndentation = info.lineNumbersWidth + info.glyphMarginWidth + info.decorationsWidth; + const marginWithIndentation = marginWithoutIndentation + this._indentationWidth; + const isEnoughAvailableSpaceWithIndentation = this._availableSpaceWithIndentation() > 400; + this._indentationWidth = isEnoughAvailableSpaceWithIndentation ? this._indentationWidth : 0; + const spaceLeft = isEnoughAvailableSpaceWithIndentation ? marginWithIndentation : marginWithoutIndentation; const spaceRight = info.minimap.minimapWidth + info.verticalScrollbarWidth; this.widget.domNode.style.marginLeft = `${spaceLeft}px`; this.widget.domNode.style.marginRight = `${spaceRight}px`; From 73baf5f098ffdcb3cf12e1662ed906748884eecf Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Thu, 8 Jun 2023 16:48:36 +0200 Subject: [PATCH 011/128] cleanin the code --- src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index f24a7ba797c..992f241c65b 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -813,7 +813,7 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { } } this._indentationWidth = this.editor.getOffsetForColumn(indentationLineNumber ?? endLineNumber, indentationLevel ?? viewModel.getLineFirstNonWhitespaceColumn(endLineNumber)); - const marginWithoutIndentation = info.lineNumbersWidth + info.glyphMarginWidth + info.decorationsWidth; + const marginWithoutIndentation = info.glyphMarginWidth + info.decorationsWidth + info.lineNumbersWidth; const marginWithIndentation = marginWithoutIndentation + this._indentationWidth; const isEnoughAvailableSpaceWithIndentation = this._availableSpaceWithIndentation() > 400; this._indentationWidth = isEnoughAvailableSpaceWithIndentation ? this._indentationWidth : 0; From 72d20c98c3702532bffb6e472352b176e6138ab5 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Thu, 8 Jun 2023 16:51:19 +0200 Subject: [PATCH 012/128] renaming from with to given in the function name --- .../contrib/inlineChat/browser/inlineChatWidget.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index 992f241c65b..8932df9d3bb 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -764,13 +764,13 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { protected override _doLayout(heightInPixel: number): void { const maxWidth = !this.widget.showsAnyPreview() ? 640 : Number.MAX_SAFE_INTEGER; - const width = Math.min(maxWidth, this._availableSpaceWithIndentation()); + const width = Math.min(maxWidth, this._availableSpaceGivenIndentation()); this._dimension = new Dimension(width, heightInPixel); this.widget.domNode.style.width = `${width}px`; this.widget.layout(this._dimension); } - private _availableSpaceWithIndentation(): number { + private _availableSpaceGivenIndentation(): number { const info = this.editor.getLayoutInfo(); return info.contentWidth - (info.glyphMarginWidth + info.decorationsWidth + this._indentationWidth); } @@ -815,7 +815,7 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { this._indentationWidth = this.editor.getOffsetForColumn(indentationLineNumber ?? endLineNumber, indentationLevel ?? viewModel.getLineFirstNonWhitespaceColumn(endLineNumber)); const marginWithoutIndentation = info.glyphMarginWidth + info.decorationsWidth + info.lineNumbersWidth; const marginWithIndentation = marginWithoutIndentation + this._indentationWidth; - const isEnoughAvailableSpaceWithIndentation = this._availableSpaceWithIndentation() > 400; + const isEnoughAvailableSpaceWithIndentation = this._availableSpaceGivenIndentation() > 400; this._indentationWidth = isEnoughAvailableSpaceWithIndentation ? this._indentationWidth : 0; const spaceLeft = isEnoughAvailableSpaceWithIndentation ? marginWithIndentation : marginWithoutIndentation; const spaceRight = info.minimap.minimapWidth + info.verticalScrollbarWidth; From 13e2176f854685ea0e7f84b5beccda0b517c53d1 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Thu, 8 Jun 2023 17:01:51 +0200 Subject: [PATCH 013/128] resetting the code as it was --- .../browser/inlineChatController.ts | 14 +----- .../inlineChat/browser/inlineChatWidget.ts | 48 ++++--------------- 2 files changed, 11 insertions(+), 51 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 9be2c6c6b23..8b41fc56def 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -249,13 +249,6 @@ export class InteractiveEditorController implements IEditorContribution { return State.INIT_UI; } - private _showWidget(): void { - assertType(this._activeSession); - const selectionRange = this._activeSession.wholeRange.value; - const position = this._strategy?.getWidgetPosition(selectionRange); - this._zone.value.showWidget(selectionRange, position); - } - private async [State.INIT_UI](options: InteractiveEditorRunOptions | undefined): Promise { assertType(this._activeSession); @@ -276,9 +269,8 @@ export class InteractiveEditorController implements IEditorContribution { this._zone.value.widget.placeholder = this._getPlaceholderText(); this._zone.value.widget.value = this._activeSession.lastInput ?? ''; this._zone.value.widget.updateInfo(this._activeSession.session.message ?? localize('welcome.1', "AI-generated code may be incorrect")); + this._zone.value.show(this._activeSession.wholeRange.value.getEndPosition()); this._zone.value.widget.preferredExpansionState = this._activeSession.lastExpansionState; - console.log('before show of the init ui'); - this._showWidget(); this._sessionStore.add(this._editor.onDidChangeModel((e) => { const msg = this._activeSession?.lastExchange @@ -367,9 +359,7 @@ export class InteractiveEditorController implements IEditorContribution { assertType(this._activeSession); this._zone.value.widget.placeholder = this._getPlaceholderText(); - - console.log('before show of wait_for_input'); - this._showWidget(); + this._zone.value.show(this._activeSession.wholeRange.value.getEndPosition()); if (options?.message) { this._zone.value.widget.value = options?.message; diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index 026eb1f478a..c517f32ae59 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -26,7 +26,7 @@ import { EmbeddedCodeEditorWidget, EmbeddedDiffEditorWidget } from 'vs/editor/br import { HiddenItemStrategy, MenuWorkbenchToolBar } from 'vs/platform/actions/browser/toolbar'; import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; import { SuggestController } from 'vs/editor/contrib/suggest/browser/suggestController'; -import { Position } from 'vs/editor/common/core/position'; +import { IPosition, Position } from 'vs/editor/common/core/position'; import { DEFAULT_FONT_FAMILY } from 'vs/workbench/browser/style'; import { DropdownWithDefaultActionViewItem, IMenuEntryActionViewItemOptions, MenuEntryActionViewItem, createActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { CompletionItem, CompletionItemInsertTextRule, CompletionItemKind, CompletionItemProvider, CompletionList, ProviderResult, TextEdit } from 'vs/editor/common/languages'; @@ -183,7 +183,6 @@ export class InteractiveEditorWidget { private _isLayouting: boolean = false; private _preferredExpansionState: ExpansionState | undefined; private _expansionState: ExpansionState = ExpansionState.NOT_CROPPED; - private _indentationWidth: number = 0; constructor( private readonly parentEditor: ICodeEditor, @@ -465,14 +464,6 @@ export class InteractiveEditorWidget { this._preferredExpansionState = expansionState; } - set indentationWidth(indentationWidth: number) { - this._indentationWidth = indentationWidth; - } - - get indentationWidth(): number { - return this._indentationWidth; - } - updateMarkdownMessage(message: Node | undefined) { this._elements.markdownMessage.classList.toggle('hidden', !message); let expansionState: ExpansionState; @@ -772,9 +763,14 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { protected override _doLayout(heightInPixel: number): void { const info = this.editor.getLayoutInfo(); + const spaceLeft = info.lineNumbersWidth + info.glyphMarginWidth + info.decorationsWidth; + const spaceRight = info.minimap.minimapWidth + info.verticalScrollbarWidth; + const maxWidth = !this.widget.showsAnyPreview() ? 640 : Number.MAX_SAFE_INTEGER; - const width = Math.min(maxWidth, info.contentWidth - (info.glyphMarginWidth + info.decorationsWidth + this.widget.indentationWidth)); + const width = Math.min(maxWidth, info.contentWidth - (info.glyphMarginWidth + info.decorationsWidth)); this._dimension = new Dimension(width, heightInPixel); + this.widget.domNode.style.marginLeft = `${spaceLeft}px`; + this.widget.domNode.style.marginRight = `${spaceRight}px`; this.widget.domNode.style.width = `${width}px`; this.widget.layout(this._dimension); } @@ -791,36 +787,10 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { super._relayout(this._computeHeightInLines()); } - showWidget(selectionRange: Range, position: Position | undefined): void { - console.log('selectionRange : ', selectionRange); - console.log('position : ', position); - - super.show(position ?? selectionRange.getEndPosition(), this._computeHeightInLines()); + override show(where: IPosition): void { + super.show(where, this._computeHeightInLines()); this.widget.focus(); this._ctxVisible.set(true); - this._setMargins(selectionRange); - } - - private _setMargins(selectionRange: Range): void { - const info = this.editor.getLayoutInfo(); - const startLineNumber = selectionRange.getStartPosition().lineNumber; - const endLineNumber = selectionRange.getEndPosition().lineNumber; - const viewModel = this.editor._getViewModel(); - let indentationLineNumber = endLineNumber; - let indentationLevel = viewModel?.getLineFirstNonWhitespaceColumn(endLineNumber); - for (let lineNumber = endLineNumber; lineNumber >= startLineNumber; lineNumber--) { - const currentIndentationLevel = viewModel?.getLineFirstNonWhitespaceColumn(lineNumber); - if (currentIndentationLevel && currentIndentationLevel !== 0) { - indentationLineNumber = lineNumber; - indentationLevel = currentIndentationLevel; - break; - } - } - this.widget.indentationWidth = (indentationLevel ? this.editor.getOffsetForColumn(indentationLineNumber, indentationLevel) : 0); - const spaceLeft = info.lineNumbersWidth + info.glyphMarginWidth + info.decorationsWidth + this.widget.indentationWidth; - const spaceRight = info.minimap.minimapWidth + info.verticalScrollbarWidth; - this.widget.domNode.style.marginLeft = `${spaceLeft}px`; - this.widget.domNode.style.marginRight = `${spaceRight}px`; } override hide(): void { From aa4daa451cb3b6891c9fee59bd81cca737f30d98 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 9 Jun 2023 09:58:39 +0200 Subject: [PATCH 014/128] Change to the code after review --- .../browser/inlineChatController.ts | 48 +++++++++++++++++-- .../inlineChat/browser/inlineChatSession.ts | 2 +- .../browser/inlineChatStrategies.ts | 43 ++++++++++++++--- .../inlineChat/browser/inlineChatWidget.ts | 15 +++--- 4 files changed, 88 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index d883e5170a6..49a3f4bfbd3 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -67,6 +67,7 @@ export interface InteractiveEditorRunOptions { autoSend?: boolean; existingSession?: Session; isUnstashed?: boolean; + initialRender?: boolean; } export class InteractiveEditorController implements IEditorContribution { @@ -99,6 +100,8 @@ export class InteractiveEditorController implements IEditorContribution { private _activeSession?: Session; private _strategy?: EditModeStrategy; private _ignoreModelContentChanged = false; + private _initialRender?: boolean = true; + private _updateEditMode?: boolean = false; constructor( private readonly _editor: ICodeEditor, @@ -232,26 +235,55 @@ export class InteractiveEditorController implements IEditorContribution { return State.CANCEL; } + this._initializeStratetgy(session); + this._activeSession = session; + this._store.add(this._configurationService.onDidChangeConfiguration((e) => { + console.log('e : ', e); + console.log('e.affectsConfiguration(interactiveEditor.editModes) : ', e.affectsConfiguration('interactiveEditor.editMode')); + console.log('this._activeSession : ', this._activeSession); + if (e.affectsConfiguration('interactiveEditor.editMode')) { + console.log('entered into inner if loop of onDidChangeConfiguration'); + console.log('this._getMode() : ', this._getMode()); + this._updateEditMode = true; + } + })); + + return State.INIT_UI; + } + + private _initializeStratetgy(session: Session): void { + console.log('inside of initial strategy'); switch (session.editMode) { case EditMode.Live: this._strategy = this._instaService.createInstance(LiveStrategy, session, this._editor, this._zone.value.widget); break; case EditMode.Preview: - this._strategy = this._instaService.createInstance(PreviewStrategy, session, this._zone.value.widget); + this._strategy = this._instaService.createInstance(PreviewStrategy, session, this._editor, this._zone.value.widget); break; case EditMode.LivePreview: default: this._strategy = this._instaService.createInstance(LivePreviewStrategy, session, this._editor, this._zone.value.widget); break; } + } - this._activeSession = session; - return State.INIT_UI; + private _showWidget(initialRender: boolean = false) { + console.log('inside of _showWidget'); + console.log('initialRender : ', initialRender); + assertType(this._activeSession); + const selectionRange = this._activeSession.wholeRange.value; + this._zone.value.showWidget(selectionRange, this._strategy?.getWidgetPosition(initialRender, selectionRange)); } private async [State.INIT_UI](options: InteractiveEditorRunOptions | undefined): Promise { assertType(this._activeSession); + if (this._updateEditMode) { + this._activeSession.editMode = this._getMode(); + this._initializeStratetgy(this._activeSession); + this._updateEditMode = false; + } + // hide/cancel inline completions when invoking IE InlineCompletionsController.get(this._editor)?.hide(); @@ -269,8 +301,10 @@ export class InteractiveEditorController implements IEditorContribution { this._zone.value.widget.placeholder = this._getPlaceholderText(); this._zone.value.widget.value = this._activeSession.lastInput ?? ''; this._zone.value.widget.updateInfo(this._activeSession.session.message ?? localize('welcome.1', "AI-generated code may be incorrect")); - this._zone.value.show(this._activeSession.wholeRange.value); this._zone.value.widget.preferredExpansionState = this._activeSession.lastExpansionState; + console.log('inside of init ui before show widget'); + this._initialRender = true; + this._showWidget(this._initialRender); this._sessionStore.add(this._editor.onDidChangeModel((e) => { const msg = this._activeSession?.lastExchange @@ -358,8 +392,10 @@ export class InteractiveEditorController implements IEditorContribution { private async [State.WAIT_FOR_INPUT](options: InteractiveEditorRunOptions | undefined): Promise { assertType(this._activeSession); + console.log('inside of wait for input'); this._zone.value.widget.placeholder = this._getPlaceholderText(); - this._zone.value.show(this._activeSession.wholeRange.value); + this._showWidget(this._initialRender); + this._initialRender = false; if (options?.message) { this._zone.value.widget.value = options?.message; @@ -398,6 +434,7 @@ export class InteractiveEditorController implements IEditorContribution { } if (!this._zone.value.widget.value) { + console.log('before the case when we call WAIT_FOR_INPUT'); return State.WAIT_FOR_INPUT; } @@ -427,6 +464,7 @@ export class InteractiveEditorController implements IEditorContribution { private async [State.MAKE_REQUEST](): Promise { assertType(this._editor.hasModel()); assertType(this._activeSession); + console.log('this._activeSession.lastInput : ', this._activeSession.lastInput); assertType(this._activeSession.lastInput); const requestCts = new CancellationTokenSource(); diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts index c45dd008972..4a3a5e077b9 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts @@ -120,7 +120,7 @@ export class Session { private _textModelNSnapshotAltVersion: number | undefined; constructor( - readonly editMode: EditMode, + public editMode: EditMode, readonly editor: ICodeEditor, readonly textModel0: ITextModel, readonly textModelN: ITextModel, diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts index d57c6e7d862..5289f91c2c7 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts @@ -41,7 +41,28 @@ export abstract class EditModeStrategy { abstract toggleDiff(): void; - abstract getWidgetPosition(range: Range): Position; + abstract getWidgetPosition(initialRender: boolean, range: Range): Position | undefined; +} + +function positionCalculation(editor: ICodeEditor, initialRender: boolean, range: Range): Position | undefined { + const viewModel = editor._getViewModel(); + if (!viewModel) { + return; + } + const primaryCursorPosition = viewModel.getPrimaryCursorState().viewState.position; + if (initialRender) { + return primaryCursorPosition; + } else { + const visibleRange = viewModel.getCompletelyVisibleViewRange(); + const endPosition = range.getEndPosition(); + const endLine = endPosition.lineNumber; + + if (endLine >= visibleRange.startLineNumber && endLine <= visibleRange.endLineNumber) { + return endPosition; + } else { + return primaryCursorPosition; + } + } } export class PreviewStrategy extends EditModeStrategy { @@ -51,6 +72,7 @@ export class PreviewStrategy extends EditModeStrategy { constructor( private readonly _session: Session, + private readonly _editor: ICodeEditor, private readonly _widget: InteractiveEditorWidget, @IContextKeyService contextKeyService: IContextKeyService, @IBulkEditService private readonly _bulkEditService: IBulkEditService, @@ -129,8 +151,9 @@ export class PreviewStrategy extends EditModeStrategy { // nothing to do } - getWidgetPosition(range: Range): Position { - throw new Error('not supported'); + getWidgetPosition(initialRender: boolean, range: Range): Position | undefined { + console.log('inside of preview strategy, getWidgetPosition'); + return positionCalculation(this._editor, initialRender, range); } } @@ -325,8 +348,9 @@ export class LiveStrategy extends EditModeStrategy { this._widget.updateStatus(message); } - getWidgetPosition(range: Range): Position { - throw new Error('not supported'); + getWidgetPosition(initialRender: boolean, range: Range): Position | undefined { + console.log('inside of live strategy, getWidgetPosition'); + return positionCalculation(this._editor, initialRender, range); } } @@ -383,8 +407,13 @@ export class LivePreviewStrategy extends LiveStrategy { scrollState.restore(this._editor); } - override getWidgetPosition(range: Range): Position { - throw new Error('not supported'); + override getWidgetPosition(initialRender: boolean, range: Range): Position | undefined { + console.log('inside of live preview strategy, getWidgetPosition'); + if (initialRender) { + return this._editor._getViewModel()?.getPrimaryCursorState().viewState.position; + } else { + return range.getEndPosition(); + } } } diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index 8932df9d3bb..e6320d136ed 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -787,24 +787,25 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { super._relayout(this._computeHeightInLines()); } - override show(selectionRange: Range): void { - super.show(selectionRange.getEndPosition(), this._computeHeightInLines()); + showWidget(selectionRange: Range, position: Position | undefined): void { + const widgetPosition = position ?? selectionRange.getEndPosition(); + super.show(widgetPosition, this._computeHeightInLines()); this.widget.focus(); this._ctxVisible.set(true); - this._setMargins(selectionRange); + this._setMargins(selectionRange, widgetPosition); } - private _setMargins(selectionRange: Range): void { + private _setMargins(selectionRange: Range, position: Position): void { + const positionLineNumber = position.lineNumber; const info = this.editor.getLayoutInfo(); const startLineNumber = selectionRange.getStartPosition().lineNumber; - const endLineNumber = selectionRange.getEndPosition().lineNumber; const viewModel = this.editor._getViewModel(); if (!viewModel) { return; } let indentationLineNumber; let indentationLevel; - for (let lineNumber = endLineNumber; lineNumber >= startLineNumber; lineNumber--) { + for (let lineNumber = positionLineNumber; lineNumber >= startLineNumber; lineNumber--) { const currentIndentationLevel = viewModel.getLineFirstNonWhitespaceColumn(lineNumber); if (currentIndentationLevel !== 0) { indentationLineNumber = lineNumber; @@ -812,7 +813,7 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { break; } } - this._indentationWidth = this.editor.getOffsetForColumn(indentationLineNumber ?? endLineNumber, indentationLevel ?? viewModel.getLineFirstNonWhitespaceColumn(endLineNumber)); + this._indentationWidth = this.editor.getOffsetForColumn(indentationLineNumber ?? positionLineNumber, indentationLevel ?? viewModel.getLineFirstNonWhitespaceColumn(positionLineNumber)); const marginWithoutIndentation = info.glyphMarginWidth + info.decorationsWidth + info.lineNumbersWidth; const marginWithIndentation = marginWithoutIndentation + this._indentationWidth; const isEnoughAvailableSpaceWithIndentation = this._availableSpaceGivenIndentation() > 400; From e05a47d00135e82bd5a7489e489f29751a819090 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 9 Jun 2023 10:08:56 +0200 Subject: [PATCH 015/128] taking into account the last rendering position of the active session --- .../inlineChat/browser/inlineChatController.ts | 17 ++++++++++++++++- .../inlineChat/browser/inlineChatSession.ts | 10 ++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 49a3f4bfbd3..f525c318276 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -272,7 +272,22 @@ export class InteractiveEditorController implements IEditorContribution { console.log('initialRender : ', initialRender); assertType(this._activeSession); const selectionRange = this._activeSession.wholeRange.value; - this._zone.value.showWidget(selectionRange, this._strategy?.getWidgetPosition(initialRender, selectionRange)); + + if (!initialRender) { + if (this._activeSession.lastPosition) { + this._zone.value.showWidget(selectionRange, this._activeSession.lastPosition); + } else { + const widgetPosition = this._strategy?.getWidgetPosition(initialRender, selectionRange); + this._activeSession.lastPosition = widgetPosition; + this._zone.value.showWidget(selectionRange, widgetPosition); + } + } else { + if (this._activeSession.lastPosition) { + this._zone.value.showWidget(selectionRange, this._activeSession.lastPosition); + } else { + this._zone.value.showWidget(selectionRange, this._strategy?.getWidgetPosition(initialRender, selectionRange)); + } + } } private async [State.INIT_UI](options: InteractiveEditorRunOptions | undefined): Promise { diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts index 4a3a5e077b9..349d672e629 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts @@ -25,6 +25,7 @@ import { toErrorMessage } from 'vs/base/common/errorMessage'; import { isCancellationError } from 'vs/base/common/errors'; import { LineRangeMapping } from 'vs/editor/common/diff/linesDiffComputer'; import { ISingleEditOperation } from 'vs/editor/common/core/editOperation'; +import { Position } from 'vs/editor/common/core/position'; export type Recording = { when: Date; @@ -112,6 +113,7 @@ export class Session { private _lastExpansionState: ExpansionState | undefined; private _lastTextModelChanges: readonly LineRangeMapping[] | undefined; private _isUnstashed: boolean = false; + private _lastPosition: Position | undefined; private readonly _exchange: SessionExchange[] = []; private readonly _startTime = new Date(); private readonly _teldata: Partial; @@ -155,6 +157,14 @@ export class Session { return this._lastInput; } + get lastPosition() { + return this._lastPosition; + } + + set lastPosition(position: Position | undefined) { + this._lastPosition = position; + } + get lastExpansionState(): ExpansionState | undefined { return this._lastExpansionState; } From 561854e98861233e9f05c01bd9b10c550b6b86e0 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 9 Jun 2023 10:43:47 +0200 Subject: [PATCH 016/128] making the position be reset on update edit mode --- .../browser/inlineChatController.ts | 52 ++++++++++++++++--- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index f525c318276..1eeb3e267cb 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -67,7 +67,6 @@ export interface InteractiveEditorRunOptions { autoSend?: boolean; existingSession?: Session; isUnstashed?: boolean; - initialRender?: boolean; } export class InteractiveEditorController implements IEditorContribution { @@ -238,12 +237,16 @@ export class InteractiveEditorController implements IEditorContribution { this._initializeStratetgy(session); this._activeSession = session; this._store.add(this._configurationService.onDidChangeConfiguration((e) => { + console.log('e : ', e); console.log('e.affectsConfiguration(interactiveEditor.editModes) : ', e.affectsConfiguration('interactiveEditor.editMode')); console.log('this._activeSession : ', this._activeSession); + if (e.affectsConfiguration('interactiveEditor.editMode')) { + console.log('entered into inner if loop of onDidChangeConfiguration'); console.log('this._getMode() : ', this._getMode()); + this._updateEditMode = true; } })); @@ -252,7 +255,9 @@ export class InteractiveEditorController implements IEditorContribution { } private _initializeStratetgy(session: Session): void { + console.log('inside of initial strategy'); + switch (session.editMode) { case EditMode.Live: this._strategy = this._instaService.createInstance(LiveStrategy, session, this._editor, this._zone.value.widget); @@ -267,24 +272,49 @@ export class InteractiveEditorController implements IEditorContribution { } } - private _showWidget(initialRender: boolean = false) { + private _showWidget(initialRender: boolean = false, updateEditMode: boolean = false) { + console.log('inside of _showWidget'); console.log('initialRender : ', initialRender); + console.log('updateEditMode : ', updateEditMode); + assertType(this._activeSession); const selectionRange = this._activeSession.wholeRange.value; if (!initialRender) { + console.log('initial render is false'); + console.log('this._activeSession.lastPosition : ', this._activeSession.lastPosition); if (this._activeSession.lastPosition) { - this._zone.value.showWidget(selectionRange, this._activeSession.lastPosition); + console.log('inside if'); + if (updateEditMode) { + console.log('inside if'); + this._zone.value.showWidget(selectionRange, this._strategy?.getWidgetPosition(initialRender, selectionRange)); + } else { + console.log('inside else'); + this._zone.value.showWidget(selectionRange, this._activeSession.lastPosition); + } } else { + console.log('inside else'); const widgetPosition = this._strategy?.getWidgetPosition(initialRender, selectionRange); this._activeSession.lastPosition = widgetPosition; this._zone.value.showWidget(selectionRange, widgetPosition); } } else { + console.log('initial render is true'); + console.log('this._activeSession.lastPosition : ', this._activeSession.lastPosition); + if (this._activeSession.lastPosition) { - this._zone.value.showWidget(selectionRange, this._activeSession.lastPosition); + console.log('inside if'); + if (updateEditMode) { + console.log('inside if'); + this._zone.value.showWidget(selectionRange, this._strategy?.getWidgetPosition(initialRender, selectionRange)); + this._activeSession.lastPosition = undefined; + } else { + console.log('inside else'); + this._zone.value.showWidget(selectionRange, this._activeSession.lastPosition); + } } else { + console.log('inside else'); this._zone.value.showWidget(selectionRange, this._strategy?.getWidgetPosition(initialRender, selectionRange)); } } @@ -296,7 +326,6 @@ export class InteractiveEditorController implements IEditorContribution { if (this._updateEditMode) { this._activeSession.editMode = this._getMode(); this._initializeStratetgy(this._activeSession); - this._updateEditMode = false; } // hide/cancel inline completions when invoking IE @@ -317,9 +346,11 @@ export class InteractiveEditorController implements IEditorContribution { this._zone.value.widget.value = this._activeSession.lastInput ?? ''; this._zone.value.widget.updateInfo(this._activeSession.session.message ?? localize('welcome.1', "AI-generated code may be incorrect")); this._zone.value.widget.preferredExpansionState = this._activeSession.lastExpansionState; + console.log('inside of init ui before show widget'); + this._initialRender = true; - this._showWidget(this._initialRender); + this._showWidget(this._initialRender, this._updateEditMode); this._sessionStore.add(this._editor.onDidChangeModel((e) => { const msg = this._activeSession?.lastExchange @@ -407,10 +438,13 @@ export class InteractiveEditorController implements IEditorContribution { private async [State.WAIT_FOR_INPUT](options: InteractiveEditorRunOptions | undefined): Promise { assertType(this._activeSession); + console.log('inside of wait for input'); + this._zone.value.widget.placeholder = this._getPlaceholderText(); - this._showWidget(this._initialRender); + this._showWidget(this._initialRender, this._updateEditMode); this._initialRender = false; + this._updateEditMode = false; if (options?.message) { this._zone.value.widget.value = options?.message; @@ -449,7 +483,9 @@ export class InteractiveEditorController implements IEditorContribution { } if (!this._zone.value.widget.value) { + console.log('before the case when we call WAIT_FOR_INPUT'); + return State.WAIT_FOR_INPUT; } @@ -479,7 +515,9 @@ export class InteractiveEditorController implements IEditorContribution { private async [State.MAKE_REQUEST](): Promise { assertType(this._editor.hasModel()); assertType(this._activeSession); + console.log('this._activeSession.lastInput : ', this._activeSession.lastInput); + assertType(this._activeSession.lastInput); const requestCts = new CancellationTokenSource(); From ad3b07c0a7cffb90ad24b3d572858d293768bf67 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 9 Jun 2023 16:41:47 +0200 Subject: [PATCH 017/128] cleaned the code --- .../browser/inlineChatController.ts | 107 ++---------------- .../inlineChat/browser/inlineChatSession.ts | 10 -- .../browser/inlineChatStrategies.ts | 91 +++++++++------ 3 files changed, 71 insertions(+), 137 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 1eeb3e267cb..e22afba705c 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -99,8 +99,6 @@ export class InteractiveEditorController implements IEditorContribution { private _activeSession?: Session; private _strategy?: EditModeStrategy; private _ignoreModelContentChanged = false; - private _initialRender?: boolean = true; - private _updateEditMode?: boolean = false; constructor( private readonly _editor: ICodeEditor, @@ -195,6 +193,13 @@ export class InteractiveEditorController implements IEditorContribution { // ---- state machine + private _showWidget(initialRender: boolean = false, hasEditResponse: boolean = false) { + assertType(this._activeSession); + const selectionRange = this._activeSession.wholeRange.value; + const widgetPosition = this._strategy?.getWidgetPosition(initialRender, selectionRange, hasEditResponse); + this._zone.value.showWidget(selectionRange, widgetPosition); + } + protected async _nextState(state: State, options: InteractiveEditorRunOptions | undefined): Promise { this._log('setState to ', state); const nextState = await this[state](options); @@ -234,30 +239,7 @@ export class InteractiveEditorController implements IEditorContribution { return State.CANCEL; } - this._initializeStratetgy(session); - this._activeSession = session; - this._store.add(this._configurationService.onDidChangeConfiguration((e) => { - - console.log('e : ', e); - console.log('e.affectsConfiguration(interactiveEditor.editModes) : ', e.affectsConfiguration('interactiveEditor.editMode')); - console.log('this._activeSession : ', this._activeSession); - - if (e.affectsConfiguration('interactiveEditor.editMode')) { - - console.log('entered into inner if loop of onDidChangeConfiguration'); - console.log('this._getMode() : ', this._getMode()); - - this._updateEditMode = true; - } - })); - - return State.INIT_UI; - } - - private _initializeStratetgy(session: Session): void { - - console.log('inside of initial strategy'); - + session.editMode = this._getMode(); switch (session.editMode) { case EditMode.Live: this._strategy = this._instaService.createInstance(LiveStrategy, session, this._editor, this._zone.value.widget); @@ -270,64 +252,14 @@ export class InteractiveEditorController implements IEditorContribution { this._strategy = this._instaService.createInstance(LivePreviewStrategy, session, this._editor, this._zone.value.widget); break; } - } - private _showWidget(initialRender: boolean = false, updateEditMode: boolean = false) { - - console.log('inside of _showWidget'); - console.log('initialRender : ', initialRender); - console.log('updateEditMode : ', updateEditMode); - - assertType(this._activeSession); - const selectionRange = this._activeSession.wholeRange.value; - - if (!initialRender) { - console.log('initial render is false'); - console.log('this._activeSession.lastPosition : ', this._activeSession.lastPosition); - if (this._activeSession.lastPosition) { - console.log('inside if'); - if (updateEditMode) { - console.log('inside if'); - this._zone.value.showWidget(selectionRange, this._strategy?.getWidgetPosition(initialRender, selectionRange)); - } else { - console.log('inside else'); - this._zone.value.showWidget(selectionRange, this._activeSession.lastPosition); - } - } else { - console.log('inside else'); - const widgetPosition = this._strategy?.getWidgetPosition(initialRender, selectionRange); - this._activeSession.lastPosition = widgetPosition; - this._zone.value.showWidget(selectionRange, widgetPosition); - } - } else { - console.log('initial render is true'); - console.log('this._activeSession.lastPosition : ', this._activeSession.lastPosition); - - if (this._activeSession.lastPosition) { - console.log('inside if'); - if (updateEditMode) { - console.log('inside if'); - this._zone.value.showWidget(selectionRange, this._strategy?.getWidgetPosition(initialRender, selectionRange)); - this._activeSession.lastPosition = undefined; - } else { - console.log('inside else'); - this._zone.value.showWidget(selectionRange, this._activeSession.lastPosition); - } - } else { - console.log('inside else'); - this._zone.value.showWidget(selectionRange, this._strategy?.getWidgetPosition(initialRender, selectionRange)); - } - } + this._activeSession = session; + return State.INIT_UI; } private async [State.INIT_UI](options: InteractiveEditorRunOptions | undefined): Promise { assertType(this._activeSession); - if (this._updateEditMode) { - this._activeSession.editMode = this._getMode(); - this._initializeStratetgy(this._activeSession); - } - // hide/cancel inline completions when invoking IE InlineCompletionsController.get(this._editor)?.hide(); @@ -346,11 +278,7 @@ export class InteractiveEditorController implements IEditorContribution { this._zone.value.widget.value = this._activeSession.lastInput ?? ''; this._zone.value.widget.updateInfo(this._activeSession.session.message ?? localize('welcome.1', "AI-generated code may be incorrect")); this._zone.value.widget.preferredExpansionState = this._activeSession.lastExpansionState; - - console.log('inside of init ui before show widget'); - - this._initialRender = true; - this._showWidget(this._initialRender, this._updateEditMode); + this._showWidget(true); this._sessionStore.add(this._editor.onDidChangeModel((e) => { const msg = this._activeSession?.lastExchange @@ -438,13 +366,7 @@ export class InteractiveEditorController implements IEditorContribution { private async [State.WAIT_FOR_INPUT](options: InteractiveEditorRunOptions | undefined): Promise { assertType(this._activeSession); - - console.log('inside of wait for input'); - this._zone.value.widget.placeholder = this._getPlaceholderText(); - this._showWidget(this._initialRender, this._updateEditMode); - this._initialRender = false; - this._updateEditMode = false; if (options?.message) { this._zone.value.widget.value = options?.message; @@ -483,9 +405,6 @@ export class InteractiveEditorController implements IEditorContribution { } if (!this._zone.value.widget.value) { - - console.log('before the case when we call WAIT_FOR_INPUT'); - return State.WAIT_FOR_INPUT; } @@ -515,9 +434,6 @@ export class InteractiveEditorController implements IEditorContribution { private async [State.MAKE_REQUEST](): Promise { assertType(this._editor.hasModel()); assertType(this._activeSession); - - console.log('this._activeSession.lastInput : ', this._activeSession.lastInput); - assertType(this._activeSession.lastInput); const requestCts = new CancellationTokenSource(); @@ -628,6 +544,7 @@ export class InteractiveEditorController implements IEditorContribution { assertType(this._strategy); const { response } = this._activeSession.lastExchange!; + this._showWidget(false, response instanceof EditResponse); // this._updateEditMode, r this._ctxLastResponseType.set(response instanceof EditResponse || response instanceof MarkdownResponse ? response.raw.type diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts index 349d672e629..4a3a5e077b9 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts @@ -25,7 +25,6 @@ import { toErrorMessage } from 'vs/base/common/errorMessage'; import { isCancellationError } from 'vs/base/common/errors'; import { LineRangeMapping } from 'vs/editor/common/diff/linesDiffComputer'; import { ISingleEditOperation } from 'vs/editor/common/core/editOperation'; -import { Position } from 'vs/editor/common/core/position'; export type Recording = { when: Date; @@ -113,7 +112,6 @@ export class Session { private _lastExpansionState: ExpansionState | undefined; private _lastTextModelChanges: readonly LineRangeMapping[] | undefined; private _isUnstashed: boolean = false; - private _lastPosition: Position | undefined; private readonly _exchange: SessionExchange[] = []; private readonly _startTime = new Date(); private readonly _teldata: Partial; @@ -157,14 +155,6 @@ export class Session { return this._lastInput; } - get lastPosition() { - return this._lastPosition; - } - - set lastPosition(position: Position | undefined) { - this._lastPosition = position; - } - get lastExpansionState(): ExpansionState | undefined { return this._lastExpansionState; } diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts index 5289f91c2c7..6bef227d5a0 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts @@ -41,34 +41,14 @@ export abstract class EditModeStrategy { abstract toggleDiff(): void; - abstract getWidgetPosition(initialRender: boolean, range: Range): Position | undefined; -} - -function positionCalculation(editor: ICodeEditor, initialRender: boolean, range: Range): Position | undefined { - const viewModel = editor._getViewModel(); - if (!viewModel) { - return; - } - const primaryCursorPosition = viewModel.getPrimaryCursorState().viewState.position; - if (initialRender) { - return primaryCursorPosition; - } else { - const visibleRange = viewModel.getCompletelyVisibleViewRange(); - const endPosition = range.getEndPosition(); - const endLine = endPosition.lineNumber; - - if (endLine >= visibleRange.startLineNumber && endLine <= visibleRange.endLineNumber) { - return endPosition; - } else { - return primaryCursorPosition; - } - } + abstract getWidgetPosition(initialRender: boolean, range: Range, hasEditResponse: boolean | undefined): Position | undefined; } export class PreviewStrategy extends EditModeStrategy { private readonly _ctxDocumentChanged: IContextKey; private readonly _listener: IDisposable; + private _initialPosition: Position | undefined; constructor( private readonly _session: Session, @@ -151,9 +131,30 @@ export class PreviewStrategy extends EditModeStrategy { // nothing to do } - getWidgetPosition(initialRender: boolean, range: Range): Position | undefined { - console.log('inside of preview strategy, getWidgetPosition'); - return positionCalculation(this._editor, initialRender, range); + getWidgetPosition(initialRender: boolean, range: Range, hasEditResponse: boolean | undefined): Position | undefined { + console.log('inside of preview strategy'); + const viewModel = this._editor._getViewModel(); + if (!viewModel) { + return; + } + const primaryCursorPosition = viewModel.getPrimaryCursorState().viewState.position; + if (initialRender) { + this._initialPosition = primaryCursorPosition; + return this._initialPosition; + } else { + if (hasEditResponse) { + const visibleRange = viewModel.getCompletelyVisibleViewRange(); + const endPosition = range.getEndPosition(); + const endLine = endPosition.lineNumber; + if (endLine >= visibleRange.startLineNumber && endLine <= visibleRange.endLineNumber) { + return endPosition; + } else { + return this._initialPosition; + } + } else { + return this._initialPosition; + } + } } } @@ -233,6 +234,7 @@ export class LiveStrategy extends EditModeStrategy { private readonly _ctxShowingDiff: IContextKey; private _lastResponse?: EditResponse; private _editCount: number = 0; + protected _initialPosition: Position | undefined; constructor( protected readonly _session: Session, @@ -348,9 +350,28 @@ export class LiveStrategy extends EditModeStrategy { this._widget.updateStatus(message); } - getWidgetPosition(initialRender: boolean, range: Range): Position | undefined { - console.log('inside of live strategy, getWidgetPosition'); - return positionCalculation(this._editor, initialRender, range); + getWidgetPosition(initialRender: boolean, range: Range, hasEditResponse: boolean | undefined): Position | undefined { + const viewModel = this._editor._getViewModel(); + if (!viewModel) { + return; + } + if (initialRender) { + this._initialPosition = viewModel.getPrimaryCursorState().viewState.position; + return this._initialPosition; + } else { + if (hasEditResponse) { + const visibleRange = viewModel.getCompletelyVisibleViewRange(); + const endPosition = range.getEndPosition(); + const endLine = endPosition.lineNumber; + if (endLine >= visibleRange.startLineNumber && endLine <= visibleRange.endLineNumber) { + return endPosition; + } else { + return this._initialPosition; + } + } else { + return this._initialPosition; + } + } } } @@ -407,12 +428,18 @@ export class LivePreviewStrategy extends LiveStrategy { scrollState.restore(this._editor); } - override getWidgetPosition(initialRender: boolean, range: Range): Position | undefined { - console.log('inside of live preview strategy, getWidgetPosition'); + override getWidgetPosition(initialRender: boolean, range: Range, hasEditResponse: boolean | undefined): Position | undefined { + console.log('inside of live preview strategy'); + const primaryCursorPosition = this._editor._getViewModel()?.getPrimaryCursorState().viewState.position; if (initialRender) { - return this._editor._getViewModel()?.getPrimaryCursorState().viewState.position; + this._initialPosition = primaryCursorPosition; + return this._initialPosition; } else { - return range.getEndPosition(); + if (hasEditResponse) { + return range.getEndPosition(); + } else { + return this._initialPosition; + } } } } From b85927d1080ca8f616946948bb9814bb15c82346 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 9 Jun 2023 16:51:59 +0200 Subject: [PATCH 018/128] cleaning the code --- .../inlineChat/browser/inlineChatController.ts | 2 +- .../inlineChat/browser/inlineChatWidget.ts | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index e22afba705c..b28c76a8ac9 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -197,7 +197,7 @@ export class InteractiveEditorController implements IEditorContribution { assertType(this._activeSession); const selectionRange = this._activeSession.wholeRange.value; const widgetPosition = this._strategy?.getWidgetPosition(initialRender, selectionRange, hasEditResponse); - this._zone.value.showWidget(selectionRange, widgetPosition); + this._zone.value.showWidget(widgetPosition ?? selectionRange.getStartPosition()); } protected async _nextState(state: State, options: InteractiveEditorRunOptions | undefined): Promise { diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index e6320d136ed..135ec8fb1bd 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -787,22 +787,22 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { super._relayout(this._computeHeightInLines()); } - showWidget(selectionRange: Range, position: Position | undefined): void { - const widgetPosition = position ?? selectionRange.getEndPosition(); + showWidget(position: Position): void { + const widgetPosition = position; + console.log('widgetPosition : ', widgetPosition); super.show(widgetPosition, this._computeHeightInLines()); this.widget.focus(); this._ctxVisible.set(true); - this._setMargins(selectionRange, widgetPosition); + this._setMargins(widgetPosition); } - private _setMargins(selectionRange: Range, position: Position): void { - const positionLineNumber = position.lineNumber; - const info = this.editor.getLayoutInfo(); - const startLineNumber = selectionRange.getStartPosition().lineNumber; + private _setMargins(position: Position): void { const viewModel = this.editor._getViewModel(); if (!viewModel) { return; } + const positionLineNumber = position.lineNumber; + const startLineNumber = viewModel.getCompletelyVisibleViewRange().startLineNumber; let indentationLineNumber; let indentationLevel; for (let lineNumber = positionLineNumber; lineNumber >= startLineNumber; lineNumber--) { @@ -814,6 +814,7 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { } } this._indentationWidth = this.editor.getOffsetForColumn(indentationLineNumber ?? positionLineNumber, indentationLevel ?? viewModel.getLineFirstNonWhitespaceColumn(positionLineNumber)); + const info = this.editor.getLayoutInfo(); const marginWithoutIndentation = info.glyphMarginWidth + info.decorationsWidth + info.lineNumbersWidth; const marginWithIndentation = marginWithoutIndentation + this._indentationWidth; const isEnoughAvailableSpaceWithIndentation = this._availableSpaceGivenIndentation() > 400; From 7efbcacd8d38a6a653fac3bd94e35752a48b7be8 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 9 Jun 2023 16:52:40 +0200 Subject: [PATCH 019/128] setting the margins --- src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index 135ec8fb1bd..91b470c401c 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -789,7 +789,6 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { showWidget(position: Position): void { const widgetPosition = position; - console.log('widgetPosition : ', widgetPosition); super.show(widgetPosition, this._computeHeightInLines()); this.widget.focus(); this._ctxVisible.set(true); From e4126d88dbea3ec38b2b4a388233995d1d437f22 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 9 Jun 2023 17:14:59 +0200 Subject: [PATCH 020/128] using instead the position, instead of the selection --- .../browser/inlineChatController.ts | 4 ++-- .../inlineChat/browser/inlineChatWidget.ts | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index d883e5170a6..8b41fc56def 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -269,7 +269,7 @@ export class InteractiveEditorController implements IEditorContribution { this._zone.value.widget.placeholder = this._getPlaceholderText(); this._zone.value.widget.value = this._activeSession.lastInput ?? ''; this._zone.value.widget.updateInfo(this._activeSession.session.message ?? localize('welcome.1', "AI-generated code may be incorrect")); - this._zone.value.show(this._activeSession.wholeRange.value); + this._zone.value.show(this._activeSession.wholeRange.value.getEndPosition()); this._zone.value.widget.preferredExpansionState = this._activeSession.lastExpansionState; this._sessionStore.add(this._editor.onDidChangeModel((e) => { @@ -359,7 +359,7 @@ export class InteractiveEditorController implements IEditorContribution { assertType(this._activeSession); this._zone.value.widget.placeholder = this._getPlaceholderText(); - this._zone.value.show(this._activeSession.wholeRange.value); + this._zone.value.show(this._activeSession.wholeRange.value.getEndPosition()); if (options?.message) { this._zone.value.widget.value = options?.message; diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index 8932df9d3bb..8057610cc56 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -787,24 +787,24 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { super._relayout(this._computeHeightInLines()); } - override show(selectionRange: Range): void { - super.show(selectionRange.getEndPosition(), this._computeHeightInLines()); + override show(position: Position): void { + super.show(position, this._computeHeightInLines()); this.widget.focus(); this._ctxVisible.set(true); - this._setMargins(selectionRange); + this._setMargins(position); } - private _setMargins(selectionRange: Range): void { - const info = this.editor.getLayoutInfo(); - const startLineNumber = selectionRange.getStartPosition().lineNumber; - const endLineNumber = selectionRange.getEndPosition().lineNumber; + private _setMargins(position: Position): void { const viewModel = this.editor._getViewModel(); if (!viewModel) { return; } + const visibleRange = viewModel.getCompletelyVisibleViewRange(); + const startLineVisibleRange = visibleRange.startLineNumber; + const positionLine = position.lineNumber; let indentationLineNumber; let indentationLevel; - for (let lineNumber = endLineNumber; lineNumber >= startLineNumber; lineNumber--) { + for (let lineNumber = positionLine; lineNumber >= startLineVisibleRange; lineNumber--) { const currentIndentationLevel = viewModel.getLineFirstNonWhitespaceColumn(lineNumber); if (currentIndentationLevel !== 0) { indentationLineNumber = lineNumber; @@ -812,7 +812,8 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { break; } } - this._indentationWidth = this.editor.getOffsetForColumn(indentationLineNumber ?? endLineNumber, indentationLevel ?? viewModel.getLineFirstNonWhitespaceColumn(endLineNumber)); + this._indentationWidth = this.editor.getOffsetForColumn(indentationLineNumber ?? positionLine, indentationLevel ?? viewModel.getLineFirstNonWhitespaceColumn(positionLine)); + const info = this.editor.getLayoutInfo(); const marginWithoutIndentation = info.glyphMarginWidth + info.decorationsWidth + info.lineNumbersWidth; const marginWithIndentation = marginWithoutIndentation + this._indentationWidth; const isEnoughAvailableSpaceWithIndentation = this._availableSpaceGivenIndentation() > 400; From b2c2ba8691a1de28ec7963411f7b0d1cecda0d2e Mon Sep 17 00:00:00 2001 From: Flo Date: Fri, 9 Jun 2023 15:18:17 +0000 Subject: [PATCH 021/128] Restore ShellIntegration for fish (#184659) Resolves #184659 --- src/vs/server/node/server.cli.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/server/node/server.cli.ts b/src/vs/server/node/server.cli.ts index 138f6dd8130..6163df61949 100644 --- a/src/vs/server/node/server.cli.ts +++ b/src/vs/server/node/server.cli.ts @@ -145,7 +145,7 @@ export async function main(desc: ProductDescription, args: string[]): Promise Date: Fri, 9 Jun 2023 09:00:09 -0700 Subject: [PATCH 022/128] node-pty@0.11.0-beta33 and fix Windows clear issue Fixes #75141 --- package.json | 2 +- remote/package.json | 2 +- remote/yarn.lock | 8 ++++---- src/vs/platform/terminal/common/terminal.ts | 2 +- src/vs/platform/terminal/node/ptyService.ts | 1 + src/vs/platform/terminal/node/terminalProcess.ts | 4 ++++ src/vs/workbench/api/common/extHostTerminalService.ts | 4 ++++ src/vs/workbench/contrib/terminal/browser/remotePty.ts | 4 ++++ .../terminal/browser/terminalProcessExtHostProxy.ts | 4 ++++ .../terminal/test/browser/terminalProcessManager.test.ts | 1 + .../testing/browser/testingOutputTerminalService.ts | 3 +++ .../services/terminal/common/embedderTerminalService.ts | 3 +++ yarn.lock | 8 ++++---- 13 files changed, 35 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 31f141a161a..4c8db46c218 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "native-is-elevated": "0.6.0", "native-keymap": "^3.3.2", "native-watchdog": "^1.4.1", - "node-pty": "0.11.0-beta32", + "node-pty": "0.11.0-beta33", "tas-client-umd": "0.1.8", "v8-inspect-profiler": "^0.1.0", "vscode-oniguruma": "1.7.0", diff --git a/remote/package.json b/remote/package.json index 120e99f84b8..0e72fe0e265 100644 --- a/remote/package.json +++ b/remote/package.json @@ -19,7 +19,7 @@ "keytar": "7.9.0", "minimist": "^1.2.6", "native-watchdog": "^1.4.1", - "node-pty": "0.11.0-beta32", + "node-pty": "0.11.0-beta33", "tas-client-umd": "0.1.8", "vscode-oniguruma": "1.7.0", "vscode-regexpp": "^3.1.0", diff --git a/remote/yarn.lock b/remote/yarn.lock index ad0d8b73120..7731c8ef4e0 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -537,10 +537,10 @@ node-gyp-build@^4.3.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== -node-pty@0.11.0-beta32: - version "0.11.0-beta32" - resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.11.0-beta32.tgz#49c0f174f600ac3f54a21df2a41b6f78256ff6ce" - integrity sha512-xtzB4/jYH64ksdVatYQnaU3TtCtSaDiiZPsZITmLHnywFSpI2bgfyj/bu6ofOXbe8PTtziL8bDn1U3xkRmx3mg== +node-pty@0.11.0-beta33: + version "0.11.0-beta33" + resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.11.0-beta33.tgz#722a729fb9449f591279bee1f8b431b71a9af4a1" + integrity sha512-SoP5BbSfvc8Um51rIriUEOPvMltc43iTaKXGJaJKLR3+NfQbjcCcNQGyOd9P9pvBccWYg+Rncv18qMtJKIAi1Q== dependencies: nan "^2.17.0" diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index 3bf2e8902dd..8f2ede4ed4d 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -707,7 +707,7 @@ export interface ITerminalChildProcess { input(data: string): void; processBinary(data: string): Promise; resize(cols: number, rows: number): void; - clearBuffer?(): Promise; + clearBuffer(): void | Promise; /** * Acknowledge a data event has been parsed by the terminal, this is used to implement flow diff --git a/src/vs/platform/terminal/node/ptyService.ts b/src/vs/platform/terminal/node/ptyService.ts index 18dc2e0240e..6ad3aa2e0b1 100644 --- a/src/vs/platform/terminal/node/ptyService.ts +++ b/src/vs/platform/terminal/node/ptyService.ts @@ -759,6 +759,7 @@ class PersistentTerminalProcess extends Disposable { } async clearBuffer(): Promise { this._serializer.clearBuffer(); + this._terminalProcess.clearBuffer(); } setUnicodeVersion(version: '6' | '11'): void { this.unicodeVersion = version; diff --git a/src/vs/platform/terminal/node/terminalProcess.ts b/src/vs/platform/terminal/node/terminalProcess.ts index c641ccf6d91..3c0275c37bc 100644 --- a/src/vs/platform/terminal/node/terminalProcess.ts +++ b/src/vs/platform/terminal/node/terminalProcess.ts @@ -552,6 +552,10 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess } } + clearBuffer(): void { + this._ptyProcess?.clear(); + } + acknowledgeDataEvent(charCount: number): void { // Prevent lower than 0 to heal from errors this._unacknowledgedCharCount = Math.max(this._unacknowledgedCharCount - charCount, 0); diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index 6132bd21a93..07f2364ffed 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -288,6 +288,10 @@ class ExtHostPseudoterminal implements ITerminalChildProcess { this._pty.setDimensions?.({ columns: cols, rows }); } + clearBuffer(): void | Promise { + // no-op + } + async processBinary(data: string): Promise { // No-op, processBinary is not supported in extension owned terminals. } diff --git a/src/vs/workbench/contrib/terminal/browser/remotePty.ts b/src/vs/workbench/contrib/terminal/browser/remotePty.ts index e79774065f9..939c84ad864 100644 --- a/src/vs/workbench/contrib/terminal/browser/remotePty.ts +++ b/src/vs/workbench/contrib/terminal/browser/remotePty.ts @@ -107,6 +107,10 @@ export class RemotePty extends Disposable implements ITerminalChildProcess { }); } + async clearBuffer(): Promise { + await this._remoteTerminalChannel.clearBuffer(this.id); + } + freePortKillProcess(port: string): Promise<{ port: string; processId: string }> { if (!this._remoteTerminalChannel.freePortKillProcess) { throw new Error('freePortKillProcess does not exist on the local pty service'); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts index 42f0658757c..3c3e980b9c6 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts @@ -134,6 +134,10 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal this._onResize.fire({ cols, rows }); } + clearBuffer(): void | Promise { + // no-op + } + acknowledgeDataEvent(): void { // Flow control is disabled for extension terminals } diff --git a/src/vs/workbench/contrib/terminal/test/browser/terminalProcessManager.test.ts b/src/vs/workbench/contrib/terminal/test/browser/terminalProcessManager.test.ts index 8137e5893fc..4d8b79c9d98 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/terminalProcessManager.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/terminalProcessManager.test.ts @@ -46,6 +46,7 @@ class TestTerminalChildProcess implements ITerminalChildProcess { shutdown(immediate: boolean): void { } input(data: string): void { } resize(cols: number, rows: number): void { } + clearBuffer(): void { } acknowledgeDataEvent(charCount: number): void { } async setUnicodeVersion(version: '6' | '11'): Promise { } async getInitialCwd(): Promise { return ''; } diff --git a/src/vs/workbench/contrib/testing/browser/testingOutputTerminalService.ts b/src/vs/workbench/contrib/testing/browser/testingOutputTerminalService.ts index 65ddb17f1f1..89bcc961b5e 100644 --- a/src/vs/workbench/contrib/testing/browser/testingOutputTerminalService.ts +++ b/src/vs/workbench/contrib/testing/browser/testingOutputTerminalService.ts @@ -259,6 +259,9 @@ class TestOutputProcess extends Disposable implements ITerminalChildProcess { public resize(): void { // no-op } + public clearBuffer(): void | Promise { + // no-op + } public acknowledgeDataEvent(): void { // no-op, flow control not currently implemented } diff --git a/src/vs/workbench/services/terminal/common/embedderTerminalService.ts b/src/vs/workbench/services/terminal/common/embedderTerminalService.ts index 93a79c67693..d9174af00fe 100644 --- a/src/vs/workbench/services/terminal/common/embedderTerminalService.ts +++ b/src/vs/workbench/services/terminal/common/embedderTerminalService.ts @@ -124,6 +124,9 @@ class EmbedderTerminalProcess extends Disposable implements ITerminalChildProces resize(): void { // no-op } + clearBuffer(): void | Promise { + // no-op + } acknowledgeDataEvent(): void { // no-op, flow control not currently implemented } diff --git a/yarn.lock b/yarn.lock index 1c820bf74a5..e727e316cf3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6973,10 +6973,10 @@ node-gyp-build@^4.3.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== -node-pty@0.11.0-beta32: - version "0.11.0-beta32" - resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.11.0-beta32.tgz#49c0f174f600ac3f54a21df2a41b6f78256ff6ce" - integrity sha512-xtzB4/jYH64ksdVatYQnaU3TtCtSaDiiZPsZITmLHnywFSpI2bgfyj/bu6ofOXbe8PTtziL8bDn1U3xkRmx3mg== +node-pty@0.11.0-beta33: + version "0.11.0-beta33" + resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.11.0-beta33.tgz#722a729fb9449f591279bee1f8b431b71a9af4a1" + integrity sha512-SoP5BbSfvc8Um51rIriUEOPvMltc43iTaKXGJaJKLR3+NfQbjcCcNQGyOd9P9pvBccWYg+Rncv18qMtJKIAi1Q== dependencies: nan "^2.17.0" From af709ea46281305551e26ebad8109bf320be70f1 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 9 Jun 2023 10:02:43 -0700 Subject: [PATCH 023/128] Fix NPEs on buffer line and windowsPty option --- package.json | 14 +++++------ remote/package.json | 14 +++++------ remote/web/package.json | 10 ++++---- remote/web/yarn.lock | 40 ++++++++++++++--------------- remote/yarn.lock | 56 ++++++++++++++++++++--------------------- yarn.lock | 56 ++++++++++++++++++++--------------------- 6 files changed, 95 insertions(+), 95 deletions(-) diff --git a/package.json b/package.json index 1c7af431a7f..67196fe8fdd 100644 --- a/package.json +++ b/package.json @@ -90,14 +90,14 @@ "vscode-oniguruma": "1.7.0", "vscode-regexpp": "^3.1.0", "vscode-textmate": "9.0.0", - "xterm": "5.2.0", - "xterm-addon-canvas": "0.4.0", - "xterm-addon-image": "0.4.0", - "xterm-addon-search": "0.12.0", - "xterm-addon-serialize": "0.10.0", + "xterm": "5.3.0-beta.1", + "xterm-addon-canvas": "0.5.0-beta.1", + "xterm-addon-image": "0.4.1", + "xterm-addon-search": "0.13.0-beta.1", + "xterm-addon-serialize": "0.11.0-beta.1", "xterm-addon-unicode11": "0.5.0", - "xterm-addon-webgl": "0.15.0", - "xterm-headless": "5.2.0", + "xterm-addon-webgl": "0.16.0-beta.1", + "xterm-headless": "5.3.0-beta.1", "yauzl": "^2.9.2", "yazl": "^2.4.3" }, diff --git a/remote/package.json b/remote/package.json index 120e99f84b8..5adb475c6c7 100644 --- a/remote/package.json +++ b/remote/package.json @@ -24,14 +24,14 @@ "vscode-oniguruma": "1.7.0", "vscode-regexpp": "^3.1.0", "vscode-textmate": "9.0.0", - "xterm": "5.2.0", - "xterm-addon-canvas": "0.4.0", - "xterm-addon-image": "0.4.0", - "xterm-addon-search": "0.12.0", - "xterm-addon-serialize": "0.10.0", + "xterm": "5.3.0-beta.1", + "xterm-addon-canvas": "0.5.0-beta.1", + "xterm-addon-image": "0.4.1", + "xterm-addon-search": "0.13.0-beta.1", + "xterm-addon-serialize": "0.11.0-beta.1", "xterm-addon-unicode11": "0.5.0", - "xterm-addon-webgl": "0.15.0", - "xterm-headless": "5.2.0", + "xterm-addon-webgl": "0.16.0-beta.1", + "xterm-headless": "5.3.0-beta.1", "yauzl": "^2.9.2", "yazl": "^2.4.3" }, diff --git a/remote/web/package.json b/remote/web/package.json index 66d8bf480bf..fb573e7a0e9 100644 --- a/remote/web/package.json +++ b/remote/web/package.json @@ -11,11 +11,11 @@ "tas-client-umd": "0.1.8", "vscode-oniguruma": "1.7.0", "vscode-textmate": "9.0.0", - "xterm": "5.2.0", - "xterm-addon-canvas": "0.4.0", - "xterm-addon-image": "0.4.0", - "xterm-addon-search": "0.12.0", + "xterm": "5.3.0-beta.1", + "xterm-addon-canvas": "0.5.0-beta.1", + "xterm-addon-image": "0.4.1", + "xterm-addon-search": "0.13.0-beta.1", "xterm-addon-unicode11": "0.5.0", - "xterm-addon-webgl": "0.15.0" + "xterm-addon-webgl": "0.16.0-beta.1" } } diff --git a/remote/web/yarn.lock b/remote/web/yarn.lock index 101bcd9e9f7..325be24ac89 100644 --- a/remote/web/yarn.lock +++ b/remote/web/yarn.lock @@ -68,32 +68,32 @@ vscode-textmate@9.0.0: resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-9.0.0.tgz#313c6c8792b0507aef35aeb81b6b370b37c44d6c" integrity sha512-Cl65diFGxz7gpwbav10HqiY/eVYTO1sjQpmRmV991Bj7wAoOAjGQ97PpQcXorDE2Uc4hnGWLY17xme+5t6MlSg== -xterm-addon-canvas@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.4.0.tgz#a6ee6a56deb0c495fcef29afe6d94b7119a0f334" - integrity sha512-iTC8CdjX9+hGX7jiEuiDMXzHsY/FKJdVnbjep5xjRXNu7RKOk15xuecIkJ7HZORqMVPpr4DGS3jyd9XUoBuxqw== +xterm-addon-canvas@0.5.0-beta.1: + version "0.5.0-beta.1" + resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.5.0-beta.1.tgz#b5ae185741423715460a66029c944b4dededfab0" + integrity sha512-A7yjIpyTcOh8ckPJw1YFDvwbTbQ+grM+kTtutOvu5LjLSV9EoCHX17kVoiT2V29ywF7KJMeLYwfBwyFE3uA3QQ== -xterm-addon-image@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.4.0.tgz#36e98fa892db11755a5f6e9654f924e876e29bf8" - integrity sha512-3wumCJo4WTzxvecSMxJ7XtpVQeFe4gE2cdHCyUdo7zagVkS18YXJacGx6DjlAIccdJn6/LhGuD99xOSSvYx9Gw== +xterm-addon-image@0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.4.1.tgz#ec8f750af48005ad641c1128fa1f551ac198472a" + integrity sha512-iJpYyvtbHg4oXSv+D6J73ZfCjnboZpbZ567MLplXDBlYSUknv3kvPTfVMPJATV7Zsx7+bDgyXboCh9vsDf/m/w== -xterm-addon-search@0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.12.0.tgz#2ef8f56aecf699a3989223a1260f1e079d7c74e2" - integrity sha512-hXAuO7Ts2+Jf9K8mZrUx8IFd7c/Flgks/jyqA1L4reymyfmXtcsd+WDLel8R9Tgy2CLyKABVBP09/Ua/FmXcvg== +xterm-addon-search@0.13.0-beta.1: + version "0.13.0-beta.1" + resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.13.0-beta.1.tgz#9fb6ede402d4c369d59d5d6faefe54a05b125bcf" + integrity sha512-rdOIhwkfRASqTriUO8QP9UY0p6BosLMv1NXTZqhgq3/5xAXx4VZg6mlQjTRGnUz/GJIN1jU9e/Vp20SpocP/Hw== xterm-addon-unicode11@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.5.0.tgz#41c0d96acc1e3bb6c6596eee64e163b6bca74be7" integrity sha512-Jm4/g4QiTxiKiTbYICQgC791ubhIZyoIwxAIgOW8z8HWFNY+lwk+dwaKEaEeGBfM48Vk8fklsUW9u/PlenYEBg== -xterm-addon-webgl@0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.15.0.tgz#c10f93ca619524f5a470eaac44258bab0ae8e3c7" - integrity sha512-ZLcqogMFHr4g/YRhcCh3xE8tTklnyut/M+O/XhVsFBRB/YCvYhPdLQ5/AQk54V0wjWAQpa8CF3W8DVR9OqyMCg== +xterm-addon-webgl@0.16.0-beta.1: + version "0.16.0-beta.1" + resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0-beta.1.tgz#e2b41c6b5f838724a5cb3cfa4231e2d1b8f3f130" + integrity sha512-iJK+Uk+23Mh84BNa/44JqAdPESdNKN0ONfw6UztmDk2HTvsy47sU+d/lgF2kOcuI3ew2tRzK9YlupOUhVPwe9g== -xterm@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.2.0.tgz#7e716bbe448ecef0ea387586c59fbc51a08f9125" - integrity sha512-C1NXTZYfXPTXzF7uw7Ao6/IFGrtAkHv4e/PCQRpgYHyMobvaRs3nJNGK32hX/skdMUQJ6yhSnyzfmWCQwG9qvg== +xterm@5.3.0-beta.1: + version "5.3.0-beta.1" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0-beta.1.tgz#68e76f2818965592c60bb269360f1fc37219f4ae" + integrity sha512-2v/Qmk1A0wO5oouRWUWZ3wxqtfFjxsQbZ1sWxPGJTQvoTSdkORLG44gxrU+Sk2jB5Ojz+3Kg42bnfFghsXVzlw== diff --git a/remote/yarn.lock b/remote/yarn.lock index ad0d8b73120..404f59cb93b 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -836,45 +836,45 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -xterm-addon-canvas@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.4.0.tgz#a6ee6a56deb0c495fcef29afe6d94b7119a0f334" - integrity sha512-iTC8CdjX9+hGX7jiEuiDMXzHsY/FKJdVnbjep5xjRXNu7RKOk15xuecIkJ7HZORqMVPpr4DGS3jyd9XUoBuxqw== +xterm-addon-canvas@0.5.0-beta.1: + version "0.5.0-beta.1" + resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.5.0-beta.1.tgz#b5ae185741423715460a66029c944b4dededfab0" + integrity sha512-A7yjIpyTcOh8ckPJw1YFDvwbTbQ+grM+kTtutOvu5LjLSV9EoCHX17kVoiT2V29ywF7KJMeLYwfBwyFE3uA3QQ== -xterm-addon-image@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.4.0.tgz#36e98fa892db11755a5f6e9654f924e876e29bf8" - integrity sha512-3wumCJo4WTzxvecSMxJ7XtpVQeFe4gE2cdHCyUdo7zagVkS18YXJacGx6DjlAIccdJn6/LhGuD99xOSSvYx9Gw== +xterm-addon-image@0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.4.1.tgz#ec8f750af48005ad641c1128fa1f551ac198472a" + integrity sha512-iJpYyvtbHg4oXSv+D6J73ZfCjnboZpbZ567MLplXDBlYSUknv3kvPTfVMPJATV7Zsx7+bDgyXboCh9vsDf/m/w== -xterm-addon-search@0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.12.0.tgz#2ef8f56aecf699a3989223a1260f1e079d7c74e2" - integrity sha512-hXAuO7Ts2+Jf9K8mZrUx8IFd7c/Flgks/jyqA1L4reymyfmXtcsd+WDLel8R9Tgy2CLyKABVBP09/Ua/FmXcvg== +xterm-addon-search@0.13.0-beta.1: + version "0.13.0-beta.1" + resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.13.0-beta.1.tgz#9fb6ede402d4c369d59d5d6faefe54a05b125bcf" + integrity sha512-rdOIhwkfRASqTriUO8QP9UY0p6BosLMv1NXTZqhgq3/5xAXx4VZg6mlQjTRGnUz/GJIN1jU9e/Vp20SpocP/Hw== -xterm-addon-serialize@0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.10.0.tgz#c16a8cb456dcbd2f008fa83d15ce1d4721892e01" - integrity sha512-Syp9eSBypn70iAczcJ+kAi0foQIepAvFS6x53JwI4XylTBHn87Ep9fovslhwmUV3rwH2yMnpdDjXH5W/whx2lA== +xterm-addon-serialize@0.11.0-beta.1: + version "0.11.0-beta.1" + resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.11.0-beta.1.tgz#a4bc1ef5d8b8db0180c07f071ce543536d806db1" + integrity sha512-2I9Dq49nXUc6ymznwJp8SUsDq5owUdYviUy11HzLh35baDjzbG31CCu5Gs8KSlfUxpNRr3BxaV5/hx7MRPu7Qg== xterm-addon-unicode11@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.5.0.tgz#41c0d96acc1e3bb6c6596eee64e163b6bca74be7" integrity sha512-Jm4/g4QiTxiKiTbYICQgC791ubhIZyoIwxAIgOW8z8HWFNY+lwk+dwaKEaEeGBfM48Vk8fklsUW9u/PlenYEBg== -xterm-addon-webgl@0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.15.0.tgz#c10f93ca619524f5a470eaac44258bab0ae8e3c7" - integrity sha512-ZLcqogMFHr4g/YRhcCh3xE8tTklnyut/M+O/XhVsFBRB/YCvYhPdLQ5/AQk54V0wjWAQpa8CF3W8DVR9OqyMCg== +xterm-addon-webgl@0.16.0-beta.1: + version "0.16.0-beta.1" + resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0-beta.1.tgz#e2b41c6b5f838724a5cb3cfa4231e2d1b8f3f130" + integrity sha512-iJK+Uk+23Mh84BNa/44JqAdPESdNKN0ONfw6UztmDk2HTvsy47sU+d/lgF2kOcuI3ew2tRzK9YlupOUhVPwe9g== -xterm-headless@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.2.0.tgz#7e75d1b942e319976bf982d1682516db006a5368" - integrity sha512-FPrzB7CxyzrjEEGU7dEXVtVFjDx2YIPkx/lOfKPTarJl3BtZfFvuWUAXRD+KIrV5zy1QvAoqmiBOsG+sXC9knQ== +xterm-headless@5.3.0-beta.1: + version "5.3.0-beta.1" + resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.3.0-beta.1.tgz#8c7db703b9f57496c2f052411721c00909b08e8b" + integrity sha512-6rsv6l44hLL9Eg2UrfAbCiZcAucdHuPyIsovl2BEmluo4chwd4LD7VINRlPV/x8ML2HgD9SohFyNs5BQAc07Gg== -xterm@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.2.0.tgz#7e716bbe448ecef0ea387586c59fbc51a08f9125" - integrity sha512-C1NXTZYfXPTXzF7uw7Ao6/IFGrtAkHv4e/PCQRpgYHyMobvaRs3nJNGK32hX/skdMUQJ6yhSnyzfmWCQwG9qvg== +xterm@5.3.0-beta.1: + version "5.3.0-beta.1" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0-beta.1.tgz#68e76f2818965592c60bb269360f1fc37219f4ae" + integrity sha512-2v/Qmk1A0wO5oouRWUWZ3wxqtfFjxsQbZ1sWxPGJTQvoTSdkORLG44gxrU+Sk2jB5Ojz+3Kg42bnfFghsXVzlw== yallist@^4.0.0: version "4.0.0" diff --git a/yarn.lock b/yarn.lock index cd7ea37b40a..5c5fcda3f02 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10453,45 +10453,45 @@ xtend@~2.1.1: dependencies: object-keys "~0.4.0" -xterm-addon-canvas@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.4.0.tgz#a6ee6a56deb0c495fcef29afe6d94b7119a0f334" - integrity sha512-iTC8CdjX9+hGX7jiEuiDMXzHsY/FKJdVnbjep5xjRXNu7RKOk15xuecIkJ7HZORqMVPpr4DGS3jyd9XUoBuxqw== +xterm-addon-canvas@0.5.0-beta.1: + version "0.5.0-beta.1" + resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.5.0-beta.1.tgz#b5ae185741423715460a66029c944b4dededfab0" + integrity sha512-A7yjIpyTcOh8ckPJw1YFDvwbTbQ+grM+kTtutOvu5LjLSV9EoCHX17kVoiT2V29ywF7KJMeLYwfBwyFE3uA3QQ== -xterm-addon-image@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.4.0.tgz#36e98fa892db11755a5f6e9654f924e876e29bf8" - integrity sha512-3wumCJo4WTzxvecSMxJ7XtpVQeFe4gE2cdHCyUdo7zagVkS18YXJacGx6DjlAIccdJn6/LhGuD99xOSSvYx9Gw== +xterm-addon-image@0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.4.1.tgz#ec8f750af48005ad641c1128fa1f551ac198472a" + integrity sha512-iJpYyvtbHg4oXSv+D6J73ZfCjnboZpbZ567MLplXDBlYSUknv3kvPTfVMPJATV7Zsx7+bDgyXboCh9vsDf/m/w== -xterm-addon-search@0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.12.0.tgz#2ef8f56aecf699a3989223a1260f1e079d7c74e2" - integrity sha512-hXAuO7Ts2+Jf9K8mZrUx8IFd7c/Flgks/jyqA1L4reymyfmXtcsd+WDLel8R9Tgy2CLyKABVBP09/Ua/FmXcvg== +xterm-addon-search@0.13.0-beta.1: + version "0.13.0-beta.1" + resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.13.0-beta.1.tgz#9fb6ede402d4c369d59d5d6faefe54a05b125bcf" + integrity sha512-rdOIhwkfRASqTriUO8QP9UY0p6BosLMv1NXTZqhgq3/5xAXx4VZg6mlQjTRGnUz/GJIN1jU9e/Vp20SpocP/Hw== -xterm-addon-serialize@0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.10.0.tgz#c16a8cb456dcbd2f008fa83d15ce1d4721892e01" - integrity sha512-Syp9eSBypn70iAczcJ+kAi0foQIepAvFS6x53JwI4XylTBHn87Ep9fovslhwmUV3rwH2yMnpdDjXH5W/whx2lA== +xterm-addon-serialize@0.11.0-beta.1: + version "0.11.0-beta.1" + resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.11.0-beta.1.tgz#a4bc1ef5d8b8db0180c07f071ce543536d806db1" + integrity sha512-2I9Dq49nXUc6ymznwJp8SUsDq5owUdYviUy11HzLh35baDjzbG31CCu5Gs8KSlfUxpNRr3BxaV5/hx7MRPu7Qg== xterm-addon-unicode11@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.5.0.tgz#41c0d96acc1e3bb6c6596eee64e163b6bca74be7" integrity sha512-Jm4/g4QiTxiKiTbYICQgC791ubhIZyoIwxAIgOW8z8HWFNY+lwk+dwaKEaEeGBfM48Vk8fklsUW9u/PlenYEBg== -xterm-addon-webgl@0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.15.0.tgz#c10f93ca619524f5a470eaac44258bab0ae8e3c7" - integrity sha512-ZLcqogMFHr4g/YRhcCh3xE8tTklnyut/M+O/XhVsFBRB/YCvYhPdLQ5/AQk54V0wjWAQpa8CF3W8DVR9OqyMCg== +xterm-addon-webgl@0.16.0-beta.1: + version "0.16.0-beta.1" + resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0-beta.1.tgz#e2b41c6b5f838724a5cb3cfa4231e2d1b8f3f130" + integrity sha512-iJK+Uk+23Mh84BNa/44JqAdPESdNKN0ONfw6UztmDk2HTvsy47sU+d/lgF2kOcuI3ew2tRzK9YlupOUhVPwe9g== -xterm-headless@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.2.0.tgz#7e75d1b942e319976bf982d1682516db006a5368" - integrity sha512-FPrzB7CxyzrjEEGU7dEXVtVFjDx2YIPkx/lOfKPTarJl3BtZfFvuWUAXRD+KIrV5zy1QvAoqmiBOsG+sXC9knQ== +xterm-headless@5.3.0-beta.1: + version "5.3.0-beta.1" + resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.3.0-beta.1.tgz#8c7db703b9f57496c2f052411721c00909b08e8b" + integrity sha512-6rsv6l44hLL9Eg2UrfAbCiZcAucdHuPyIsovl2BEmluo4chwd4LD7VINRlPV/x8ML2HgD9SohFyNs5BQAc07Gg== -xterm@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.2.0.tgz#7e716bbe448ecef0ea387586c59fbc51a08f9125" - integrity sha512-C1NXTZYfXPTXzF7uw7Ao6/IFGrtAkHv4e/PCQRpgYHyMobvaRs3nJNGK32hX/skdMUQJ6yhSnyzfmWCQwG9qvg== +xterm@5.3.0-beta.1: + version "5.3.0-beta.1" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0-beta.1.tgz#68e76f2818965592c60bb269360f1fc37219f4ae" + integrity sha512-2v/Qmk1A0wO5oouRWUWZ3wxqtfFjxsQbZ1sWxPGJTQvoTSdkORLG44gxrU+Sk2jB5Ojz+3Kg42bnfFghsXVzlw== y18n@^3.2.1: version "3.2.2" From 761f2b05c4652097da1e225066cd6725a6ccf22f Mon Sep 17 00:00:00 2001 From: Tyler James Leonhardt Date: Fri, 9 Jun 2023 10:26:49 -0700 Subject: [PATCH 024/128] Use a better id for QuickPickList (#184733) Using saneLabel before is computationally more intense then just checking a few properties. Additionally, this wasn't taking into account the `id`. So this change is not only faster, but also more accurate! ref https://github.com/microsoft/vscode/issues/184615 --- src/vs/platform/quickinput/browser/quickInputList.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/vs/platform/quickinput/browser/quickInputList.ts b/src/vs/platform/quickinput/browser/quickInputList.ts index 92ffee3e676..1321e332424 100644 --- a/src/vs/platform/quickinput/browser/quickInputList.ts +++ b/src/vs/platform/quickinput/browser/quickInputList.ts @@ -466,7 +466,17 @@ export class QuickInputList { const delegate = new ListElementDelegate(); const accessibilityProvider = new QuickInputAccessibilityProvider(); this.list = options.createList('QuickInput', this.container, delegate, [new ListElementRenderer(this.options.styles.colorScheme)], { - identityProvider: { getId: element => element.saneLabel }, + identityProvider: { + getId: element => { + // always prefer item over separator because if item is defined, it must be the main item type + // always prefer a defined id if one was specified and use label as a fallback + return element.item?.id + ?? element.item?.label + ?? element.separator?.id + ?? element.separator?.label + ?? ''; + } + }, setRowLineHeight: false, multipleSelectionSupport: false, horizontalScrolling: false, From 5120683cb131b1fb49f55f1f7a7ccf6f80f5d273 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 9 Jun 2023 10:27:19 -0700 Subject: [PATCH 025/128] Handle comments in /etc/shells profile parsing properly Fixes #183933 --- src/vs/platform/terminal/node/terminalProfiles.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/vs/platform/terminal/node/terminalProfiles.ts b/src/vs/platform/terminal/node/terminalProfiles.ts index 32ee253c5ec..5e26c87958a 100644 --- a/src/vs/platform/terminal/node/terminalProfiles.ts +++ b/src/vs/platform/terminal/node/terminalProfiles.ts @@ -391,7 +391,14 @@ async function detectAvailableUnixProfiles( // Add non-quick launch profiles if (includeDetectedProfiles) { const contents = (await fsProvider.readFile('/etc/shells')).toString(); - const profiles = testPaths || contents.split('\n').filter(e => e.trim().includes('#') && e.trim().length > 0); + const profiles = ( + (testPaths || contents.split('\n')) + .map(e => { + const index = e.indexOf('#'); + return index === -1 ? e : e.substring(0, index); + }) + .filter(e => e.trim().length > 0) + ); const counts: Map = new Map(); for (const profile of profiles) { let profileName = basename(profile); From bdff5a1cc3a95dcec2deb68ceb3382e753ad959f Mon Sep 17 00:00:00 2001 From: Tyler James Leonhardt Date: Fri, 9 Jun 2023 10:32:14 -0700 Subject: [PATCH 026/128] Use correct index in QuickInputList map (#184737) I was using the value of index before we combined quickpickitems and separators... when I should have been using the result's index. This fixes that, and also adds a stopwatch for semantic similarity so we can log how see it takes. --- .../platform/quickinput/browser/quickInputList.ts | 3 ++- .../common/semanticSimilarityService.ts | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/vs/platform/quickinput/browser/quickInputList.ts b/src/vs/platform/quickinput/browser/quickInputList.ts index 1321e332424..c118110d2b6 100644 --- a/src/vs/platform/quickinput/browser/quickInputList.ts +++ b/src/vs/platform/quickinput/browser/quickInputList.ts @@ -700,8 +700,9 @@ export class QuickInputList { this._listElementChecked ); + const resultIndex = result.length; result.push(element); - elementsToIndexes.set(element.item ?? element.separator!, index); + elementsToIndexes.set(element.item ?? element.separator!, resultIndex); return result; }, [] as IListElement[]); this.elementsToIndexes = elementsToIndexes; diff --git a/src/vs/workbench/services/semanticSimilarity/common/semanticSimilarityService.ts b/src/vs/workbench/services/semanticSimilarity/common/semanticSimilarityService.ts index 19b97cc072b..ff203430c99 100644 --- a/src/vs/workbench/services/semanticSimilarity/common/semanticSimilarityService.ts +++ b/src/vs/workbench/services/semanticSimilarity/common/semanticSimilarityService.ts @@ -8,6 +8,8 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { CancelablePromise, createCancelablePromise, raceCancellablePromises, timeout } from 'vs/base/common/async'; import { IDisposable } from 'vs/base/common/lifecycle'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { StopWatch } from 'vs/base/common/stopwatch'; +import { ILogService } from 'vs/platform/log/common/log'; export const ISemanticSimilarityService = createDecorator('ISemanticSimilarityService'); @@ -30,6 +32,8 @@ export class SemanticSimilarityService implements ISemanticSimilarityService { private readonly _providers: ISemanticSimilarityProvider[] = []; + constructor(@ILogService private readonly logService: ILogService) { } + isEnabled(): boolean { return this._providers.length > 0; } @@ -51,6 +55,8 @@ export class SemanticSimilarityService implements ISemanticSimilarityService { throw new Error('No semantic similarity providers registered'); } + const stopwatch = StopWatch.create(); + const cancellablePromises: Array> = []; const timer = timeout(SemanticSimilarityService.DEFAULT_TIMEOUT); @@ -83,8 +89,13 @@ export class SemanticSimilarityService implements ISemanticSimilarityService { throw new Error('Semantic similarity provider timed out'); })); - const result = await raceCancellablePromises(cancellablePromises); - return result; + try { + const result = await raceCancellablePromises(cancellablePromises); + return result; + } finally { + stopwatch.stop(); + this.logService.trace(`[SemanticSimilarityService]: getSimilarityScore took ${stopwatch.elapsed()}ms`); + } } } From 6cd5ac180a6362b45b415a624f62173caf7428a1 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Fri, 9 Jun 2023 19:43:06 +0200 Subject: [PATCH 027/128] Implements inline diff view in diff editor v2. (#184735) --- .../workbench/workbench-dev.html | 1 + .../electron-sandbox/workbench/workbench.html | 1 + src/vs/editor/browser/editorBrowser.ts | 19 -- .../editor/browser/widget/diffEditorWidget.ts | 91 -------- .../widget/diffEditorWidget2/decorations.ts | 11 + .../diffEditorWidget2/diffEditorWidget2.ts | 70 +++--- .../widget/diffEditorWidget2/diffModel.ts | 2 +- .../inlineDiffDeletedCodeMargin.ts | 196 +++++++++++++++++ .../widget/diffEditorWidget2/lineAlignment.ts | 189 +++++++++++++++-- .../widget/diffEditorWidget2/renderLines.ts | 200 ++++++++++++++++++ src/vs/editor/common/core/lineRange.ts | 8 + src/vs/monaco.d.ts | 18 +- 12 files changed, 627 insertions(+), 179 deletions(-) create mode 100644 src/vs/editor/browser/widget/diffEditorWidget2/inlineDiffDeletedCodeMargin.ts create mode 100644 src/vs/editor/browser/widget/diffEditorWidget2/renderLines.ts diff --git a/src/vs/code/electron-sandbox/workbench/workbench-dev.html b/src/vs/code/electron-sandbox/workbench/workbench-dev.html index 42fbfd69ac3..94adff77012 100644 --- a/src/vs/code/electron-sandbox/workbench/workbench-dev.html +++ b/src/vs/code/electron-sandbox/workbench/workbench-dev.html @@ -49,6 +49,7 @@ cellRendererEditorText defaultWorkerFactory diffEditorWidget + diffEditorWidget2 diffReview domLineBreaksComputer dompurify diff --git a/src/vs/code/electron-sandbox/workbench/workbench.html b/src/vs/code/electron-sandbox/workbench/workbench.html index 9096f5261fb..369eaac1f25 100644 --- a/src/vs/code/electron-sandbox/workbench/workbench.html +++ b/src/vs/code/electron-sandbox/workbench/workbench.html @@ -49,6 +49,7 @@ cellRendererEditorText defaultWorkerFactory diffEditorWidget + diffEditorWidget2 diffReview domLineBreaksComputer dompurify diff --git a/src/vs/editor/browser/editorBrowser.ts b/src/vs/editor/browser/editorBrowser.ts index eb084bf8ac3..836448dac93 100644 --- a/src/vs/editor/browser/editorBrowser.ts +++ b/src/vs/editor/browser/editorBrowser.ts @@ -1095,13 +1095,6 @@ export interface IActiveCodeEditor extends ICodeEditor { getScrolledVisiblePosition(position: IPosition): { top: number; left: number; height: number }; } -/** - * Information about a line in the diff editor - */ -export interface IDiffLineInformation { - readonly equivalentLineNumber: number; -} - /** * @internal */ @@ -1195,18 +1188,6 @@ export interface IDiffEditor extends editorCommon.IEditor { */ getDiffComputationResult(): IDiffComputationResult | null; - /** - * Get information based on computed diff about a line number from the original model. - * If the diff computation is not finished or the model is missing, will return null. - */ - getDiffLineInformationForOriginal(lineNumber: number): IDiffLineInformation | null; - - /** - * Get information based on computed diff about a line number from the modified model. - * If the diff computation is not finished or the model is missing, will return null. - */ - getDiffLineInformationForModified(lineNumber: number): IDiffLineInformation | null; - /** * Update the editor's options after the editor has been created. */ diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index af4ac4c5eb4..e9d3e2d1ec1 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -1461,97 +1461,6 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE this._doLayout(); } - private _getLineChangeAtOrBeforeLineNumber(lineNumber: number, startLineNumberExtractor: (lineChange: ILineChange) => number): ILineChange | null { - const lineChanges = (this._diffComputationResult ? this._diffComputationResult.changes : []); - if (lineChanges.length === 0 || lineNumber < startLineNumberExtractor(lineChanges[0])) { - // There are no changes or `lineNumber` is before the first change - return null; - } - - let min = 0; - let max = lineChanges.length - 1; - while (min < max) { - const mid = Math.floor((min + max) / 2); - const midStart = startLineNumberExtractor(lineChanges[mid]); - const midEnd = (mid + 1 <= max ? startLineNumberExtractor(lineChanges[mid + 1]) : Constants.MAX_SAFE_SMALL_INTEGER); - - if (lineNumber < midStart) { - max = mid - 1; - } else if (lineNumber >= midEnd) { - min = mid + 1; - } else { - // HIT! - min = mid; - max = mid; - } - } - return lineChanges[min]; - } - - private _getEquivalentLineForOriginalLineNumber(lineNumber: number): number { - const lineChange = this._getLineChangeAtOrBeforeLineNumber(lineNumber, (lineChange) => lineChange.originalStartLineNumber); - - if (!lineChange) { - return lineNumber; - } - - const originalEquivalentLineNumber = lineChange.originalStartLineNumber + (lineChange.originalEndLineNumber > 0 ? -1 : 0); - const modifiedEquivalentLineNumber = lineChange.modifiedStartLineNumber + (lineChange.modifiedEndLineNumber > 0 ? -1 : 0); - const lineChangeOriginalLength = (lineChange.originalEndLineNumber > 0 ? (lineChange.originalEndLineNumber - lineChange.originalStartLineNumber + 1) : 0); - const lineChangeModifiedLength = (lineChange.modifiedEndLineNumber > 0 ? (lineChange.modifiedEndLineNumber - lineChange.modifiedStartLineNumber + 1) : 0); - - - const delta = lineNumber - originalEquivalentLineNumber; - - if (delta <= lineChangeOriginalLength) { - return modifiedEquivalentLineNumber + Math.min(delta, lineChangeModifiedLength); - } - - return modifiedEquivalentLineNumber + lineChangeModifiedLength - lineChangeOriginalLength + delta; - } - - private _getEquivalentLineForModifiedLineNumber(lineNumber: number): number { - const lineChange = this._getLineChangeAtOrBeforeLineNumber(lineNumber, (lineChange) => lineChange.modifiedStartLineNumber); - - if (!lineChange) { - return lineNumber; - } - - const originalEquivalentLineNumber = lineChange.originalStartLineNumber + (lineChange.originalEndLineNumber > 0 ? -1 : 0); - const modifiedEquivalentLineNumber = lineChange.modifiedStartLineNumber + (lineChange.modifiedEndLineNumber > 0 ? -1 : 0); - const lineChangeOriginalLength = (lineChange.originalEndLineNumber > 0 ? (lineChange.originalEndLineNumber - lineChange.originalStartLineNumber + 1) : 0); - const lineChangeModifiedLength = (lineChange.modifiedEndLineNumber > 0 ? (lineChange.modifiedEndLineNumber - lineChange.modifiedStartLineNumber + 1) : 0); - - - const delta = lineNumber - modifiedEquivalentLineNumber; - - if (delta <= lineChangeModifiedLength) { - return originalEquivalentLineNumber + Math.min(delta, lineChangeOriginalLength); - } - - return originalEquivalentLineNumber + lineChangeOriginalLength - lineChangeModifiedLength + delta; - } - - public getDiffLineInformationForOriginal(lineNumber: number): editorBrowser.IDiffLineInformation | null { - if (!this._diffComputationResult) { - // Cannot answer that which I don't know - return null; - } - return { - equivalentLineNumber: this._getEquivalentLineForOriginalLineNumber(lineNumber) - }; - } - - public getDiffLineInformationForModified(lineNumber: number): editorBrowser.IDiffLineInformation | null { - if (!this._diffComputationResult) { - // Cannot answer that which I don't know - return null; - } - return { - equivalentLineNumber: this._getEquivalentLineForModifiedLineNumber(lineNumber) - }; - } - public goToDiff(target: 'previous' | 'next'): void { if (target === 'next') { this._diffNavigator?.next(); diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/decorations.ts b/src/vs/editor/browser/widget/diffEditorWidget2/decorations.ts index 5fe8b883b00..4d6dcafe955 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/decorations.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/decorations.ts @@ -3,18 +3,29 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Codicon } from 'vs/base/common/codicons'; +import { ThemeIcon } from 'vs/base/common/themables'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; +import { localize } from 'vs/nls'; +import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; + +export const diffInsertIcon = registerIcon('diff-insert', Codicon.add, localize('diffInsertIcon', 'Line decoration for inserts in the diff editor.')); +export const diffRemoveIcon = registerIcon('diff-remove', Codicon.remove, localize('diffRemoveIcon', 'Line decoration for removals in the diff editor.')); export const diffFullLineAddDecoration = ModelDecorationOptions.register({ className: 'line-insert', description: 'line-insert', isWholeLine: true, + linesDecorationsClassName: 'insert-sign ' + ThemeIcon.asClassName(diffInsertIcon), + marginClassName: 'gutter-insert', }); export const diffFullLineDeleteDecoration = ModelDecorationOptions.register({ className: 'line-delete', description: 'line-delete', isWholeLine: true, + linesDecorationsClassName: 'delete-sign ' + ThemeIcon.asClassName(diffRemoveIcon), + marginClassName: 'gutter-delete', }); export const diffAddDecoration = ModelDecorationOptions.register({ diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts index 6722507b421..9ca82686cb9 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts @@ -7,13 +7,13 @@ import { IBoundarySashes } from 'vs/base/browser/ui/sash/sash'; import { findLast } from 'vs/base/common/arrays'; import { onUnexpectedError } from 'vs/base/common/errors'; import { Emitter, Event } from 'vs/base/common/event'; -import { IObservable, ISettableObservable, derived, keepAlive, observableValue, waitForState } from 'vs/base/common/observable'; -import { disposableObservableValue } from 'vs/base/common/observableImpl/base'; +import { IObservable, ISettableObservable, autorun, derived, keepAlive, observableValue, waitForState } from 'vs/base/common/observable'; +import { disposableObservableValue, transaction } from 'vs/base/common/observableImpl/base'; import { isDefined } from 'vs/base/common/types'; import { Constants } from 'vs/base/common/uint'; import 'vs/css!./style'; import { IEditorConstructionOptions } from 'vs/editor/browser/config/editorConfiguration'; -import { ICodeEditor, IDiffEditor, IDiffEditorConstructionOptions, IDiffLineInformation } from 'vs/editor/browser/editorBrowser'; +import { ICodeEditor, IDiffEditor, IDiffEditorConstructionOptions } from 'vs/editor/browser/editorBrowser'; import { EditorExtensionsRegistry, IDiffEditorContributionDescription } from 'vs/editor/browser/editorExtensions'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { CodeEditorWidget, ICodeEditorWidgetOptions } from 'vs/editor/browser/widget/codeEditorWidget'; @@ -79,7 +79,7 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { ); private readonly _rootSizeObserver: ObservableElementSizeObserver; private readonly _options: ISettableObservable; - private readonly _sash: DiffEditorSash; + private readonly _sash: IObservable; private readonly _renderOverviewRuler: IObservable; constructor( @@ -114,18 +114,33 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { this._register(applyObservableDecorations(this._modifiedEditor, this._decorations.map(d => d?.modifiedDecorations || []))); this._renderOverviewRuler = this._options.map(o => o.renderOverviewRuler); - this._sash = this._register(new DiffEditorSash( - this._options.map(o => o.enableSplitViewResizing), - this._options.map(o => o.splitViewDefaultRatio), - this.elements.root, - { - height: this._rootSizeObserver.height, - width: this._rootSizeObserver.width.map((w, reader) => w - (this._renderOverviewRuler.read(reader) ? OverviewRulerPart.ENTIRE_DIFF_OVERVIEW_WIDTH : 0)), - } - )); + const sash = this._register(disposableObservableValue('sash', undefined)); + this._sash = sash; + + this._register(autorun('update sash', reader => { + const showSash = this._options.read(reader).renderSideBySide; + + this.elements.root.classList.toggle('side-by-side', showSash); + + transaction(tx => { + sash.set(undefined, tx); + if (showSash) { + sash.set(new DiffEditorSash( + this._options.map(o => o.enableSplitViewResizing), + this._options.map(o => o.splitViewDefaultRatio), + this.elements.root, + { + height: this._rootSizeObserver.height, + width: this._rootSizeObserver.width.map((w, reader) => w - (this._renderOverviewRuler.read(reader) ? OverviewRulerPart.ENTIRE_DIFF_OVERVIEW_WIDTH : 0)), + } + ), tx); + } + }); + })); + this._register(new UnchangedRangesFeature(this._originalEditor, this._modifiedEditor, this._diffModel)); - this._register(new ViewZoneAlignment(this._originalEditor, this._modifiedEditor, this._diffModel)); + this._register(this._instantiationService.createInstance(ViewZoneAlignment, this._originalEditor, this._modifiedEditor, this._diffModel, this._options.map(o => o.renderSideBySide))); this._register(this._instantiationService.createInstance(OverviewRulerPart, this._originalEditor, @@ -157,17 +172,19 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { private readonly _layoutInfo = derived('modifiedEditorLayoutInfo', (reader) => { const width = this._rootSizeObserver.width.read(reader); const height = this._rootSizeObserver.height.read(reader); - const sashLeft = this._sash.sashLeft.read(reader); + const sashLeft = this._sash.read(reader)?.sashLeft.read(reader); - this.elements.original.style.width = sashLeft + 'px'; + const originalWidth = sashLeft ?? Math.max(5, this._originalEditor.getLayoutInfo().decorationsLeft); + + this.elements.original.style.width = originalWidth + 'px'; this.elements.original.style.left = '0px'; - this.elements.modified.style.width = (width - sashLeft) + 'px'; - this.elements.modified.style.left = sashLeft + 'px'; + this.elements.modified.style.width = (width - originalWidth) + 'px'; + this.elements.modified.style.left = originalWidth + 'px'; - this._originalEditor.layout({ width: sashLeft, height: height }); + this._originalEditor.layout({ width: originalWidth, height: height }); this._modifiedEditor.layout({ - width: width - sashLeft - + width: width - originalWidth - (this._renderOverviewRuler.read(reader) ? OverviewRulerPart.ENTIRE_DIFF_OVERVIEW_WIDTH : 0), height }); @@ -447,7 +464,7 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { this._options.map(o => o.ignoreTrimWhitespace), this._options.map(o => o.maxComputationTime), this._options.map(o => o.experimental.collapseUnchangedRegions!), - this._options.map(o => o.experimental.showMoves!), + this._options.map(o => o.experimental.showMoves! && o.renderSideBySide), this._instantiationService.createInstance(WorkerBasedDocumentDiffProvider, this._options.get()) ) : undefined, undefined); } @@ -465,7 +482,8 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { getModifiedEditor(): ICodeEditor { return this._modifiedEditor; } setBoundarySashes(sashes: IBoundarySashes): void { - this._sash.setBoundarySashes(sashes); + // TODO + this._sash.get()?.setBoundarySashes(sashes); } readonly onDidUpdateDiff: Event = e => { @@ -492,14 +510,6 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { return null; //throw new Error('Method not implemented.'); } - getDiffLineInformationForOriginal(lineNumber: number): IDiffLineInformation | null { - return null; - //throw new Error('Method not implemented.'); - } - getDiffLineInformationForModified(lineNumber: number): IDiffLineInformation | null { - return null; - //throw new Error('Method not implemented.'); - } private _goTo(diff: DiffMapping): void { this._modifiedEditor.setPosition(new Position(diff.lineRangeMapping.modifiedRange.startLineNumber, 1)); diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffModel.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffModel.ts index c8de0cdcf36..4bf5a9ae629 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffModel.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffModel.ts @@ -33,7 +33,7 @@ export class DiffModel extends Disposable { public readonly syncedMovedTexts = observableValue('syncedMovedText', undefined); constructor( - model: IDiffEditorModel, + public readonly model: IDiffEditorModel, ignoreTrimWhitespace: IObservable, maxComputationTimeMs: IObservable, private readonly _hideUnchangedRegions: IObservable, diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/inlineDiffDeletedCodeMargin.ts b/src/vs/editor/browser/widget/diffEditorWidget2/inlineDiffDeletedCodeMargin.ts new file mode 100644 index 00000000000..e31ed0d4d87 --- /dev/null +++ b/src/vs/editor/browser/widget/diffEditorWidget2/inlineDiffDeletedCodeMargin.ts @@ -0,0 +1,196 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { addStandardDisposableListener, getDomNodePagePosition } from 'vs/base/browser/dom'; +import { Action } from 'vs/base/common/actions'; +import { Codicon } from 'vs/base/common/codicons'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { isIOS } from 'vs/base/common/platform'; +import { ThemeIcon } from 'vs/base/common/themables'; +import { IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; +import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; +import { EditorOption } from 'vs/editor/common/config/editorOptions'; +import { LineRangeMapping } from 'vs/editor/common/diff/linesDiffComputer'; +import { EndOfLineSequence, ITextModel } from 'vs/editor/common/model'; +import { localize } from 'vs/nls'; +import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; + +export class InlineDiffDeletedCodeMargin extends Disposable { + private readonly _diffActions: HTMLElement; + + private _visibility: boolean = false; + + get visibility(): boolean { + return this._visibility; + } + + set visibility(_visibility: boolean) { + if (this._visibility !== _visibility) { + this._visibility = _visibility; + + if (_visibility) { + this._diffActions.style.visibility = 'visible'; + } else { + this._diffActions.style.visibility = 'hidden'; + } + } + } + + constructor( + private readonly _getViewZoneId: () => string, + private readonly _marginDomNode: HTMLElement, + private readonly editor: CodeEditorWidget, + private readonly diff: LineRangeMapping, + private readonly viewLineCounts: number[], + private readonly _originalTextModel: ITextModel, + private readonly _contextMenuService: IContextMenuService, + private readonly _clipboardService: IClipboardService, + ) { + super(); + + // make sure the diff margin shows above overlay. + this._marginDomNode.style.zIndex = '10'; + + this._diffActions = document.createElement('div'); + this._diffActions.className = ThemeIcon.asClassName(Codicon.lightBulb) + ' lightbulb-glyph'; + this._diffActions.style.position = 'absolute'; + const lineHeight = this.editor.getOption(EditorOption.lineHeight); + this._diffActions.style.right = '0px'; + this._diffActions.style.visibility = 'hidden'; + this._diffActions.style.height = `${lineHeight}px`; + this._diffActions.style.lineHeight = `${lineHeight}px`; + this._marginDomNode.appendChild(this._diffActions); + + const actions: Action[] = []; + const isDeletion = diff.modifiedRange.isEmpty; + + // default action + actions.push(new Action( + 'diff.clipboard.copyDeletedContent', + isDeletion + ? (diff.originalRange.length > 1 + ? localize('diff.clipboard.copyDeletedLinesContent.label', "Copy deleted lines") + : localize('diff.clipboard.copyDeletedLinesContent.single.label', "Copy deleted line")) + : (diff.originalRange.length > 1 + ? localize('diff.clipboard.copyChangedLinesContent.label', "Copy changed lines") + : localize('diff.clipboard.copyChangedLinesContent.single.label', "Copy changed line")), + undefined, + true, + async () => { + const originalText = this._originalTextModel.getValueInRange(diff.originalRange.toExclusiveRange()); + await this._clipboardService.writeText(originalText); + } + )); + + let currentLineNumberOffset = 0; + let copyLineAction: Action | undefined = undefined; + if (diff.originalRange.length > 1) { + copyLineAction = new Action( + 'diff.clipboard.copyDeletedLineContent', + isDeletion + ? localize('diff.clipboard.copyDeletedLineContent.label', "Copy deleted line ({0})", diff.originalRange.startLineNumber) + : localize('diff.clipboard.copyChangedLineContent.label', "Copy changed line ({0})", diff.originalRange.startLineNumber), + undefined, + true, + async () => { + let lineContent = this._originalTextModel.getLineContent(diff.originalRange.startLineNumber + currentLineNumberOffset); + if (lineContent === '') { + // empty line -> new line + const eof = this._originalTextModel.getEndOfLineSequence(); + lineContent = eof === EndOfLineSequence.LF ? '\n' : '\r\n'; + } + await this._clipboardService.writeText(lineContent); + } + ); + + actions.push(copyLineAction); + } + + const readOnly = editor.getOption(EditorOption.readOnly); + if (!readOnly) { + actions.push(new Action('diff.inline.revertChange', localize('diff.inline.revertChange.label', "Revert this change"), undefined, true, async () => { + const originalText = this._originalTextModel.getValueInRange(this.diff.originalRange.toExclusiveRange()); + editor.executeEdits('diffEditor', [ + { range: this.diff.modifiedRange.toExclusiveRange(), text: originalText } + ]); + })); + } + + const useShadowDOM = editor.getOption(EditorOption.useShadowDOM) && !isIOS; // Do not use shadow dom on IOS #122035 + + const showContextMenu = (x: number, y: number) => { + this._contextMenuService.showContextMenu({ + domForShadowRoot: useShadowDOM ? editor.getDomNode() ?? undefined : undefined, + getAnchor: () => { + return { + x, + y + }; + }, + getActions: () => { + if (copyLineAction) { + copyLineAction.label = + isDeletion + ? localize('diff.clipboard.copyDeletedLineContent.label', "Copy deleted line ({0})", diff.originalRange.startLineNumber + currentLineNumberOffset) + : localize('diff.clipboard.copyChangedLineContent.label', "Copy changed line ({0})", diff.originalRange.startLineNumber + currentLineNumberOffset); + } + return actions; + }, + autoSelectFirstItem: true + }); + }; + + this._register(addStandardDisposableListener(this._diffActions, 'mousedown', e => { + const { top, height } = getDomNodePagePosition(this._diffActions); + const pad = Math.floor(lineHeight / 3); + e.preventDefault(); + showContextMenu(e.posx, top + height + pad); + })); + + this._register(editor.onMouseMove((e: IEditorMouseEvent) => { + if ((e.target.type === MouseTargetType.CONTENT_VIEW_ZONE || e.target.type === MouseTargetType.GUTTER_VIEW_ZONE) && e.target.detail.viewZoneId === this._getViewZoneId()) { + currentLineNumberOffset = this._updateLightBulbPosition(this._marginDomNode, e.event.browserEvent.y, lineHeight); + this.visibility = true; + } else { + this.visibility = false; + } + })); + + this._register(editor.onMouseDown((e: IEditorMouseEvent) => { + if (!e.event.rightButton) { + return; + } + + if (e.target.type === MouseTargetType.CONTENT_VIEW_ZONE || e.target.type === MouseTargetType.GUTTER_VIEW_ZONE) { + const viewZoneId = e.target.detail.viewZoneId; + + if (viewZoneId === this._getViewZoneId()) { + e.event.preventDefault(); + currentLineNumberOffset = this._updateLightBulbPosition(this._marginDomNode, e.event.browserEvent.y, lineHeight); + showContextMenu(e.event.posx, e.event.posy + lineHeight); + } + } + })); + } + + private _updateLightBulbPosition(marginDomNode: HTMLElement, y: number, lineHeight: number): number { + const { top } = getDomNodePagePosition(marginDomNode); + const offset = y - top; + const lineNumberOffset = Math.floor(offset / lineHeight); + const newTop = lineNumberOffset * lineHeight; + this._diffActions.style.top = `${newTop}px`; + if (this.viewLineCounts) { + let acc = 0; + for (let i = 0; i < this.viewLineCounts.length; i++) { + acc += this.viewLineCounts[i]; + if (lineNumberOffset < acc) { + return i; + } + } + } + return lineNumberOffset; + } +} diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts b/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts index 7cd8ef95a8b..2b47702d076 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts @@ -4,17 +4,27 @@ *--------------------------------------------------------------------------------------------*/ import { ArrayQueue } from 'vs/base/common/arrays'; -import { Disposable } from 'vs/base/common/lifecycle'; -import { IObservable, observableSignalFromEvent, derived, observableValue, observableFromEvent } from 'vs/base/common/observable'; +import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { IObservable, derived, observableFromEvent, observableSignalFromEvent, observableValue } from 'vs/base/common/observable'; import { autorun, autorunWithStore2 } from 'vs/base/common/observableImpl/autorun'; +import { ThemeIcon } from 'vs/base/common/themables'; +import { applyFontInfo } from 'vs/editor/browser/config/domFontInfo'; import { IViewZone } from 'vs/editor/browser/editorBrowser'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; +import { diffDeleteDecoration, diffRemoveIcon } from 'vs/editor/browser/widget/diffEditorWidget2/decorations'; import { DiffMapping, DiffModel } from 'vs/editor/browser/widget/diffEditorWidget2/diffModel'; +import { InlineDiffDeletedCodeMargin } from 'vs/editor/browser/widget/diffEditorWidget2/inlineDiffDeletedCodeMargin'; +import { LineSource, RenderOptions, renderLines } from 'vs/editor/browser/widget/diffEditorWidget2/renderLines'; import { animatedObservable, joinCombine } from 'vs/editor/browser/widget/diffEditorWidget2/utils'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { LineRange } from 'vs/editor/common/core/lineRange'; import { Position } from 'vs/editor/common/core/position'; +import { LineRangeMapping } from 'vs/editor/common/diff/linesDiffComputer'; import { ScrollType } from 'vs/editor/common/editorCommon'; +import { BackgroundTokenizationState } from 'vs/editor/common/tokenizationTextModelPart'; +import { InlineDecoration, InlineDecorationType } from 'vs/editor/common/viewModel'; +import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; export class ViewZoneAlignment extends Disposable { private readonly _origExtraHeight = observableValue('origExtraHeight', 0); @@ -32,6 +42,9 @@ export class ViewZoneAlignment extends Disposable { private readonly _originalEditor: CodeEditorWidget, private readonly _modifiedEditor: CodeEditorWidget, private readonly _diffModel: IObservable, + private readonly _renderSideBySide: IObservable, + @IClipboardService private readonly _clipboardService: IClipboardService, + @IContextMenuService private readonly _contextMenuService: IContextMenuService, ) { super(); @@ -46,10 +59,14 @@ export class ViewZoneAlignment extends Disposable { e => this._modifiedEditor.onDidChangeViewZones((args) => { if (!isChangingViewZones) { e(args); } }) ); + const originalModelTokenizationCompleted = this._diffModel.map(m => + m ? observableFromEvent(m.model.original.onDidChangeTokens, () => m.model.original.tokenization.backgroundTokenizationState === BackgroundTokenizationState.Completed) : undefined + ).map((m, reader) => m?.read(reader)); + const alignmentViewZoneIdsOrig = new Set(); const alignmentViewZoneIdsMod = new Set(); - const alignments = derived('alignments', (reader) => { + const alignments = derived('alignments', (reader) => { const diffModel = this._diffModel.read(reader); const diff = diffModel?.diff.read(reader); if (!diffModel || !diff) { return null; } @@ -60,7 +77,7 @@ export class ViewZoneAlignment extends Disposable { return computeRangeAlignment(this._originalEditor, this._modifiedEditor, diff.mappings, alignmentViewZoneIdsOrig, alignmentViewZoneIdsMod); }); - const alignmentsSyncedMovedText = derived('alignments', (reader) => { + const alignmentsSyncedMovedText = derived('alignments', (reader) => { origViewZonesChanged.read(reader); modViewZonesChanged.read(reader); @@ -80,33 +97,137 @@ export class ViewZoneAlignment extends Disposable { return r; } - const alignmentViewZones = derived<{ orig: IViewZone[]; mod: IViewZone[] }>('alignment viewzones', (reader) => { - const alignments_ = alignments.read(reader); + const alignmentViewZonesDisposables = this._register(new DisposableStore()); + const alignmentViewZones = derived<{ orig: IViewZoneWithZoneId[]; mod: IViewZoneWithZoneId[] }>('alignment viewzones', (reader) => { + alignmentViewZonesDisposables.clear(); - const origViewZones: IViewZone[] = []; - const modViewZones: IViewZone[] = []; + const curAlignments = alignments.read(reader) || []; - const _modExtraHeight = this._modExtraHeight.read(reader); - if (_modExtraHeight > 0) { + const origViewZones: IViewZoneWithZoneId[] = []; + const modViewZones: IViewZoneWithZoneId[] = []; + + const curModExtraHeight = this._modExtraHeight.read(reader); + if (curModExtraHeight > 0) { modViewZones.push({ afterLineNumber: 0, domNode: document.createElement('div'), - heightInPx: _modExtraHeight, + heightInPx: curModExtraHeight, }); } - const _origExtraHeight = this._origExtraHeight.read(reader); - if (_origExtraHeight > 0) { + const curOrigExtraHeight = this._origExtraHeight.read(reader); + if (curOrigExtraHeight > 0) { origViewZones.push({ afterLineNumber: 0, domNode: document.createElement('div'), - heightInPx: _origExtraHeight, + heightInPx: curOrigExtraHeight, }); } + const renderSideBySide = this._renderSideBySide.read(reader); + + const deletedCodeLineBreaksComputer = !renderSideBySide ? this._modifiedEditor._getViewModel()?.createLineBreaksComputer() : undefined; + if (deletedCodeLineBreaksComputer) { + for (const a of curAlignments) { + if (a.diff) { + for (let i = a.originalRange.startLineNumber; i < a.originalRange.endLineNumberExclusive; i++) { + deletedCodeLineBreaksComputer?.addRequest(this._originalEditor.getModel()!.getLineContent(i), null, null); + } + } + } + } + + const lineBreakData = deletedCodeLineBreaksComputer?.finalize() ?? []; + let lineBreakDataIdx = 0; + + const modLineHeight = this._modifiedEditor.getOption(EditorOption.lineHeight); + const syncedMovedText = this._diffModel.read(reader)?.syncedMovedTexts.read(reader); - if (alignments_) { - for (const a of alignments_) { + const mightContainNonBasicASCII = this._originalEditor.getModel()?.mightContainNonBasicASCII() ?? false; + const mightContainRTL = this._originalEditor.getModel()?.mightContainRTL() ?? false; + const renderOptions = RenderOptions.fromEditor(this._modifiedEditor); + + for (const a of curAlignments) { + if (a.diff && !renderSideBySide) { + if (!a.originalRange.isEmpty) { + originalModelTokenizationCompleted.read(reader); // Update view-zones once tokenization completes + + const domNode = document.createElement('div'); + domNode.classList.add('view-lines', 'line-delete', 'monaco-mouse-cursor-text'); + const source = new LineSource( + a.originalRange.mapToLineArray(l => this._originalEditor.getModel()!.tokenization.getLineTokens(l)), + a.originalRange.mapToLineArray(_ => lineBreakData[lineBreakDataIdx++]), + mightContainNonBasicASCII, + mightContainRTL, + ); + const decorations: InlineDecoration[] = []; + for (const i of a.diff.innerChanges || []) { + decorations.push(new InlineDecoration( + i.originalRange.delta(-(a.diff.originalRange.startLineNumber - 1)), + diffDeleteDecoration.className!, + InlineDecorationType.Regular + )); + } + const result = renderLines(source, renderOptions, decorations, domNode); + + const marginDomNode = document.createElement('div'); + marginDomNode.className = 'inline-deleted-margin-view-zone'; + applyFontInfo(marginDomNode, renderOptions.fontInfo); + + //if (this._renderIndicators) { + for (let i = 0; i < result.heightInLines; i++) { + const marginElement = document.createElement('div'); + marginElement.className = `delete-sign ${ThemeIcon.asClassName(diffRemoveIcon)}`; + marginElement.setAttribute('style', `position:absolute;top:${i * modLineHeight}px;width:${renderOptions.lineDecorationsWidth}px;height:${modLineHeight}px;right:0;`); + marginDomNode.appendChild(marginElement); + } + //} + + let zoneId: string; + modViewZones.push({ + afterLineNumber: a.modifiedRange.startLineNumber - 1, + domNode: domNode, + heightInPx: result.heightInLines * modLineHeight, + minWidthInPx: result.minWidthInPx, + marginDomNode, + setZoneId(id) { zoneId = id; }, + }); + alignmentViewZonesDisposables.add( + new InlineDiffDeletedCodeMargin( + () => zoneId, + marginDomNode, + this._modifiedEditor, + a.diff, + result.viewLineCounts, + this._originalEditor.getModel()!, + this._contextMenuService, + this._clipboardService + ) + ); + + for (let i = 0; i < result.viewLineCounts.length; i++) { + const count = result.viewLineCounts[i]; + // Account for wrapped lines in the (collapsed) original editor (that does not have line wraps). + if (count > 1) { + origViewZones.push({ + afterLineNumber: a.originalRange.startLineNumber + i, + domNode: createFakeLinesDiv(), + heightInPx: (count - 1) * modLineHeight, + }); + } + } + } + + const marginDomNode = document.createElement('div'); + marginDomNode.className = 'gutter-delete'; + + origViewZones.push({ + afterLineNumber: a.originalRange.endLineNumberExclusive - 1, + domNode: createFakeLinesDiv(), + heightInPx: a.modifiedHeightInPx, + marginDomNode, + }); + } else { const delta = a.modifiedHeightInPx - a.originalHeightInPx; if (delta > 0) { if (syncedMovedText?.lineRangeMapping.originalRange.contains(a.originalRange.endLineNumberExclusive - 1)) { @@ -138,6 +259,7 @@ export class ViewZoneAlignment extends Disposable { // ignore unrelated alignments outside the synced moved text continue; } + const delta = a.modifiedHeightInPx - a.originalHeightInPx; if (delta > 0) { origViewZones.push({ @@ -163,12 +285,24 @@ export class ViewZoneAlignment extends Disposable { this._originalEditor.changeViewZones((aOrig) => { for (const id of alignmentViewZoneIdsOrig) { aOrig.removeZone(id); } alignmentViewZoneIdsOrig.clear(); - for (const z of alignmentViewZones_.orig) { alignmentViewZoneIdsOrig.add(aOrig.addZone(z)); } + for (const z of alignmentViewZones_.orig) { + const id = aOrig.addZone(z); + if (z.setZoneId) { + z.setZoneId(id); + } + alignmentViewZoneIdsOrig.add(id); + } }); this._modifiedEditor.changeViewZones(aMod => { for (const id of alignmentViewZoneIdsMod) { aMod.removeZone(id); } alignmentViewZoneIdsMod.clear(); - for (const z of alignmentViewZones_.mod) { alignmentViewZoneIdsMod.add(aMod.addZone(z)); } + for (const z of alignmentViewZones_.mod) { + const id = aMod.addZone(z); + if (z.setZoneId) { + z.setZoneId(id); + } + alignmentViewZoneIdsMod.add(id); + } }); isChangingViewZones = false; })); @@ -235,13 +369,24 @@ export class ViewZoneAlignment extends Disposable { } } -interface IRangeAlignment { +interface IViewZoneWithZoneId extends IViewZone { + // Tells a view zone its id. + setZoneId?(zoneId: string): void; +} + +interface ILineRangeAlignment { originalRange: LineRange; modifiedRange: LineRange; // accounts for foreign viewzones and line wrapping originalHeightInPx: number; modifiedHeightInPx: number; + + /** + * If this range alignment is a direct result of a diff, then this is the diff's line mapping. + * Only used for inline-view. + */ + diff?: LineRangeMapping; } function computeRangeAlignment( @@ -250,14 +395,14 @@ function computeRangeAlignment( diffs: readonly DiffMapping[], originalEditorAlignmentViewZones: ReadonlySet, modifiedEditorAlignmentViewZones: ReadonlySet, -): IRangeAlignment[] { +): ILineRangeAlignment[] { const originalLineHeightOverrides = new ArrayQueue(getAdditionalLineHeights(originalEditor, originalEditorAlignmentViewZones)); const modifiedLineHeightOverrides = new ArrayQueue(getAdditionalLineHeights(modifiedEditor, modifiedEditorAlignmentViewZones)); const origLineHeight = originalEditor.getOption(EditorOption.lineHeight); const modLineHeight = modifiedEditor.getOption(EditorOption.lineHeight); - const result: IRangeAlignment[] = []; + const result: ILineRangeAlignment[] = []; let lastOriginalLineNumber = 0; let lastModifiedLineNumber = 0; @@ -301,6 +446,7 @@ function computeRangeAlignment( modifiedRange: LineRange.ofLength(modNext!.lineNumber, 1), originalHeightInPx: origLineHeight + origNext!.heightInPx, modifiedHeightInPx: modLineHeight + modNext!.heightInPx, + diff: undefined, }); } } @@ -321,6 +467,7 @@ function computeRangeAlignment( modifiedRange: c.modifiedRange, originalHeightInPx: c.originalRange.length * origLineHeight + originalAdditionalHeight, modifiedHeightInPx: c.modifiedRange.length * modLineHeight + modifiedAdditionalHeight, + diff: m.lineRangeMapping, }); lastOriginalLineNumber = c.originalRange.endLineNumberExclusive; diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/renderLines.ts b/src/vs/editor/browser/widget/diffEditorWidget2/renderLines.ts new file mode 100644 index 00000000000..992d4e6d9af --- /dev/null +++ b/src/vs/editor/browser/widget/diffEditorWidget2/renderLines.ts @@ -0,0 +1,200 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { createTrustedTypesPolicy } from 'vs/base/browser/trustedTypes'; +import { applyFontInfo } from 'vs/editor/browser/config/domFontInfo'; +import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { EditorOption, EditorFontLigatures, FindComputedEditorOptionValueById } from 'vs/editor/common/config/editorOptions'; +import { FontInfo } from 'vs/editor/common/config/fontInfo'; +import { StringBuilder } from 'vs/editor/common/core/stringBuilder'; +import { ModelLineProjectionData } from 'vs/editor/common/modelLineProjectionData'; +import { IViewLineTokens, LineTokens } from 'vs/editor/common/tokens/lineTokens'; +import { LineDecoration } from 'vs/editor/common/viewLayout/lineDecorations'; +import { renderViewLine, RenderLineInput } from 'vs/editor/common/viewLayout/viewLineRenderer'; +import { InlineDecoration, ViewLineRenderingData } from 'vs/editor/common/viewModel'; + +const ttPolicy = createTrustedTypesPolicy('diffEditorWidget2', { createHTML: value => value }); + +export function renderLines(source: LineSource, options: RenderOptions, decorations: InlineDecoration[], domNode: HTMLElement): RenderLinesResult { + applyFontInfo(domNode, options.fontInfo); + + const hasCharChanges = (decorations.length > 0); + + const sb = new StringBuilder(10000); + let maxCharsPerLine = 0; + let renderedLineCount = 0; + const viewLineCounts: number[] = []; + for (let lineIndex = 0; lineIndex < source.lineTokens.length; lineIndex++) { + const lineNumber = lineIndex + 1; + const lineTokens = source.lineTokens[lineIndex]; + const lineBreakData = source.lineBreakData[lineIndex]; + const actualDecorations = LineDecoration.filter(decorations, lineNumber, 1, Number.MAX_SAFE_INTEGER); + + if (lineBreakData) { + let lastBreakOffset = 0; + for (const breakOffset of lineBreakData.breakOffsets) { + const viewLineTokens = lineTokens.sliceAndInflate(lastBreakOffset, breakOffset, 0); + maxCharsPerLine = Math.max(maxCharsPerLine, renderOriginalLine( + renderedLineCount, + viewLineTokens, + LineDecoration.extractWrapped(actualDecorations, lastBreakOffset, breakOffset), + hasCharChanges, + source.mightContainNonBasicASCII, + source.mightContainRTL, + options, + sb, + //marginDomNode + )); + renderedLineCount++; + lastBreakOffset = breakOffset; + } + viewLineCounts.push(lineBreakData.breakOffsets.length); + + + /* + const marginDomNode2 = document.createElement('div'); + marginDomNode2.className = 'gutter-delete'; + result.original.push({ + afterLineNumber: lineNumber, + afterColumn: 0, + heightInLines: lineBreakData.breakOffsets.length - 1, + domNode: createFakeLinesDiv(), + marginDomNode: marginDomNode2 + }); + */ + } else { + viewLineCounts.push(1); + maxCharsPerLine = Math.max(maxCharsPerLine, renderOriginalLine( + renderedLineCount, + lineTokens, + actualDecorations, + hasCharChanges, + source.mightContainNonBasicASCII, + source.mightContainRTL, + options, + sb, + )); + renderedLineCount++; + } + } + maxCharsPerLine += options.scrollBeyondLastColumn; + + const html = sb.build(); + const trustedhtml = ttPolicy ? ttPolicy.createHTML(html) : html; + domNode.innerHTML = trustedhtml as string; + const minWidthInPx = (maxCharsPerLine * options.typicalHalfwidthCharacterWidth); + + return { + heightInLines: renderedLineCount, + minWidthInPx, + viewLineCounts, + }; +} + + +export class LineSource { + constructor( + public readonly lineTokens: LineTokens[], + public readonly lineBreakData: (ModelLineProjectionData | null)[], + public readonly mightContainNonBasicASCII: boolean, + public readonly mightContainRTL: boolean, + ) { } +} + +export class RenderOptions { + public static fromEditor(editor: ICodeEditor): RenderOptions { + + const modifiedEditorOptions = editor.getOptions(); + const fontInfo = modifiedEditorOptions.get(EditorOption.fontInfo); + const layoutInfo = modifiedEditorOptions.get(EditorOption.layoutInfo); + + return new RenderOptions( + editor.getModel()?.getOptions().tabSize || 0, + fontInfo, + modifiedEditorOptions.get(EditorOption.disableMonospaceOptimizations), + fontInfo.typicalHalfwidthCharacterWidth, + modifiedEditorOptions.get(EditorOption.scrollBeyondLastColumn), + + modifiedEditorOptions.get(EditorOption.lineHeight), + + layoutInfo.decorationsWidth, + modifiedEditorOptions.get(EditorOption.stopRenderingLineAfter), + modifiedEditorOptions.get(EditorOption.renderWhitespace), + modifiedEditorOptions.get(EditorOption.renderControlCharacters), + modifiedEditorOptions.get(EditorOption.fontLigatures), + ); + } + + constructor( + public readonly tabSize: number, + public readonly fontInfo: FontInfo, + public readonly disableMonospaceOptimizations: boolean, + public readonly typicalHalfwidthCharacterWidth: number, + public readonly scrollBeyondLastColumn: number, + public readonly lineHeight: number, + public readonly lineDecorationsWidth: number, + public readonly stopRenderingLineAfter: number, + public readonly renderWhitespace: FindComputedEditorOptionValueById, + public readonly renderControlCharacters: boolean, + public readonly fontLigatures: FindComputedEditorOptionValueById, + ) { } +} + +export interface RenderLinesResult { + minWidthInPx: number; + heightInLines: number; + viewLineCounts: number[]; +} + +function renderOriginalLine( + viewLineIdx: number, + lineTokens: IViewLineTokens, + decorations: LineDecoration[], + hasCharChanges: boolean, + mightContainNonBasicASCII: boolean, + mightContainRTL: boolean, + options: RenderOptions, + sb: StringBuilder, +): number { + + sb.appendString('
'); + + const lineContent = lineTokens.getLineContent(); + const isBasicASCII = ViewLineRenderingData.isBasicASCII(lineContent, mightContainNonBasicASCII); + const containsRTL = ViewLineRenderingData.containsRTL(lineContent, isBasicASCII, mightContainRTL); + const output = renderViewLine(new RenderLineInput( + (options.fontInfo.isMonospace && !options.disableMonospaceOptimizations), + options.fontInfo.canUseHalfwidthRightwardsArrow, + lineContent, + false, + isBasicASCII, + containsRTL, + 0, + lineTokens, + decorations, + options.tabSize, + 0, + options.fontInfo.spaceWidth, + options.fontInfo.middotWidth, + options.fontInfo.wsmiddotWidth, + options.stopRenderingLineAfter, + options.renderWhitespace, + options.renderControlCharacters, + options.fontLigatures !== EditorFontLigatures.OFF, + null // Send no selections, original line cannot be selected + ), sb); + + sb.appendString('
'); + + return output.characterMapping.getHorizontalOffset(output.characterMapping.length); +} + diff --git a/src/vs/editor/common/core/lineRange.ts b/src/vs/editor/common/core/lineRange.ts index 4789968d244..046dccbe58e 100644 --- a/src/vs/editor/common/core/lineRange.ts +++ b/src/vs/editor/common/core/lineRange.ts @@ -203,4 +203,12 @@ export class LineRange { public toExclusiveRange(): Range { return new Range(this.startLineNumber, 1, this.endLineNumberExclusive, 1); } + + public mapToLineArray(f: (lineNumber: number) => T): T[] { + const result: T[] = []; + for (let lineNumber = this.startLineNumber; lineNumber < this.endLineNumberExclusive; lineNumber++) { + result.push(f(lineNumber)); + } + return result; + } } diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 1aeebd607de..f4f733504e9 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -2475,6 +2475,7 @@ declare namespace monaco.editor { equals(b: LineRange): boolean; toInclusiveRange(): Range | null; toExclusiveRange(): Range; + mapToLineArray(f: (lineNumber: number) => T): T[]; } /** @@ -5991,13 +5992,6 @@ declare namespace monaco.editor { setBanner(bannerDomNode: HTMLElement | null, height: number): void; } - /** - * Information about a line in the diff editor - */ - export interface IDiffLineInformation { - readonly equivalentLineNumber: number; - } - /** * A rich diff editor. */ @@ -6049,16 +6043,6 @@ declare namespace monaco.editor { * Get the computed diff information. */ getLineChanges(): ILineChange[] | null; - /** - * Get information based on computed diff about a line number from the original model. - * If the diff computation is not finished or the model is missing, will return null. - */ - getDiffLineInformationForOriginal(lineNumber: number): IDiffLineInformation | null; - /** - * Get information based on computed diff about a line number from the modified model. - * If the diff computation is not finished or the model is missing, will return null. - */ - getDiffLineInformationForModified(lineNumber: number): IDiffLineInformation | null; /** * Update the editor's options after the editor has been created. */ From 0128b0ce3db6b56c55bda48256edfea2ebf930e0 Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Fri, 9 Jun 2023 12:28:36 -0700 Subject: [PATCH 028/128] Fix #178829. Update editor options for iw input (#184749) --- .../interactive/browser/interactiveEditor.ts | 56 ++++++++++++++----- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/contrib/interactive/browser/interactiveEditor.ts b/src/vs/workbench/contrib/interactive/browser/interactiveEditor.ts index 56999d92b7b..faf374d8746 100644 --- a/src/vs/workbench/contrib/interactive/browser/interactiveEditor.ts +++ b/src/vs/workbench/contrib/interactive/browser/interactiveEditor.ts @@ -61,6 +61,8 @@ import { isEqual } from 'vs/base/common/resources'; import { NotebookFindContrib } from 'vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget'; import { INTERACTIVE_WINDOW_EDITOR_ID } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import 'vs/css!./interactiveEditor'; +import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; +import { deepClone } from 'vs/base/common/objects'; const DECORATION_KEY = 'interactiveInputDecoration'; const INTERACTIVE_EDITOR_VIEW_STATE_PREFERENCE_KEY = 'InteractiveEditorViewState'; @@ -93,6 +95,7 @@ export class InteractiveEditor extends EditorPane { #instantiationService: IInstantiationService; #languageService: ILanguageService; #contextKeyService: IContextKeyService; + #configurationService: IConfigurationService; #notebookKernelService: INotebookKernelService; #keybindingService: IKeybindingService; #menuService: IMenuService; @@ -102,6 +105,7 @@ export class InteractiveEditor extends EditorPane { #extensionService: IExtensionService; #widgetDisposableStore: DisposableStore = this._register(new DisposableStore()); #lastLayoutDimensions?: { readonly dimension: DOM.Dimension; readonly position: DOM.IDomPosition }; + #editorOptions: IEditorOptions; #notebookOptions: NotebookOptions; #editorMemento: IEditorMemento; #groupListener = this._register(new DisposableStore()); @@ -123,7 +127,7 @@ export class InteractiveEditor extends EditorPane { @INotebookKernelService notebookKernelService: INotebookKernelService, @ILanguageService languageService: ILanguageService, @IKeybindingService keybindingService: IKeybindingService, - @IConfigurationService private configurationService: IConfigurationService, + @IConfigurationService configurationService: IConfigurationService, @IMenuService menuService: IMenuService, @IContextMenuService contextMenuService: IContextMenuService, @IEditorGroupsService editorGroupService: IEditorGroupsService, @@ -140,6 +144,7 @@ export class InteractiveEditor extends EditorPane { this.#instantiationService = instantiationService; this.#notebookWidgetService = notebookWidgetService; this.#contextKeyService = contextKeyService; + this.#configurationService = configurationService; this.#notebookKernelService = notebookKernelService; this.#languageService = languageService; this.#keybindingService = keybindingService; @@ -149,6 +154,12 @@ export class InteractiveEditor extends EditorPane { this.#notebookExecutionStateService = notebookExecutionStateService; this.#extensionService = extensionService; + this.#editorOptions = this.#computeEditorOptions(); + this._register(this.#configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('editor') || e.affectsConfiguration('notebook')) { + this.#editorOptions = this.#computeEditorOptions(); + } + })); this.#notebookOptions = new NotebookOptions(configurationService, notebookExecutionStateService, true, { cellToolbarInteraction: 'hover', globalToolbar: true, dragAndDropEnabled: false }); this.#editorMemento = this.getEditorMemento(editorGroupService, textResourceConfigurationService, INTERACTIVE_EDITOR_VIEW_STATE_PREFERENCE_KEY); @@ -259,6 +270,31 @@ export class InteractiveEditor extends EditorPane { this.#styleElement.textContent = styleSheets.join('\n'); } + #computeEditorOptions(): IEditorOptions { + let overrideIdentifier: string | undefined = undefined; + if (this.#codeEditorWidget) { + overrideIdentifier = this.#codeEditorWidget.getModel()?.getLanguageId(); + } + const editorOptions = deepClone(this.#configurationService.getValue('editor', { overrideIdentifier })); + const editorOptionsOverride = getSimpleEditorOptions(); + const computed = Object.freeze({ + ...editorOptions, + ...editorOptionsOverride, + ...{ + glyphMargin: true, + padding: { + top: INPUT_EDITOR_PADDING, + bottom: INPUT_EDITOR_PADDING + }, + hover: { + enabled: true + } + } + }); + + return computed; + } + protected override saveState(): void { this.#saveEditorViewState(this.input); super.saveState(); @@ -350,19 +386,7 @@ export class InteractiveEditor extends EditorPane { options: this.#notebookOptions }); - this.#codeEditorWidget = this.#instantiationService.createInstance(CodeEditorWidget, this.#inputEditorContainer, { - ...getSimpleEditorOptions(), - ...{ - glyphMargin: true, - padding: { - top: INPUT_EDITOR_PADDING, - bottom: INPUT_EDITOR_PADDING - }, - hover: { - enabled: true - } - } - }, { + this.#codeEditorWidget = this.#instantiationService.createInstance(CodeEditorWidget, this.#inputEditorContainer, this.#editorOptions, { ...{ isSimpleWidget: false, contributions: EditorExtensionsRegistry.getSomeEditorContributions([ @@ -438,6 +462,8 @@ export class InteractiveEditor extends EditorPane { if (viewState?.input) { this.#codeEditorWidget.restoreViewState(viewState.input); } + this.#editorOptions = this.#computeEditorOptions(); + this.#codeEditorWidget.updateOptions(this.#editorOptions); this.#widgetDisposableStore.add(this.#codeEditorWidget.onDidFocusEditorWidget(() => this.#onDidFocusWidget.fire())); this.#widgetDisposableStore.add(this.#codeEditorWidget.onDidContentSizeChange(e => { @@ -536,7 +562,7 @@ export class InteractiveEditor extends EditorPane { const index = this.#notebookWidget.value!.getCellIndex(cvm); if (index === this.#notebookWidget.value!.getLength() - 1) { // If we're already at the bottom or auto scroll is enabled, scroll to the bottom - if (this.configurationService.getValue(InteractiveWindowSetting.interactiveWindowAlwaysScrollOnNewCell) || this.#cellAtBottom(cvm)) { + if (this.#configurationService.getValue(InteractiveWindowSetting.interactiveWindowAlwaysScrollOnNewCell) || this.#cellAtBottom(cvm)) { this.#notebookWidget.value!.scrollToBottom(); } } From d81ca6dfcae29a9bf0f648b94dff145b3665fac1 Mon Sep 17 00:00:00 2001 From: Raymond Zhao <7199958+rzhao271@users.noreply.github.com> Date: Fri, 9 Jun 2023 13:02:58 -0700 Subject: [PATCH 029/128] Bump windows-registry to 1.1.0 (#184741) --- build/.moduleignore.darwin | 9 ++++++++- build/.moduleignore.linux | 9 ++++++++- package.json | 2 +- remote/package.json | 4 ++-- remote/yarn.lock | 8 ++++---- src/typings/windows-registry.d.ts | 9 --------- yarn.lock | 8 ++++---- 7 files changed, 27 insertions(+), 22 deletions(-) delete mode 100644 src/typings/windows-registry.d.ts diff --git a/build/.moduleignore.darwin b/build/.moduleignore.darwin index 3d1897f9dc6..fc3f48af069 100644 --- a/build/.moduleignore.darwin +++ b/build/.moduleignore.darwin @@ -1,4 +1,11 @@ @vscode/windows-mutex/index.js @vscode/windows-mutex/**/*.node @vscode/windows-mutex/*.md -@vscode/windows-mutex/package.json \ No newline at end of file +@vscode/windows-mutex/package.json + +@vscode/windows-registry/dist/** +@vscode/windows-registry/**/*.node +@vscode/windows-registry/*.md +@vscode/windows-registry/*.txt +@vscode/windows-registry/package.json +!@vscode/windows-registry/dist/index.d.ts \ No newline at end of file diff --git a/build/.moduleignore.linux b/build/.moduleignore.linux index 3d1897f9dc6..fc3f48af069 100644 --- a/build/.moduleignore.linux +++ b/build/.moduleignore.linux @@ -1,4 +1,11 @@ @vscode/windows-mutex/index.js @vscode/windows-mutex/**/*.node @vscode/windows-mutex/*.md -@vscode/windows-mutex/package.json \ No newline at end of file +@vscode/windows-mutex/package.json + +@vscode/windows-registry/dist/** +@vscode/windows-registry/**/*.node +@vscode/windows-registry/*.md +@vscode/windows-registry/*.txt +@vscode/windows-registry/package.json +!@vscode/windows-registry/dist/index.d.ts \ No newline at end of file diff --git a/package.json b/package.json index 6c95d237009..f6c482987a7 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "@vscode/sudo-prompt": "9.3.1", "@vscode/vscode-languagedetection": "1.0.21", "@vscode/windows-mutex": "^0.4.4", + "@vscode/windows-registry": "^1.1.0", "graceful-fs": "4.2.8", "http-proxy-agent": "^2.1.0", "https-proxy-agent": "^2.2.3", @@ -227,7 +228,6 @@ }, "optionalDependencies": { "@vscode/windows-process-tree": "0.4.2", - "@vscode/windows-registry": "1.0.10", "windows-foreground-love": "0.5.0" } } diff --git a/remote/package.json b/remote/package.json index 30c213e955c..ffd7fb5e5d4 100644 --- a/remote/package.json +++ b/remote/package.json @@ -11,6 +11,7 @@ "@vscode/ripgrep": "^1.15.4", "@vscode/spdlog": "^0.13.10", "@vscode/vscode-languagedetection": "1.0.21", + "@vscode/windows-registry": "^1.1.0", "cookie": "^0.4.0", "graceful-fs": "4.2.8", "http-proxy-agent": "^2.1.0", @@ -36,7 +37,6 @@ "yazl": "^2.4.3" }, "optionalDependencies": { - "@vscode/windows-process-tree": "0.4.2", - "@vscode/windows-registry": "1.0.10" + "@vscode/windows-process-tree": "0.4.2" } } diff --git a/remote/yarn.lock b/remote/yarn.lock index 47b0f0e5024..cfc9cb6c801 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -108,10 +108,10 @@ dependencies: nan "^2.17.0" -"@vscode/windows-registry@1.0.10": - version "1.0.10" - resolved "https://registry.yarnpkg.com/@vscode/windows-registry/-/windows-registry-1.0.10.tgz#17e4e2f8fdd41990206d1bab2daf99c803206247" - integrity sha512-n2rLdTgv95fQUpDxZqgAURg9neQGymtOKkLW4eYP2SODmaxoL2WzgrxEz1kW0w5TI+J4tsPeuZylpRfrDJKQWw== +"@vscode/windows-registry@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@vscode/windows-registry/-/windows-registry-1.1.0.tgz#03dace7c29c46f658588b9885b9580e453ad21f9" + integrity sha512-5AZzuWJpGscyiMOed0IuyEwt6iKmV5Us7zuwCDCFYMIq7tsvooO9BUiciywsvuthGz6UG4LSpeDeCxvgMVhnIw== agent-base@4: version "4.2.0" diff --git a/src/typings/windows-registry.d.ts b/src/typings/windows-registry.d.ts deleted file mode 100644 index 165a20613ab..00000000000 --- a/src/typings/windows-registry.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -declare module '@vscode/windows-registry' { - export type HKEY = 'HKEY_CURRENT_USER' | 'HKEY_LOCAL_MACHINE' | 'HKEY_CLASSES_ROOT' | 'HKEY_USERS' | 'HKEY_CURRENT_CONFIG'; - export function GetStringRegKey(hive: HKEY, path: string, name: string): string | undefined; -} diff --git a/yarn.lock b/yarn.lock index 0da15fa4e80..a2146d5721a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1407,10 +1407,10 @@ dependencies: nan "^2.17.0" -"@vscode/windows-registry@1.0.10": - version "1.0.10" - resolved "https://registry.yarnpkg.com/@vscode/windows-registry/-/windows-registry-1.0.10.tgz#17e4e2f8fdd41990206d1bab2daf99c803206247" - integrity sha512-n2rLdTgv95fQUpDxZqgAURg9neQGymtOKkLW4eYP2SODmaxoL2WzgrxEz1kW0w5TI+J4tsPeuZylpRfrDJKQWw== +"@vscode/windows-registry@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@vscode/windows-registry/-/windows-registry-1.1.0.tgz#03dace7c29c46f658588b9885b9580e453ad21f9" + integrity sha512-5AZzuWJpGscyiMOed0IuyEwt6iKmV5Us7zuwCDCFYMIq7tsvooO9BUiciywsvuthGz6UG4LSpeDeCxvgMVhnIw== "@webassemblyjs/ast@1.11.1": version "1.11.1" From 12533c5490dc9d2a82be9e1fa1977f829638e229 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Fri, 9 Jun 2023 23:54:38 +0200 Subject: [PATCH 030/128] Git - extract close repository management into its own class (#184752) --- extensions/git/package.json | 2 +- extensions/git/src/model.ts | 59 ++++++++++++++++++++------- extensions/git/src/observable.ts | 70 -------------------------------- 3 files changed, 45 insertions(+), 86 deletions(-) delete mode 100644 extensions/git/src/observable.ts diff --git a/extensions/git/package.json b/extensions/git/package.json index 17e8de43d38..e9e667dcc33 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -88,7 +88,7 @@ "command": "git.reopenClosedRepositories", "title": "%command.reopenClosedRepositories%", "category": "Git", - "enablement": "!operationInProgress && git.ClosedRepositoryCount != 0" + "enablement": "!operationInProgress && git.closedRepositoryCount != 0" }, { "command": "git.close", diff --git a/extensions/git/src/model.ts b/extensions/git/src/model.ts index 48f3a5c43e6..3315b3eee58 100644 --- a/extensions/git/src/model.ts +++ b/extensions/git/src/model.ts @@ -19,7 +19,6 @@ import { ApiRepository } from './api/api1'; import { IRemoteSourcePublisherRegistry } from './remotePublisher'; import { IPostCommitCommandsProviderRegistry } from './postCommitCommands'; import { IBranchProtectionProviderRegistry } from './branchProtection'; -import { ObservableSet } from './observable'; class RepositoryPick implements QuickPickItem { @memoize get label(): string { @@ -93,6 +92,42 @@ interface OpenRepository extends Disposable { repository: Repository; } +class ClosedRepositoriesManager { + + private _repositories: Set; + get repositories(): string[] { + return [...this._repositories.values()]; + } + + constructor(private readonly workspaceState: Memento) { + this._repositories = new Set(workspaceState.get('closedRepositories', [])); + this.onDidChangeRepositories(); + } + + addRepository(repository: string): void { + this._repositories.add(repository); + this.onDidChangeRepositories(); + } + + deleteRepository(repository: string): boolean { + const result = this._repositories.delete(repository); + if (result) { + this.onDidChangeRepositories(); + } + + return result; + } + + isRepositoryClosed(repository: string): boolean { + return this._repositories.has(repository); + } + + private onDidChangeRepositories(): void { + this.workspaceState.update('closedRepositories', [...this._repositories.values()]); + commands.executeCommand('setContext', 'git.closedRepositoryCount', this._repositories.size); + } +} + export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePublisherRegistry, IPostCommitCommandsProviderRegistry, IPushErrorHandlerRegistry { private _onDidOpenRepository = new EventEmitter(); @@ -170,9 +205,9 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu return this._parentRepositories; } - private _closedRepositories: ObservableSet; + private _closedRepositoriesManager: ClosedRepositoriesManager; get closedRepositories(): string[] { - return [...this._closedRepositories.values()]; + return [...this._closedRepositoriesManager.repositories]; } /** @@ -187,10 +222,9 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu private disposables: Disposable[] = []; - constructor(readonly git: Git, private readonly askpass: Askpass, private globalState: Memento, private workspaceState: Memento, private logger: LogOutputChannel, private telemetryReporter: TelemetryReporter) { - this._closedRepositories = new ObservableSet(workspaceState.get('closedRepositories', [])); - this._closedRepositories.onDidChange(this.onDidChangeClosedRepositories, this, this.disposables); - this.onDidChangeClosedRepositories(); + constructor(readonly git: Git, private readonly askpass: Askpass, private globalState: Memento, readonly workspaceState: Memento, private logger: LogOutputChannel, private telemetryReporter: TelemetryReporter) { + // Repositories managers + this._closedRepositoriesManager = new ClosedRepositoriesManager(workspaceState); workspace.onDidChangeWorkspaceFolders(this.onDidChangeWorkspaceFolders, this, this.disposables); window.onDidChangeVisibleTextEditors(this.onDidChangeVisibleTextEditors, this, this.disposables); @@ -379,11 +413,6 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu openRepositoriesToDispose.forEach(r => r.dispose()); } - private onDidChangeClosedRepositories(): void { - this.workspaceState.update('closedRepositories', [...this._closedRepositories.values()]); - commands.executeCommand('setContext', 'git.closedRepositoryCount', this._closedRepositories.size); - } - private async onDidChangeVisibleTextEditors(editors: readonly TextEditor[]): Promise { if (!workspace.isTrusted) { this.logger.trace('[svte] Workspace is not trusted.'); @@ -496,7 +525,7 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu } // Handle repositories that were closed by the user - if (!openIfClosed && this._closedRepositories.has(repositoryRoot)) { + if (!openIfClosed && this._closedRepositoriesManager.isRepositoryClosed(repositoryRoot)) { this.logger.trace(`Repository for path ${repositoryRoot} is closed`); return; } @@ -506,7 +535,7 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu const repository = new Repository(this.git.open(repositoryRoot, dotGit, this.logger), this, this, this, this, this.globalState, this.logger, this.telemetryReporter); this.open(repository); - this._closedRepositories.delete(repository.root); + this._closedRepositoriesManager.deleteRepository(repository.root); // Do not await this, we want SCM // to know about the repo asap @@ -658,7 +687,7 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu } this.logger.info(`Close repository: ${repository.root}`); - this._closedRepositories.add(openRepository.repository.root.toString()); + this._closedRepositoriesManager.addRepository(openRepository.repository.root); openRepository.dispose(); } diff --git a/extensions/git/src/observable.ts b/extensions/git/src/observable.ts deleted file mode 100644 index b32fbf156dd..00000000000 --- a/extensions/git/src/observable.ts +++ /dev/null @@ -1,70 +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 { EventEmitter } from 'vscode'; - -export class ObservableSet implements Set { - - readonly [Symbol.toStringTag]: string = 'ObservableSet'; - - private _set: Set; - private _onDidChange = new EventEmitter(); - readonly onDidChange = this._onDidChange.event; - - constructor(values?: readonly T[] | null) { - this._set = new Set(values); - } - - get size(): number { - return this._set.size; - } - - add(value: T): this { - this._set.add(value); - this._onDidChange.fire(); - - return this; - } - - clear(): void { - if (this._set.size > 0) { - this._set.clear(); - this._onDidChange.fire(); - } - } - - delete(value: T): boolean { - const result = this._set.delete(value); - if (result) { - this._onDidChange.fire(); - } - - return result; - } - - forEach(callbackfn: (value: T, value2: T, set: Set) => void, thisArg?: any): void { - this._set.forEach((_value, key) => callbackfn.call(thisArg, key, key, this)); - } - - has(value: T): boolean { - return this._set.has(value); - } - - entries(): IterableIterator<[T, T]> { - return this._set.entries(); - } - - keys(): IterableIterator { - return this._set.keys(); - } - - values(): IterableIterator { - return this._set.keys(); - } - - [Symbol.iterator](): IterableIterator { - return this.keys(); - } -} From 5a55352cf7f8a4f582c57849eaa209a31621b841 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 9 Jun 2023 14:55:05 -0700 Subject: [PATCH 031/128] Combine esbuild scripts (#184531) * Combine esbuild scripts This combines the various build scripts used for building webview/notebook content. This should make it easier to update settings for them As part of this, I also fixed the script so that on watch it restarts automatically on syntax errors instead of exiting * Migrate other build script * Fixing math build script --- extensions/esbuild-webview-common.js | 91 +++++++++++++++++++ extensions/ipynb/esbuild.js | 49 ++-------- .../esbuild-notebook.js | 44 ++------- .../esbuild-preview.js | 45 ++------- extensions/markdown-math/esbuild.js | 46 ++-------- extensions/notebook-renderers/esbuild.js | 43 ++------- extensions/simple-browser/esbuild-preview.js | 49 +++------- 7 files changed, 145 insertions(+), 222 deletions(-) create mode 100644 extensions/esbuild-webview-common.js diff --git a/extensions/esbuild-webview-common.js b/extensions/esbuild-webview-common.js new file mode 100644 index 00000000000..8a2a7d07a2d --- /dev/null +++ b/extensions/esbuild-webview-common.js @@ -0,0 +1,91 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// @ts-check + +/** + * @fileoverview Common build script for extension scripts used in in webviews. + */ + +const path = require('path'); +const esbuild = require('esbuild'); + +/** + * @typedef {Partial & { + * entryPoints: string[] | Record | { in: string, out: string }[]; + * outdir: string; + * }} BuildOptions + */ + +/** + * Build the source code once using esbuild. + * + * @param {BuildOptions} options + * @param {(outDir: string) => unknown} [didBuild] + */ +async function build(options, didBuild) { + await esbuild.build({ + bundle: true, + minify: true, + sourcemap: false, + format: 'esm', + platform: 'browser', + target: ['es2020'], + ...options, + }); + + await didBuild?.(options.outdir); +} + +/** + * Build the source code once using esbuild, logging errors instead of throwing. + * + * @param {BuildOptions} options + * @param {(outDir: string) => unknown} [didBuild] + */ +async function tryBuild(options, didBuild) { + try { + await build(options, didBuild); + } catch (err) { + console.error(err); + } +} + +/** + * @param {{ + * srcDir: string; + * outdir: string; + * entryPoints: string[] | Record | { in: string, out: string }[]; + * additionalOptions?: Partial + * }} config + * @param {string[]} args + * @param {(outDir: string) => unknown} [didBuild] + */ +module.exports.run = function (config, args, didBuild) { + let outdir = config.outdir; + + const outputRootIndex = args.indexOf('--outputRoot'); + if (outputRootIndex >= 0) { + const outputRoot = args[outputRootIndex + 1]; + const outputDirName = path.basename(outdir); + outdir = path.join(outputRoot, outputDirName); + } + + /** @type {BuildOptions} */ + const resolvedOptions = { + entryPoints: config.entryPoints, + outdir, + ...(config.additionalOptions || {}), + }; + + const isWatch = args.indexOf('--watch') >= 0; + if (isWatch) { + tryBuild(resolvedOptions); + + const watcher = require('@parcel/watcher'); + watcher.subscribe(config.srcDir, () => tryBuild(resolvedOptions, didBuild)); + } else { + return build(resolvedOptions, didBuild).catch(() => process.exit(1)); + } +}; diff --git a/extensions/ipynb/esbuild.js b/extensions/ipynb/esbuild.js index 28000f1ebf9..64b58109fec 100644 --- a/extensions/ipynb/esbuild.js +++ b/extensions/ipynb/esbuild.js @@ -5,47 +5,14 @@ //@ts-check const path = require('path'); -const fse = require('fs-extra'); -const esbuild = require('esbuild'); - -const args = process.argv.slice(2); - -const isWatch = args.indexOf('--watch') >= 0; - -let outputRoot = __dirname; -const outputRootIndex = args.indexOf('--outputRoot'); -if (outputRootIndex >= 0) { - outputRoot = args[outputRootIndex + 1]; -} const srcDir = path.join(__dirname, 'notebook-src'); -const outDir = path.join(outputRoot, 'notebook-out'); +const outDir = path.join(__dirname, 'notebook-out'); -async function build() { - await esbuild.build({ - entryPoints: [ - path.join(srcDir, 'cellAttachmentRenderer.ts'), - ], - bundle: true, - minify: false, - sourcemap: false, - format: 'esm', - outdir: outDir, - platform: 'browser', - target: ['es2020'], - }); -} - - -build().catch(() => process.exit(1)); - -if (isWatch) { - const watcher = require('@parcel/watcher'); - watcher.subscribe(srcDir, async () => { - try { - await build(); - } catch (e) { - console.error(e); - } - }); -} +require('../esbuild-webview-common').run({ + entryPoints: [ + path.join(srcDir, 'cellAttachmentRenderer.ts'), + ], + srcDir, + outdir: outDir, +}, process.argv); diff --git a/extensions/markdown-language-features/esbuild-notebook.js b/extensions/markdown-language-features/esbuild-notebook.js index fb32a3e986e..87275940f4c 100644 --- a/extensions/markdown-language-features/esbuild-notebook.js +++ b/extensions/markdown-language-features/esbuild-notebook.js @@ -4,42 +4,14 @@ *--------------------------------------------------------------------------------------------*/ // @ts-check const path = require('path'); -const esbuild = require('esbuild'); - -const args = process.argv.slice(2); - -const isWatch = args.indexOf('--watch') >= 0; - -let outputRoot = __dirname; -const outputRootIndex = args.indexOf('--outputRoot'); -if (outputRootIndex >= 0) { - outputRoot = args[outputRootIndex + 1]; -} const srcDir = path.join(__dirname, 'notebook'); -const outDir = path.join(outputRoot, 'notebook-out'); +const outDir = path.join(__dirname, 'notebook-out'); -function build() { - return esbuild.build({ - entryPoints: [ - path.join(__dirname, 'notebook', 'index.ts'), - ], - bundle: true, - minify: true, - sourcemap: false, - format: 'esm', - outdir: outDir, - platform: 'browser', - target: ['es2020'], - }); -} - - -build().catch(() => process.exit(1)); - -if (isWatch) { - const watcher = require('@parcel/watcher'); - watcher.subscribe(srcDir, () => { - return build(); - }); -} +require('../esbuild-webview-common').run({ + entryPoints: [ + path.join(srcDir, 'index.ts'), + ], + srcDir, + outdir: outDir, +}, process.argv); diff --git a/extensions/markdown-language-features/esbuild-preview.js b/extensions/markdown-language-features/esbuild-preview.js index c25dab4dbae..5a2e51cca09 100644 --- a/extensions/markdown-language-features/esbuild-preview.js +++ b/extensions/markdown-language-features/esbuild-preview.js @@ -4,42 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // @ts-check const path = require('path'); -const esbuild = require('esbuild'); - -const args = process.argv.slice(2); - -const isWatch = args.indexOf('--watch') >= 0; - -let outputRoot = __dirname; -const outputRootIndex = args.indexOf('--outputRoot'); -if (outputRootIndex >= 0) { - outputRoot = args[outputRootIndex + 1]; -} const srcDir = path.join(__dirname, 'preview-src'); -const outDir = path.join(outputRoot, 'media'); +const outDir = path.join(__dirname, 'media'); -function build() { - return esbuild.build({ - entryPoints: [ - path.join(srcDir, 'index.ts'), - path.join(srcDir, 'pre'), - ], - bundle: true, - minify: true, - sourcemap: false, - format: 'iife', - outdir: outDir, - platform: 'browser', - target: ['es2020'], - }); -} - -build().catch(() => process.exit(1)); - -if (isWatch) { - const watcher = require('@parcel/watcher'); - watcher.subscribe(srcDir, () => { - return build(); - }); -} +require('../esbuild-webview-common').run({ + entryPoints: [ + path.join(srcDir, 'index.ts'), + path.join(srcDir, 'pre'), + ], + srcDir, + outdir: outDir, +}, process.argv); diff --git a/extensions/markdown-math/esbuild.js b/extensions/markdown-math/esbuild.js index 88475257524..f8196075a69 100644 --- a/extensions/markdown-math/esbuild.js +++ b/extensions/markdown-math/esbuild.js @@ -6,35 +6,13 @@ const path = require('path'); const fse = require('fs-extra'); -const esbuild = require('esbuild'); const args = process.argv.slice(2); -const isWatch = args.indexOf('--watch') >= 0; - -let outputRoot = __dirname; -const outputRootIndex = args.indexOf('--outputRoot'); -if (outputRootIndex >= 0) { - outputRoot = args[outputRootIndex + 1]; -} - const srcDir = path.join(__dirname, 'notebook'); -const outDir = path.join(outputRoot, 'notebook-out'); - -async function build() { - await esbuild.build({ - entryPoints: [ - path.join(srcDir, 'katex.ts'), - ], - bundle: true, - minify: true, - sourcemap: false, - format: 'esm', - outdir: outDir, - platform: 'browser', - target: ['es2020'], - }); +const outDir = path.join(__dirname, 'notebook-out'); +function postBuild(outDir) { fse.copySync( path.join(__dirname, 'node_modules', 'katex', 'dist', 'katex.min.css'), path.join(outDir, 'katex.min.css')); @@ -51,16 +29,10 @@ async function build() { } } - -build().catch(() => process.exit(1)); - -if (isWatch) { - const watcher = require('@parcel/watcher'); - watcher.subscribe(srcDir, async () => { - try { - await build(); - } catch (e) { - console.error(e); - } - }); -} +require('../esbuild-webview-common').run({ + entryPoints: [ + path.join(srcDir, 'katex.ts'), + ], + srcDir, + outdir: outDir, +}, process.argv, postBuild); diff --git a/extensions/notebook-renderers/esbuild.js b/extensions/notebook-renderers/esbuild.js index c374cc5fc1c..55d462f8bc3 100644 --- a/extensions/notebook-renderers/esbuild.js +++ b/extensions/notebook-renderers/esbuild.js @@ -4,41 +4,14 @@ *--------------------------------------------------------------------------------------------*/ // @ts-check const path = require('path'); -const esbuild = require('esbuild'); - -const args = process.argv.slice(2); - -const isWatch = args.indexOf('--watch') >= 0; - -let outputRoot = __dirname; -const outputRootIndex = args.indexOf('--outputRoot'); -if (outputRootIndex >= 0) { - outputRoot = args[outputRootIndex + 1]; -} const srcDir = path.join(__dirname, 'src'); -const outDir = path.join(outputRoot, 'renderer-out'); +const outDir = path.join(__dirname, 'renderer-out'); -function build() { - return esbuild.build({ - entryPoints: [ - path.join(srcDir, 'index.ts'), - ], - bundle: true, - minify: false, - sourcemap: false, - format: 'esm', - outdir: outDir, - platform: 'browser', - target: ['es2020'], - }); -} - -build().catch(() => process.exit(1)); - -if (isWatch) { - const watcher = require('@parcel/watcher'); - watcher.subscribe(srcDir, () => { - return build(); - }); -} +require('../esbuild-webview-common').run({ + entryPoints: [ + path.join(srcDir, 'index.ts'), + ], + srcDir, + outdir: outDir, +}, process.argv); diff --git a/extensions/simple-browser/esbuild-preview.js b/extensions/simple-browser/esbuild-preview.js index 3133283f6b9..cf6e99ca6cb 100644 --- a/extensions/simple-browser/esbuild-preview.js +++ b/extensions/simple-browser/esbuild-preview.js @@ -4,45 +4,20 @@ *--------------------------------------------------------------------------------------------*/ // @ts-check const path = require('path'); -const esbuild = require('esbuild'); - -const args = process.argv.slice(2); - -const isWatch = args.indexOf('--watch') >= 0; - -let outputRoot = __dirname; -const outputRootIndex = args.indexOf('--outputRoot'); -if (outputRootIndex >= 0) { - outputRoot = args[outputRootIndex + 1]; -} const srcDir = path.join(__dirname, 'preview-src'); -const outDir = path.join(outputRoot, 'media'); +const outDir = path.join(__dirname, 'media'); -async function build() { - await esbuild.build({ - entryPoints: { - 'index': path.join(srcDir, 'index.ts'), - 'codicon': path.join(__dirname, 'node_modules', 'vscode-codicons', 'dist', 'codicon.css'), - }, +require('../esbuild-webview-common').run({ + entryPoints: { + 'index': path.join(srcDir, 'index.ts'), + 'codicon': path.join(__dirname, 'node_modules', 'vscode-codicons', 'dist', 'codicon.css'), + }, + srcDir, + outdir: outDir, + additionalOptions: { loader: { '.ttf': 'dataurl', - }, - bundle: true, - minify: true, - sourcemap: false, - format: 'esm', - outdir: outDir, - platform: 'browser', - target: ['es2020'], - }); -} - -build().catch(() => process.exit(1)); - -if (isWatch) { - const watcher = require('@parcel/watcher'); - watcher.subscribe(srcDir, () => { - return build(); - }); -} + } + } +}, process.argv); From c550a7b52c52f5622f6525e541196be736300d5d Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Fri, 9 Jun 2023 15:14:11 -0700 Subject: [PATCH 032/128] debug: auto recover from shifted tmpdirs in auto lauch (#184764) I think this should fix https://github.com/microsoft/vscode-js-debug/issues/1660 --- extensions/debug-auto-launch/src/extension.ts | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/extensions/debug-auto-launch/src/extension.ts b/extensions/debug-auto-launch/src/extension.ts index 6a23319b805..d947d4eb8b0 100644 --- a/extensions/debug-auto-launch/src/extension.ts +++ b/extensions/debug-auto-launch/src/extension.ts @@ -5,6 +5,7 @@ import { promises as fs } from 'fs'; import { createServer, Server } from 'net'; +import { dirname } from 'path'; import * as vscode from 'vscode'; const enum State { @@ -72,8 +73,7 @@ export function activate(context: vscode.ExtensionContext): void { e.affectsConfiguration(`${SETTING_SECTION}.${SETTING_STATE}`) || [...SETTINGS_CAUSE_REFRESH].some(setting => e.affectsConfiguration(setting)) ) { - updateAutoAttach(State.Disabled); - updateAutoAttach(readCurrentState()); + refreshAutoAttachVars(); } }), ); @@ -85,6 +85,11 @@ export async function deactivate(): Promise { await destroyAttachServer(); } +function refreshAutoAttachVars() { + updateAutoAttach(State.Disabled); + updateAutoAttach(readCurrentState()); +} + function getDefaultScope(info: ReturnType) { if (!info) { return vscode.ConfigurationTarget.Global; @@ -204,8 +209,22 @@ async function createAttachServer(context: vscode.ExtensionContext) { return undefined; } - server = createServerInner(ipcAddress).catch(err => { - console.error(err); + server = createServerInner(ipcAddress).catch(async err => { + console.error('[debug-auto-launch] Error creating auto attach server: ', err); + + if (process.platform !== 'win32') { + // On macOS, and perhaps some Linux distros, the temporary directory can + // sometimes change. If it looks like that's the cause of a listener + // error, automatically refresh the auto attach vars. + try { + await fs.access(dirname(ipcAddress)); + } catch { + console.error('[debug-auto-launch] Refreshing variables from error'); + refreshAutoAttachVars(); + return undefined; + } + } + return undefined; }); From 7e1125f9a74ba4551c9be58c0969c26dab5a4960 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 9 Jun 2023 15:49:50 -0700 Subject: [PATCH 033/128] Remove log (#184768) Fixes #184731 --- src/vs/workbench/contrib/update/browser/releaseNotesEditor.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/vs/workbench/contrib/update/browser/releaseNotesEditor.ts b/src/vs/workbench/contrib/update/browser/releaseNotesEditor.ts index 1cd887c1d22..044a7a24227 100644 --- a/src/vs/workbench/contrib/update/browser/releaseNotesEditor.ts +++ b/src/vs/workbench/contrib/update/browser/releaseNotesEditor.ts @@ -258,8 +258,6 @@ export class ReleaseNotesManager { container.appendChild(label); const beforeElement = document.querySelector("body > h1")?.nextElementSibling; - console.log(beforeElement); - if (beforeElement) { document.body.insertBefore(container, beforeElement); } else { From 7ff66b360d5f1cdbdbfa8e10842457e38117713d Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Sat, 10 Jun 2023 19:28:01 +0200 Subject: [PATCH 034/128] Diff Editor v2 Bugfixes (#184797) --- .../diffEditorWidget2/diffEditorWidget2.ts | 22 ++-- .../widget/diffEditorWidget2/lineAlignment.ts | 107 +++++++++--------- 2 files changed, 71 insertions(+), 58 deletions(-) diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts index 9ca82686cb9..7435f80c111 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts @@ -20,7 +20,7 @@ import { CodeEditorWidget, ICodeEditorWidgetOptions } from 'vs/editor/browser/wi import { IDiffCodeEditorWidgetOptions } from 'vs/editor/browser/widget/diffEditorWidget'; import { diffAddDecoration, diffDeleteDecoration, diffFullLineAddDecoration, diffFullLineDeleteDecoration } from 'vs/editor/browser/widget/diffEditorWidget2/decorations'; import { DiffEditorSash } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorSash'; -import { ViewZoneAlignment } from 'vs/editor/browser/widget/diffEditorWidget2/lineAlignment'; +import { ViewZoneManager } from 'vs/editor/browser/widget/diffEditorWidget2/lineAlignment'; import { MovedBlocksLinesPart } from 'vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines'; import { OverviewRulerPart } from 'vs/editor/browser/widget/diffEditorWidget2/overviewRulerPart'; import { UnchangedRangesFeature } from 'vs/editor/browser/widget/diffEditorWidget2/unchangedRanges'; @@ -140,7 +140,7 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { this._register(new UnchangedRangesFeature(this._originalEditor, this._modifiedEditor, this._diffModel)); - this._register(this._instantiationService.createInstance(ViewZoneAlignment, this._originalEditor, this._modifiedEditor, this._diffModel, this._options.map(o => o.renderSideBySide))); + this._register(this._instantiationService.createInstance(ViewZoneManager, this._originalEditor, this._modifiedEditor, this._diffModel, this._options.map(o => o.renderSideBySide))); this._register(this._instantiationService.createInstance(OverviewRulerPart, this._originalEditor, @@ -442,13 +442,21 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { return this._originalEditor.hasTextFocus() || this._modifiedEditor.hasTextFocus(); } - override saveViewState(): IDiffEditorViewState | null { - return null; - //throw new Error('Method not implemented.'); + public override saveViewState(): IDiffEditorViewState { + const originalViewState = this._originalEditor.saveViewState(); + const modifiedViewState = this._modifiedEditor.saveViewState(); + return { + original: originalViewState, + modified: modifiedViewState + }; } - override restoreViewState(state: IDiffEditorViewState | null): void { - //throw new Error('Method not implemented.'); + public override restoreViewState(s: IDiffEditorViewState): void { + if (s && s.original && s.modified) { + const diffEditorState = s as IDiffEditorViewState; + this._originalEditor.restoreViewState(diffEditorState.original); + this._modifiedEditor.restoreViewState(diffEditorState.modified); + } } override getModel(): IDiffEditorModel | null { return this._model.get(); } diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts b/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts index 2b47702d076..98d93ee8161 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts @@ -8,8 +8,10 @@ import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IObservable, derived, observableFromEvent, observableSignalFromEvent, observableValue } from 'vs/base/common/observable'; import { autorun, autorunWithStore2 } from 'vs/base/common/observableImpl/autorun'; import { ThemeIcon } from 'vs/base/common/themables'; +import { assertIsDefined } from 'vs/base/common/types'; import { applyFontInfo } from 'vs/editor/browser/config/domFontInfo'; import { IViewZone } from 'vs/editor/browser/editorBrowser'; +import { StableEditorScrollState } from 'vs/editor/browser/stableEditorScroll'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { diffDeleteDecoration, diffRemoveIcon } from 'vs/editor/browser/widget/diffEditorWidget2/decorations'; import { DiffMapping, DiffModel } from 'vs/editor/browser/widget/diffEditorWidget2/diffModel'; @@ -26,14 +28,18 @@ import { InlineDecoration, InlineDecorationType } from 'vs/editor/common/viewMod import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -export class ViewZoneAlignment extends Disposable { - private readonly _origExtraHeight = observableValue('origExtraHeight', 0); - private readonly _modExtraHeight = observableValue('modExtraHeight', 0); - +/** + * Ensures both editors have the same height by aligning unchanged lines. + * In inline view mode, inserts viewzones to show deleted code from the original text model in the modified code editor. + * Synchronizes scrolling. + */ +export class ViewZoneManager extends Disposable { + private readonly _originalTopPadding = observableValue('originalTopPadding', 0); private readonly _originalScrollTop: IObservable; private readonly _originalScrollOffset = observableValue('originalScrollOffset', 0); private readonly _originalScrollOffsetAnimated = animatedObservable(this._originalScrollOffset, this._store); + private readonly _modifiedTopPadding = observableValue('modifiedTopPadding', 0); private readonly _modifiedScrollTop: IObservable; private readonly _modifiedScrollOffset = observableValue('modifiedScrollOffset', 0); private readonly _modifiedScrollOffsetAnimated = animatedObservable(this._modifiedScrollOffset, this._store); @@ -50,11 +56,11 @@ export class ViewZoneAlignment extends Disposable { let isChangingViewZones = false; - const origViewZonesChanged = observableSignalFromEvent( + const originalViewZonesChanged = observableSignalFromEvent( 'origViewZonesChanged', e => this._originalEditor.onDidChangeViewZones((args) => { if (!isChangingViewZones) { e(args); } }) ); - const modViewZonesChanged = observableSignalFromEvent( + const modifiedViewZonesChanged = observableSignalFromEvent( 'modViewZonesChanged', e => this._modifiedEditor.onDidChangeViewZones((args) => { if (!isChangingViewZones) { e(args); } }) ); @@ -70,24 +76,18 @@ export class ViewZoneAlignment extends Disposable { const diffModel = this._diffModel.read(reader); const diff = diffModel?.diff.read(reader); if (!diffModel || !diff) { return null; } - - origViewZonesChanged.read(reader); - modViewZonesChanged.read(reader); - + originalViewZonesChanged.read(reader); + modifiedViewZonesChanged.read(reader); return computeRangeAlignment(this._originalEditor, this._modifiedEditor, diff.mappings, alignmentViewZoneIdsOrig, alignmentViewZoneIdsMod); }); const alignmentsSyncedMovedText = derived('alignments', (reader) => { - origViewZonesChanged.read(reader); - modViewZonesChanged.read(reader); - const syncedMovedText = this._diffModel.read(reader)?.syncedMovedTexts.read(reader); - if (!syncedMovedText) { - return null; - } + if (!syncedMovedText) { return null; } + originalViewZonesChanged.read(reader); + modifiedViewZonesChanged.read(reader); const mappings = syncedMovedText.changes.map(c => new DiffMapping(c)); - - // TOD dont include alignments outside syncedMovedText + // TODO dont include alignments outside syncedMovedText return computeRangeAlignment(this._originalEditor, this._modifiedEditor, mappings, alignmentViewZoneIdsOrig, alignmentViewZoneIdsMod); }); @@ -101,25 +101,25 @@ export class ViewZoneAlignment extends Disposable { const alignmentViewZones = derived<{ orig: IViewZoneWithZoneId[]; mod: IViewZoneWithZoneId[] }>('alignment viewzones', (reader) => { alignmentViewZonesDisposables.clear(); - const curAlignments = alignments.read(reader) || []; + const alignmentsVal = alignments.read(reader) || []; const origViewZones: IViewZoneWithZoneId[] = []; const modViewZones: IViewZoneWithZoneId[] = []; - const curModExtraHeight = this._modExtraHeight.read(reader); - if (curModExtraHeight > 0) { + const modifiedTopPaddingVal = this._modifiedTopPadding.read(reader); + if (modifiedTopPaddingVal > 0) { modViewZones.push({ afterLineNumber: 0, domNode: document.createElement('div'), - heightInPx: curModExtraHeight, + heightInPx: modifiedTopPaddingVal, }); } - const curOrigExtraHeight = this._origExtraHeight.read(reader); - if (curOrigExtraHeight > 0) { + const originalTopPaddingVal = this._originalTopPadding.read(reader); + if (originalTopPaddingVal > 0) { origViewZones.push({ afterLineNumber: 0, domNode: document.createElement('div'), - heightInPx: curOrigExtraHeight, + heightInPx: originalTopPaddingVal, }); } @@ -127,7 +127,7 @@ export class ViewZoneAlignment extends Disposable { const deletedCodeLineBreaksComputer = !renderSideBySide ? this._modifiedEditor._getViewModel()?.createLineBreaksComputer() : undefined; if (deletedCodeLineBreaksComputer) { - for (const a of curAlignments) { + for (const a of alignmentsVal) { if (a.diff) { for (let i = a.originalRange.startLineNumber; i < a.originalRange.endLineNumberExclusive; i++) { deletedCodeLineBreaksComputer?.addRequest(this._originalEditor.getModel()!.getLineContent(i), null, null); @@ -147,13 +147,13 @@ export class ViewZoneAlignment extends Disposable { const mightContainRTL = this._originalEditor.getModel()?.mightContainRTL() ?? false; const renderOptions = RenderOptions.fromEditor(this._modifiedEditor); - for (const a of curAlignments) { + for (const a of alignmentsVal) { if (a.diff && !renderSideBySide) { if (!a.originalRange.isEmpty) { originalModelTokenizationCompleted.read(reader); // Update view-zones once tokenization completes - const domNode = document.createElement('div'); - domNode.classList.add('view-lines', 'line-delete', 'monaco-mouse-cursor-text'); + const deletedCodeDomNode = document.createElement('div'); + deletedCodeDomNode.classList.add('view-lines', 'line-delete', 'monaco-mouse-cursor-text'); const source = new LineSource( a.originalRange.mapToLineArray(l => this._originalEditor.getModel()!.tokenization.getLineTokens(l)), a.originalRange.mapToLineArray(_ => lineBreakData[lineBreakDataIdx++]), @@ -168,7 +168,7 @@ export class ViewZoneAlignment extends Disposable { InlineDecorationType.Regular )); } - const result = renderLines(source, renderOptions, decorations, domNode); + const result = renderLines(source, renderOptions, decorations, deletedCodeDomNode); const marginDomNode = document.createElement('div'); marginDomNode.className = 'inline-deleted-margin-view-zone'; @@ -183,18 +183,10 @@ export class ViewZoneAlignment extends Disposable { } //} - let zoneId: string; - modViewZones.push({ - afterLineNumber: a.modifiedRange.startLineNumber - 1, - domNode: domNode, - heightInPx: result.heightInLines * modLineHeight, - minWidthInPx: result.minWidthInPx, - marginDomNode, - setZoneId(id) { zoneId = id; }, - }); + let zoneId: string | undefined = undefined; alignmentViewZonesDisposables.add( new InlineDiffDeletedCodeMargin( - () => zoneId, + () => assertIsDefined(zoneId), marginDomNode, this._modifiedEditor, a.diff, @@ -207,7 +199,7 @@ export class ViewZoneAlignment extends Disposable { for (let i = 0; i < result.viewLineCounts.length; i++) { const count = result.viewLineCounts[i]; - // Account for wrapped lines in the (collapsed) original editor (that does not have line wraps). + // Account for wrapped lines in the (collapsed) original editor (which doesn't wrap lines). if (count > 1) { origViewZones.push({ afterLineNumber: a.originalRange.startLineNumber + i, @@ -216,6 +208,15 @@ export class ViewZoneAlignment extends Disposable { }); } } + + modViewZones.push({ + afterLineNumber: a.modifiedRange.startLineNumber - 1, + domNode: deletedCodeDomNode, + heightInPx: result.heightInLines * modLineHeight, + minWidthInPx: result.minWidthInPx, + marginDomNode, + setZoneId(id) { zoneId = id; }, + }); } const marginDomNode = document.createElement('div'); @@ -280,6 +281,8 @@ export class ViewZoneAlignment extends Disposable { }); this._register(autorunWithStore2('alignment viewzones', (reader) => { + const scrollState = StableEditorScrollState.capture(this._modifiedEditor); + const alignmentViewZones_ = alignmentViewZones.read(reader); isChangingViewZones = true; this._originalEditor.changeViewZones((aOrig) => { @@ -305,6 +308,8 @@ export class ViewZoneAlignment extends Disposable { } }); isChangingViewZones = false; + + scrollState.restore(this._modifiedEditor); })); this._originalScrollTop = observableFromEvent(this._originalEditor.onDidScrollChange, () => this._originalEditor.getScrollTop()); @@ -321,7 +326,7 @@ export class ViewZoneAlignment extends Disposable { this._register(autorun('update scroll modified', (reader) => { const newScrollTopModified = this._originalScrollTop.read(reader) - (this._originalScrollOffsetAnimated.get() - this._modifiedScrollOffsetAnimated.read(reader)) - - (this._origExtraHeight.get() - this._modExtraHeight.read(reader)); + - (this._originalTopPadding.get() - this._modifiedTopPadding.read(reader)); if (newScrollTopModified !== this._modifiedEditor.getScrollTop()) { this._modifiedEditor.setScrollTop(newScrollTopModified, ScrollType.Immediate); } @@ -330,7 +335,7 @@ export class ViewZoneAlignment extends Disposable { this._register(autorun('update scroll original', (reader) => { const newScrollTopOriginal = this._modifiedScrollTop.read(reader) - (this._modifiedScrollOffsetAnimated.get() - this._originalScrollOffsetAnimated.read(reader)) - - (this._modExtraHeight.get() - this._origExtraHeight.read(reader)); + - (this._modifiedTopPadding.get() - this._originalTopPadding.read(reader)); if (newScrollTopOriginal !== this._originalEditor.getScrollTop()) { this._originalEditor.setScrollTop(newScrollTopOriginal, ScrollType.Immediate); } @@ -342,21 +347,21 @@ export class ViewZoneAlignment extends Disposable { let deltaOrigToMod = 0; if (m) { - const trueTopOriginal = this._originalEditor.getTopForLineNumber(m.lineRangeMapping.originalRange.startLineNumber, true) - this._origExtraHeight.get(); - const trueTopModified = this._modifiedEditor.getTopForLineNumber(m.lineRangeMapping.modifiedRange.startLineNumber, true) - this._modExtraHeight.get(); + const trueTopOriginal = this._originalEditor.getTopForLineNumber(m.lineRangeMapping.originalRange.startLineNumber, true) - this._originalTopPadding.get(); + const trueTopModified = this._modifiedEditor.getTopForLineNumber(m.lineRangeMapping.modifiedRange.startLineNumber, true) - this._modifiedTopPadding.get(); deltaOrigToMod = trueTopModified - trueTopOriginal; } if (deltaOrigToMod > 0) { - this._modExtraHeight.set(0, undefined); - this._origExtraHeight.set(deltaOrigToMod, undefined); + this._modifiedTopPadding.set(0, undefined); + this._originalTopPadding.set(deltaOrigToMod, undefined); } else if (deltaOrigToMod < 0) { - this._modExtraHeight.set(-deltaOrigToMod, undefined); - this._origExtraHeight.set(0, undefined); + this._modifiedTopPadding.set(-deltaOrigToMod, undefined); + this._originalTopPadding.set(0, undefined); } else { setTimeout(() => { - this._modExtraHeight.set(0, undefined); - this._origExtraHeight.set(0, undefined); + this._modifiedTopPadding.set(0, undefined); + this._originalTopPadding.set(0, undefined); }, 400); } From ef6abe4cd1573689d070b8715e97019cfadaeb51 Mon Sep 17 00:00:00 2001 From: Bhavya U Date: Sun, 11 Jun 2023 13:37:10 -0700 Subject: [PATCH 035/128] Adopt editor resolver for Welcome/Walkthrough pages (#184770) * Register walkthrough pages via editorResolverService * Clean up code --- .../browser/gettingStarted.contribution.ts | 12 ++--- .../browser/gettingStartedInput.ts | 17 ++++++- .../browser/startupPage.ts | 44 +++++++++++++++---- .../editor/common/editorResolverService.ts | 1 - 4 files changed, 59 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.contribution.ts b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.contribution.ts index 9bbb99b8ab6..977423bbe85 100644 --- a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.contribution.ts +++ b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.contribution.ts @@ -16,7 +16,7 @@ import { KeyCode } from 'vs/base/common/keyCodes'; import { EditorPaneDescriptor, IEditorPaneRegistry } from 'vs/workbench/browser/editor'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { IWalkthroughsService } from 'vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService'; -import { GettingStartedInput } from 'vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedInput'; +import { GettingStartedEditorOptions, GettingStartedInput } from 'vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedInput'; import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { ConfigurationScope, Extensions as ConfigurationExtensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; @@ -100,20 +100,22 @@ registerAction2(class extends Action2 { return; } - const gettingStartedInput = instantiationService.createInstance(GettingStartedInput, { selectedCategory: selectedCategory, selectedStep: selectedStep }); // If it's the extension install page then lets replace it with the getting started page if (activeEditor instanceof ExtensionsInput) { const activeGroup = editorGroupsService.activeGroup; activeGroup.replaceEditors([{ editor: activeEditor, - replacement: gettingStartedInput + replacement: instantiationService.createInstance(GettingStartedInput, { selectedCategory: selectedCategory, selectedStep: selectedStep }) }]); } else if (!openedWalkthroughExists) { // else open respecting toSide - editorService.openEditor(gettingStartedInput, { preserveFocus: toSide ?? false }, toSide ? SIDE_GROUP : undefined); + editorService.openEditor({ + resource: GettingStartedInput.RESOURCE, + options: { selectedCategory: selectedCategory, selectedStep: selectedStep, preserveFocus: toSide ?? false } + }, toSide ? SIDE_GROUP : undefined); } } else { - editorService.openEditor(new GettingStartedInput({}), {}); + editorService.openEditor({ resource: GettingStartedInput.RESOURCE }); } } }); diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedInput.ts b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedInput.ts index 7c9d8ec1f7f..23df7b598be 100644 --- a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedInput.ts +++ b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedInput.ts @@ -9,9 +9,14 @@ import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { URI } from 'vs/base/common/uri'; import { Schemas } from 'vs/base/common/network'; import { IUntypedEditorInput } from 'vs/workbench/common/editor'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; export const gettingStartedInputTypeId = 'workbench.editors.gettingStartedInput'; +export interface GettingStartedEditorOptions extends IEditorOptions { + selectedCategory?: string; selectedStep?: string; showTelemetryNotice?: boolean; +} + export class GettingStartedInput extends EditorInput { static readonly ID = gettingStartedInputTypeId; @@ -21,6 +26,16 @@ export class GettingStartedInput extends EditorInput { return GettingStartedInput.ID; } + override toUntyped(): IUntypedEditorInput { + return { + resource: GettingStartedInput.RESOURCE, + options: { + override: GettingStartedInput.ID, + pinned: false + } + }; + } + get resource(): URI | undefined { return GettingStartedInput.RESOURCE; } @@ -37,7 +52,7 @@ export class GettingStartedInput extends EditorInput { } constructor( - options: { selectedCategory?: string; selectedStep?: string; showTelemetryNotice?: boolean } + options: GettingStartedEditorOptions ) { super(); this.selectedCategory = options.selectedCategory; diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/browser/startupPage.ts b/src/vs/workbench/contrib/welcomeGettingStarted/browser/startupPage.ts index bc4c8455907..857ae064148 100644 --- a/src/vs/workbench/contrib/welcomeGettingStarted/browser/startupPage.ts +++ b/src/vs/workbench/contrib/welcomeGettingStarted/browser/startupPage.ts @@ -18,7 +18,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { joinPath } from 'vs/base/common/resources'; import { IEditorOptions } from 'vs/platform/editor/common/editor'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; -import { GettingStartedInput, gettingStartedInputTypeId } from 'vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedInput'; +import { GettingStartedEditorOptions, GettingStartedInput, gettingStartedInputTypeId } from 'vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedInput'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { getTelemetryLevel } from 'vs/platform/telemetry/common/telemetryUtils'; @@ -27,6 +27,7 @@ import { IProductService } from 'vs/platform/product/common/productService'; import { ILogService } from 'vs/platform/log/common/log'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { localize } from 'vs/nls'; +import { IEditorResolverService, RegisteredEditorPriority } from 'vs/workbench/services/editor/common/editorResolverService'; export const restoreWalkthroughsConfigurationKey = 'workbench.welcomePage.restorableWalkthroughs'; export type RestoreWalkthroughsConfigurationValue = { folder: string; category?: string; step?: string }; @@ -51,9 +52,34 @@ export class StartupPageContribution implements IWorkbenchContribution { @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, @IStorageService private readonly storageService: IStorageService, @ILogService private readonly logService: ILogService, - @INotificationService private readonly notificationService: INotificationService + @INotificationService private readonly notificationService: INotificationService, + @IEditorResolverService editorResolverService: IEditorResolverService ) { this.run().then(undefined, onUnexpectedError); + + editorResolverService.registerEditor( + `${GettingStartedInput.RESOURCE.scheme}:/**`, + { + id: GettingStartedInput.ID, + label: localize('welcome.displayName', "Welcome Page"), + priority: RegisteredEditorPriority.builtin, + }, + { + singlePerResource: false, + canSupportResource: uri => uri.scheme === GettingStartedInput.RESOURCE.scheme, + }, + { + createEditorInput: ({ resource, options }) => { + return { + editor: this.instantiationService.createInstance(GettingStartedInput, options as GettingStartedEditorOptions), + options: { + ...options, + pinned: false + } + }; + } + } + ); } private async run() { @@ -114,11 +140,10 @@ export class StartupPageContribution implements IWorkbenchContribution { const restoreData: RestoreWalkthroughsConfigurationValue = JSON.parse(toRestore); const currentWorkspace = this.contextService.getWorkspace(); if (restoreData.folder === currentWorkspace.folders[0].uri.toString() || restoreData.folder === UNKNOWN_EMPTY_WINDOW_WORKSPACE.id) { - this.editorService.openEditor( - this.instantiationService.createInstance( - GettingStartedInput, - { selectedCategory: restoreData.category, selectedStep: restoreData.step }), - { pinned: false }); + this.editorService.openEditor({ + resource: GettingStartedInput.RESOURCE, + options: { selectedCategory: restoreData.category, selectedStep: restoreData.step, pinned: false }, + }); this.storageService.remove(restoreWalkthroughsConfigurationKey, StorageScope.PROFILE); return true; } @@ -165,7 +190,10 @@ export class StartupPageContribution implements IWorkbenchContribution { const options: IEditorOptions = editor ? { pinned: false, index: 0 } : { pinned: false }; if (startupEditorTypeID === gettingStartedInputTypeId) { - this.editorService.openEditor(this.instantiationService.createInstance(GettingStartedInput, { showTelemetryNotice }), options); + this.editorService.openEditor({ + resource: GettingStartedInput.RESOURCE, + options: { showTelemetryNotice, ...options }, + }); } } } diff --git a/src/vs/workbench/services/editor/common/editorResolverService.ts b/src/vs/workbench/services/editor/common/editorResolverService.ts index da86d1fa3e1..33b17849182 100644 --- a/src/vs/workbench/services/editor/common/editorResolverService.ts +++ b/src/vs/workbench/services/editor/common/editorResolverService.ts @@ -204,7 +204,6 @@ export function globMatchesResource(globPattern: string | glob.IRelativePattern, Schemas.extension, Schemas.webviewPanel, Schemas.vscodeWorkspaceTrust, - Schemas.walkThrough, Schemas.vscodeSettings ]); // We want to say that the above schemes match no glob patterns From 89ec834df20d597ff96f7d303e7e0f2f055d2a4e Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Mon, 12 Jun 2023 07:03:26 +0200 Subject: [PATCH 036/128] Diff Editor Rewrite Progress (#184857) --- src/vs/base/common/observableImpl/derived.ts | 16 ++- src/vs/base/common/observableImpl/utils.ts | 4 +- .../diffEditorWidget2/diffEditorWidget2.ts | 122 +++++++++++++----- .../widget/diffEditorWidget2/diffModel.ts | 6 +- .../common/diff/smartLinesDiffComputer.ts | 1 + 5 files changed, 113 insertions(+), 36 deletions(-) diff --git a/src/vs/base/common/observableImpl/derived.ts b/src/vs/base/common/observableImpl/derived.ts index 8980f26b77f..0bfe5d71681 100644 --- a/src/vs/base/common/observableImpl/derived.ts +++ b/src/vs/base/common/observableImpl/derived.ts @@ -4,11 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { BugIndicatingError } from 'vs/base/common/errors'; +import { DisposableStore } from 'vs/base/common/lifecycle'; import { IReader, IObservable, BaseObservable, IObserver, _setDerived, IChangeContext } from 'vs/base/common/observableImpl/base'; import { getLogger } from 'vs/base/common/observableImpl/logging'; export function derived(debugName: string | (() => string), computeFn: (reader: IReader) => T): IObservable { - return new Derived(debugName, computeFn, undefined, undefined); + return new Derived(debugName, computeFn, undefined, undefined, undefined); } export function derivedHandleChanges( @@ -18,7 +19,15 @@ export function derivedHandleChanges( handleChange: (context: IChangeContext, changeSummary: TChangeSummary) => boolean; }, computeFn: (reader: IReader, changeSummary: TChangeSummary) => T): IObservable { - return new Derived(debugName, computeFn, options.createEmptyChangeSummary, options.handleChange); + return new Derived(debugName, computeFn, options.createEmptyChangeSummary, options.handleChange, undefined); +} + +export function derivedWithStore(name: string, computeFn: (reader: IReader, store: DisposableStore) => T): IObservable { + const store = new DisposableStore(); + return new Derived(name, r => { + store.clear(); + return computeFn(r, store); + }, undefined, undefined, () => store.dispose()); } _setDerived(derived); @@ -62,6 +71,7 @@ export class Derived extends BaseObservable im private readonly computeFn: (reader: IReader, changeSummary: TChangeSummary) => T, private readonly createChangeSummary: (() => TChangeSummary) | undefined, private readonly _handleChange: ((context: IChangeContext, summary: TChangeSummary) => boolean) | undefined, + private readonly _handleLastObserverRemoved: (() => void) | undefined = undefined ) { super(); this.changeSummary = this.createChangeSummary?.(); @@ -79,6 +89,8 @@ export class Derived extends BaseObservable im d.removeObserver(this); } this.dependencies.clear(); + + this._handleLastObserverRemoved?.(); } public override get(): T { diff --git a/src/vs/base/common/observableImpl/utils.ts b/src/vs/base/common/observableImpl/utils.ts index 9d13c29ade6..5d9a2c568a8 100644 --- a/src/vs/base/common/observableImpl/utils.ts +++ b/src/vs/base/common/observableImpl/utils.ts @@ -3,11 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Event } from 'vs/base/common/event'; import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { autorun } from 'vs/base/common/observableImpl/autorun'; -import { IObservable, BaseObservable, transaction, IReader, ITransaction, ConvenientObservable, IObserver, observableValue, getFunctionName } from 'vs/base/common/observableImpl/base'; +import { BaseObservable, ConvenientObservable, IObservable, IObserver, IReader, ITransaction, getFunctionName, observableValue, transaction } from 'vs/base/common/observableImpl/base'; import { derived } from 'vs/base/common/observableImpl/derived'; -import { Event } from 'vs/base/common/event'; import { getLogger } from 'vs/base/common/observableImpl/logging'; export function constObservable(value: T): IObservable { diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts index 7435f80c111..dc355e41d60 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts @@ -8,7 +8,8 @@ import { findLast } from 'vs/base/common/arrays'; import { onUnexpectedError } from 'vs/base/common/errors'; import { Emitter, Event } from 'vs/base/common/event'; import { IObservable, ISettableObservable, autorun, derived, keepAlive, observableValue, waitForState } from 'vs/base/common/observable'; -import { disposableObservableValue, transaction } from 'vs/base/common/observableImpl/base'; +import { disposableObservableValue } from 'vs/base/common/observableImpl/base'; +import { derivedWithStore } from 'vs/base/common/observableImpl/derived'; import { isDefined } from 'vs/base/common/types'; import { Constants } from 'vs/base/common/uint'; import 'vs/css!./style'; @@ -80,6 +81,7 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { private readonly _rootSizeObserver: ObservableElementSizeObserver; private readonly _options: ISettableObservable; private readonly _sash: IObservable; + private readonly _boundarySashes = observableValue('boundarySashes', undefined); private readonly _renderOverviewRuler: IObservable; constructor( @@ -114,30 +116,30 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { this._register(applyObservableDecorations(this._modifiedEditor, this._decorations.map(d => d?.modifiedDecorations || []))); this._renderOverviewRuler = this._options.map(o => o.renderOverviewRuler); - const sash = this._register(disposableObservableValue('sash', undefined)); - this._sash = sash; - - this._register(autorun('update sash', reader => { + this._sash = derivedWithStore('sash', (reader, store) => { const showSash = this._options.read(reader).renderSideBySide; - this.elements.root.classList.toggle('side-by-side', showSash); - - transaction(tx => { - sash.set(undefined, tx); - if (showSash) { - sash.set(new DiffEditorSash( - this._options.map(o => o.enableSplitViewResizing), - this._options.map(o => o.splitViewDefaultRatio), - this.elements.root, - { - height: this._rootSizeObserver.height, - width: this._rootSizeObserver.width.map((w, reader) => w - (this._renderOverviewRuler.read(reader) ? OverviewRulerPart.ENTIRE_DIFF_OVERVIEW_WIDTH : 0)), - } - ), tx); + if (!showSash) { + return undefined; + } + const result = store.add(new DiffEditorSash( + this._options.map(o => o.enableSplitViewResizing), + this._options.map(o => o.splitViewDefaultRatio), + this.elements.root, + { + height: this._rootSizeObserver.height, + width: this._rootSizeObserver.width.map((w, reader) => w - (this._renderOverviewRuler.read(reader) ? OverviewRulerPart.ENTIRE_DIFF_OVERVIEW_WIDTH : 0)), } - }); - })); - + )); + store.add(autorun('setBoundarySashes', reader => { + const boundarySashes = this._boundarySashes.read(reader); + if (boundarySashes) { + result.setBoundarySashes(boundarySashes); + } + })); + return result; + }); + this._register(keepAlive(this._sash, true)); this._register(new UnchangedRangesFeature(this._originalEditor, this._modifiedEditor, this._diffModel)); this._register(this._instantiationService.createInstance(ViewZoneManager, this._originalEditor, this._modifiedEditor, this._diffModel, this._options.map(o => o.renderSideBySide))); @@ -490,13 +492,11 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { getModifiedEditor(): ICodeEditor { return this._modifiedEditor; } setBoundarySashes(sashes: IBoundarySashes): void { - // TODO - this._sash.get()?.setBoundarySashes(sashes); + this._boundarySashes.set(sashes, undefined); } - readonly onDidUpdateDiff: Event = e => { - return { dispose: () => { } }; - }; + private readonly _diffValue = this._diffModel.map((m, r) => m?.diff.read(r)); + readonly onDidUpdateDiff: Event = Event.fromObservableLight(this._diffValue); get ignoreTrimWhitespace(): boolean { return this._options.get().ignoreTrimWhitespace; @@ -510,13 +510,73 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { return this._options.get().renderSideBySide; } + /** + * @deprecated Use `this.getDiffComputationResult().changes2` instead. + */ getLineChanges(): ILineChange[] | null { - return null; - //throw new Error('Method not implemented.'); + const diffState = this._diffModel.get()?.diff.get(); + if (!diffState) { + return null; + } + return diffState.mappings.map(x => { + const m = x.lineRangeMapping; + let originalStartLineNumber: number; + let originalEndLineNumber: number; + let modifiedStartLineNumber: number; + let modifiedEndLineNumber: number; + let innerChanges = m.innerChanges; + + if (m.originalRange.isEmpty) { + // Insertion + originalStartLineNumber = m.originalRange.startLineNumber - 1; + originalEndLineNumber = 0; + innerChanges = undefined; + } else { + originalStartLineNumber = m.originalRange.startLineNumber; + originalEndLineNumber = m.originalRange.endLineNumberExclusive - 1; + } + + if (m.modifiedRange.isEmpty) { + // Deletion + modifiedStartLineNumber = m.modifiedRange.startLineNumber - 1; + modifiedEndLineNumber = 0; + innerChanges = undefined; + } else { + modifiedStartLineNumber = m.modifiedRange.startLineNumber; + modifiedEndLineNumber = m.modifiedRange.endLineNumberExclusive - 1; + } + + return { + originalStartLineNumber, + originalEndLineNumber, + modifiedStartLineNumber, + modifiedEndLineNumber, + charChanges: innerChanges?.map(m => ({ + originalStartLineNumber: m.originalRange.startLineNumber, + originalStartColumn: m.originalRange.startColumn, + originalEndLineNumber: m.originalRange.endLineNumber, + originalEndColumn: m.originalRange.endColumn, + modifiedStartLineNumber: m.modifiedRange.startLineNumber, + modifiedStartColumn: m.modifiedRange.startColumn, + modifiedEndLineNumber: m.modifiedRange.endLineNumber, + modifiedEndColumn: m.modifiedRange.endColumn, + })) + }; + }); } + getDiffComputationResult(): IDiffComputationResult | null { - return null; - //throw new Error('Method not implemented.'); + const diffState = this._diffModel.get()?.diff.get(); + if (!diffState) { + return null; + } + + return { + changes: this.getLineChanges()!, + changes2: diffState.mappings.map(m => m.lineRangeMapping), + identical: diffState.identical, + quitEarly: diffState.quitEarly, + }; } private _goTo(diff: DiffMapping): void { diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffModel.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffModel.ts index 4bf5a9ae629..cfab19c8ed4 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffModel.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffModel.ts @@ -177,13 +177,17 @@ export class DiffState { public static fromDiffResult(result: IDocumentDiff): DiffState { return new DiffState( result.changes.map(c => new DiffMapping(c)), - result.moves || [] + result.moves || [], + result.identical, + result.quitEarly, ); } constructor( public readonly mappings: readonly DiffMapping[], public readonly movedTexts: readonly MovedText[], + public readonly identical: boolean, + public readonly quitEarly: boolean, ) { } } diff --git a/src/vs/editor/common/diff/smartLinesDiffComputer.ts b/src/vs/editor/common/diff/smartLinesDiffComputer.ts index 1dbcd56a95a..fe7fdcdc5bf 100644 --- a/src/vs/editor/common/diff/smartLinesDiffComputer.ts +++ b/src/vs/editor/common/diff/smartLinesDiffComputer.ts @@ -85,6 +85,7 @@ export interface IDiffComputationResult { /** * The changes as (legacy) line change array. + * @deprecated Use `changes2` instead. */ changes: ILineChange[]; From e2d9e43ea63b8bcea23894e18efdb7437490a7c0 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Mon, 12 Jun 2023 09:35:48 +0200 Subject: [PATCH 037/128] setting the type of the indentation line number and the level --- .../workbench/contrib/inlineChat/browser/inlineChatWidget.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index 8057610cc56..fec2035c4f6 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -802,8 +802,8 @@ export class InteractiveEditorZoneWidget extends ZoneWidget { const visibleRange = viewModel.getCompletelyVisibleViewRange(); const startLineVisibleRange = visibleRange.startLineNumber; const positionLine = position.lineNumber; - let indentationLineNumber; - let indentationLevel; + let indentationLineNumber: number | undefined; + let indentationLevel: number | undefined; for (let lineNumber = positionLine; lineNumber >= startLineVisibleRange; lineNumber--) { const currentIndentationLevel = viewModel.getLineFirstNonWhitespaceColumn(lineNumber); if (currentIndentationLevel !== 0) { From 323e6df4e78e25ad99903e287b07fb42f05fc38d Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Mon, 12 Jun 2023 10:05:02 +0200 Subject: [PATCH 038/128] Git - improve repositories quick pick (#184794) --- extensions/git/src/commands.ts | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 905e102c7cd..fb5e2108102 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -196,9 +196,9 @@ class FetchAllRemotesItem implements QuickPickItem { } class RepositoryItem implements QuickPickItem { - get label(): string { - return `$(repo) ${this.path}`; - } + get label(): string { return `$(repo) ${getRepositoryLabel(this.path)}`; } + + get description(): string { return this.path; } constructor(public readonly path: string) { } } @@ -358,6 +358,15 @@ function getCheckoutProcessor(repository: Repository, type: string): CheckoutPro return undefined; } +function getRepositoryLabel(repositoryRoot: string): string { + const workspaceFolder = workspace.getWorkspaceFolder(Uri.file(repositoryRoot)); + return workspaceFolder?.uri.toString() === repositoryRoot ? workspaceFolder.name : path.basename(repositoryRoot); +} + +function compareRepositoryLabel(repositoryRoot1: string, repositoryRoot2: string): number { + return getRepositoryLabel(repositoryRoot1).localeCompare(getRepositoryLabel(repositoryRoot2)); +} + function sanitizeBranchName(name: string, whitespaceChar: string): string { return name ? name.trim().replace(/^-+/, '').replace(/^\.|\/\.|\.\.|~|\^|:|\/$|\.lock$|\.lock\/|\\|\*|\s|^\s*$|\.$|\[|\]$/g, whitespaceChar) : name; } @@ -896,7 +905,8 @@ export class CommandCenter { const allRepositoriesLabel = l10n.t('All Repositories'); const allRepositoriesQuickPickItem: QuickPickItem = { label: allRepositoriesLabel }; - const repositoriesQuickPickItems: QuickPickItem[] = this.model.closedRepositories.sort().map(r => new RepositoryItem(r)); + const repositoriesQuickPickItems: QuickPickItem[] = this.model.closedRepositories + .sort(compareRepositoryLabel).map(r => new RepositoryItem(r)); const items = this.model.closedRepositories.length === 1 ? [...repositoriesQuickPickItems] : [...repositoriesQuickPickItems, { label: '', kind: QuickPickItemKind.Separator }, allRepositoriesQuickPickItem]; @@ -3459,7 +3469,8 @@ export class CommandCenter { const allRepositoriesLabel = l10n.t('All Repositories'); const allRepositoriesQuickPickItem: QuickPickItem = { label: allRepositoriesLabel }; - const repositoriesQuickPickItems: QuickPickItem[] = Array.from(this.model.parentRepositories.keys()).sort().map(r => new RepositoryItem(r)); + const repositoriesQuickPickItems: QuickPickItem[] = Array.from(this.model.parentRepositories.keys()) + .sort(compareRepositoryLabel).map(r => new RepositoryItem(r)); const items = this.model.parentRepositories.size === 1 ? [...repositoriesQuickPickItems] : [...repositoriesQuickPickItems, { label: '', kind: QuickPickItemKind.Separator }, allRepositoriesQuickPickItem]; @@ -3492,7 +3503,8 @@ export class CommandCenter { const allRepositoriesLabel = l10n.t('All Repositories'); const allRepositoriesQuickPickItem: QuickPickItem = { label: allRepositoriesLabel }; - const repositoriesQuickPickItems: QuickPickItem[] = Array.from(this.model.unsafeRepositories.keys()).sort().map(r => new RepositoryItem(r)); + const repositoriesQuickPickItems: QuickPickItem[] = Array.from(this.model.unsafeRepositories.keys()) + .sort(compareRepositoryLabel).map(r => new RepositoryItem(r)); quickpick.items = this.model.unsafeRepositories.size === 1 ? [...repositoriesQuickPickItems] : [...repositoriesQuickPickItems, { label: '', kind: QuickPickItemKind.Separator }, allRepositoriesQuickPickItem]; From b0b1af125cc50b7eb58e8ae911bf2ed46d9e4c51 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Mon, 12 Jun 2023 11:47:30 +0200 Subject: [PATCH 039/128] Git - extract code into ParentRepositoriesManager (#184891) --- extensions/git/src/commands.ts | 6 +-- extensions/git/src/model.ts | 73 ++++++++++++++++++++++++---------- 2 files changed, 54 insertions(+), 25 deletions(-) diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index fb5e2108102..731105b7e5a 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -3469,10 +3469,10 @@ export class CommandCenter { const allRepositoriesLabel = l10n.t('All Repositories'); const allRepositoriesQuickPickItem: QuickPickItem = { label: allRepositoriesLabel }; - const repositoriesQuickPickItems: QuickPickItem[] = Array.from(this.model.parentRepositories.keys()) + const repositoriesQuickPickItems: QuickPickItem[] = this.model.parentRepositories .sort(compareRepositoryLabel).map(r => new RepositoryItem(r)); - const items = this.model.parentRepositories.size === 1 ? [...repositoriesQuickPickItems] : + const items = this.model.parentRepositories.length === 1 ? [...repositoriesQuickPickItems] : [...repositoriesQuickPickItems, { label: '', kind: QuickPickItemKind.Separator }, allRepositoriesQuickPickItem]; const repositoryItem = await window.showQuickPick(items, { title, placeHolder }); @@ -3482,7 +3482,7 @@ export class CommandCenter { if (repositoryItem === allRepositoriesQuickPickItem) { // All Repositories - parentRepositories.push(...this.model.parentRepositories.keys()); + parentRepositories.push(...this.model.parentRepositories); } else { // One Repository parentRepositories.push((repositoryItem as RepositoryItem).path); diff --git a/extensions/git/src/model.ts b/extensions/git/src/model.ts index 3315b3eee58..813160a2096 100644 --- a/extensions/git/src/model.ts +++ b/extensions/git/src/model.ts @@ -68,16 +68,6 @@ class UnsafeRepositoryMap extends RepositoryMap { } } -/** - * Key - normalized path used in user interface - * Value - value indicating whether the repository should be opened - */ -class ParentRepositoryMap extends RepositoryMap { - updateContextKey(): void { - commands.executeCommand('setContext', 'git.parentRepositoryCount', this.size); - } -} - export interface ModelChangeEvent { repository: Repository; uri: Uri; @@ -128,6 +118,47 @@ class ClosedRepositoriesManager { } } +class ParentRepositoriesManager { + + /** + * Key - normalized path used in user interface + * Value - value indicating whether the repository should be opened + */ + private _repositories = new Set; + get repositories(): string[] { + return [...this._repositories.values()]; + } + + constructor(private readonly globalState: Memento) { } + + addRepository(repository: string): void { + this._repositories.add(repository); + this.onDidChangeRepositories(); + } + + deleteRepository(repository: string): boolean { + const result = this._repositories.delete(repository); + if (result) { + this.onDidChangeRepositories(); + } + + return result; + } + + hasRepository(repository: string): boolean { + return this._repositories.has(repository); + } + + openRepository(repository: string): void { + this.globalState.update(`parentRepository:${repository}`, true); + this.deleteRepository(repository); + } + + private onDidChangeRepositories(): void { + commands.executeCommand('setContext', 'git.parentRepositoryCount', this._repositories.size); + } +} + export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePublisherRegistry, IPostCommitCommandsProviderRegistry, IPushErrorHandlerRegistry { private _onDidOpenRepository = new EventEmitter(); @@ -200,9 +231,9 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu return this._unsafeRepositories; } - private _parentRepositories = new ParentRepositoryMap(); - get parentRepositories(): ParentRepositoryMap { - return this._parentRepositories; + private _parentRepositoriesManager: ParentRepositoriesManager; + get parentRepositories(): string[] { + return this._parentRepositoriesManager.repositories; } private _closedRepositoriesManager: ClosedRepositoriesManager; @@ -225,6 +256,7 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu constructor(readonly git: Git, private readonly askpass: Askpass, private globalState: Memento, readonly workspaceState: Memento, private logger: LogOutputChannel, private telemetryReporter: TelemetryReporter) { // Repositories managers this._closedRepositoriesManager = new ClosedRepositoriesManager(workspaceState); + this._parentRepositoriesManager = new ParentRepositoriesManager(globalState); workspace.onDidChangeWorkspaceFolders(this.onDidChangeWorkspaceFolders, this, this.disposables); window.onDidChangeVisibleTextEditors(this.onDidChangeVisibleTextEditors, this, this.disposables); @@ -260,7 +292,7 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu await initialScanFn(); } - if (this._parentRepositories.size !== 0 && + if (this.parentRepositories.length !== 0 && parentRepositoryConfig === 'prompt') { // Parent repositories notification this.showParentRepositoryNotification(); @@ -497,13 +529,13 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu if (isRepositoryOutsideWorkspace) { this.logger.trace(`Repository in parent folder: ${repositoryRoot}`); - if (!this._parentRepositories.has(repositoryRoot)) { + if (!this._parentRepositoriesManager.hasRepository(repositoryRoot)) { // Show a notification if the parent repository is opened after the initial scan if (this.state === 'initialized' && parentRepositoryConfig === 'prompt') { this.showParentRepositoryNotification(); } - this._parentRepositories.set(repositoryRoot); + this._parentRepositoriesManager.addRepository(repositoryRoot); } return; @@ -547,11 +579,8 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu } async openParentRepository(repoPath: string): Promise { - // Mark the repository to be opened from the parent folders - this.globalState.update(`parentRepository:${repoPath}`, true); - await this.openRepository(repoPath); - this.parentRepositories.delete(repoPath); + this._parentRepositoriesManager.openRepository(repoPath); } private async getRepositoryRoot(repoPath: string): Promise<{ repositoryRoot: string; unsafeRepositoryMatch: RegExpMatchArray | null }> { @@ -907,7 +936,7 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu } private async showParentRepositoryNotification(): Promise { - const message = this.parentRepositories.size === 1 ? + const message = this.parentRepositories.length === 1 ? l10n.t('A git repository was found in the parent folders of the workspace or the open file(s). Would you like to open the repository?') : l10n.t('Git repositories were found in the parent folders of the workspace or the open file(s). Would you like to open the repositories?'); @@ -925,7 +954,7 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu await config.update('openRepositoryInParentFolders', choice === always ? 'always' : 'never', true); if (choice === always) { - for (const parentRepository of [...this.parentRepositories.keys()]) { + for (const parentRepository of this.parentRepositories) { await this.openParentRepository(parentRepository); } } From 70dff6df08d008e895e3f23013c3d54088d90d50 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 12 Jun 2023 11:50:11 +0200 Subject: [PATCH 040/128] make sure to send undo feedback when cancelling or undoing (#184892) --- .../contrib/inlineChat/browser/inlineChatController.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index c3a238bb052..16e5cc607f0 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -720,7 +720,10 @@ export class InlineChatController implements IEditorContribution { } const changedText = this._activeSession.asChangedText(); + if (changedText && this._activeSession?.lastExchange?.response instanceof EditResponse) { + this._activeSession.provider.handleInlineChatResponseFeedback?.(this._activeSession.session, this._activeSession.lastExchange.response.raw, InlineChatResponseFeedbackKind.Undone); + } this._messages.fire(Message.CANCEL_SESSION); return changedText; } From 5e921debad5c7ac19887b8905eb4d161415638a6 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Mon, 12 Jun 2023 12:07:20 +0200 Subject: [PATCH 041/128] removing the duplicate implementation --- .../contrib/inlineChat/browser/inlineChatController.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 5f979baca2a..61b9b141cdd 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -200,13 +200,6 @@ export class InlineChatController implements IEditorContribution { this._zone.value.showWidget(widgetPosition ?? selectionRange.getStartPosition()); } - private _showWidget(initialRender: boolean = false, hasEditResponse: boolean = false) { - assertType(this._activeSession); - const selectionRange = this._activeSession.wholeRange.value; - const widgetPosition = this._strategy?.getWidgetPosition(initialRender, selectionRange, hasEditResponse); - this._zone.value.showWidget(widgetPosition ?? selectionRange.getStartPosition()); - } - protected async _nextState(state: State, options: InlineChatRunOptions | undefined): Promise { this._log('setState to ', state); const nextState = await this[state](options); From 17c88bf045b21b7b07275cfc1eeb8c22b76b4228 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Mon, 12 Jun 2023 12:29:47 +0200 Subject: [PATCH 042/128] Git - extract code into UnsafeRepositoryManager (#184896) --- extensions/git/src/commands.ts | 10 ++-- extensions/git/src/model.ts | 96 +++++++++++++++++++--------------- 2 files changed, 60 insertions(+), 46 deletions(-) diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 731105b7e5a..4213aafa495 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -3503,10 +3503,10 @@ export class CommandCenter { const allRepositoriesLabel = l10n.t('All Repositories'); const allRepositoriesQuickPickItem: QuickPickItem = { label: allRepositoriesLabel }; - const repositoriesQuickPickItems: QuickPickItem[] = Array.from(this.model.unsafeRepositories.keys()) + const repositoriesQuickPickItems: QuickPickItem[] = this.model.unsafeRepositories .sort(compareRepositoryLabel).map(r => new RepositoryItem(r)); - quickpick.items = this.model.unsafeRepositories.size === 1 ? [...repositoriesQuickPickItems] : + quickpick.items = this.model.unsafeRepositories.length === 1 ? [...repositoriesQuickPickItems] : [...repositoriesQuickPickItems, { label: '', kind: QuickPickItemKind.Separator }, allRepositoriesQuickPickItem]; quickpick.show(); @@ -3523,7 +3523,7 @@ export class CommandCenter { if (repositoryItem.label === allRepositoriesLabel) { // All Repositories - unsafeRepositories.push(...this.model.unsafeRepositories.keys()); + unsafeRepositories.push(...this.model.unsafeRepositories); } else { // One Repository unsafeRepositories.push((repositoryItem as RepositoryItem).path); @@ -3531,11 +3531,11 @@ export class CommandCenter { for (const unsafeRepository of unsafeRepositories) { // Mark as Safe - await this.git.addSafeDirectory(this.model.unsafeRepositories.get(unsafeRepository)!); + await this.git.addSafeDirectory(this.model.getUnsafeRepositoryPath(unsafeRepository)!); // Open Repository await this.model.openRepository(unsafeRepository); - this.model.unsafeRepositories.delete(unsafeRepository); + this.model.deleteUnsafeRepository(unsafeRepository); } } diff --git a/extensions/git/src/model.ts b/extensions/git/src/model.ts index 813160a2096..35975a78233 100644 --- a/extensions/git/src/model.ts +++ b/extensions/git/src/model.ts @@ -34,40 +34,6 @@ class RepositoryPick implements QuickPickItem { constructor(public readonly repository: Repository, public readonly index: number) { } } -abstract class RepositoryMap extends Map { - constructor() { - super(); - this.updateContextKey(); - } - - override set(key: string, value: T): this { - const result = super.set(key, value); - this.updateContextKey(); - - return result; - } - - override delete(key: string): boolean { - const result = super.delete(key); - this.updateContextKey(); - - return result; - } - - abstract updateContextKey(): void; -} - -/** - * Key - normalized path used in user interface - * Value - path extracted from the output of the `git status` command - * used when calling `git config --global --add safe.directory` - */ -class UnsafeRepositoryMap extends RepositoryMap { - updateContextKey(): void { - commands.executeCommand('setContext', 'git.unsafeRepositoryCount', this.size); - } -} - export interface ModelChangeEvent { repository: Repository; uri: Uri; @@ -159,6 +125,45 @@ class ParentRepositoriesManager { } } +class UnsafeRepositoriesManager { + + /** + * Key - normalized path used in user interface + * Value - path extracted from the output of the `git status` command + * used when calling `git config --global --add safe.directory` + */ + private _repositories = new Map(); + get repositories(): string[] { + return [...this._repositories.keys()]; + } + + addRepository(repository: string, path: string): void { + this._repositories.set(repository, path); + this.onDidChangeRepositories(); + } + + deleteRepository(repository: string): boolean { + const result = this._repositories.delete(repository); + if (result) { + this.onDidChangeRepositories(); + } + + return result; + } + + getRepositoryPath(repository: string): string | undefined { + return this._repositories.get(repository); + } + + hasRepository(repository: string): boolean { + return this._repositories.has(repository); + } + + private onDidChangeRepositories(): void { + commands.executeCommand('setContext', 'git.unsafeRepositoryCount', this._repositories.size); + } +} + export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePublisherRegistry, IPostCommitCommandsProviderRegistry, IPushErrorHandlerRegistry { private _onDidOpenRepository = new EventEmitter(); @@ -226,9 +231,9 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu private pushErrorHandlers = new Set(); - private _unsafeRepositories = new UnsafeRepositoryMap(); - get unsafeRepositories(): UnsafeRepositoryMap { - return this._unsafeRepositories; + private _unsafeRepositoriesManager: UnsafeRepositoriesManager; + get unsafeRepositories(): string[] { + return this._unsafeRepositoriesManager.repositories; } private _parentRepositoriesManager: ParentRepositoriesManager; @@ -257,6 +262,7 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu // Repositories managers this._closedRepositoriesManager = new ClosedRepositoriesManager(workspaceState); this._parentRepositoriesManager = new ParentRepositoriesManager(globalState); + this._unsafeRepositoriesManager = new UnsafeRepositoriesManager(); workspace.onDidChangeWorkspaceFolders(this.onDidChangeWorkspaceFolders, this, this.disposables); window.onDidChangeVisibleTextEditors(this.onDidChangeVisibleTextEditors, this, this.disposables); @@ -296,7 +302,7 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu parentRepositoryConfig === 'prompt') { // Parent repositories notification this.showParentRepositoryNotification(); - } else if (this._unsafeRepositories.size !== 0) { + } else if (this.unsafeRepositories.length !== 0) { // Unsafe repositories notification this.showUnsafeRepositoryNotification(); } @@ -547,11 +553,11 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu this.logger.trace(`Unsafe repository: ${repositoryRoot}`); // Show a notification if the unsafe repository is opened after the initial scan - if (this._state === 'initialized' && !this._unsafeRepositories.has(repositoryRoot)) { + if (this._state === 'initialized' && !this._unsafeRepositoriesManager.hasRepository(repositoryRoot)) { this.showUnsafeRepositoryNotification(); } - this._unsafeRepositories.set(repositoryRoot, unsafeRepositoryMatch[2]); + this._unsafeRepositoriesManager.addRepository(repositoryRoot, unsafeRepositoryMatch[2]); return; } @@ -903,6 +909,14 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu return [...this.pushErrorHandlers]; } + getUnsafeRepositoryPath(repository: string): string | undefined { + return this._unsafeRepositoriesManager.getRepositoryPath(repository); + } + + deleteUnsafeRepository(repository: string): boolean { + return this._unsafeRepositoriesManager.deleteRepository(repository); + } + private async isRepositoryOutsideWorkspace(repositoryPath: string): Promise { const workspaceFolders = (workspace.workspaceFolders || []) .filter(folder => folder.uri.scheme === 'file'); @@ -969,7 +983,7 @@ export class Model implements IBranchProtectionProviderRegistry, IRemoteSourcePu return; } - const message = this._unsafeRepositories.size === 1 ? + const message = this.unsafeRepositories.length === 1 ? l10n.t('The git repository in the current folder is potentially unsafe as the folder is owned by someone other than the current user.') : l10n.t('The git repositories in the current folder are potentially unsafe as the folders are owned by someone other than the current user.'); From b10d6b0309bb49e64ca5b475e9de4ffbf2610e21 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Mon, 12 Jun 2023 13:12:59 +0200 Subject: [PATCH 043/128] cleaning the code --- .../browser/inlineChatController.ts | 4 +- .../browser/inlineChatStrategies.ts | 75 ++++++++----------- .../inlineChat/browser/inlineChatWidget.ts | 22 +++--- 3 files changed, 45 insertions(+), 56 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 61b9b141cdd..1aebb6b912c 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -197,7 +197,7 @@ export class InlineChatController implements IEditorContribution { assertType(this._activeSession); const selectionRange = this._activeSession.wholeRange.value; const widgetPosition = this._strategy?.getWidgetPosition(initialRender, selectionRange, hasEditResponse); - this._zone.value.showWidget(widgetPosition ?? selectionRange.getStartPosition()); + this._zone.value.show(widgetPosition ?? selectionRange.getStartPosition()); } protected async _nextState(state: State, options: InlineChatRunOptions | undefined): Promise { @@ -544,7 +544,7 @@ export class InlineChatController implements IEditorContribution { assertType(this._strategy); const { response } = this._activeSession.lastExchange!; - this._showWidget(false, response instanceof EditResponse); // this._updateEditMode, r + this._showWidget(false, response instanceof EditResponse); this._ctxLastResponseType.set(response instanceof EditResponse || response instanceof MarkdownResponse ? response.raw.type diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts index 1b6b2aa404a..3317215f085 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts @@ -5,6 +5,7 @@ import { Event } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; +import { assertType } from 'vs/base/common/types'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService'; import { StableEditorScrollState } from 'vs/editor/browser/stableEditorScroll'; @@ -27,6 +28,8 @@ import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/ export abstract class EditModeStrategy { + protected _initialPosition: Position | undefined; + abstract dispose(): void; abstract checkChanges(response: EditResponse): boolean; @@ -41,16 +44,15 @@ export abstract class EditModeStrategy { abstract toggleDiff(): void; - abstract getWidgetPosition(initialRender: boolean, range: Range, hasEditResponse: boolean | undefined): Position | undefined; - abstract hasFocus(): boolean; + + abstract getWidgetPosition(initialRender: boolean, range: Range, hasEditResponse: boolean | undefined): Position | undefined; } export class PreviewStrategy extends EditModeStrategy { private readonly _ctxDocumentChanged: IContextKey; private readonly _listener: IDisposable; - private _initialPosition: Position | undefined; constructor( private readonly _session: Session, @@ -134,28 +136,13 @@ export class PreviewStrategy extends EditModeStrategy { } getWidgetPosition(initialRender: boolean, range: Range, hasEditResponse: boolean | undefined): Position | undefined { - console.log('inside of preview strategy'); const viewModel = this._editor._getViewModel(); - if (!viewModel) { - return; - } - const primaryCursorPosition = viewModel.getPrimaryCursorState().viewState.position; + assertType(viewModel); if (initialRender) { - this._initialPosition = primaryCursorPosition; + this._initialPosition = viewModel.getPrimaryCursorState().viewState.position; return this._initialPosition; } else { - if (hasEditResponse) { - const visibleRange = viewModel.getCompletelyVisibleViewRange(); - const endPosition = range.getEndPosition(); - const endLine = endPosition.lineNumber; - if (endLine >= visibleRange.startLineNumber && endLine <= visibleRange.endLineNumber) { - return endPosition; - } else { - return this._initialPosition; - } - } else { - return this._initialPosition; - } + return minimalJumpPosition(this._editor, this._initialPosition, range, hasEditResponse); } } @@ -240,7 +227,6 @@ export class LiveStrategy extends EditModeStrategy { private readonly _ctxShowingDiff: IContextKey; private _lastResponse?: EditResponse; private _editCount: number = 0; - protected _initialPosition: Position | undefined; constructor( protected readonly _session: Session, @@ -315,7 +301,7 @@ export class LiveStrategy extends EditModeStrategy { const cursorStateComputerAndInlineDiffCollection: ICursorStateComputer = (undoEdits) => { let last: Position | null = null; for (const edit of undoEdits) { - last = !last || last.isBefore(edit.range.getEndPosition()) ? edit.range.getEndPosition() : last; + last = !last || last.isBefore(edit.range.getStartPosition()) ? edit.range.getStartPosition() : last; this._inlineDiffDecorations.collectEditOperation(edit); } return last && [Selection.fromPositions(last)]; @@ -356,27 +342,14 @@ export class LiveStrategy extends EditModeStrategy { this._widget.updateStatus(message); } - getWidgetPosition(initialRender: boolean, range: Range, hasEditResponse: boolean | undefined): Position | undefined { + override getWidgetPosition(initialRender: boolean, range: Range, hasEditResponse: boolean | undefined): Position | undefined { const viewModel = this._editor._getViewModel(); - if (!viewModel) { - return; - } + assertType(viewModel); if (initialRender) { this._initialPosition = viewModel.getPrimaryCursorState().viewState.position; return this._initialPosition; } else { - if (hasEditResponse) { - const visibleRange = viewModel.getCompletelyVisibleViewRange(); - const endPosition = range.getEndPosition(); - const endLine = endPosition.lineNumber; - if (endLine >= visibleRange.startLineNumber && endLine <= visibleRange.endLineNumber) { - return endPosition; - } else { - return this._initialPosition; - } - } else { - return this._initialPosition; - } + return minimalJumpPosition(this._editor, this._initialPosition, range, hasEditResponse); } } @@ -439,14 +412,14 @@ export class LivePreviewStrategy extends LiveStrategy { } override getWidgetPosition(initialRender: boolean, range: Range, hasEditResponse: boolean | undefined): Position | undefined { - console.log('inside of live preview strategy'); - const primaryCursorPosition = this._editor._getViewModel()?.getPrimaryCursorState().viewState.position; if (initialRender) { - this._initialPosition = primaryCursorPosition; + const viewModel = this._editor._getViewModel(); + assertType(viewModel); + this._initialPosition = viewModel.getPrimaryCursorState().viewState.position; return this._initialPosition; } else { if (hasEditResponse) { - return range.getEndPosition(); + return range.getStartPosition(); } else { return this._initialPosition; } @@ -464,3 +437,19 @@ function showSingleCreateFile(accessor: ServicesAccessor, edit: EditResponse) { editorService.openEditor({ resource: edit.singleCreateFileEdit.uri }, SIDE_GROUP); } } + +function minimalJumpPosition(editor: ICodeEditor, initialPosition: Position | undefined, range: Range, hasEditResponse: boolean | undefined): Position | undefined { + const viewModel = editor._getViewModel(); + assertType(viewModel); + if (hasEditResponse) { + const endPosition = range.getStartPosition(); + const visibleRange = viewModel.getCompletelyVisibleViewRange(); + if (visibleRange.containsPosition(endPosition)) { + return endPosition; + } else { + return initialPosition; + } + } else { + return initialPosition; + } +} diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index 65164d63a20..9e14ef591c1 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -430,7 +430,7 @@ export class InlineChatWidget { set value(value: string) { this._inputModel.setValue(value); - this._inputEditor.setPosition(this._inputModel.getFullModelRange().getEndPosition()); + this._inputEditor.setPosition(this._inputModel.getFullModelRange().getStartPosition()); } selectAll() { @@ -791,12 +791,11 @@ export class InlineChatZoneWidget extends ZoneWidget { super._relayout(this._computeHeightInLines()); } - showWidget(position: Position): void { - const widgetPosition = position; - super.show(widgetPosition, this._computeHeightInLines()); + override show(position: Position): void { + super.show(position, this._computeHeightInLines()); this.widget.focus(); this._ctxVisible.set(true); - this._setMargins(widgetPosition); + this._setMargins(position); } private _setMargins(position: Position): void { @@ -804,11 +803,12 @@ export class InlineChatZoneWidget extends ZoneWidget { if (!viewModel) { return; } - const positionLineNumber = position.lineNumber; - const startLineNumber = viewModel.getCompletelyVisibleViewRange().startLineNumber; - let indentationLineNumber; - let indentationLevel; - for (let lineNumber = positionLineNumber; lineNumber >= startLineNumber; lineNumber--) { + const visibleRange = viewModel.getCompletelyVisibleViewRange(); + const startLineVisibleRange = visibleRange.startLineNumber; + const positionLine = position.lineNumber; + let indentationLineNumber: number | undefined; + let indentationLevel: number | undefined; + for (let lineNumber = positionLine; lineNumber >= startLineVisibleRange; lineNumber--) { const currentIndentationLevel = viewModel.getLineFirstNonWhitespaceColumn(lineNumber); if (currentIndentationLevel !== 0) { indentationLineNumber = lineNumber; @@ -816,7 +816,7 @@ export class InlineChatZoneWidget extends ZoneWidget { break; } } - this._indentationWidth = this.editor.getOffsetForColumn(indentationLineNumber ?? positionLineNumber, indentationLevel ?? viewModel.getLineFirstNonWhitespaceColumn(positionLineNumber)); + this._indentationWidth = this.editor.getOffsetForColumn(indentationLineNumber ?? positionLine, indentationLevel ?? viewModel.getLineFirstNonWhitespaceColumn(positionLine)); const info = this.editor.getLayoutInfo(); const marginWithoutIndentation = info.glyphMarginWidth + info.decorationsWidth + info.lineNumbersWidth; const marginWithIndentation = marginWithoutIndentation + this._indentationWidth; From 8904b3e90182805a54db2e755ad1c535da938ea3 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Mon, 12 Jun 2023 13:15:38 +0200 Subject: [PATCH 044/128] cleaning the code --- .../contrib/inlineChat/browser/inlineChatController.ts | 2 +- .../contrib/inlineChat/browser/inlineChatStrategies.ts | 2 +- src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 1aebb6b912c..de96b68407c 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -197,7 +197,7 @@ export class InlineChatController implements IEditorContribution { assertType(this._activeSession); const selectionRange = this._activeSession.wholeRange.value; const widgetPosition = this._strategy?.getWidgetPosition(initialRender, selectionRange, hasEditResponse); - this._zone.value.show(widgetPosition ?? selectionRange.getStartPosition()); + this._zone.value.show(widgetPosition ?? selectionRange.getEndPosition()); } protected async _nextState(state: State, options: InlineChatRunOptions | undefined): Promise { diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts index 3317215f085..34b581494aa 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts @@ -301,7 +301,7 @@ export class LiveStrategy extends EditModeStrategy { const cursorStateComputerAndInlineDiffCollection: ICursorStateComputer = (undoEdits) => { let last: Position | null = null; for (const edit of undoEdits) { - last = !last || last.isBefore(edit.range.getStartPosition()) ? edit.range.getStartPosition() : last; + last = !last || last.isBefore(edit.range.getEndPosition()) ? edit.range.getEndPosition() : last; this._inlineDiffDecorations.collectEditOperation(edit); } return last && [Selection.fromPositions(last)]; diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index 9e14ef591c1..53ffd4ace2e 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -430,7 +430,7 @@ export class InlineChatWidget { set value(value: string) { this._inputModel.setValue(value); - this._inputEditor.setPosition(this._inputModel.getFullModelRange().getStartPosition()); + this._inputEditor.setPosition(this._inputModel.getFullModelRange().getEndPosition()); } selectAll() { From a9cf4fb089b6ccd2d1f262f876debaf510af91bb Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Mon, 12 Jun 2023 13:23:53 +0200 Subject: [PATCH 045/128] changing to end position --- .../contrib/inlineChat/browser/inlineChatStrategies.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts index 34b581494aa..089c94614a9 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts @@ -419,7 +419,7 @@ export class LivePreviewStrategy extends LiveStrategy { return this._initialPosition; } else { if (hasEditResponse) { - return range.getStartPosition(); + return range.getEndPosition(); } else { return this._initialPosition; } @@ -442,7 +442,7 @@ function minimalJumpPosition(editor: ICodeEditor, initialPosition: Position | un const viewModel = editor._getViewModel(); assertType(viewModel); if (hasEditResponse) { - const endPosition = range.getStartPosition(); + const endPosition = range.getEndPosition(); const visibleRange = viewModel.getCompletelyVisibleViewRange(); if (visibleRange.containsPosition(endPosition)) { return endPosition; From 46041c9f0e80956529cdd969299a4403c2edcad7 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 12 Jun 2023 13:37:50 +0200 Subject: [PATCH 046/128] Implement troubleshoot issue (#184901) * implement troubleshoot issue action * move issue troubleshooting to a service * feedback * fix stable check --- build/lib/i18n.resources.json | 4 + .../browser/extensionBisect.ts | 8 +- .../issue/browser/issueTroubleshoot.ts | 370 ++++++++++++++++++ .../browser/extensionsResource.ts | 12 +- .../userDataProfileImportExportService.ts | 35 +- .../userDataProfile/common/userDataProfile.ts | 1 + src/vs/workbench/workbench.common.main.ts | 1 + 7 files changed, 410 insertions(+), 21 deletions(-) create mode 100644 src/vs/workbench/services/issue/browser/issueTroubleshoot.ts diff --git a/build/lib/i18n.resources.json b/build/lib/i18n.resources.json index e5aaf1ee2dd..d684f4d945e 100644 --- a/build/lib/i18n.resources.json +++ b/build/lib/i18n.resources.json @@ -521,6 +521,10 @@ { "name": "vs/workbench/contrib/accessibility", "project": "vscode-workbench" + }, + { + "name": "vs/workbench/services/issue", + "project": "vscode-workbench" } ] } diff --git a/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts b/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts index a7d6df43571..1029b67197d 100644 --- a/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts +++ b/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts @@ -185,11 +185,11 @@ class ExtensionBisectUi { private _showBisectPrompt(): void { const goodPrompt: IPromptChoice = { - label: 'Good Now', + label: localize('I cannot reproduce', "I can't reproduce"), run: () => this._commandService.executeCommand('extension.bisect.next', false) }; const badPrompt: IPromptChoice = { - label: 'This is Bad', + label: localize('This is Bad', "I can reproduce"), run: () => this._commandService.executeCommand('extension.bisect.next', true) }; const stop: IPromptChoice = { @@ -329,11 +329,11 @@ registerAction2(class extends Action2 { detail: localize('bisect', "Extension Bisect is active and has disabled {0} extensions. Check if you can still reproduce the problem and proceed by selecting from these options.", bisectService.disabledCount), buttons: [ { - label: localize({ key: 'next.good', comment: ['&& denotes a mnemonic'] }, "&&Good now"), + label: localize({ key: 'next.good', comment: ['&& denotes a mnemonic'] }, "I ca&&n't reproduce"), run: () => false // good now }, { - label: localize({ key: 'next.bad', comment: ['&& denotes a mnemonic'] }, "This is &&bad"), + label: localize({ key: 'next.bad', comment: ['&& denotes a mnemonic'] }, "I can &&reproduce"), run: () => true // bad }, { diff --git a/src/vs/workbench/services/issue/browser/issueTroubleshoot.ts b/src/vs/workbench/services/issue/browser/issueTroubleshoot.ts new file mode 100644 index 00000000000..ef2b6b1f38d --- /dev/null +++ b/src/vs/workbench/services/issue/browser/issueTroubleshoot.ts @@ -0,0 +1,370 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { localize } from 'vs/nls'; +import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { ExtensionType } from 'vs/platform/extensions/common/extensions'; +import { IProductService } from 'vs/platform/product/common/productService'; +import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; +import { IUserDataProfileImportExportService, IUserDataProfileManagementService, IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { IExtensionBisectService } from 'vs/workbench/services/extensionManagement/browser/extensionBisect'; +import { INotificationHandle, INotificationService, IPromptChoice, NotificationPriority, Severity } from 'vs/platform/notification/common/notification'; +import { IWorkbenchExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; +import { IHostService } from 'vs/workbench/services/host/browser/host'; +import { IUserDataProfile, IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile'; +import { ServicesAccessor, createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { Categories } from 'vs/platform/action/common/actionCommonCategories'; +import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { Extensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; +import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; +import { IOpenerService } from 'vs/platform/opener/common/opener'; +import { URI } from 'vs/base/common/uri'; + +const ITroubleshootIssueService = createDecorator('ITroubleshootIssueService'); + +interface ITroubleshootIssueService { + _serviceBrand: undefined; + isActive(): boolean; + start(): Promise; + resume(): Promise; + stop(): Promise; +} + +enum TroubleshootStage { + EXTENSIONS = 1, + WORKBENCH, +} + +type TroubleShootResult = 'good' | 'bad' | 'stop'; + +class TroubleShootState { + + static fromJSON(raw: string | undefined): TroubleShootState | undefined { + if (!raw) { + return undefined; + } + try { + interface Raw extends TroubleShootState { } + const data: Raw = JSON.parse(raw); + if ( + (data.stage === TroubleshootStage.EXTENSIONS || data.stage === TroubleshootStage.WORKBENCH) + && typeof data.profile === 'string' + ) { + return new TroubleShootState(data.stage, data.profile); + } + } catch { /* ignore */ } + return undefined; + } + + constructor( + readonly stage: TroubleshootStage, + readonly profile: string, + ) { } +} + +class TroubleshootIssueService extends Disposable implements ITroubleshootIssueService { + + readonly _serviceBrand: undefined; + + static readonly storageKey = 'issueTroubleshootState'; + + private notificationHandle: INotificationHandle | undefined; + + constructor( + @IUserDataProfileService private readonly userDataProfileService: IUserDataProfileService, + @IUserDataProfilesService private readonly userDataProfilesService: IUserDataProfilesService, + @IUserDataProfileManagementService private readonly userDataProfileManagementService: IUserDataProfileManagementService, + @IUserDataProfileImportExportService private readonly userDataProfileImportExportService: IUserDataProfileImportExportService, + @IDialogService private readonly dialogService: IDialogService, + @IExtensionBisectService private readonly extensionBisectService: IExtensionBisectService, + @INotificationService private readonly notificationService: INotificationService, + @IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService, + @IWorkbenchExtensionEnablementService private readonly extensionEnablementService: IWorkbenchExtensionEnablementService, + @IWorkbenchIssueService private readonly issueService: IWorkbenchIssueService, + @IProductService private readonly productService: IProductService, + @IHostService private readonly hostService: IHostService, + @IStorageService private readonly storageService: IStorageService, + @IOpenerService private readonly openerService: IOpenerService, + ) { + super(); + } + + isActive(): boolean { + return this.state !== undefined; + } + + async start(): Promise { + if (this.isActive()) { + throw new Error('invalid state'); + } + + const res = await this.dialogService.confirm({ + message: localize('troubleshoot issue', "Troubleshoot Issue"), + detail: localize('detail.start', "Issue troubleshooting is a process to help you identify if the issue is with {0} or caused by an extension.\n\nDuring the process the window reloads repeatedly. Each time you must confirm if you are still seeing problems.", this.productService.nameShort), + primaryButton: localize({ key: 'msg', comment: ['&& denotes a mnemonic'] }, "&&Troubleshoot Issue"), + custom: true + }); + + if (!res.confirmed) { + return; + } + + const originalProfile = this.userDataProfileService.currentProfile; + await this.userDataProfileImportExportService.createTemporaryProfile(this.userDataProfileService.currentProfile, localize('troubleshoot issue', "Troubleshoot Issue"), true); + this.state = new TroubleShootState(TroubleshootStage.EXTENSIONS, originalProfile.id); + await this.resume(); + } + + async resume(): Promise { + if (!this.isActive()) { + return; + } + + if (this.state?.stage === TroubleshootStage.EXTENSIONS && !this.extensionBisectService.isActive) { + await this.reproduceIssueWithExtensionsDisabled(); + } + + if (this.state?.stage === TroubleshootStage.WORKBENCH) { + await this.reproduceIssueWithEmptyProfile(); + } + + await this.stop(); + } + + async stop(): Promise { + if (!this.isActive()) { + return; + } + + if (this.notificationHandle) { + this.notificationHandle.close(); + this.notificationHandle = undefined; + } + + if (this.extensionBisectService.isActive) { + await this.extensionBisectService.reset(); + } + + const profile = this.userDataProfilesService.profiles.find(p => p.id === this.state?.profile) ?? this.userDataProfilesService.defaultProfile; + this.state = undefined; + await this.userDataProfileManagementService.switchProfile(profile); + } + + private async reproduceIssueWithExtensionsDisabled(): Promise { + const result = await this.askToReproduceIssue(localize('profile.extensions.disabled', "Issue troubleshooting is active and has temprarily disabled all extensions. Check if you can still reproduce the problem and proceed by selecting from these options.")); + if (result === 'good') { + const profile = this.userDataProfilesService.profiles.find(p => p.id === this.state!.profile) ?? this.userDataProfilesService.defaultProfile; + await this.reproduceIssueWithExtensionsBisect(profile); + } + if (result === 'bad') { + this.state = new TroubleShootState(TroubleshootStage.WORKBENCH, this.state!.profile); + } + if (result === 'stop') { + await this.stop(); + } + } + + private async reproduceIssueWithEmptyProfile(): Promise { + await this.userDataProfileManagementService.createAndEnterTransientProfile(); + this.updateState(this.state); + const result = await this.askToReproduceIssue(localize('empty.profile', "Issue troubleshooting is active and has temporarily reset your settings to defaults. Check if you can still reproduce the problem and proceed by selecting from these options.")); + if (result === 'stop') { + await this.stop(); + } + if (result === 'good') { + await this.askToReportIssue(localize('issue is with configuration', "Issue troubleshooting is done and has identified that the issue is caused by your settings. Please report the issue by sharing your settings.")); + } + if (result === 'bad') { + await this.askToReportIssue(localize('issue is in core', "Issue troubleshooting is done and has identified that the issue is with {0}.", this.productService.nameShort)); + } + } + + private async reproduceIssueWithExtensionsBisect(profile: IUserDataProfile): Promise { + await this.userDataProfileManagementService.switchProfile(profile); + const extensions = (await this.extensionManagementService.getInstalled(ExtensionType.User)).filter(ext => this.extensionEnablementService.isEnabled(ext)); + await this.extensionBisectService.start(extensions); + await this.hostService.reload(); + } + + private askToReproduceIssue(message: string): Promise { + return new Promise((c, e) => { + const goodPrompt: IPromptChoice = { + label: localize('I cannot reproduce', "I can't reproduce"), + run: () => c('good') + }; + const badPrompt: IPromptChoice = { + label: localize('This is Bad', "I can reproduce"), + run: () => c('bad') + }; + const stop: IPromptChoice = { + label: localize('Stop', "Stop"), + run: () => c('stop') + }; + this.notificationHandle = this.notificationService.prompt( + Severity.Info, + message, + [goodPrompt, badPrompt, stop], + { sticky: true, priority: NotificationPriority.URGENT } + ); + }); + } + + private async askToReportIssue(detail: string): Promise { + const isStable = this.productService.quality === 'stable'; + if (isStable) { + const res = await this.askToReproduceIssueWithInsiders(); + if (res === undefined) { + return this.reportIssue(false); + } + if (res) { + await this.dialogService.prompt({ + type: Severity.Info, + message: localize('troubleshoot issue', "Troubleshoot Issue"), + detail: localize('use insiders', "This likely means that the issue has been addressed already and will be available in an upcoming release. You can safely use {0} insiders until the new stable version is available.", this.productService.nameShort), + custom: true + }); + return; + } + } + const res = await this.dialogService.confirm({ + type: Severity.Info, + message: localize('troubleshoot issue', "Troubleshoot Issue"), + primaryButton: localize({ key: 'report', comment: ['&& denotes a mnemonic'] }, "&&Report Issue & Continue"), + cancelButton: localize('continue', "Continue"), + detail, + custom: true + }); + if (res.confirmed) { + await this.reportIssue(isStable); + } + } + + private async askToReproduceIssueWithInsiders(): Promise { + const confirmRes = await this.dialogService.confirm({ + type: 'info', + message: localize('troubleshoot issue', "Troubleshoot Issue"), + primaryButton: localize('download insiders', "Download {0} Insiders", this.productService.nameShort), + cancelButton: localize('report anyway', "Report Issue Anyway"), + detail: localize('ask to download insiders', "Please try to download and reproduce the issue in {0} insiders.", this.productService.nameShort), + custom: true + }); + if (!confirmRes.confirmed) { + return undefined; + } + + const opened = await this.openerService.open(URI.parse('https://aka.ms/vscode-insiders')); + if (!opened) { + return undefined; + } + + const res = await this.dialogService.confirm({ + type: 'info', + message: localize('troubleshoot issue', "Troubleshoot Issue"), + primaryButton: localize('good', "I can't reproduce"), + cancelButton: localize('bad', "I can reproduce"), + detail: localize('ask to reproduce issue', "Please try to reproduce the issue in {0} insiders and confirm if the issue exists there.", this.productService.nameShort), + custom: true + }); + + return !!res.confirmed; + } + + private reportIssue(checkedInInsiders: boolean): Promise { + return this.issueService.openReporter({ + issueBody: `> This issue is reported using the **Troubleshoot Issue** feature. ${checkedInInsiders ? localize('confirmed in insiders', "It is confirmed that the issue exists in Insiders.") : ''}`, + }); + } + + private _state: TroubleShootState | undefined | null; + get state(): TroubleShootState | undefined { + if (this._state === undefined) { + const raw = this.storageService.get(TroubleshootIssueService.storageKey, StorageScope.PROFILE); + this._state = TroubleShootState.fromJSON(raw); + } + return this._state || undefined; + } + + set state(state: TroubleShootState | undefined) { + this._state = state ?? null; + this.updateState(state); + } + + private updateState(state: TroubleShootState | undefined) { + if (state) { + this.storageService.store(TroubleshootIssueService.storageKey, JSON.stringify(state), StorageScope.PROFILE, StorageTarget.MACHINE); + } else { + this.storageService.remove(TroubleshootIssueService.storageKey, StorageScope.PROFILE); + } + } +} + +class IssueTroubleshootUi extends Disposable { + + static ctxIsTroubleshootActive = new RawContextKey('isIssueTroubleshootActive', false); + + constructor( + @IContextKeyService private readonly contextKeyService: IContextKeyService, + @ITroubleshootIssueService private readonly troubleshootIssueService: ITroubleshootIssueService, + @IStorageService storageService: IStorageService, + ) { + super(); + this.updateContext(); + if (troubleshootIssueService.isActive()) { + troubleshootIssueService.resume(); + } + this._register(storageService.onDidChangeValue(e => { + if (e.key === TroubleshootIssueService.storageKey) { + this.updateContext(); + } + })); + } + + private updateContext(): void { + IssueTroubleshootUi.ctxIsTroubleshootActive.bindTo(this.contextKeyService).set(this.troubleshootIssueService.isActive()); + } + +} + +Registry.as(Extensions.Workbench).registerWorkbenchContribution(IssueTroubleshootUi, LifecyclePhase.Restored); + +registerAction2(class TroubleshootIssueAction extends Action2 { + constructor() { + super({ + id: 'workbench.action.troubleshootIssue.start', + title: { value: localize('troubleshootIssue', "Troubleshoot Issue..."), original: 'Troubleshoot Issue...' }, + category: Categories.Help, + f1: true, + precondition: IssueTroubleshootUi.ctxIsTroubleshootActive.negate(), + }); + } + run(accessor: ServicesAccessor): Promise { + return accessor.get(ITroubleshootIssueService).start(); + } +}); + +registerAction2(class extends Action2 { + constructor() { + super({ + id: 'workbench.action.troubleshootIssue.stop', + title: { value: localize('title.stop', "Stop Troubleshoot Issue"), original: 'Stop Troubleshoot Issue' }, + category: Categories.Help, + f1: true, + precondition: IssueTroubleshootUi.ctxIsTroubleshootActive + }); + } + + async run(accessor: ServicesAccessor): Promise { + return accessor.get(ITroubleshootIssueService).stop(); + } +}); + + +registerSingleton(ITroubleshootIssueService, TroubleshootIssueService, InstantiationType.Delayed); diff --git a/src/vs/workbench/services/userDataProfile/browser/extensionsResource.ts b/src/vs/workbench/services/userDataProfile/browser/extensionsResource.ts index e8fa77e0839..3585557e837 100644 --- a/src/vs/workbench/services/userDataProfile/browser/extensionsResource.ts +++ b/src/vs/workbench/services/userDataProfile/browser/extensionsResource.ts @@ -96,6 +96,7 @@ export class ExtensionsResourceInitializer implements IProfileResourceInitialize export class ExtensionsResource implements IProfileResource { constructor( + private readonly extensionsDisabled: boolean, @IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService, @IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService, @IUserDataProfileStorageService private readonly userDataProfileStorageService: IUserDataProfileStorageService, @@ -189,7 +190,7 @@ export class ExtensionsResource implements IProfileResource { } } const profileExtension: IProfileExtension = { identifier, displayName: extension.manifest.displayName }; - if (disabled) { + if (this.extensionsDisabled || disabled) { profileExtension.disabled = true; } if (!extension.isBuiltin && extension.pinned) { @@ -276,17 +277,18 @@ export class ExtensionsResourceExportTreeItem extends ExtensionsResourceTreeItem constructor( private readonly profile: IUserDataProfile, + private readonly extensionsDisabled: boolean, @IInstantiationService private readonly instantiationService: IInstantiationService, ) { super(); } protected getExtensions(): Promise { - return this.instantiationService.createInstance(ExtensionsResource).getLocalExtensions(this.profile); + return this.instantiationService.createInstance(ExtensionsResource, this.extensionsDisabled).getLocalExtensions(this.profile); } async getContent(): Promise { - return this.instantiationService.createInstance(ExtensionsResource).getContent(this.profile, [...this.excludedExtensions.values()]); + return this.instantiationService.createInstance(ExtensionsResource, this.extensionsDisabled).getContent(this.profile, [...this.excludedExtensions.values()]); } } @@ -301,11 +303,11 @@ export class ExtensionsResourceImportTreeItem extends ExtensionsResourceTreeItem } protected getExtensions(): Promise { - return this.instantiationService.createInstance(ExtensionsResource).getProfileExtensions(this.content); + return this.instantiationService.createInstance(ExtensionsResource, false).getProfileExtensions(this.content); } async getContent(): Promise { - const extensionsResource = this.instantiationService.createInstance(ExtensionsResource); + const extensionsResource = this.instantiationService.createInstance(ExtensionsResource, false); const extensions = await extensionsResource.getProfileExtensions(this.content); return extensionsResource.toContent(extensions, [...this.excludedExtensions.values()]); } diff --git a/src/vs/workbench/services/userDataProfile/browser/userDataProfileImportExportService.ts b/src/vs/workbench/services/userDataProfile/browser/userDataProfileImportExportService.ts index bfc1c7169e1..3437286add9 100644 --- a/src/vs/workbench/services/userDataProfile/browser/userDataProfileImportExportService.ts +++ b/src/vs/workbench/services/userDataProfile/browser/userDataProfileImportExportService.ts @@ -225,7 +225,7 @@ export class UserDataProfileImportExportService extends Disposable implements IU } const disposables = new DisposableStore(); try { - const userDataProfilesExportState = disposables.add(this.instantiationService.createInstance(UserDataProfileExportState, this.userDataProfileService.currentProfile)); + const userDataProfilesExportState = disposables.add(this.instantiationService.createInstance(UserDataProfileExportState, this.userDataProfileService.currentProfile, false)); const barrier = new Barrier(); const exportAction = new BarrierAction(barrier, new Action('export', localize('export', "Export"), undefined, true, async () => { exportAction.enabled = false; @@ -247,7 +247,7 @@ export class UserDataProfileImportExportService extends Disposable implements IU } async createFromCurrentProfile(name: string): Promise { - const userDataProfilesExportState = this.instantiationService.createInstance(UserDataProfileExportState, this.userDataProfileService.currentProfile); + const userDataProfilesExportState = this.instantiationService.createInstance(UserDataProfileExportState, this.userDataProfileService.currentProfile, false); try { const profileTemplate = await userDataProfilesExportState.getProfileTemplate(name, undefined); await this.doImportProfile(profileTemplate); @@ -256,6 +256,16 @@ export class UserDataProfileImportExportService extends Disposable implements IU } } + async createTemporaryProfile(profile: IUserDataProfile, name: string, extensionsDisabled: boolean): Promise { + const userDataProfilesExportState = this.instantiationService.createInstance(UserDataProfileExportState, profile, extensionsDisabled); + try { + const profileTemplate = await userDataProfilesExportState.getProfileTemplate(name, undefined); + await this.importAndSwitch(profileTemplate, true, true, extensionsDisabled, localize('import', "Create Profile")); + } finally { + userDataProfilesExportState.dispose(); + } + } + private async doExportProfile(userDataProfilesExportState: UserDataProfileExportState): Promise { const profile = await userDataProfilesExportState.getProfileToExport(); if (!profile) { @@ -342,7 +352,7 @@ export class UserDataProfileImportExportService extends Disposable implements IU const userDataProfileImportState = disposables.add(this.instantiationService.createInstance(UserDataProfileImportState, profileTemplate)); profileTemplate = await userDataProfileImportState.getProfileTemplateToImport(); - const importedProfile = await this.importAndSwitch(profileTemplate, true, false, localize('preview profile', "Preview Profile")); + const importedProfile = await this.importAndSwitch(profileTemplate, true, false, false, localize('preview profile', "Preview Profile")); if (!importedProfile) { return; @@ -385,7 +395,7 @@ export class UserDataProfileImportExportService extends Disposable implements IU view.setMessage(undefined); const profileTemplate = await userDataProfileImportState.getProfileTemplateToImport(); if (profileTemplate.extensions) { - await that.instantiationService.createInstance(ExtensionsResource).apply(profileTemplate.extensions, importedProfile); + await that.instantiationService.createInstance(ExtensionsResource, false).apply(profileTemplate.extensions, importedProfile); } }); } @@ -393,7 +403,7 @@ export class UserDataProfileImportExportService extends Disposable implements IU disposables.add(Event.debounce(this.extensionManagementService.onDidInstallExtensions, () => undefined, 100)(async () => { const profileTemplate = await userDataProfileImportState.getProfileTemplateToImport(); if (profileTemplate.extensions) { - const profileExtensions = await that.instantiationService.createInstance(ExtensionsResource).getProfileExtensions(profileTemplate.extensions!); + const profileExtensions = await that.instantiationService.createInstance(ExtensionsResource, false).getProfileExtensions(profileTemplate.extensions!); const installed = await this.extensionManagementService.getInstalled(ExtensionType.User); if (profileExtensions.every(e => installed.some(i => areSameExtensions(e.identifier, i.identifier)))) { disposable.dispose(); @@ -432,7 +442,7 @@ export class UserDataProfileImportExportService extends Disposable implements IU const importProfileFn = async () => { importAction.enabled = false; const profileTemplate = await userDataProfileImportState.getProfileTemplateToImport(); - const importedProfile = await this.importAndSwitch(profileTemplate, false, true, title); + const importedProfile = await this.importAndSwitch(profileTemplate, false, true, false, title); if (!importedProfile) { return; } @@ -448,7 +458,7 @@ export class UserDataProfileImportExportService extends Disposable implements IU return importAction; } - private async importAndSwitch(profileTemplate: IUserDataProfileTemplate, temporaryProfile: boolean, extensions: boolean, title: string): Promise { + private async importAndSwitch(profileTemplate: IUserDataProfileTemplate, temporaryProfile: boolean, extensions: boolean, extensionsDisabled: boolean, title: string): Promise { return this.progressService.withProgress({ location: ProgressLocation.Window, command: showWindowLogActionId, @@ -481,7 +491,7 @@ export class UserDataProfileImportExportService extends Disposable implements IU } if (profileTemplate.extensions && extensions) { progress.report({ message: localize('progress extensions', "{0} ({1}): Applying Extensions...", title, profileTemplate.name) }); - await this.instantiationService.createInstance(ExtensionsResource).apply(profileTemplate.extensions, profile); + await this.instantiationService.createInstance(ExtensionsResource, extensionsDisabled).apply(profileTemplate.extensions, profile); } progress.report({ message: localize('switching profile', "{0} ({1}): Applying...", title, profileTemplate.name) }); @@ -545,8 +555,8 @@ export class UserDataProfileImportExportService extends Disposable implements IU return result?.id; } - private async getProfileToImport(profileTemplate: IUserDataProfileTemplate, temp?: boolean): Promise { - const profileName = temp ? `${profileTemplate.name} (${localize('preview', "Preview")})` : profileTemplate.name; + private async getProfileToImport(profileTemplate: IUserDataProfileTemplate, temp: boolean): Promise { + const profileName = profileTemplate.name; const profile = this.userDataProfilesService.profiles.find(p => p.name === profileName); if (profile) { if (temp) { @@ -666,7 +676,7 @@ export class UserDataProfileImportExportService extends Disposable implements IU await this.instantiationService.createInstance(GlobalStateResource).apply(profile.globalState, this.userDataProfileService.currentProfile); } if (profile.extensions) { - await this.instantiationService.createInstance(ExtensionsResource).apply(profile.extensions, this.userDataProfileService.currentProfile); + await this.instantiationService.createInstance(ExtensionsResource, false).apply(profile.extensions, this.userDataProfileService.currentProfile); } }); this.notificationService.info(localize('applied profile', "{0}: Applied successfully.", PROFILES_CATEGORY.value)); @@ -997,6 +1007,7 @@ class UserDataProfileExportState extends UserDataProfileImportExportState { constructor( readonly profile: IUserDataProfile, + private readonly disableExtensions: boolean, @IQuickInputService quickInputService: IQuickInputService, @IFileService private readonly fileService: IFileService, @IInstantiationService private readonly instantiationService: IInstantiationService @@ -1052,7 +1063,7 @@ class UserDataProfileExportState extends UserDataProfileImportExportState { roots.push(globalStateResourceTreeItem); } - const extensionsResourceTreeItem = this.instantiationService.createInstance(ExtensionsResourceExportTreeItem, exportPreviewProfle); + const extensionsResourceTreeItem = this.instantiationService.createInstance(ExtensionsResourceExportTreeItem, exportPreviewProfle, this.disableExtensions); if (await extensionsResourceTreeItem.hasContent()) { roots.push(extensionsResourceTreeItem); } diff --git a/src/vs/workbench/services/userDataProfile/common/userDataProfile.ts b/src/vs/workbench/services/userDataProfile/common/userDataProfile.ts index e21e7efd690..1b933f99641 100644 --- a/src/vs/workbench/services/userDataProfile/common/userDataProfile.ts +++ b/src/vs/workbench/services/userDataProfile/common/userDataProfile.ts @@ -89,6 +89,7 @@ export interface IUserDataProfileImportExportService { importProfile(uri: URI, options?: IProfileImportOptions): Promise; showProfileContents(): Promise; createFromCurrentProfile(name: string): Promise; + createTemporaryProfile(from: IUserDataProfile, name: string, extensionsDisabled: boolean): Promise; setProfile(profile: IUserDataProfileTemplate): Promise; } diff --git a/src/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index 6145d9dd04d..7728aab4fbc 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -109,6 +109,7 @@ import 'vs/editor/common/services/treeViewsDndService'; import 'vs/workbench/services/textMate/browser/textMateTokenizationFeature.contribution'; import 'vs/workbench/services/userActivity/common/userActivityService'; import 'vs/workbench/services/userActivity/browser/userActivityBrowser'; +import 'vs/workbench/services/issue/browser/issueTroubleshoot'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService'; From 76b31a166db70d1398c19313c1d89334f35f3aa5 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Mon, 12 Jun 2023 14:13:40 +0200 Subject: [PATCH 047/128] using a different widget position strategy --- .../browser/inlineChatController.ts | 8 +-- .../inlineChat/browser/inlineChatSession.ts | 3 +- .../browser/inlineChatStrategies.ts | 59 +++++++++++-------- 3 files changed, 39 insertions(+), 31 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index de96b68407c..bb00fe80b98 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -28,7 +28,7 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ILogService } from 'vs/platform/log/common/log'; -import { EditResponse, EmptyResponse, ErrorResponse, ExpansionState, IInlineChatSessionService, MarkdownResponse, Session, SessionExchange } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession'; +import { EditResponse, EmptyResponse, ErrorResponse, ExpansionState, IInlineChatSessionService, MarkdownResponse, Session, SessionExchange, SessionResponse } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession'; import { EditModeStrategy, LivePreviewStrategy, LiveStrategy, PreviewStrategy } from 'vs/workbench/contrib/inlineChat/browser/inlineChatStrategies'; import { InlineChatZoneWidget } from 'vs/workbench/contrib/inlineChat/browser/inlineChatWidget'; import { CTX_INLINE_CHAT_HAS_ACTIVE_REQUEST, CTX_INLINE_CHAT_LAST_FEEDBACK, IInlineChatRequest, IInlineChatResponse, INLINE_CHAT_ID, EditMode, InlineChatResponseFeedbackKind, CTX_INLINE_CHAT_LAST_RESPONSE_TYPE, InlineChatResponseType, CTX_INLINE_CHAT_DID_EDIT, CTX_INLINE_CHAT_HAS_STASHED_SESSION } from 'vs/workbench/contrib/inlineChat/common/inlineChat'; @@ -193,10 +193,10 @@ export class InlineChatController implements IEditorContribution { // ---- state machine - private _showWidget(initialRender: boolean = false, hasEditResponse: boolean = false) { + private _showWidget(initialRender: boolean = false, response?: SessionResponse) { assertType(this._activeSession); const selectionRange = this._activeSession.wholeRange.value; - const widgetPosition = this._strategy?.getWidgetPosition(initialRender, selectionRange, hasEditResponse); + const widgetPosition = this._strategy?.getWidgetPosition(initialRender, selectionRange, response); this._zone.value.show(widgetPosition ?? selectionRange.getEndPosition()); } @@ -544,7 +544,7 @@ export class InlineChatController implements IEditorContribution { assertType(this._strategy); const { response } = this._activeSession.lastExchange!; - this._showWidget(false, response instanceof EditResponse); + this._showWidget(false, response); this._ctxLastResponseType.set(response instanceof EditResponse || response instanceof MarkdownResponse ? response.raw.type diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts index cdc71d8cb97..8128705aba4 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts @@ -236,11 +236,12 @@ export class Session { } } +export type SessionResponse = EditResponse | MarkdownResponse | ErrorResponse | EmptyResponse; export class SessionExchange { constructor( readonly prompt: string, - readonly response: MarkdownResponse | EditResponse | EmptyResponse | ErrorResponse + readonly response: SessionResponse ) { } } diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts index 089c94614a9..318fb90dc96 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts @@ -21,7 +21,7 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { InlineChatFileCreatePreviewWidget, InlineChatLivePreviewWidget } from 'vs/workbench/contrib/inlineChat/browser/inlineChatLivePreviewWidget'; -import { EditResponse, Session } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession'; +import { EditResponse, Session, SessionResponse } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession'; import { InlineChatWidget } from 'vs/workbench/contrib/inlineChat/browser/inlineChatWidget'; import { CTX_INLINE_CHAT_SHOWING_DIFF, CTX_INLINE_CHAT_DOCUMENT_CHANGED } from 'vs/workbench/contrib/inlineChat/common/inlineChat'; import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; @@ -46,7 +46,7 @@ export abstract class EditModeStrategy { abstract hasFocus(): boolean; - abstract getWidgetPosition(initialRender: boolean, range: Range, hasEditResponse: boolean | undefined): Position | undefined; + abstract getWidgetPosition(initialRender: boolean, range?: Range, response?: SessionResponse): Position | undefined; } export class PreviewStrategy extends EditModeStrategy { @@ -135,15 +135,13 @@ export class PreviewStrategy extends EditModeStrategy { // nothing to do } - getWidgetPosition(initialRender: boolean, range: Range, hasEditResponse: boolean | undefined): Position | undefined { + getWidgetPosition(initialRender: boolean, _range: Range, _response: SessionResponse): Position | undefined { const viewModel = this._editor._getViewModel(); assertType(viewModel); if (initialRender) { this._initialPosition = viewModel.getPrimaryCursorState().viewState.position; - return this._initialPosition; - } else { - return minimalJumpPosition(this._editor, this._initialPosition, range, hasEditResponse); } + return this._initialPosition; } hasFocus(): boolean { @@ -342,14 +340,39 @@ export class LiveStrategy extends EditModeStrategy { this._widget.updateStatus(message); } - override getWidgetPosition(initialRender: boolean, range: Range, hasEditResponse: boolean | undefined): Position | undefined { + private _findEditsMaxLineNumber(response: EditResponse): number | void { + const edits = response.localEdits; + if (edits.length) { + let editsMaxLineNumber = 0; + for (const edit of edits) { + const editStartLine = edit.range.startLineNumber; + const editNumberOfLines = (edit.text.match(/\n/g) || []).length; + const endLine = editStartLine + editNumberOfLines - 1; + if (endLine > editsMaxLineNumber) { + editsMaxLineNumber = endLine; + } + } + return editsMaxLineNumber; + } + } + + override getWidgetPosition(initialRender: boolean, _range: Range, response: SessionResponse): Position | undefined { const viewModel = this._editor._getViewModel(); assertType(viewModel); if (initialRender) { this._initialPosition = viewModel.getPrimaryCursorState().viewState.position; return this._initialPosition; } else { - return minimalJumpPosition(this._editor, this._initialPosition, range, hasEditResponse); + if (response instanceof EditResponse) { + const editsMaxLineNumber = this._findEditsMaxLineNumber(response); + if (editsMaxLineNumber) { + return new Position(editsMaxLineNumber, 1); + } else { + return this._initialPosition; + } + } else { + return this._initialPosition; + } } } @@ -411,14 +434,14 @@ export class LivePreviewStrategy extends LiveStrategy { scrollState.restore(this._editor); } - override getWidgetPosition(initialRender: boolean, range: Range, hasEditResponse: boolean | undefined): Position | undefined { + override getWidgetPosition(initialRender: boolean, range: Range, response: SessionResponse): Position | undefined { if (initialRender) { const viewModel = this._editor._getViewModel(); assertType(viewModel); this._initialPosition = viewModel.getPrimaryCursorState().viewState.position; return this._initialPosition; } else { - if (hasEditResponse) { + if (range && response instanceof EditResponse) { return range.getEndPosition(); } else { return this._initialPosition; @@ -437,19 +460,3 @@ function showSingleCreateFile(accessor: ServicesAccessor, edit: EditResponse) { editorService.openEditor({ resource: edit.singleCreateFileEdit.uri }, SIDE_GROUP); } } - -function minimalJumpPosition(editor: ICodeEditor, initialPosition: Position | undefined, range: Range, hasEditResponse: boolean | undefined): Position | undefined { - const viewModel = editor._getViewModel(); - assertType(viewModel); - if (hasEditResponse) { - const endPosition = range.getEndPosition(); - const visibleRange = viewModel.getCompletelyVisibleViewRange(); - if (visibleRange.containsPosition(endPosition)) { - return endPosition; - } else { - return initialPosition; - } - } else { - return initialPosition; - } -} From 46b43d1deff2249c0946ee6538a01abff28262d8 Mon Sep 17 00:00:00 2001 From: Jean Pierre Date: Mon, 12 Jun 2023 08:01:35 -0500 Subject: [PATCH 048/128] Fix `remote.autoForwardPortsSource` sometimes not respected from machine settings (#184860) Fix #184859 --- src/vs/workbench/contrib/remote/browser/remoteExplorer.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts index b262bd5656c..66ac320105c 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts @@ -31,6 +31,7 @@ import { IExternalUriOpenerService } from 'vs/workbench/contrib/externalUriOpene import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; import { ILogService } from 'vs/platform/log/common/log'; +import { IWorkbenchConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; export const VIEWLET_ID = 'workbench.view.remote'; @@ -181,7 +182,7 @@ export class AutomaticPortForwarding extends Disposable implements IWorkbenchCon @IRemoteExplorerService remoteExplorerService: IRemoteExplorerService, @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, @IContextKeyService contextKeyService: IContextKeyService, - @IConfigurationService configurationService: IConfigurationService, + @IWorkbenchConfigurationService configurationService: IWorkbenchConfigurationService, @IDebugService debugService: IDebugService, @IRemoteAgentService remoteAgentService: IRemoteAgentService, @ITunnelService tunnelService: ITunnelService, @@ -193,7 +194,7 @@ export class AutomaticPortForwarding extends Disposable implements IWorkbenchCon return; } - remoteAgentService.getEnvironment().then(environment => { + configurationService.whenRemoteConfigurationLoaded().then(() => remoteAgentService.getEnvironment()).then(environment => { if (environment?.os !== OperatingSystem.Linux) { Registry.as(ConfigurationExtensions.Configuration) .registerDefaultConfigurations([{ overrides: { 'remote.autoForwardPortsSource': PORT_AUTO_SOURCE_SETTING_OUTPUT } }]); From 02ec02e967d251614b34551f659d7197a5bcbdf8 Mon Sep 17 00:00:00 2001 From: Robo Date: Mon, 12 Jun 2023 22:01:50 +0900 Subject: [PATCH 049/128] fix: disable app sandbox when --no-sandbox is present (#184897) --- src/main.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/main.js b/src/main.js index d986fee6f6d..18bc6a86d38 100644 --- a/src/main.js +++ b/src/main.js @@ -27,8 +27,11 @@ const { getUNCHost, addUNCHostToAllowlist } = require('./vs/base/node/unc'); const product = require('../product.json'); const { app, protocol, crashReporter, Menu } = require('electron'); -// Enable sandbox globally -app.enableSandbox(); +// Enable sandbox globally unless disabled via `--no-sandbox` argument +const args = parseCLIArgs(); +if (args['sandbox']) { + app.enableSandbox(); +} // Enable portable support const portable = bootstrapNode.configurePortable(product); @@ -37,7 +40,6 @@ const portable = bootstrapNode.configurePortable(product); bootstrap.enableASARSupport(); // Set userData path before app 'ready' event -const args = parseCLIArgs(); const userDataPath = getUserDataPath(args, product.nameShort ?? 'code-oss-dev'); if (process.platform === 'win32') { const userDataUNCHost = getUNCHost(userDataPath); @@ -464,7 +466,13 @@ function parseCLIArgs() { 'locale', 'js-flags', 'crash-reporter-directory' - ] + ], + default: { + 'sandbox': true + }, + alias: { + 'no-sandbox': 'sandbox' + } }); } From 4dd7a526cd620e557f6539cb4468e279fafea60f Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Mon, 12 Jun 2023 15:07:14 +0200 Subject: [PATCH 050/128] Implements diff editor revert button. (#184909) --- .../widget/diffEditorWidget2/decorations.ts | 8 +++ .../diffEditorWidget2/diffEditorWidget2.ts | 62 ++++++++++++++----- .../inlineDiffDeletedCodeMargin.ts | 51 ++++++++------- .../widget/diffEditorWidget2/lineAlignment.ts | 19 +++++- 4 files changed, 99 insertions(+), 41 deletions(-) diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/decorations.ts b/src/vs/editor/browser/widget/diffEditorWidget2/decorations.ts index 4d6dcafe955..717c8b5e14d 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/decorations.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/decorations.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Codicon } from 'vs/base/common/codicons'; +import { MarkdownString } from 'vs/base/common/htmlContent'; import { ThemeIcon } from 'vs/base/common/themables'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; import { localize } from 'vs/nls'; @@ -37,3 +38,10 @@ export const diffDeleteDecoration = ModelDecorationOptions.register({ className: 'char-delete', description: 'char-delete', }); + +export const arrowRevertChange = ModelDecorationOptions.register({ + description: 'diff-editor-arrow-revert-change', + glyphMarginHoverMessage: new MarkdownString(undefined, { isTrusted: true, supportThemeIcons: true }).appendMarkdown(localize('revertChangeHoverMessage', 'Click to revert change')), + glyphMarginClassName: 'arrow-revert-change ' + ThemeIcon.asClassName(Codicon.arrowRight), + zIndex: 10001, +}); diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts index dc355e41d60..74346212f94 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts @@ -14,12 +14,12 @@ import { isDefined } from 'vs/base/common/types'; import { Constants } from 'vs/base/common/uint'; import 'vs/css!./style'; import { IEditorConstructionOptions } from 'vs/editor/browser/config/editorConfiguration'; -import { ICodeEditor, IDiffEditor, IDiffEditorConstructionOptions } from 'vs/editor/browser/editorBrowser'; +import { ICodeEditor, IDiffEditor, IDiffEditorConstructionOptions, IMouseTargetViewZone } from 'vs/editor/browser/editorBrowser'; import { EditorExtensionsRegistry, IDiffEditorContributionDescription } from 'vs/editor/browser/editorExtensions'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { CodeEditorWidget, ICodeEditorWidgetOptions } from 'vs/editor/browser/widget/codeEditorWidget'; import { IDiffCodeEditorWidgetOptions } from 'vs/editor/browser/widget/diffEditorWidget'; -import { diffAddDecoration, diffDeleteDecoration, diffFullLineAddDecoration, diffFullLineDeleteDecoration } from 'vs/editor/browser/widget/diffEditorWidget2/decorations'; +import { arrowRevertChange, diffAddDecoration, diffDeleteDecoration, diffFullLineAddDecoration, diffFullLineDeleteDecoration } from 'vs/editor/browser/widget/diffEditorWidget2/decorations'; import { DiffEditorSash } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorSash'; import { ViewZoneManager } from 'vs/editor/browser/widget/diffEditorWidget2/lineAlignment'; import { MovedBlocksLinesPart } from 'vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines'; @@ -40,6 +40,8 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { DelegatingEditor } from './delegatingEditorImpl'; import { DiffMapping, DiffModel } from './diffModel'; +import { Range } from 'vs/editor/common/core/range'; +import { LineRangeMapping } from 'vs/editor/common/diff/linesDiffComputer'; const diffEditorDefaultOptions: ValidDiffEditorBaseOptions = { enableSplitViewResizing: true, @@ -142,7 +144,16 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { this._register(keepAlive(this._sash, true)); this._register(new UnchangedRangesFeature(this._originalEditor, this._modifiedEditor, this._diffModel)); - this._register(this._instantiationService.createInstance(ViewZoneManager, this._originalEditor, this._modifiedEditor, this._diffModel, this._options.map(o => o.renderSideBySide))); + this._register( + this._instantiationService.createInstance( + ViewZoneManager, + this._originalEditor, + this._modifiedEditor, + this._diffModel, + this._options.map((o) => o.renderSideBySide), + this + ) + ); this._register(this._instantiationService.createInstance(OverviewRulerPart, this._originalEditor, @@ -229,6 +240,10 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { originalDecorations.push({ range: i.originalRange, options: diffDeleteDecoration }); modifiedDecorations.push({ range: i.modifiedRange, options: diffAddDecoration }); } + + if (!m.lineRangeMapping.modifiedRange.isEmpty) { + modifiedDecorations.push({ range: Range.fromPositions(new Position(m.lineRangeMapping.modifiedRange.startLineNumber, 1)), options: arrowRevertChange }); + } } if (currentMove) { @@ -311,24 +326,32 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { m.syncedMovedTexts.set(movedText, undefined); })); // Revert change when an arrow is clicked. - /*TODO this._register(editor.onMouseDown(event => { if (!event.event.rightButton && event.target.position && event.target.element?.className.includes('arrow-revert-change')) { const lineNumber = event.target.position.lineNumber; - const viewZone = event.target as editorBrowser.IMouseTargetViewZone | undefined; - const change = this._diffComputationResult?.changes.find(c => - // delete change - viewZone?.detail.afterLineNumber === c.modifiedStartLineNumber || - // other changes - (c.modifiedEndLineNumber > 0 && c.modifiedStartLineNumber === lineNumber)); - if (change) { - this.revertChange(change); + const viewZone = event.target as IMouseTargetViewZone | undefined; + + const model = this._diffModel.get(); + if (!model) { + return; } + const diffs = model.diff.get()?.mappings; + if (!diffs) { + return; + } + const diff = diffs.find(d => + viewZone?.detail.afterLineNumber === d.lineRangeMapping.modifiedRange.startLineNumber - 1 || + d.lineRangeMapping.modifiedRange.startLineNumber === lineNumber + ); + if (!diff) { + return; + } + this.revert(diff.lineRangeMapping); + event.event.stopPropagation(); - this._updateDecorations(); return; } - }));*/ + })); return editor; } @@ -579,6 +602,17 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { }; } + public revert(diff: LineRangeMapping): void { + const model = this._model.get(); + if (!model) { + return; + } + const originalText = model.original.getValueInRange(diff.originalRange.toExclusiveRange()); + this._modifiedEditor.executeEdits('diffEditor', [ + { range: diff.modifiedRange.toExclusiveRange(), text: originalText } + ]); + } + private _goTo(diff: DiffMapping): void { this._modifiedEditor.setPosition(new Position(diff.lineRangeMapping.modifiedRange.startLineNumber, 1)); this._modifiedEditor.revealRangeInCenter(diff.lineRangeMapping.modifiedRange.toExclusiveRange()); diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/inlineDiffDeletedCodeMargin.ts b/src/vs/editor/browser/widget/diffEditorWidget2/inlineDiffDeletedCodeMargin.ts index e31ed0d4d87..da0b9ff8d17 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/inlineDiffDeletedCodeMargin.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/inlineDiffDeletedCodeMargin.ts @@ -11,6 +11,7 @@ import { isIOS } from 'vs/base/common/platform'; import { ThemeIcon } from 'vs/base/common/themables'; import { IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; +import { DiffEditorWidget2 } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { LineRangeMapping } from 'vs/editor/common/diff/linesDiffComputer'; import { EndOfLineSequence, ITextModel } from 'vs/editor/common/model'; @@ -42,9 +43,10 @@ export class InlineDiffDeletedCodeMargin extends Disposable { constructor( private readonly _getViewZoneId: () => string, private readonly _marginDomNode: HTMLElement, - private readonly editor: CodeEditorWidget, - private readonly diff: LineRangeMapping, - private readonly viewLineCounts: number[], + private readonly _modifiedEditor: CodeEditorWidget, + private readonly _diff: LineRangeMapping, + private readonly _editor: DiffEditorWidget2, + private readonly _viewLineCounts: number[], private readonly _originalTextModel: ITextModel, private readonly _contextMenuService: IContextMenuService, private readonly _clipboardService: IClipboardService, @@ -57,7 +59,7 @@ export class InlineDiffDeletedCodeMargin extends Disposable { this._diffActions = document.createElement('div'); this._diffActions.className = ThemeIcon.asClassName(Codicon.lightBulb) + ' lightbulb-glyph'; this._diffActions.style.position = 'absolute'; - const lineHeight = this.editor.getOption(EditorOption.lineHeight); + const lineHeight = this._modifiedEditor.getOption(EditorOption.lineHeight); this._diffActions.style.right = '0px'; this._diffActions.style.visibility = 'hidden'; this._diffActions.style.height = `${lineHeight}px`; @@ -65,38 +67,38 @@ export class InlineDiffDeletedCodeMargin extends Disposable { this._marginDomNode.appendChild(this._diffActions); const actions: Action[] = []; - const isDeletion = diff.modifiedRange.isEmpty; + const isDeletion = _diff.modifiedRange.isEmpty; // default action actions.push(new Action( 'diff.clipboard.copyDeletedContent', isDeletion - ? (diff.originalRange.length > 1 + ? (_diff.originalRange.length > 1 ? localize('diff.clipboard.copyDeletedLinesContent.label', "Copy deleted lines") : localize('diff.clipboard.copyDeletedLinesContent.single.label', "Copy deleted line")) - : (diff.originalRange.length > 1 + : (_diff.originalRange.length > 1 ? localize('diff.clipboard.copyChangedLinesContent.label', "Copy changed lines") : localize('diff.clipboard.copyChangedLinesContent.single.label', "Copy changed line")), undefined, true, async () => { - const originalText = this._originalTextModel.getValueInRange(diff.originalRange.toExclusiveRange()); + const originalText = this._originalTextModel.getValueInRange(_diff.originalRange.toExclusiveRange()); await this._clipboardService.writeText(originalText); } )); let currentLineNumberOffset = 0; let copyLineAction: Action | undefined = undefined; - if (diff.originalRange.length > 1) { + if (_diff.originalRange.length > 1) { copyLineAction = new Action( 'diff.clipboard.copyDeletedLineContent', isDeletion - ? localize('diff.clipboard.copyDeletedLineContent.label', "Copy deleted line ({0})", diff.originalRange.startLineNumber) - : localize('diff.clipboard.copyChangedLineContent.label', "Copy changed line ({0})", diff.originalRange.startLineNumber), + ? localize('diff.clipboard.copyDeletedLineContent.label', "Copy deleted line ({0})", _diff.originalRange.startLineNumber) + : localize('diff.clipboard.copyChangedLineContent.label', "Copy changed line ({0})", _diff.originalRange.startLineNumber), undefined, true, async () => { - let lineContent = this._originalTextModel.getLineContent(diff.originalRange.startLineNumber + currentLineNumberOffset); + let lineContent = this._originalTextModel.getLineContent(_diff.originalRange.startLineNumber + currentLineNumberOffset); if (lineContent === '') { // empty line -> new line const eof = this._originalTextModel.getEndOfLineSequence(); @@ -109,21 +111,18 @@ export class InlineDiffDeletedCodeMargin extends Disposable { actions.push(copyLineAction); } - const readOnly = editor.getOption(EditorOption.readOnly); + const readOnly = _modifiedEditor.getOption(EditorOption.readOnly); if (!readOnly) { actions.push(new Action('diff.inline.revertChange', localize('diff.inline.revertChange.label', "Revert this change"), undefined, true, async () => { - const originalText = this._originalTextModel.getValueInRange(this.diff.originalRange.toExclusiveRange()); - editor.executeEdits('diffEditor', [ - { range: this.diff.modifiedRange.toExclusiveRange(), text: originalText } - ]); + this._editor.revert(this._diff); })); } - const useShadowDOM = editor.getOption(EditorOption.useShadowDOM) && !isIOS; // Do not use shadow dom on IOS #122035 + const useShadowDOM = _modifiedEditor.getOption(EditorOption.useShadowDOM) && !isIOS; // Do not use shadow dom on IOS #122035 const showContextMenu = (x: number, y: number) => { this._contextMenuService.showContextMenu({ - domForShadowRoot: useShadowDOM ? editor.getDomNode() ?? undefined : undefined, + domForShadowRoot: useShadowDOM ? _modifiedEditor.getDomNode() ?? undefined : undefined, getAnchor: () => { return { x, @@ -134,8 +133,8 @@ export class InlineDiffDeletedCodeMargin extends Disposable { if (copyLineAction) { copyLineAction.label = isDeletion - ? localize('diff.clipboard.copyDeletedLineContent.label', "Copy deleted line ({0})", diff.originalRange.startLineNumber + currentLineNumberOffset) - : localize('diff.clipboard.copyChangedLineContent.label', "Copy changed line ({0})", diff.originalRange.startLineNumber + currentLineNumberOffset); + ? localize('diff.clipboard.copyDeletedLineContent.label', "Copy deleted line ({0})", _diff.originalRange.startLineNumber + currentLineNumberOffset) + : localize('diff.clipboard.copyChangedLineContent.label', "Copy changed line ({0})", _diff.originalRange.startLineNumber + currentLineNumberOffset); } return actions; }, @@ -150,7 +149,7 @@ export class InlineDiffDeletedCodeMargin extends Disposable { showContextMenu(e.posx, top + height + pad); })); - this._register(editor.onMouseMove((e: IEditorMouseEvent) => { + this._register(_modifiedEditor.onMouseMove((e: IEditorMouseEvent) => { if ((e.target.type === MouseTargetType.CONTENT_VIEW_ZONE || e.target.type === MouseTargetType.GUTTER_VIEW_ZONE) && e.target.detail.viewZoneId === this._getViewZoneId()) { currentLineNumberOffset = this._updateLightBulbPosition(this._marginDomNode, e.event.browserEvent.y, lineHeight); this.visibility = true; @@ -159,7 +158,7 @@ export class InlineDiffDeletedCodeMargin extends Disposable { } })); - this._register(editor.onMouseDown((e: IEditorMouseEvent) => { + this._register(_modifiedEditor.onMouseDown((e: IEditorMouseEvent) => { if (!e.event.rightButton) { return; } @@ -182,10 +181,10 @@ export class InlineDiffDeletedCodeMargin extends Disposable { const lineNumberOffset = Math.floor(offset / lineHeight); const newTop = lineNumberOffset * lineHeight; this._diffActions.style.top = `${newTop}px`; - if (this.viewLineCounts) { + if (this._viewLineCounts) { let acc = 0; - for (let i = 0; i < this.viewLineCounts.length; i++) { - acc += this.viewLineCounts[i]; + for (let i = 0; i < this._viewLineCounts.length; i++) { + acc += this._viewLineCounts[i]; if (lineNumberOffset < acc) { return i; } diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts b/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts index 98d93ee8161..7208098e374 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts @@ -3,7 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { $ } from 'vs/base/browser/dom'; import { ArrayQueue } from 'vs/base/common/arrays'; +import { Codicon } from 'vs/base/common/codicons'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IObservable, derived, observableFromEvent, observableSignalFromEvent, observableValue } from 'vs/base/common/observable'; import { autorun, autorunWithStore2 } from 'vs/base/common/observableImpl/autorun'; @@ -14,6 +16,7 @@ import { IViewZone } from 'vs/editor/browser/editorBrowser'; import { StableEditorScrollState } from 'vs/editor/browser/stableEditorScroll'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { diffDeleteDecoration, diffRemoveIcon } from 'vs/editor/browser/widget/diffEditorWidget2/decorations'; +import { DiffEditorWidget2 } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2'; import { DiffMapping, DiffModel } from 'vs/editor/browser/widget/diffEditorWidget2/diffModel'; import { InlineDiffDeletedCodeMargin } from 'vs/editor/browser/widget/diffEditorWidget2/inlineDiffDeletedCodeMargin'; import { LineSource, RenderOptions, renderLines } from 'vs/editor/browser/widget/diffEditorWidget2/renderLines'; @@ -49,6 +52,7 @@ export class ViewZoneManager extends Disposable { private readonly _modifiedEditor: CodeEditorWidget, private readonly _diffModel: IObservable, private readonly _renderSideBySide: IObservable, + private readonly _diffEditorWidget: DiffEditorWidget2, @IClipboardService private readonly _clipboardService: IClipboardService, @IContextMenuService private readonly _contextMenuService: IContextMenuService, ) { @@ -190,10 +194,11 @@ export class ViewZoneManager extends Disposable { marginDomNode, this._modifiedEditor, a.diff, + this._diffEditorWidget, result.viewLineCounts, this._originalEditor.getModel()!, this._contextMenuService, - this._clipboardService + this._clipboardService, ) ); @@ -245,10 +250,22 @@ export class ViewZoneManager extends Disposable { continue; } + function createViewZoneMarginArrow(): HTMLElement { + const arrow = document.createElement('div'); + arrow.className = 'arrow-revert-change ' + ThemeIcon.asClassName(Codicon.arrowRight); + return $('div', {}, arrow); + } + + let marginDomNode: HTMLElement | undefined = undefined; + if (a.diff && a.diff.modifiedRange.isEmpty) { + marginDomNode = createViewZoneMarginArrow(); + } + modViewZones.push({ afterLineNumber: a.modifiedRange.endLineNumberExclusive - 1, domNode: createFakeLinesDiv(), heightInPx: -delta, + marginDomNode, }); } } From f66024052627a96ee3a11fd369c684b3e9134327 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 12 Jun 2023 15:23:48 +0200 Subject: [PATCH 051/128] finetune issue troubleshooting (#184907) --- .../issue/browser/issueTroubleshoot.ts | 81 ++++++++++--------- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/src/vs/workbench/services/issue/browser/issueTroubleshoot.ts b/src/vs/workbench/services/issue/browser/issueTroubleshoot.ts index ef2b6b1f38d..0f90beef6ba 100644 --- a/src/vs/workbench/services/issue/browser/issueTroubleshoot.ts +++ b/src/vs/workbench/services/issue/browser/issueTroubleshoot.ts @@ -108,7 +108,7 @@ class TroubleshootIssueService extends Disposable implements ITroubleshootIssueS const res = await this.dialogService.confirm({ message: localize('troubleshoot issue', "Troubleshoot Issue"), - detail: localize('detail.start', "Issue troubleshooting is a process to help you identify if the issue is with {0} or caused by an extension.\n\nDuring the process the window reloads repeatedly. Each time you must confirm if you are still seeing problems.", this.productService.nameShort), + detail: localize('detail.start', "Issue troubleshooting is a process to help you identify if the issue is with {0} or caused by an extension.\n\nDuring the process the window reloads repeatedly. Each time you must confirm if you are still seeing problems.", this.productService.nameLong), primaryButton: localize({ key: 'msg', comment: ['&& denotes a mnemonic'] }, "&&Troubleshoot Issue"), custom: true }); @@ -159,7 +159,7 @@ class TroubleshootIssueService extends Disposable implements ITroubleshootIssueS } private async reproduceIssueWithExtensionsDisabled(): Promise { - const result = await this.askToReproduceIssue(localize('profile.extensions.disabled', "Issue troubleshooting is active and has temprarily disabled all extensions. Check if you can still reproduce the problem and proceed by selecting from these options.")); + const result = await this.askToReproduceIssue(localize('profile.extensions.disabled', "Issue troubleshooting is active and has temprarily disabled all installed extensions. Check if you can still reproduce the problem and proceed by selecting from these options.")); if (result === 'good') { const profile = this.userDataProfilesService.profiles.find(p => p.id === this.state!.profile) ?? this.userDataProfilesService.defaultProfile; await this.reproduceIssueWithExtensionsBisect(profile); @@ -180,10 +180,10 @@ class TroubleshootIssueService extends Disposable implements ITroubleshootIssueS await this.stop(); } if (result === 'good') { - await this.askToReportIssue(localize('issue is with configuration', "Issue troubleshooting is done and has identified that the issue is caused by your settings. Please report the issue by sharing your settings.")); + await this.askToReportIssue(localize('issue is with configuration', "Issue troubleshooting has identified that the issue is caused by your settings. Please report the issue by sharing your settings.")); } if (result === 'bad') { - await this.askToReportIssue(localize('issue is in core', "Issue troubleshooting is done and has identified that the issue is with {0}.", this.productService.nameShort)); + await this.askToReportIssue(localize('issue is in core', "Issue troubleshooting has identified that the issue is with {0}.", this.productService.nameLong)); } } @@ -217,45 +217,45 @@ class TroubleshootIssueService extends Disposable implements ITroubleshootIssueS }); } - private async askToReportIssue(detail: string): Promise { - const isStable = this.productService.quality === 'stable'; - if (isStable) { + private async askToReportIssue(message: string): Promise { + let isCheckedInInsiders = false; + if (this.productService.quality === 'stable') { const res = await this.askToReproduceIssueWithInsiders(); - if (res === undefined) { - return this.reportIssue(false); - } - if (res) { + if (res === 'good') { await this.dialogService.prompt({ type: Severity.Info, message: localize('troubleshoot issue', "Troubleshoot Issue"), - detail: localize('use insiders', "This likely means that the issue has been addressed already and will be available in an upcoming release. You can safely use {0} insiders until the new stable version is available.", this.productService.nameShort), + detail: localize('use insiders', "This likely means that the issue has been addressed already and will be available in an upcoming release. You can safely use {0} insiders until the new stable version is available.", this.productService.nameLong), custom: true }); return; } + if (res === 'stop') { + await this.stop(); + return; + } + if (res === 'bad') { + isCheckedInInsiders = true; + } } - const res = await this.dialogService.confirm({ - type: Severity.Info, - message: localize('troubleshoot issue', "Troubleshoot Issue"), - primaryButton: localize({ key: 'report', comment: ['&& denotes a mnemonic'] }, "&&Report Issue & Continue"), - cancelButton: localize('continue', "Continue"), - detail, - custom: true + + await this.issueService.openReporter({ + issueBody: `> ${message} ${isCheckedInInsiders ? `It is confirmed that the issue exists in ${this.productService.nameLong} Insiders` : ''}`, }); - if (res.confirmed) { - await this.reportIssue(isStable); - } } - private async askToReproduceIssueWithInsiders(): Promise { + private async askToReproduceIssueWithInsiders(): Promise { const confirmRes = await this.dialogService.confirm({ type: 'info', message: localize('troubleshoot issue', "Troubleshoot Issue"), - primaryButton: localize('download insiders', "Download {0} Insiders", this.productService.nameShort), + primaryButton: localize('download insiders', "Download {0} Insiders", this.productService.nameLong), cancelButton: localize('report anyway', "Report Issue Anyway"), - detail: localize('ask to download insiders', "Please try to download and reproduce the issue in {0} insiders.", this.productService.nameShort), - custom: true + detail: localize('ask to download insiders', "Please try to download and reproduce the issue in {0} insiders.", this.productService.nameLong), + custom: { + disableCloseAction: true, + } }); + if (!confirmRes.confirmed) { return undefined; } @@ -265,22 +265,27 @@ class TroubleshootIssueService extends Disposable implements ITroubleshootIssueS return undefined; } - const res = await this.dialogService.confirm({ + const res = await this.dialogService.prompt({ type: 'info', message: localize('troubleshoot issue', "Troubleshoot Issue"), - primaryButton: localize('good', "I can't reproduce"), - cancelButton: localize('bad', "I can reproduce"), - detail: localize('ask to reproduce issue', "Please try to reproduce the issue in {0} insiders and confirm if the issue exists there.", this.productService.nameShort), - custom: true + buttons: [{ + label: localize('good', "I can't reproduce"), + run: () => 'good' + }, { + label: localize('bad', "I can reproduce"), + run: () => 'bad' + }], + cancelButton: { + label: localize('stop', "Stop"), + run: () => 'stop' + }, + detail: localize('ask to reproduce issue', "Please try to reproduce the issue in {0} insiders and confirm if the issue exists there.", this.productService.nameLong), + custom: { + disableCloseAction: true, + } }); - return !!res.confirmed; - } - - private reportIssue(checkedInInsiders: boolean): Promise { - return this.issueService.openReporter({ - issueBody: `> This issue is reported using the **Troubleshoot Issue** feature. ${checkedInInsiders ? localize('confirmed in insiders', "It is confirmed that the issue exists in Insiders.") : ''}`, - }); + return res.result; } private _state: TroubleShootState | undefined | null; From bfffb9d8abd3996b375bdf823a01945c2ad39048 Mon Sep 17 00:00:00 2001 From: Robo Date: Mon, 12 Jun 2023 23:19:00 +0900 Subject: [PATCH 052/128] fix: loading minimist in packaged builds (#184915) --- src/main.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main.js b/src/main.js index 18bc6a86d38..5b3bcf8b9ab 100644 --- a/src/main.js +++ b/src/main.js @@ -27,18 +27,18 @@ const { getUNCHost, addUNCHostToAllowlist } = require('./vs/base/node/unc'); const product = require('../product.json'); const { app, protocol, crashReporter, Menu } = require('electron'); -// Enable sandbox globally unless disabled via `--no-sandbox` argument -const args = parseCLIArgs(); -if (args['sandbox']) { - app.enableSandbox(); -} - // Enable portable support const portable = bootstrapNode.configurePortable(product); // Enable ASAR support bootstrap.enableASARSupport(); +// Enable sandbox globally unless disabled via `--no-sandbox` argument +const args = parseCLIArgs(); +if (args['sandbox']) { + app.enableSandbox(); +} + // Set userData path before app 'ready' event const userDataPath = getUserDataPath(args, product.nameShort ?? 'code-oss-dev'); if (process.platform === 'win32') { From b0bcc33d34f504d0bef88cdb1514bb9eecc93bd6 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 12 Jun 2023 16:25:07 +0200 Subject: [PATCH 053/128] joh/cautious cephalopod (#184692) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * improve performance of `TraitSpliceable#splice`, avoid O(n2), avoid loop when not removing anything https://github.com/microsoft/vscode/issues/184615 * improve `Trait#splice` by reducing how often arrays are iterated over (from eight to three) * one more cleanup --------- Co-authored-by: João Moreno --- src/vs/base/browser/ui/list/listWidget.ts | 35 +++++++++++++++++------ 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index 1aa861d3068..2a282e9f1a3 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -129,17 +129,30 @@ class Trait implements ISpliceable, IDisposable { const diff = elements.length - deleteCount; const end = start + deleteCount; - const sortedIndexes = [ - ...this.sortedIndexes.filter(i => i < start), - ...elements.map((hasTrait, i) => hasTrait ? i + start : -1).filter(i => i !== -1), - ...this.sortedIndexes.filter(i => i >= end).map(i => i + diff) - ]; + const sortedIndexes: number[] = []; + let firstSortedIndex: number | undefined = undefined; + let i = 0; + + while (i < this.sortedIndexes.length && this.sortedIndexes[i] < start) { + sortedIndexes.push(this.sortedIndexes[i++]); + } + + for (let j = 0; j < elements.length; j++) { + if (elements[j]) { + sortedIndexes.push(j + start); + firstSortedIndex = firstSortedIndex ?? sortedIndexes[sortedIndexes.length - 1]; + } + } + + while (i < this.sortedIndexes.length && this.sortedIndexes[i] >= end) { + sortedIndexes.push(this.sortedIndexes[i++] + diff); + firstSortedIndex = firstSortedIndex ?? sortedIndexes[sortedIndexes.length - 1]; + } const length = this.length + diff; if (this.sortedIndexes.length > 0 && sortedIndexes.length === 0 && length > 0) { - const first = this.sortedIndexes.find(index => index >= start) ?? length - 1; - sortedIndexes.push(Math.min(first, length - 1)); + sortedIndexes.push(Math.min(firstSortedIndex ?? length - 1, length - 1)); } this.renderer.splice(start, deleteCount, elements.length); @@ -226,12 +239,16 @@ class TraitSpliceable implements ISpliceable { splice(start: number, deleteCount: number, elements: T[]): void { if (!this.identityProvider) { - return this.trait.splice(start, deleteCount, elements.map(() => false)); + return this.trait.splice(start, deleteCount, new Array(elements.length).fill(false)); } const pastElementsWithTrait = this.trait.get().map(i => this.identityProvider!.getId(this.view.element(i)).toString()); - const elementsWithTrait = elements.map(e => pastElementsWithTrait.indexOf(this.identityProvider!.getId(e).toString()) > -1); + if (pastElementsWithTrait.length === 0) { + return this.trait.splice(start, deleteCount, new Array(elements.length).fill(false)); + } + const pastElementsWithTraitSet = new Set(pastElementsWithTrait); + const elementsWithTrait = elements.map(e => pastElementsWithTraitSet.has(this.identityProvider!.getId(e).toString())); this.trait.splice(start, deleteCount, elementsWithTrait); } } From b13ff339fad2fa4e48630eba8a6a608022c995f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= Date: Mon, 12 Jun 2023 17:02:34 +0200 Subject: [PATCH 054/128] fix: remove side effect from `some` callback --- .../workbench/api/common/extHostTerminalService.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index 07f2364ffed..04b61d8b808 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -816,15 +816,12 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I } private _getTerminalObjectIndexById(array: T[], id: ExtHostTerminalIdentifier): number | null { - let index: number | null = null; - array.some((item, i) => { - const thisId = item._id; - if (thisId === id) { - index = i; - return true; - } - return false; + const index = array.findIndex(item => { + return item._id === id; }); + if (index === -1) { + return null; + } return index; } From 8e39fc64bbee6fd4800236d1e94659e2dfe410fb Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Mon, 12 Jun 2023 17:46:33 +0200 Subject: [PATCH 055/128] removing the update of the session edit mode --- .../contrib/inlineChat/browser/inlineChatController.ts | 1 - .../workbench/contrib/inlineChat/browser/inlineChatSession.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index bb00fe80b98..47073adfb81 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -239,7 +239,6 @@ export class InlineChatController implements IEditorContribution { return State.CANCEL; } - session.editMode = this._getMode(); switch (session.editMode) { case EditMode.Live: this._strategy = this._instaService.createInstance(LiveStrategy, session, this._editor, this._zone.value.widget); diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts index 8128705aba4..3cdff58823c 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts @@ -120,7 +120,7 @@ export class Session { private _textModelNSnapshotAltVersion: number | undefined; constructor( - public editMode: EditMode, + readonly editMode: EditMode, readonly editor: ICodeEditor, readonly textModel0: ITextModel, readonly textModelN: ITextModel, From b4dd4d51fa90b07089b5438696b149ec3a6dcb9e Mon Sep 17 00:00:00 2001 From: Robo Date: Tue, 13 Jun 2023 00:50:36 +0900 Subject: [PATCH 056/128] ci: switch to bionic agents for arm64 and armhf clients (#184906) * ci: switch to bionic agents for arm64 and armhf clients * ci: invalidate cache * ci: fix docker client installation * chore: update debian dependencies * chore: update rpm dependencies --- build/.cachesalt | 2 +- build/azure-pipelines/linux/product-build-linux.yml | 10 ++-------- build/azure-pipelines/product-build.yml | 4 ++-- build/linux/debian/dep-lists.js | 12 +++++------- build/linux/debian/dep-lists.ts | 10 ++++------ build/linux/rpm/dep-lists.js | 4 +--- build/linux/rpm/dep-lists.ts | 2 -- 7 files changed, 15 insertions(+), 29 deletions(-) diff --git a/build/.cachesalt b/build/.cachesalt index e41ee49d6db..d63bdc31189 100644 --- a/build/.cachesalt +++ b/build/.cachesalt @@ -1 +1 @@ -2023-03-31T12:39:03.753Z +2023-06-12T12:55:48.130Z diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index a3c47d8e15e..38522b2d00e 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -86,16 +86,10 @@ steps: # TODO@joaomoreno TODO@deepak1556 this should be part of the base image - ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}: - script: | - if [ "$VSCODE_ARCH" = "x64" ]; then - OS=ubuntu - else - OS=debian - fi - sudo apt-get update && sudo apt-get install -y ca-certificates curl gnupg sudo mkdir -m 0755 -p /etc/apt/keyrings - curl -fsSL https://download.docker.com/linux/$OS/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg - echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/$OS "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg + echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt update && sudo apt install -y docker-ce-cli displayName: Install Docker client condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true')) diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index 235e1656209..28d1130c02d 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -144,11 +144,11 @@ resources: endpoint: VSCodeHub options: --user 0:0 --cap-add SYS_ADMIN - container: vscode-arm64 - image: vscodehub.azurecr.io/vscode-linux-build-agent:buster-arm64 + image: vscodehub.azurecr.io/vscode-linux-build-agent:bionic-arm64 endpoint: VSCodeHub options: --user 0:0 --cap-add SYS_ADMIN - container: vscode-armhf - image: vscodehub.azurecr.io/vscode-linux-build-agent:buster-armhf + image: vscodehub.azurecr.io/vscode-linux-build-agent:bionic-armhf endpoint: VSCodeHub options: --user 0:0 --cap-add SYS_ADMIN - container: snapcraft diff --git a/build/linux/debian/dep-lists.js b/build/linux/debian/dep-lists.js index 498fb4ea6ed..2444e401703 100644 --- a/build/linux/debian/dep-lists.js +++ b/build/linux/debian/dep-lists.js @@ -63,9 +63,10 @@ exports.referenceGeneratedDepsByArch = { 'libatk-bridge2.0-0 (>= 2.5.3)', 'libatk1.0-0 (>= 2.2.0)', 'libatspi2.0-0 (>= 2.9.90)', + 'libc6 (>= 2.15)', 'libc6 (>= 2.17)', - 'libc6 (>= 2.28)', 'libc6 (>= 2.4)', + 'libc6 (>= 2.8)', 'libc6 (>= 2.9)', 'libcairo2 (>= 1.6.0)', 'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3', @@ -73,7 +74,7 @@ exports.referenceGeneratedDepsByArch = { 'libdrm2 (>= 2.4.60)', 'libexpat1 (>= 2.0.1)', 'libgbm1 (>= 17.1.0~rc2)', - 'libglib2.0-0 (>= 2.16.0)', + 'libglib2.0-0 (>= 2.12.0)', 'libglib2.0-0 (>= 2.39.4)', 'libgtk-3-0 (>= 3.9.10)', 'libgtk-3-0 (>= 3.9.10) | libgtk-4-1', @@ -82,7 +83,6 @@ exports.referenceGeneratedDepsByArch = { 'libnss3 (>= 3.26)', 'libpango-1.0-0 (>= 1.14.0)', 'libsecret-1-0 (>= 0.18)', - 'libstdc++6 (>= 4.1.1)', 'libstdc++6 (>= 5)', 'libstdc++6 (>= 5.2)', 'libstdc++6 (>= 6)', @@ -105,14 +105,13 @@ exports.referenceGeneratedDepsByArch = { 'libatk1.0-0 (>= 2.2.0)', 'libatspi2.0-0 (>= 2.9.90)', 'libc6 (>= 2.17)', - 'libc6 (>= 2.28)', 'libcairo2 (>= 1.6.0)', 'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3', 'libdbus-1-3 (>= 1.0.2)', 'libdrm2 (>= 2.4.60)', 'libexpat1 (>= 2.0.1)', 'libgbm1 (>= 17.1.0~rc2)', - 'libglib2.0-0 (>= 2.16.0)', + 'libglib2.0-0 (>= 2.12.0)', 'libglib2.0-0 (>= 2.39.4)', 'libgtk-3-0 (>= 3.9.10)', 'libgtk-3-0 (>= 3.9.10) | libgtk-4-1', @@ -121,7 +120,6 @@ exports.referenceGeneratedDepsByArch = { 'libnss3 (>= 3.26)', 'libpango-1.0-0 (>= 1.14.0)', 'libsecret-1-0 (>= 0.18)', - 'libstdc++6 (>= 4.1.1)', 'libstdc++6 (>= 5)', 'libstdc++6 (>= 5.2)', 'libstdc++6 (>= 6)', @@ -138,4 +136,4 @@ exports.referenceGeneratedDepsByArch = { 'xdg-utils (>= 1.0.2)' ] }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwLWxpc3RzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZGVwLWxpc3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7O0FBRWhHLGtIQUFrSDtBQUNsSCw0REFBNEQ7QUFDL0MsUUFBQSxjQUFjLEdBQUc7SUFDN0IsaUJBQWlCO0lBQ2pCLHFDQUFxQztJQUNyQyxtQkFBbUI7SUFDbkIsc0RBQXNEO0lBQ3RELHNCQUFzQixDQUFDLGlCQUFpQjtDQUN4QyxDQUFDO0FBRUYsb0hBQW9IO0FBQ3BILDBDQUEwQztBQUMxQyw4REFBOEQ7QUFDakQsUUFBQSxlQUFlLEdBQUc7SUFDOUIsWUFBWSxDQUFDLHlFQUF5RTtDQUN0RixDQUFDO0FBRVcsUUFBQSw0QkFBNEIsR0FBRztJQUMzQyxPQUFPLEVBQUU7UUFDUixpQkFBaUI7UUFDakIsd0JBQXdCO1FBQ3hCLCtCQUErQjtRQUMvQix3QkFBd0I7UUFDeEIsMkJBQTJCO1FBQzNCLGlCQUFpQjtRQUNqQixpQkFBaUI7UUFDakIsa0JBQWtCO1FBQ2xCLHNCQUFzQjtRQUN0QixzREFBc0Q7UUFDdEQseUJBQXlCO1FBQ3pCLHFCQUFxQjtRQUNyQixzQkFBc0I7UUFDdEIseUJBQXlCO1FBQ3pCLDBCQUEwQjtRQUMxQiwwQkFBMEI7UUFDMUIsd0JBQXdCO1FBQ3hCLHFDQUFxQztRQUNyQyx3QkFBd0I7UUFDeEIscUJBQXFCO1FBQ3JCLG1CQUFtQjtRQUNuQiw0QkFBNEI7UUFDNUIseUJBQXlCO1FBQ3pCLFVBQVU7UUFDViwwQkFBMEI7UUFDMUIsb0JBQW9CO1FBQ3BCLCtCQUErQjtRQUMvQix3QkFBd0I7UUFDeEIsVUFBVTtRQUNWLFlBQVk7UUFDWiwwQkFBMEI7UUFDMUIsYUFBYTtRQUNiLFlBQVk7UUFDWixzQkFBc0I7S0FDdEI7SUFDRCxPQUFPLEVBQUU7UUFDUixpQkFBaUI7UUFDakIsd0JBQXdCO1FBQ3hCLCtCQUErQjtRQUMvQix3QkFBd0I7UUFDeEIsMkJBQTJCO1FBQzNCLGlCQUFpQjtRQUNqQixpQkFBaUI7UUFDakIsZ0JBQWdCO1FBQ2hCLGdCQUFnQjtRQUNoQixzQkFBc0I7UUFDdEIsc0RBQXNEO1FBQ3RELHlCQUF5QjtRQUN6QixxQkFBcUI7UUFDckIsc0JBQXNCO1FBQ3RCLHlCQUF5QjtRQUN6QiwwQkFBMEI7UUFDMUIsMEJBQTBCO1FBQzFCLHdCQUF3QjtRQUN4QixxQ0FBcUM7UUFDckMsd0JBQXdCO1FBQ3hCLHFCQUFxQjtRQUNyQixtQkFBbUI7UUFDbkIsNEJBQTRCO1FBQzVCLHlCQUF5QjtRQUN6Qix1QkFBdUI7UUFDdkIsbUJBQW1CO1FBQ25CLHFCQUFxQjtRQUNyQixtQkFBbUI7UUFDbkIsVUFBVTtRQUNWLDBCQUEwQjtRQUMxQixvQkFBb0I7UUFDcEIsK0JBQStCO1FBQy9CLHdCQUF3QjtRQUN4QixVQUFVO1FBQ1YsWUFBWTtRQUNaLDBCQUEwQjtRQUMxQixhQUFhO1FBQ2IsWUFBWTtRQUNaLHNCQUFzQjtLQUN0QjtJQUNELE9BQU8sRUFBRTtRQUNSLGlCQUFpQjtRQUNqQix3QkFBd0I7UUFDeEIsK0JBQStCO1FBQy9CLHdCQUF3QjtRQUN4QiwyQkFBMkI7UUFDM0IsaUJBQWlCO1FBQ2pCLGlCQUFpQjtRQUNqQixzQkFBc0I7UUFDdEIsc0RBQXNEO1FBQ3RELHdCQUF3QjtRQUN4QixxQkFBcUI7UUFDckIsc0JBQXNCO1FBQ3RCLHlCQUF5QjtRQUN6QiwwQkFBMEI7UUFDMUIsMEJBQTBCO1FBQzFCLHdCQUF3QjtRQUN4QixxQ0FBcUM7UUFDckMsd0JBQXdCO1FBQ3hCLHFCQUFxQjtRQUNyQixtQkFBbUI7UUFDbkIsNEJBQTRCO1FBQzVCLHlCQUF5QjtRQUN6Qix1QkFBdUI7UUFDdkIsbUJBQW1CO1FBQ25CLHFCQUFxQjtRQUNyQixtQkFBbUI7UUFDbkIsVUFBVTtRQUNWLDBCQUEwQjtRQUMxQixvQkFBb0I7UUFDcEIsK0JBQStCO1FBQy9CLHdCQUF3QjtRQUN4QixVQUFVO1FBQ1YsWUFBWTtRQUNaLDBCQUEwQjtRQUMxQixhQUFhO1FBQ2IsWUFBWTtRQUNaLHNCQUFzQjtLQUN0QjtDQUNELENBQUMifQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwLWxpc3RzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZGVwLWxpc3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7O0FBRWhHLGtIQUFrSDtBQUNsSCw0REFBNEQ7QUFDL0MsUUFBQSxjQUFjLEdBQUc7SUFDN0IsaUJBQWlCO0lBQ2pCLHFDQUFxQztJQUNyQyxtQkFBbUI7SUFDbkIsc0RBQXNEO0lBQ3RELHNCQUFzQixDQUFDLGlCQUFpQjtDQUN4QyxDQUFDO0FBRUYsb0hBQW9IO0FBQ3BILDBDQUEwQztBQUMxQyw4REFBOEQ7QUFDakQsUUFBQSxlQUFlLEdBQUc7SUFDOUIsWUFBWSxDQUFDLHlFQUF5RTtDQUN0RixDQUFDO0FBRVcsUUFBQSw0QkFBNEIsR0FBRztJQUMzQyxPQUFPLEVBQUU7UUFDUixpQkFBaUI7UUFDakIsd0JBQXdCO1FBQ3hCLCtCQUErQjtRQUMvQix3QkFBd0I7UUFDeEIsMkJBQTJCO1FBQzNCLGlCQUFpQjtRQUNqQixpQkFBaUI7UUFDakIsa0JBQWtCO1FBQ2xCLHNCQUFzQjtRQUN0QixzREFBc0Q7UUFDdEQseUJBQXlCO1FBQ3pCLHFCQUFxQjtRQUNyQixzQkFBc0I7UUFDdEIseUJBQXlCO1FBQ3pCLDBCQUEwQjtRQUMxQiwwQkFBMEI7UUFDMUIsd0JBQXdCO1FBQ3hCLHFDQUFxQztRQUNyQyx3QkFBd0I7UUFDeEIscUJBQXFCO1FBQ3JCLG1CQUFtQjtRQUNuQiw0QkFBNEI7UUFDNUIseUJBQXlCO1FBQ3pCLFVBQVU7UUFDViwwQkFBMEI7UUFDMUIsb0JBQW9CO1FBQ3BCLCtCQUErQjtRQUMvQix3QkFBd0I7UUFDeEIsVUFBVTtRQUNWLFlBQVk7UUFDWiwwQkFBMEI7UUFDMUIsYUFBYTtRQUNiLFlBQVk7UUFDWixzQkFBc0I7S0FDdEI7SUFDRCxPQUFPLEVBQUU7UUFDUixpQkFBaUI7UUFDakIsd0JBQXdCO1FBQ3hCLCtCQUErQjtRQUMvQix3QkFBd0I7UUFDeEIsMkJBQTJCO1FBQzNCLGlCQUFpQjtRQUNqQixpQkFBaUI7UUFDakIsZ0JBQWdCO1FBQ2hCLGdCQUFnQjtRQUNoQixnQkFBZ0I7UUFDaEIsc0JBQXNCO1FBQ3RCLHNEQUFzRDtRQUN0RCx5QkFBeUI7UUFDekIscUJBQXFCO1FBQ3JCLHNCQUFzQjtRQUN0Qix5QkFBeUI7UUFDekIsMEJBQTBCO1FBQzFCLDBCQUEwQjtRQUMxQix3QkFBd0I7UUFDeEIscUNBQXFDO1FBQ3JDLHdCQUF3QjtRQUN4QixxQkFBcUI7UUFDckIsbUJBQW1CO1FBQ25CLDRCQUE0QjtRQUM1Qix5QkFBeUI7UUFDekIsbUJBQW1CO1FBQ25CLHFCQUFxQjtRQUNyQixtQkFBbUI7UUFDbkIsVUFBVTtRQUNWLDBCQUEwQjtRQUMxQixvQkFBb0I7UUFDcEIsK0JBQStCO1FBQy9CLHdCQUF3QjtRQUN4QixVQUFVO1FBQ1YsWUFBWTtRQUNaLDBCQUEwQjtRQUMxQixhQUFhO1FBQ2IsWUFBWTtRQUNaLHNCQUFzQjtLQUN0QjtJQUNELE9BQU8sRUFBRTtRQUNSLGlCQUFpQjtRQUNqQix3QkFBd0I7UUFDeEIsK0JBQStCO1FBQy9CLHdCQUF3QjtRQUN4QiwyQkFBMkI7UUFDM0IsaUJBQWlCO1FBQ2pCLHNCQUFzQjtRQUN0QixzREFBc0Q7UUFDdEQsd0JBQXdCO1FBQ3hCLHFCQUFxQjtRQUNyQixzQkFBc0I7UUFDdEIseUJBQXlCO1FBQ3pCLDBCQUEwQjtRQUMxQiwwQkFBMEI7UUFDMUIsd0JBQXdCO1FBQ3hCLHFDQUFxQztRQUNyQyx3QkFBd0I7UUFDeEIscUJBQXFCO1FBQ3JCLG1CQUFtQjtRQUNuQiw0QkFBNEI7UUFDNUIseUJBQXlCO1FBQ3pCLG1CQUFtQjtRQUNuQixxQkFBcUI7UUFDckIsbUJBQW1CO1FBQ25CLFVBQVU7UUFDViwwQkFBMEI7UUFDMUIsb0JBQW9CO1FBQ3BCLCtCQUErQjtRQUMvQix3QkFBd0I7UUFDeEIsVUFBVTtRQUNWLFlBQVk7UUFDWiwwQkFBMEI7UUFDMUIsYUFBYTtRQUNiLFlBQVk7UUFDWixzQkFBc0I7S0FDdEI7Q0FDRCxDQUFDIn0= \ No newline at end of file diff --git a/build/linux/debian/dep-lists.ts b/build/linux/debian/dep-lists.ts index 52aa56d960b..7f6cd6ca8cc 100644 --- a/build/linux/debian/dep-lists.ts +++ b/build/linux/debian/dep-lists.ts @@ -63,9 +63,10 @@ export const referenceGeneratedDepsByArch = { 'libatk-bridge2.0-0 (>= 2.5.3)', 'libatk1.0-0 (>= 2.2.0)', 'libatspi2.0-0 (>= 2.9.90)', + 'libc6 (>= 2.15)', 'libc6 (>= 2.17)', - 'libc6 (>= 2.28)', 'libc6 (>= 2.4)', + 'libc6 (>= 2.8)', 'libc6 (>= 2.9)', 'libcairo2 (>= 1.6.0)', 'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3', @@ -73,7 +74,7 @@ export const referenceGeneratedDepsByArch = { 'libdrm2 (>= 2.4.60)', 'libexpat1 (>= 2.0.1)', 'libgbm1 (>= 17.1.0~rc2)', - 'libglib2.0-0 (>= 2.16.0)', + 'libglib2.0-0 (>= 2.12.0)', 'libglib2.0-0 (>= 2.39.4)', 'libgtk-3-0 (>= 3.9.10)', 'libgtk-3-0 (>= 3.9.10) | libgtk-4-1', @@ -82,7 +83,6 @@ export const referenceGeneratedDepsByArch = { 'libnss3 (>= 3.26)', 'libpango-1.0-0 (>= 1.14.0)', 'libsecret-1-0 (>= 0.18)', - 'libstdc++6 (>= 4.1.1)', 'libstdc++6 (>= 5)', 'libstdc++6 (>= 5.2)', 'libstdc++6 (>= 6)', @@ -105,14 +105,13 @@ export const referenceGeneratedDepsByArch = { 'libatk1.0-0 (>= 2.2.0)', 'libatspi2.0-0 (>= 2.9.90)', 'libc6 (>= 2.17)', - 'libc6 (>= 2.28)', 'libcairo2 (>= 1.6.0)', 'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3', 'libdbus-1-3 (>= 1.0.2)', 'libdrm2 (>= 2.4.60)', 'libexpat1 (>= 2.0.1)', 'libgbm1 (>= 17.1.0~rc2)', - 'libglib2.0-0 (>= 2.16.0)', + 'libglib2.0-0 (>= 2.12.0)', 'libglib2.0-0 (>= 2.39.4)', 'libgtk-3-0 (>= 3.9.10)', 'libgtk-3-0 (>= 3.9.10) | libgtk-4-1', @@ -121,7 +120,6 @@ export const referenceGeneratedDepsByArch = { 'libnss3 (>= 3.26)', 'libpango-1.0-0 (>= 1.14.0)', 'libsecret-1-0 (>= 0.18)', - 'libstdc++6 (>= 4.1.1)', 'libstdc++6 (>= 5)', 'libstdc++6 (>= 5.2)', 'libstdc++6 (>= 6)', diff --git a/build/linux/rpm/dep-lists.js b/build/linux/rpm/dep-lists.js index 1c9177c1671..c836348ef51 100644 --- a/build/linux/rpm/dep-lists.js +++ b/build/linux/rpm/dep-lists.js @@ -127,7 +127,6 @@ exports.referenceGeneratedDepsByArch = { 'libc.so.6(GLIBC_2.16)', 'libc.so.6(GLIBC_2.17)', 'libc.so.6(GLIBC_2.25)', - 'libc.so.6(GLIBC_2.28)', 'libc.so.6(GLIBC_2.4)', 'libc.so.6(GLIBC_2.6)', 'libc.so.6(GLIBC_2.7)', @@ -221,7 +220,6 @@ exports.referenceGeneratedDepsByArch = { 'libc.so.6()(64bit)', 'libc.so.6(GLIBC_2.17)(64bit)', 'libc.so.6(GLIBC_2.25)(64bit)', - 'libc.so.6(GLIBC_2.28)(64bit)', 'libcairo.so.2()(64bit)', 'libcurl.so.4()(64bit)', 'libdbus-1.so.3()(64bit)', @@ -291,4 +289,4 @@ exports.referenceGeneratedDepsByArch = { 'xdg-utils' ] }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwLWxpc3RzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZGVwLWxpc3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7O0FBRWhHLCtHQUErRztBQUMvRywrREFBK0Q7QUFDbEQsUUFBQSxjQUFjLEdBQUc7SUFDN0IsaUJBQWlCO0lBQ2pCLHdCQUF3QjtJQUN4Qiw2QkFBNkI7SUFDN0IsNkJBQTZCO0lBQzdCLGdDQUFnQztJQUNoQyx5QkFBeUI7SUFDekIsdUJBQXVCO0lBQ3ZCLFdBQVcsQ0FBQyxpQkFBaUI7Q0FDN0IsQ0FBQztBQUVXLFFBQUEsNEJBQTRCLEdBQUc7SUFDM0MsUUFBUSxFQUFFO1FBQ1QsaUJBQWlCO1FBQ2pCLCtCQUErQjtRQUMvQiwwQ0FBMEM7UUFDMUMsd0NBQXdDO1FBQ3hDLHNCQUFzQjtRQUN0Qiw2QkFBNkI7UUFDN0IsMEJBQTBCO1FBQzFCLHVCQUF1QjtRQUN2Qix5QkFBeUI7UUFDekIseUJBQXlCO1FBQ3pCLHlCQUF5QjtRQUN6QixpQ0FBaUM7UUFDakMsc0NBQXNDO1FBQ3RDLDBCQUEwQjtRQUMxQixpQ0FBaUM7UUFDakMsd0JBQXdCO1FBQ3hCLG9CQUFvQjtRQUNwQiw4QkFBOEI7UUFDOUIsOEJBQThCO1FBQzlCLDhCQUE4QjtRQUM5Qiw4QkFBOEI7UUFDOUIsOEJBQThCO1FBQzlCLDhCQUE4QjtRQUM5QiwrQkFBK0I7UUFDL0IsNkJBQTZCO1FBQzdCLCtCQUErQjtRQUMvQiwrQkFBK0I7UUFDL0IsK0JBQStCO1FBQy9CLDZCQUE2QjtRQUM3Qiw2QkFBNkI7UUFDN0IsNkJBQTZCO1FBQzdCLDZCQUE2QjtRQUM3Qiw2QkFBNkI7UUFDN0Isd0JBQXdCO1FBQ3hCLHVCQUF1QjtRQUN2Qix5QkFBeUI7UUFDekIscUJBQXFCO1FBQ3JCLGdDQUFnQztRQUNoQyxzQkFBc0I7UUFDdEIsd0JBQXdCO1FBQ3hCLHNCQUFzQjtRQUN0Qix3QkFBd0I7UUFDeEIsK0JBQStCO1FBQy9CLDBCQUEwQjtR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 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwLWxpc3RzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZGVwLWxpc3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7O0FBRWhHLCtHQUErRztBQUMvRywrREFBK0Q7QUFDbEQsUUFBQSxjQUFjLEdBQUc7SUFDN0IsaUJBQWlCO0lBQ2pCLHdCQUF3QjtJQUN4Qiw2QkFBNkI7SUFDN0IsNkJBQTZCO0lBQzdCLGdDQUFnQztJQUNoQyx5QkFBeUI7SUFDekIsdUJBQXVCO0lBQ3ZCLFdBQVcsQ0FBQyxpQkFBaUI7Q0FDN0IsQ0FBQztBQUVXLFFBQUEsNEJBQTRCLEdBQUc7SUFDM0MsUUFBUSxFQUFFO1FBQ1QsaUJBQWlCO1FBQ2pCLCtCQUErQjtRQUMvQiwwQ0FBMEM7UUFDMUMsd0NBQXdDO1FBQ3hDLHNCQUFzQjtRQUN0Qiw2QkFBNkI7UUFDN0IsMEJBQTBCO1FBQzFCLHVCQUF1QjtRQUN2Qix5QkFBeUI7UUFDekIseUJBQXlCO1FBQ3pCLHlCQUF5QjtRQUN6QixpQ0FBaUM7UUFDakMsc0NBQXNDO1FBQ3RDLDBCQUEwQjtRQUMxQixpQ0FBaUM7UUFDakMsd0JBQXdCO1FBQ3hCLG9CQUFvQjtRQUNwQiw4QkFBOEI7UUFDOUIsOEJBQThCO1FBQzlCLDhCQUE4QjtRQUM5Qiw4QkFBOEI7UUFDOUIsOEJBQThCO1FBQzlCLDhCQUE4QjtRQUM5QiwrQkFBK0I7UUFDL0IsNkJBQTZCO1FBQzdCLCtCQUErQjtRQUMvQiwrQkFBK0I7UUFDL0IsK0JBQStCO1FBQy9CLDZCQUE2QjtRQUM3Qiw2QkFBNkI7UUFDN0IsNkJBQTZCO1FBQzdCLDZCQUE2QjtRQUM3Qiw2QkFBNkI7UUFDN0Isd0JBQXdCO1FBQ3hCLHVCQUF1QjtRQUN2Qix5QkFBeUI7UUFDekIscUJBQXFCO1FBQ3JCLGdDQUFnQztRQUNoQyxzQkFBc0I7UUFDdEIsd0JBQXdCO1FBQ3hCLHNCQUFzQjtRQUN0Qix3QkFBd0I7UUFDeEIsK0JBQStCO1FBQy9CLDBCQUEwQjtR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 \ No newline at end of file diff --git a/build/linux/rpm/dep-lists.ts b/build/linux/rpm/dep-lists.ts index ad7c2db4f4a..c262448c318 100644 --- a/build/linux/rpm/dep-lists.ts +++ b/build/linux/rpm/dep-lists.ts @@ -126,7 +126,6 @@ export const referenceGeneratedDepsByArch = { 'libc.so.6(GLIBC_2.16)', 'libc.so.6(GLIBC_2.17)', 'libc.so.6(GLIBC_2.25)', - 'libc.so.6(GLIBC_2.28)', 'libc.so.6(GLIBC_2.4)', 'libc.so.6(GLIBC_2.6)', 'libc.so.6(GLIBC_2.7)', @@ -220,7 +219,6 @@ export const referenceGeneratedDepsByArch = { 'libc.so.6()(64bit)', 'libc.so.6(GLIBC_2.17)(64bit)', 'libc.so.6(GLIBC_2.25)(64bit)', - 'libc.so.6(GLIBC_2.28)(64bit)', 'libcairo.so.2()(64bit)', 'libcurl.so.4()(64bit)', 'libdbus-1.so.3()(64bit)', From 4a3fb62cccdf591cd9bac05cc32ce819bec6b055 Mon Sep 17 00:00:00 2001 From: Jean Pierre Date: Mon, 12 Jun 2023 11:16:43 -0500 Subject: [PATCH 057/128] Fix #184921 --- .../terminal/browser/xterm/xtermTerminal.ts | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts index 650a3db9d72..c6f4d4ea87f 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts @@ -404,18 +404,20 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal, II }; } - private async _getSearchAddon(): Promise { - if (this._searchAddon) { - return this._searchAddon; + private _searchAddonPromise: Promise | undefined; + private _getSearchAddon(): Promise { + if (!this._searchAddonPromise) { + this._searchAddonPromise = this._getSearchAddonConstructor().then((AddonCtor) => { + this._searchAddon = new AddonCtor({ highlightLimit: XtermTerminalConstants.SearchHighlightLimit }); + this.raw.loadAddon(this._searchAddon); + this._searchAddon.onDidChangeResults((results: { resultIndex: number; resultCount: number }) => { + this._lastFindResult = results; + this._onDidChangeFindResults.fire(results); + }); + return this._searchAddon; + }); } - const AddonCtor = await this._getSearchAddonConstructor(); - this._searchAddon = new AddonCtor({ highlightLimit: XtermTerminalConstants.SearchHighlightLimit }); - this.raw.loadAddon(this._searchAddon); - this._searchAddon.onDidChangeResults((results: { resultIndex: number; resultCount: number }) => { - this._lastFindResult = results; - this._onDidChangeFindResults.fire(results); - }); - return this._searchAddon; + return this._searchAddonPromise; } clearSearchDecorations(): void { From c9c3321afc2d624ad7e8ff213f4bd072e3ac0dc5 Mon Sep 17 00:00:00 2001 From: Bhavya U Date: Mon, 12 Jun 2023 10:07:44 -0700 Subject: [PATCH 058/128] Simplify welcome widget (#184876) --- .../browser/media/welcomeWidget.css | 9 +- .../browser/welcomeDialog.contribution.ts | 9 +- .../welcomeDialog/browser/welcomeWidget.ts | 111 ++++++++---------- 3 files changed, 56 insertions(+), 73 deletions(-) diff --git a/src/vs/workbench/contrib/welcomeDialog/browser/media/welcomeWidget.css b/src/vs/workbench/contrib/welcomeDialog/browser/media/welcomeWidget.css index 1537528a1e9..79dade268d9 100644 --- a/src/vs/workbench/contrib/welcomeDialog/browser/media/welcomeWidget.css +++ b/src/vs/workbench/contrib/welcomeDialog/browser/media/welcomeWidget.css @@ -6,14 +6,15 @@ border-radius: 6px; } -.welcome-widget { - height: min-content; - border-radius: 6px; +.dialog-message-detail-title > div > p > .codicon[class*='codicon-']::before{ + position: relative; + color: var(--vscode-textLink-foreground); + padding-right: 10px; + font-size: larger; } .dialog-message-detail-title { height: 22px; - padding-bottom: 4px; font-size: large; } diff --git a/src/vs/workbench/contrib/welcomeDialog/browser/welcomeDialog.contribution.ts b/src/vs/workbench/contrib/welcomeDialog/browser/welcomeDialog.contribution.ts index c136c0fbbad..e5286635bb5 100644 --- a/src/vs/workbench/contrib/welcomeDialog/browser/welcomeDialog.contribution.ts +++ b/src/vs/workbench/contrib/welcomeDialog/browser/welcomeDialog.contribution.ts @@ -23,7 +23,6 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { LanguageService } from 'vs/editor/common/services/languageService'; import { ILanguageService } from 'vs/editor/common/languages/language'; -import { GettingStartedDetailsRenderer } from 'vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedDetailsRenderer'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { localize } from 'vs/nls'; import { applicationConfigurationNodeBase } from 'vs/workbench/common/configuration'; @@ -77,22 +76,18 @@ class WelcomeDialogContribution extends Disposable implements IWorkbenchContribu const scheduler = new RunOnceScheduler(() => { if (codeEditor === codeEditorService.getActiveCodeEditor()) { this.isRendered = true; - const detailsRenderer = new GettingStartedDetailsRenderer(fileService, notificationService, extensionService, languageService); const welcomeWidget = new WelcomeWidget( codeEditor, instantiationService, commandService, telemetryService, - openerService, - webviewService, - detailsRenderer); + openerService); welcomeWidget.render(welcomeDialog.title, welcomeDialog.message, welcomeDialog.buttonText, - welcomeDialog.buttonCommand, - welcomeDialog.media); + welcomeDialog.buttonCommand); } }, 3000); diff --git a/src/vs/workbench/contrib/welcomeDialog/browser/welcomeWidget.ts b/src/vs/workbench/contrib/welcomeDialog/browser/welcomeWidget.ts index 54d76842f36..38ef2e32529 100644 --- a/src/vs/workbench/contrib/welcomeDialog/browser/welcomeWidget.ts +++ b/src/vs/workbench/contrib/welcomeDialog/browser/welcomeWidget.ts @@ -6,14 +6,14 @@ import 'vs/css!./media/welcomeWidget'; import { Disposable } from 'vs/base/common/lifecycle'; import { ICodeEditor, IOverlayWidget, IOverlayWidgetPosition, OverlayWidgetPositionPreference } from 'vs/editor/browser/editorBrowser'; -import { $, append, hide } from 'vs/base/browser/dom'; import { RunOnceScheduler } from 'vs/base/common/async'; +import { $, append, hide } from 'vs/base/browser/dom'; import { MarkdownString } from 'vs/base/common/htmlContent'; import { MarkdownRenderer } from 'vs/editor/contrib/markdownRenderer/browser/markdownRenderer'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ButtonBar } from 'vs/base/browser/ui/button/button'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { defaultButtonStyles, defaultDialogStyles } from 'vs/platform/theme/browser/defaultStyles'; +import { defaultButtonStyles } from 'vs/platform/theme/browser/defaultStyles'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { Action, WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from 'vs/base/common/actions'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; @@ -25,16 +25,12 @@ import { Link } from 'vs/platform/opener/browser/link'; import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels'; import { renderFormattedText } from 'vs/base/browser/formattedTextRenderer'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { generateUuid } from 'vs/base/common/uuid'; -import { GettingStartedDetailsRenderer } from 'vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedDetailsRenderer'; -import { FileAccess } from 'vs/base/common/network'; -import { IWebviewService } from 'vs/workbench/contrib/webview/browser/webview'; +import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { Color } from 'vs/base/common/color'; +import { contrastBorder, editorWidgetBackground, editorWidgetForeground, widgetBorder, widgetShadow } from 'vs/platform/theme/common/colorRegistry'; export class WelcomeWidget extends Disposable implements IOverlayWidget { - private static readonly WIDGET_TIMEOUT: number = 15000; - private static readonly WELCOME_MEDIA_PATH = 'vs/workbench/contrib/welcomeGettingStarted/common/media/'; - private readonly _rootDomNode: HTMLElement; private readonly element: HTMLElement; private readonly messageContainer: HTMLElement; @@ -45,9 +41,7 @@ export class WelcomeWidget extends Disposable implements IOverlayWidget { private readonly instantiationService: IInstantiationService, private readonly commandService: ICommandService, private readonly telemetryService: ITelemetryService, - private readonly openerService: IOpenerService, - private readonly webviewService: IWebviewService, - private readonly detailsRenderer: GettingStartedDetailsRenderer + private readonly openerService: IOpenerService ) { super(); this._rootDomNode = document.createElement('div'); @@ -64,7 +58,6 @@ export class WelcomeWidget extends Disposable implements IOverlayWidget { async executeCommand(commandId: string, ...args: string[]) { try { await this.commandService.executeCommand(commandId, ...args); - this._hide(false); this.telemetryService.publicLog2('workbenchActionExecuted', { id: commandId, from: 'welcomeWidget' @@ -74,41 +67,38 @@ export class WelcomeWidget extends Disposable implements IOverlayWidget { } } - public async render(title: string, message: string, buttonText: string, buttonAction: string, media: { altText: string; path: string }) { + public async render(title: string, message: string, buttonText: string, buttonAction: string) { if (!this._editor._getViewModel()) { return; } - await this.buildWidgetContent(title, message, buttonText, buttonAction, media); + await this.buildWidgetContent(title, message, buttonText, buttonAction); this._editor.addOverlayWidget(this); - this._revealTemporarily(); + this._show(); this.telemetryService.publicLog2('workbenchActionExecuted', { id: 'welcomeWidgetRendered', from: 'welcomeWidget' }); } - private async buildWidgetContent(title: string, message: string, buttonText: string, buttonAction: string, media: { altText: string; path: string }) { + private async buildWidgetContent(title: string, message: string, buttonText: string, buttonAction: string) { const actionBar = this._register(new ActionBar(this.element, {})); const action = this._register(new Action('dialog.close', localize('dialogClose', "Close Dialog"), ThemeIcon.asClassName(Codicon.dialogClose), true, async () => { - this._hide(true); + this._hide(); })); actionBar.push(action, { icon: true, label: false }); - if (media) { - await this.buildSVGMediaComponent(media.path); - } - - const renderBody = (message: string): MarkdownString => { - const mds = new MarkdownString(undefined, { supportHtml: true }); + const renderBody = (message: string, icon: string): MarkdownString => { + const mds = new MarkdownString(undefined, { supportThemeIcons: true, supportHtml: true }); + mds.appendMarkdown(`$(${icon})`); mds.appendMarkdown(message); return mds; }; const titleElement = this.messageContainer.appendChild($('#monaco-dialog-message-detail.dialog-message-detail-title')); - const titleElementMdt = this.markdownRenderer.render(renderBody(title)); + const titleElementMdt = this.markdownRenderer.render(renderBody(title, 'zap')); titleElement.appendChild(titleElementMdt.element); this.buildStepMarkdownDescription(this.messageContainer, message.split('\n').filter(x => x).map(text => parseLinkedText(text))); @@ -125,7 +115,6 @@ export class WelcomeWidget extends Disposable implements IOverlayWidget { })); buttonBar.buttons[0].focus(); - this.applyStyles(); } private buildStepMarkdownDescription(container: HTMLElement, text: LinkedText[]) { @@ -158,18 +147,6 @@ export class WelcomeWidget extends Disposable implements IOverlayWidget { return container; } - private async buildSVGMediaComponent(path: string) { - - const mediaContainer = this.messageContainer.appendChild($('.dialog-image-container')); - mediaContainer.id = generateUuid(); - - const webview = this._register(this.webviewService.createWebviewElement({ title: undefined, options: {}, contentOptions: {}, extension: undefined })); - webview.mountTo(mediaContainer); - - const body = await this.detailsRenderer.renderSVG(FileAccess.asFileUri(`${WelcomeWidget.WELCOME_MEDIA_PATH}${path}`)); - webview.setHtml(body); - } - getId(): string { return 'editor.contrib.welcomeWidget'; } @@ -184,14 +161,8 @@ export class WelcomeWidget extends Disposable implements IOverlayWidget { }; } - private _hideSoon = this._register(new RunOnceScheduler(() => this._hide(false), WelcomeWidget.WIDGET_TIMEOUT)); private _isVisible: boolean = false; - private _revealTemporarily(): void { - this._show(); - this._hideSoon.schedule(); - } - private _show(): void { if (this._isVisible) { return; @@ -200,32 +171,48 @@ export class WelcomeWidget extends Disposable implements IOverlayWidget { this._rootDomNode.style.display = 'block'; } - private _hide(isUserDismissed: boolean): void { + private _hide(): void { if (!this._isVisible) { return; } - this._isVisible = false; + this._isVisible = true; this._rootDomNode.style.display = 'none'; this._editor.removeOverlayWidget(this); this.telemetryService.publicLog2('workbenchActionExecuted', { - id: isUserDismissed ? 'welcomeWidgetDismissed' : 'welcomeWidgetHidden', + id: 'welcomeWidgetDismissed', from: 'welcomeWidget' }); } - - private applyStyles(): void { - const style = defaultDialogStyles; - - const fgColor = style.dialogForeground; - const bgColor = style.dialogBackground; - const shadowColor = style.dialogShadow ? `0 0px 8px ${style.dialogShadow}` : ''; - const border = style.dialogBorder ? `1px solid ${style.dialogBorder}` : ''; - - this._rootDomNode.style.boxShadow = shadowColor; - - this._rootDomNode.style.color = fgColor ?? ''; - this._rootDomNode.style.backgroundColor = bgColor ?? ''; - this._rootDomNode.style.border = border; - } } + +registerThemingParticipant((theme, collector) => { + const addBackgroundColorRule = (selector: string, color: Color | undefined): void => { + if (color) { + collector.addRule(`.monaco-editor ${selector} { background-color: ${color}; }`); + } + }; + + const widgetBackground = theme.getColor(editorWidgetBackground); + addBackgroundColorRule('.welcome-widget', widgetBackground); + + const widgetShadowColor = theme.getColor(widgetShadow); + if (widgetShadowColor) { + collector.addRule(`.welcome-widget { box-shadow: 0 0 8px 2px ${widgetShadowColor}; }`); + } + + const widgetBorderColor = theme.getColor(widgetBorder); + if (widgetBorderColor) { + collector.addRule(`.welcome-widget { border-left: 1px solid ${widgetBorderColor}; border-right: 1px solid ${widgetBorderColor}; border-bottom: 1px solid ${widgetBorderColor}; }`); + } + + const hcBorder = theme.getColor(contrastBorder); + if (hcBorder) { + collector.addRule(`.welcome-widget { border: 1px solid ${hcBorder}; }`); + } + + const foreground = theme.getColor(editorWidgetForeground); + if (foreground) { + collector.addRule(`.welcome-widget { color: ${foreground}; }`); + } +}); From 51f585634279bef5868efedf066d55ea54c75b93 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Mon, 12 Jun 2023 12:54:56 -0500 Subject: [PATCH 059/128] improve inline chat menu --- .../browser/actions/chatAccessibilityHelp.ts | 35 +++++++------------ 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts index 8deaffc1f27..d7fbd840751 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts @@ -10,14 +10,11 @@ import { withNullAsUndefined } from 'vs/base/common/types'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; import { IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { EditMode } from 'vs/workbench/contrib/inlineChat/common/inlineChat'; import { IAccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView'; import { InlineChatController } from 'vs/workbench/contrib/inlineChat/browser/inlineChatController'; -export function getAccessibilityHelpText(accessor: ServicesAccessor, type: 'chat' | 'inline', currentInput?: string): string { +export function getAccessibilityHelpText(accessor: ServicesAccessor, type: 'chat' | 'inline'): string { const keybindingService = accessor.get(IKeybindingService); - const configurationService = accessor.get(IConfigurationService); const content = []; if (type === 'chat') { content.push(localize('chat.overview', 'Chat responses will be announced as they come in. A response will indicate the number of code blocks, if any, and then the rest of the response.')); @@ -27,23 +24,16 @@ export function getAccessibilityHelpText(accessor: ServicesAccessor, type: 'chat content.push(descriptionForCommand('workbench.action.chat.nextCodeBlock', localize('workbench.action.chat.nextCodeBlock', 'The Chat: Next Code Block command ({0}) focuses the next code block within a response.'), localize('workbench.action.chat.nextCodeBlockNoKb', 'The Chat: Next Code Block command focuses the next code block within a response and is currently not triggerable by a keybinding.'), keybindingService)); content.push(descriptionForCommand('workbench.action.chat.clear', localize('workbench.action.chat.clear', 'The Chat Clear command ({0}) clears the request/response list.'), localize('workbench.action.chat.clearNoKb', 'The Chat Clear command clears the request/response list and is currently not triggerable by a keybinding.'), keybindingService)); } else { - content.push(localize('inlineChat.makeRequest', "Tab once to reach the make request button, which will re-run the request.")); - const regex = /^(\/fix|\/explain)/; - const match = currentInput?.match(regex); - const command = match && match.length ? match[0].substring(1) : undefined; - if (command === 'fix') { - const editMode = configurationService.getValue('inlineChat.mode'); - if (editMode === EditMode.Preview) { - const keybinding = keybindingService.lookupKeybinding('editor.action.diffReview.next')?.getAriaLabel(); - content.push(keybinding ? localize('inlineChat.diff', "Tab again to enter the Diff editor with the changes and enter review mode with ({0}). Use Up/DownArrow to navigate lines with the proposed changes.", keybinding) : localize('inlineChat.diffNoKb', "Tab again to enter the Diff editor with the changes and enter review mode with the Go to Next Difference Command. Use Up/DownArrow to navigate lines with the proposed changes.")); - content.push(localize('inlineChat.acceptReject', "Tab again to reach the action bar, which can be navigated with Left/RightArrow.")); - } - } else if (command === 'explain') { - content.push(localize('inlineChat.explain', "/explain commands will be run in the chat view.")); - content.push(localize('inlineChat.chatViewFocus', "To focus the chat view, run the GitHub Copilot: Focus on GitHub Copilot View command, which will focus the input box.")); - } else { - content.push(localize('inlineChat.toolbar', "Use tab to reach conditional parts like commands, status message, message responses and more.")); - } + const startChatKeybininding = keybindingService.lookupKeybinding('inlineChat.start')?.getAriaLabel(); + content.push(localize('inlineChat.overview', "Inline chat occurs within a code editor and takes into account current selection. It is useful for refactoring, fixing, and more. Keep in mind that Copilot generated code may be incorrect.")); + content.push(localize('inlineChat.access', "It can be activated via the Fix and Explain with Copilot context menu actions or directly using the command: Inline Chat: Start Code Chat {0}.", startChatKeybininding)); + content.push(localize('chat.requestHistoryInline', 'In the input box, use UpArrow/DownArrow to navigate your request history. Edit input and use enter or the make request button to run a new request.')); + content.push(localize('inlineChat.contextActions', "Explain and Fix with Copilot actions run a request prefixed with /fix or /explain. These prefixes can be used directly in the input box to apply those specific actions.")); + content.push(localize('inlineChat.fix', "When a request is prefixed with /fix, a response will indicate the problem with the current code. A diff editor will be rendered and can be reached by tabbing.")); + const diffReviewKeybinding = keybindingService.lookupKeybinding('editor.action.diffReview.next')?.getAriaLabel(); + content.push(diffReviewKeybinding ? localize('inlineChat.diff', "Once in the diff editor, enter review mode with ({0}). Use Up/DownArrow to navigate lines with the proposed changes.", diffReviewKeybinding) : localize('inlineChat.diffNoKb', "Tab again to enter the Diff editor with the changes and enter review mode with the Go to Next Difference Command. Use Up/DownArrow to navigate lines with the proposed changes.")); + content.push(localize('inlineChat.explain', "When a request is prefixed with /explain, a response will explain the code in the current selection and the chat view will be focused.")); + content.push(localize('inlineChat.toolbar', "Use tab to reach conditional parts like commands, status, message responses and more.")); } return content.join('\n'); } @@ -70,10 +60,9 @@ export async function runAccessibilityHelpAction(accessor: ServicesAccessor, edi return; } - const cachedInput = inputEditor.getValue(); const cachedPosition = inputEditor.getPosition(); inputEditor.getSupportedActions(); - const helpText = getAccessibilityHelpText(accessor, type, type === 'inline' ? cachedInput : undefined); + const helpText = getAccessibilityHelpText(accessor, type); const provider = accessibleViewService.registerProvider({ id: type, provideContent: () => helpText, From c2a85cbcc081e9cfeaa158bffe7d8b4e87247a46 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 29 May 2023 17:34:14 -0400 Subject: [PATCH 060/128] =?UTF-8?q?Don=E2=80=99t=20re-wrap=20`prepareStack?= =?UTF-8?q?Trace`=20when=20assigned=20to=20itself?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/vs/workbench/api/common/extensionHostMain.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/vs/workbench/api/common/extensionHostMain.ts b/src/vs/workbench/api/common/extensionHostMain.ts index e07d63c5c7c..f99e28f37ed 100644 --- a/src/vs/workbench/api/common/extensionHostMain.ts +++ b/src/vs/workbench/api/common/extensionHostMain.ts @@ -85,17 +85,26 @@ abstract class ErrorHandler { return `${error.name || 'Error'}: ${error.message || ''}${stackTraceMessage}`; } + let _wasWrapped = Symbol('prepareStackTrace wrapped'); let _prepareStackTrace = prepareStackTraceAndFindExtension; + Object.assign(_prepareStackTrace, { [_wasWrapped]: true }); Object.defineProperty(Error, 'prepareStackTrace', { configurable: false, get() { return _prepareStackTrace; }, set(v) { + if (v && (v as any)[_wasWrapped]) { + _prepareStackTrace = v; + return + } + _prepareStackTrace = function (error, stackTrace) { prepareStackTraceAndFindExtension(error, stackTrace); return v.call(Error, error, stackTrace); }; + + Object.assign(_prepareStackTrace, { [_wasWrapped]: true }); }, }); From 27a99c26ab53ec06f8ab7fd37fb4a5bf7e6e2ffd Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 12 Jun 2023 13:54:46 -0400 Subject: [PATCH 061/128] Fix code hygeine issues --- src/vs/workbench/api/common/extensionHostMain.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/api/common/extensionHostMain.ts b/src/vs/workbench/api/common/extensionHostMain.ts index f99e28f37ed..5422226e795 100644 --- a/src/vs/workbench/api/common/extensionHostMain.ts +++ b/src/vs/workbench/api/common/extensionHostMain.ts @@ -85,7 +85,7 @@ abstract class ErrorHandler { return `${error.name || 'Error'}: ${error.message || ''}${stackTraceMessage}`; } - let _wasWrapped = Symbol('prepareStackTrace wrapped'); + const _wasWrapped = Symbol('prepareStackTrace wrapped'); let _prepareStackTrace = prepareStackTraceAndFindExtension; Object.assign(_prepareStackTrace, { [_wasWrapped]: true }); Object.defineProperty(Error, 'prepareStackTrace', { @@ -96,7 +96,7 @@ abstract class ErrorHandler { set(v) { if (v && (v as any)[_wasWrapped]) { _prepareStackTrace = v; - return + return; } _prepareStackTrace = function (error, stackTrace) { From bfe6dcb6f3a7977e131f5819f26ed8856bd41bd9 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 12 Jun 2023 11:09:41 -0700 Subject: [PATCH 062/128] Remove block cursor character from chat (#184936) * Remove block cursor character from chat * Remove comment --- .../contrib/chat/browser/chatListRenderer.ts | 24 +++---------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts index 7565dd39138..e0d4b740cf5 100644 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts +++ b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @@ -88,7 +88,6 @@ export interface IChatRendererDelegate { } export class ChatListItemRenderer extends Disposable implements ITreeRenderer { - static readonly cursorCharacter = '\u258c'; static readonly ID = 'item'; private readonly codeBlocksByResponseId = new Map(); @@ -368,12 +367,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer 0) { - currentText = currentText.slice(0, currentText.length - removedChars); - } - if (newText.startsWith(currentText)) { const text = newText.slice(currentText.length); const lastLine = this.textModel.getLineCount(); const lastCol = this.textModel.getLineMaxColumn(lastLine); - const insertAtCol = lastCol - removedChars; - this.textModel.applyEdits([{ range: new Range(lastLine, insertAtCol, lastLine, lastCol), text }]); + this.textModel.applyEdits([{ range: new Range(lastLine, lastCol, lastLine, lastCol), text }]); } else { // console.log(`Failed to optimize setText`); this.textModel.setValue(newText); From ecb489bbb0cdc7e37dd19461eaca6a0e4fd6b7e5 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Mon, 12 Jun 2023 11:30:42 -0700 Subject: [PATCH 063/128] node-pty@1.0 --- package.json | 2 +- remote/package.json | 2 +- remote/yarn.lock | 8 ++++---- yarn.lock | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index f6c482987a7..dadd36a4356 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "native-is-elevated": "0.6.0", "native-keymap": "^3.3.2", "native-watchdog": "^1.4.1", - "node-pty": "0.11.0-beta33", + "node-pty": "1.0", "tas-client-umd": "0.1.8", "v8-inspect-profiler": "^0.1.0", "vscode-oniguruma": "1.7.0", diff --git a/remote/package.json b/remote/package.json index ffd7fb5e5d4..5ed2fb03633 100644 --- a/remote/package.json +++ b/remote/package.json @@ -20,7 +20,7 @@ "keytar": "7.9.0", "minimist": "^1.2.6", "native-watchdog": "^1.4.1", - "node-pty": "0.11.0-beta33", + "node-pty": "1.0", "tas-client-umd": "0.1.8", "vscode-oniguruma": "1.7.0", "vscode-regexpp": "^3.1.0", diff --git a/remote/yarn.lock b/remote/yarn.lock index cfc9cb6c801..829d6235298 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -537,10 +537,10 @@ node-gyp-build@^4.3.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== -node-pty@0.11.0-beta33: - version "0.11.0-beta33" - resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.11.0-beta33.tgz#722a729fb9449f591279bee1f8b431b71a9af4a1" - integrity sha512-SoP5BbSfvc8Um51rIriUEOPvMltc43iTaKXGJaJKLR3+NfQbjcCcNQGyOd9P9pvBccWYg+Rncv18qMtJKIAi1Q== +node-pty@1.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-1.0.0.tgz#7daafc0aca1c4ca3de15c61330373af4af5861fd" + integrity sha512-wtBMWWS7dFZm/VgqElrTvtfMq4GzJ6+edFI0Y0zyzygUSZMgZdraDUMUhCIvkjhJjme15qWmbyJbtAx4ot4uZA== dependencies: nan "^2.17.0" diff --git a/yarn.lock b/yarn.lock index a2146d5721a..d2941fd84eb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6973,10 +6973,10 @@ node-gyp-build@^4.3.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== -node-pty@0.11.0-beta33: - version "0.11.0-beta33" - resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.11.0-beta33.tgz#722a729fb9449f591279bee1f8b431b71a9af4a1" - integrity sha512-SoP5BbSfvc8Um51rIriUEOPvMltc43iTaKXGJaJKLR3+NfQbjcCcNQGyOd9P9pvBccWYg+Rncv18qMtJKIAi1Q== +node-pty@1.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-1.0.0.tgz#7daafc0aca1c4ca3de15c61330373af4af5861fd" + integrity sha512-wtBMWWS7dFZm/VgqElrTvtfMq4GzJ6+edFI0Y0zyzygUSZMgZdraDUMUhCIvkjhJjme15qWmbyJbtAx4ot4uZA== dependencies: nan "^2.17.0" From 13e7d80fcd896d295f977145001793ed71ecb33a Mon Sep 17 00:00:00 2001 From: Raymond Zhao <7199958+rzhao271@users.noreply.github.com> Date: Mon, 12 Jun 2023 11:36:56 -0700 Subject: [PATCH 064/128] Bump windows-process-tree (#184759) Fixes https://github.com/microsoft/vscode/issues/179697 --- build/.moduleignore | 2 + build/.moduleignore.darwin | 6 +++ build/.moduleignore.linux | 6 +++ package.json | 2 +- remote/package.json | 4 +- remote/yarn.lock | 8 +-- src/typings/windows-process-tree.d.ts | 75 --------------------------- src/vs/base/node/ps.ts | 13 ++--- yarn.lock | 8 +-- 9 files changed, 29 insertions(+), 95 deletions(-) delete mode 100644 src/typings/windows-process-tree.d.ts diff --git a/build/.moduleignore b/build/.moduleignore index 56e2fb15718..abc37e3138c 100644 --- a/build/.moduleignore +++ b/build/.moduleignore @@ -37,6 +37,8 @@ fsevents/test/** @vscode/windows-process-tree/binding.gyp @vscode/windows-process-tree/build/** @vscode/windows-process-tree/src/** +@vscode/windows-process-tree/tsconfig.json +@vscode/windows-process-tree/tslint.json !@vscode/windows-process-tree/**/*.node @vscode/windows-registry/binding.gyp diff --git a/build/.moduleignore.darwin b/build/.moduleignore.darwin index fc3f48af069..dbc12762f7d 100644 --- a/build/.moduleignore.darwin +++ b/build/.moduleignore.darwin @@ -3,6 +3,12 @@ @vscode/windows-mutex/*.md @vscode/windows-mutex/package.json +@vscode/windows-process-tree/lib/** +@vscode/windows-process-tree/**/*.node +@vscode/windows-process-tree/LICENSE +@vscode/windows-process-tree/package.json +@vscode/windows-process-tree/*.md + @vscode/windows-registry/dist/** @vscode/windows-registry/**/*.node @vscode/windows-registry/*.md diff --git a/build/.moduleignore.linux b/build/.moduleignore.linux index fc3f48af069..dbc12762f7d 100644 --- a/build/.moduleignore.linux +++ b/build/.moduleignore.linux @@ -3,6 +3,12 @@ @vscode/windows-mutex/*.md @vscode/windows-mutex/package.json +@vscode/windows-process-tree/lib/** +@vscode/windows-process-tree/**/*.node +@vscode/windows-process-tree/LICENSE +@vscode/windows-process-tree/package.json +@vscode/windows-process-tree/*.md + @vscode/windows-registry/dist/** @vscode/windows-registry/**/*.node @vscode/windows-registry/*.md diff --git a/package.json b/package.json index f6c482987a7..84154f8aeb5 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "@vscode/sudo-prompt": "9.3.1", "@vscode/vscode-languagedetection": "1.0.21", "@vscode/windows-mutex": "^0.4.4", + "@vscode/windows-process-tree": "^0.5.0", "@vscode/windows-registry": "^1.1.0", "graceful-fs": "4.2.8", "http-proxy-agent": "^2.1.0", @@ -227,7 +228,6 @@ "url": "https://github.com/microsoft/vscode/issues" }, "optionalDependencies": { - "@vscode/windows-process-tree": "0.4.2", "windows-foreground-love": "0.5.0" } } diff --git a/remote/package.json b/remote/package.json index ffd7fb5e5d4..dcf21887900 100644 --- a/remote/package.json +++ b/remote/package.json @@ -11,6 +11,7 @@ "@vscode/ripgrep": "^1.15.4", "@vscode/spdlog": "^0.13.10", "@vscode/vscode-languagedetection": "1.0.21", + "@vscode/windows-process-tree": "^0.5.0", "@vscode/windows-registry": "^1.1.0", "cookie": "^0.4.0", "graceful-fs": "4.2.8", @@ -35,8 +36,5 @@ "xterm-headless": "5.3.0-beta.1", "yauzl": "^2.9.2", "yazl": "^2.4.3" - }, - "optionalDependencies": { - "@vscode/windows-process-tree": "0.4.2" } } diff --git a/remote/yarn.lock b/remote/yarn.lock index cfc9cb6c801..e85609c19b8 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -101,10 +101,10 @@ dependencies: node-addon-api "^3.0.2" -"@vscode/windows-process-tree@0.4.2": - version "0.4.2" - resolved "https://registry.yarnpkg.com/@vscode/windows-process-tree/-/windows-process-tree-0.4.2.tgz#54d010fdeb06dfe3a9c6d58fcb3ed9acfc962f33" - integrity sha512-b20865s1HG1VtGt887KrB1blwFS6p4L1Fl1o/WplO9j7sGBle8sLqkNnGXbCaRNgdIgfXtitmzG366FVynJZdQ== +"@vscode/windows-process-tree@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@vscode/windows-process-tree/-/windows-process-tree-0.5.0.tgz#b8205b862c75a1e0ad8b7bf4350dc85036ee3a2c" + integrity sha512-y8Oliel/rBSYh9f1T4F0zQjJNPeJRgYRhEKZsjas7JXKLf46FpE3Ux8e9+7HelUD8dXFH7C7N6895nU0WhrMlg== dependencies: nan "^2.17.0" diff --git a/src/typings/windows-process-tree.d.ts b/src/typings/windows-process-tree.d.ts deleted file mode 100644 index a8708a6cccc..00000000000 --- a/src/typings/windows-process-tree.d.ts +++ /dev/null @@ -1,75 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// Copied from the `@vscode/windows-process-tree` package. -// The dependency is an optional dependency that is only used on Windows, -// but we need the typings to compile on all platforms. -// The `@types/windows-process-tree` package has also been deprecated. -declare module '@vscode/windows-process-tree' { - export enum ProcessDataFlag { } - - export interface IProcessInfo { - pid: number; - ppid: number; - name: string; - - /** - * The working set size of the process, in bytes. - */ - memory?: number; - - /** - * The string returned is at most 512 chars, strings exceeding this length are truncated. - */ - commandLine?: string; - } - - export interface IProcessCpuInfo extends IProcessInfo { - cpu?: number; - } - - export interface IProcessTreeNode { - pid: number; - name: string; - memory?: number; - commandLine?: string; - children: IProcessTreeNode[]; - } - - /** - * Returns a tree of processes with the rootPid process as the root. - * @param rootPid - The pid of the process that will be the root of the tree. - * @param callback - The callback to use with the returned list of processes. - * @param flags - The flags for what process data should be included. - */ - export function getProcessTree(rootPid: number, callback: (tree: IProcessTreeNode | undefined) => void, flags?: ProcessDataFlag): void; - - namespace getProcessTree { - function __promisify__(rootPid: number, flags?: ProcessDataFlag): Promise; - } - - /** - * Returns a list of processes containing the rootPid process and all of its descendants. - * @param rootPid - The pid of the process of interest. - * @param callback - The callback to use with the returned set of processes. - * @param flags - The flags for what process data should be included. - */ - export function getProcessList(rootPid: number, callback: (processList: IProcessInfo[] | undefined) => void, flags?: ProcessDataFlag): void; - - namespace getProcessList { - function __promisify__(rootPid: number, flags?: ProcessDataFlag): Promise; - } - - /** - * Returns the list of processes annotated with cpu usage information. - * @param processList - The list of processes. - * @param callback - The callback to use with the returned list of processes. - */ - export function getProcessCpuUsage(processList: IProcessInfo[], callback: (processListWithCpu: IProcessCpuInfo[]) => void): void; - - namespace getProcessCpuUsage { - function __promisify__(processList: IProcessInfo[]): Promise; - } -} diff --git a/src/vs/base/node/ps.ts b/src/vs/base/node/ps.ts index 5eb35eddc66..f61af2b8117 100644 --- a/src/vs/base/node/ps.ts +++ b/src/vs/base/node/ps.ts @@ -115,13 +115,13 @@ export function listProcesses(rootPid: number): Promise { const cleanUNCPrefix = (value: string): string => { if (value.indexOf('\\\\?\\') === 0) { - return value.substr(4); + return value.substring(4); } else if (value.indexOf('\\??\\') === 0) { - return value.substr(4); + return value.substring(4); } else if (value.indexOf('"\\\\?\\') === 0) { - return '"' + value.substr(5); + return '"' + value.substring(5); } else if (value.indexOf('"\\??\\') === 0) { - return '"' + value.substr(5); + return '"' + value.substring(5); } else { return value; } @@ -169,10 +169,7 @@ export function listProcesses(rootPid: number): Promise { reject(new Error(`Root process ${rootPid} not found`)); } }); - }, - // Workaround duplicate enum identifiers issue in @vscode/windows-process-tree - // Ref https://github.com/microsoft/vscode/pull/179508 - (windowsProcessTree.ProcessDataFlag as any).CommandLine | (windowsProcessTree.ProcessDataFlag as any).Memory); + }, windowsProcessTree.ProcessDataFlag.CommandLine | windowsProcessTree.ProcessDataFlag.Memory); }); } else { // OS X & Linux function calculateLinuxCpuUsage() { diff --git a/yarn.lock b/yarn.lock index a2146d5721a..2f3676a6211 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1400,10 +1400,10 @@ bindings "^1.2.1" nan "^2.17.0" -"@vscode/windows-process-tree@0.4.2": - version "0.4.2" - resolved "https://registry.yarnpkg.com/@vscode/windows-process-tree/-/windows-process-tree-0.4.2.tgz#54d010fdeb06dfe3a9c6d58fcb3ed9acfc962f33" - integrity sha512-b20865s1HG1VtGt887KrB1blwFS6p4L1Fl1o/WplO9j7sGBle8sLqkNnGXbCaRNgdIgfXtitmzG366FVynJZdQ== +"@vscode/windows-process-tree@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@vscode/windows-process-tree/-/windows-process-tree-0.5.0.tgz#b8205b862c75a1e0ad8b7bf4350dc85036ee3a2c" + integrity sha512-y8Oliel/rBSYh9f1T4F0zQjJNPeJRgYRhEKZsjas7JXKLf46FpE3Ux8e9+7HelUD8dXFH7C7N6895nU0WhrMlg== dependencies: nan "^2.17.0" From 75ba646d7be4ea2cb53b5c9bd6479f465fb3faf9 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Mon, 12 Jun 2023 13:52:44 -0500 Subject: [PATCH 065/128] fix #184618 --- .../contrib/accessibility/browser/accessibleView.ts | 6 +++--- .../codeEditor/browser/accessibility/accessibility.css | 8 +++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index c2153ac4878..56237b5b882 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -96,7 +96,7 @@ class AccessibleView extends Disposable { if (!domNode) { return; } - container.appendChild(domNode); + container.appendChild(this._editorContainer); this._layout(); this._register(this._editorWidget.onKeyDown((e) => { if (e.keyCode === KeyCode.Escape) { @@ -125,9 +125,9 @@ class AccessibleView extends Disposable { const height = Math.min(.4 * windowHeight, this._editorWidget.getContentHeight()); this._editorWidget.layout({ width, height }); const top = Math.round((windowHeight - height) / 2); - domNode.style.top = `${top}px`; + this._editorContainer.style.top = `${top}px`; const left = Math.round((windowWidth - width) / 2); - domNode.style.left = `${left}px`; + this._editorContainer.style.left = `${left}px`; } private async _getTextModel(resource: URI): Promise { diff --git a/src/vs/workbench/contrib/codeEditor/browser/accessibility/accessibility.css b/src/vs/workbench/contrib/codeEditor/browser/accessibility/accessibility.css index 11d5f7a9f18..d56086e674c 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/accessibility/accessibility.css +++ b/src/vs/workbench/contrib/codeEditor/browser/accessibility/accessibility.css @@ -3,12 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.monaco-editor .accessibilityHelpWidget { - padding: 10px; - vertical-align: middle; - overflow: auto; +.accessible-view { + position: relative; background-color: var(--vscode-editorWidget-background); color: var(--vscode-editorWidget-foreground); box-shadow: 0 2px 8px var(--vscode-widget-shadow); - border: 2px solid var(--vscode-contrastBorder); + border: 2px solid var(--vscode-contrastActiveBorder); } From 05a76f327479ec73f34e6d309fceef5f06425d6c Mon Sep 17 00:00:00 2001 From: meganrogge Date: Mon, 12 Jun 2023 13:53:42 -0500 Subject: [PATCH 066/128] rm unused check --- .../contrib/accessibility/browser/accessibleView.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index 56237b5b882..c1517faf84a 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -113,11 +113,6 @@ class AccessibleView extends Disposable { } private _layout(): void { - const domNode = this._editorWidget.getDomNode(); - if (!domNode) { - return; - } - const windowWidth = window.innerWidth; const windowHeight = window.innerHeight; From ab8ed4b717bad6c2a8e6cfb74cb667d98a31de88 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 12 Jun 2023 12:11:42 -0700 Subject: [PATCH 067/128] Fallback to use insert text when label is falsy (#184944) For #184812 --- .../src/languageFeatures/completions.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/completions.ts b/extensions/typescript-language-features/src/languageFeatures/completions.ts index 8b5100f876e..b97c9b8b3fb 100644 --- a/extensions/typescript-language-features/src/languageFeatures/completions.ts +++ b/extensions/typescript-language-features/src/languageFeatures/completions.ts @@ -58,7 +58,8 @@ class MyCompletionItem extends vscode.CompletionItem { public readonly metadata: any | undefined, client: ITypeScriptServiceClient, ) { - super(tsEntry.name, MyCompletionItem.convertKind(tsEntry.kind)); + const label = tsEntry.name || (tsEntry.insertText ?? ''); + super(label, MyCompletionItem.convertKind(tsEntry.kind)); if (tsEntry.source && tsEntry.hasAction && client.apiVersion.lt(API.v490)) { // De-prioritze auto-imports @@ -72,18 +73,18 @@ class MyCompletionItem extends vscode.CompletionItem { // Render "fancy" when source is a workspace path const qualifierCandidate = vscode.workspace.asRelativePath(tsEntry.source); if (qualifierCandidate !== tsEntry.source) { - this.label = { label: tsEntry.name, description: qualifierCandidate }; + this.label = { label, description: qualifierCandidate }; } } const { sourceDisplay, isSnippet } = tsEntry; if (sourceDisplay) { - this.label = { label: tsEntry.name, description: Previewer.asPlainTextWithLinks(sourceDisplay, client) }; + this.label = { label, description: Previewer.asPlainTextWithLinks(sourceDisplay, client) }; } if (tsEntry.labelDetails) { - this.label = { label: tsEntry.name, ...tsEntry.labelDetails }; + this.label = { label, ...tsEntry.labelDetails }; } this.preselect = tsEntry.isRecommended; From 6178b02e762bbf15eb7bf6cd2b9a8677feeccdf6 Mon Sep 17 00:00:00 2001 From: Michael Lively Date: Mon, 12 Jun 2023 12:26:35 -0700 Subject: [PATCH 068/128] Notebooks -- lightbulbs hide upon leaving cell focus (#184929) * lightbulbs hide upon cell leaving focus * whitespace/format --- .../contrib/codeAction/browser/codeActionController.ts | 8 ++++++++ .../contrib/notebook/browser/view/cellParts/codeCell.ts | 3 +++ 2 files changed, 11 insertions(+) diff --git a/src/vs/editor/contrib/codeAction/browser/codeActionController.ts b/src/vs/editor/contrib/codeAction/browser/codeActionController.ts index 45426a756c0..d441eef1d2e 100644 --- a/src/vs/editor/contrib/codeAction/browser/codeActionController.ts +++ b/src/vs/editor/contrib/codeAction/browser/codeActionController.ts @@ -97,6 +97,10 @@ export class CodeActionController extends Disposable implements IEditorContribut return this.showCodeActionList(actions, at, { includeDisabledActions: false, fromLightbulb: false }); } + public hideCodeActions(): void { + this._actionWidgetService.hide(); + } + public manualTriggerAtCurrentPosition( notAvailableMessage: string, triggerAction: CodeActionTriggerSource, @@ -126,6 +130,10 @@ export class CodeActionController extends Disposable implements IEditorContribut } } + public hideLightBulbWidget(): void { + this._lightBulbWidget.rawValue?.hide(); + } + private async update(newState: CodeActionsState.State): Promise { if (newState.type !== CodeActionsState.Type.Triggered) { this._lightBulbWidget.rawValue?.hide(); diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCell.ts index 78ecc25d693..b110caed2fa 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCell.ts @@ -30,6 +30,7 @@ import { CodeCellRenderTemplate } from 'vs/workbench/contrib/notebook/browser/vi import { CodeCellViewModel, outputDisplayLimit } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService'; import { WordHighlighterContribution } from 'vs/editor/contrib/wordHighlighter/browser/wordHighlighter'; +import { CodeActionController } from 'vs/editor/contrib/codeAction/browser/codeActionController'; export class CodeCell extends Disposable { private _outputContainerRenderer: CellOutputContainer; @@ -267,6 +268,8 @@ export class CodeCell extends Disposable { this._register(this.templateData.editor.onDidBlurEditorWidget(() => { WordHighlighterContribution.get(this.templateData.editor)?.stopHighlighting(); + CodeActionController.get(this.templateData.editor)?.hideCodeActions(); + CodeActionController.get(this.templateData.editor)?.hideLightBulbWidget(); })); this._register(this.templateData.editor.onDidFocusEditorWidget(() => { WordHighlighterContribution.get(this.templateData.editor)?.restoreViewState(true); From 69defeced64987e1e7c2d3b2ea1df0903ae738bd Mon Sep 17 00:00:00 2001 From: meganrogge Date: Mon, 12 Jun 2023 14:27:56 -0500 Subject: [PATCH 069/128] reformat --- .../contrib/accessibility/browser/accessibleView.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index c1517faf84a..1e051c6429b 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -22,7 +22,14 @@ import { getSimpleEditorOptions } from 'vs/workbench/contrib/codeEditor/browser/ import { IDisposable } from 'xterm'; -export interface IAccessibleContentProvider { id: string; provideContent(): string; onClose(): void; onKeyDown?(e: IKeyboardEvent): void; options: IAccessibleViewOptions } +export interface IAccessibleContentProvider { + id: string; + provideContent(): string; + onClose(): void; + onKeyDown?(e: IKeyboardEvent): void; + options: IAccessibleViewOptions; +} + export const IAccessibleViewService = createDecorator('accessibleViewService'); export interface IAccessibleViewService { From 4558410d11bdaa3e5c9ed60bdbb1fe96b680f31f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dirk=20B=C3=A4umer?= Date: Mon, 12 Jun 2023 21:28:57 +0200 Subject: [PATCH 070/128] Disable rich navigation (#184949) --- .../workflows/{rich-navigation.yml => rich-navigation.yml.off} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{rich-navigation.yml => rich-navigation.yml.off} (100%) diff --git a/.github/workflows/rich-navigation.yml b/.github/workflows/rich-navigation.yml.off similarity index 100% rename from .github/workflows/rich-navigation.yml rename to .github/workflows/rich-navigation.yml.off From a33dc50be87b9a9af026ece43a5f06d413f1763e Mon Sep 17 00:00:00 2001 From: Michael Lively Date: Mon, 12 Jun 2023 13:32:45 -0700 Subject: [PATCH 071/128] Filter out notebook codeaction kind (#184930) * filter notebook codeactions unless specifically invoked * feedback revisions * fix some mistakes/formatting * simplify --- src/vs/workbench/api/common/extHostLanguageFeatures.ts | 8 +++++++- .../browser/contrib/saveParticipants/saveParticipants.ts | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 976490d0b64..edfbdc9a1f6 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, SemanticTokens, SemanticTokensEdit, Location, InlineCompletionTriggerKind, InternalDataTransferItem } from 'vs/workbench/api/common/extHostTypes'; +import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, DocumentSymbol, SemanticTokensEdits, SemanticTokens, SemanticTokensEdit, Location, InlineCompletionTriggerKind, InternalDataTransferItem, CodeActionTriggerKind } from 'vs/workbench/api/common/extHostTypes'; import { ISingleEditOperation } from 'vs/editor/common/core/editOperation'; import * as languages from 'vs/editor/common/languages'; import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments'; @@ -376,6 +376,7 @@ class CodeActionAdapter { private readonly _cache = new Cache('CodeAction'); private readonly _disposables = new Map(); + private readonly nbKind = new CodeActionKind('notebook'); constructor( private readonly _documents: ExtHostDocuments, @@ -414,6 +415,7 @@ class CodeActionAdapter { if (!isNonEmptyArray(commandsOrActions) || token.isCancellationRequested) { return undefined; } + const cacheId = this._cache.add(commandsOrActions); const disposables = new DisposableStore(); this._disposables.set(cacheId, disposables); @@ -434,6 +436,10 @@ class CodeActionAdapter { command: this._commands.toInternal(candidate, disposables), }); } else { + if (codeActionContext.triggerKind !== CodeActionTriggerKind.Invoke && candidate.kind && this.nbKind.contains(candidate.kind)) { + continue; + } + if (codeActionContext.only) { if (!candidate.kind) { this._logService.warn(`${this._extension.identifier.value} - Code actions of kind '${codeActionContext.only.value} 'requested but returned code action does not have a 'kind'. Code action will be dropped. Please set 'CodeAction.kind'.`); diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/saveParticipants/saveParticipants.ts b/src/vs/workbench/contrib/notebook/browser/contrib/saveParticipants/saveParticipants.ts index fbc321c50c4..89989e87bfa 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/saveParticipants/saveParticipants.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/saveParticipants/saveParticipants.ts @@ -280,7 +280,7 @@ class CodeActionOnSaveParticipant implements IStoredFileWorkingCopySaveParticipa private getActionsToRun(model: ITextModel, codeActionKind: CodeActionKind, excludes: readonly CodeActionKind[], progress: IProgress, token: CancellationToken) { return getCodeActions(this.languageFeaturesService.codeActionProvider, model, model.getFullModelRange(), { - type: CodeActionTriggerType.Auto, + type: CodeActionTriggerType.Invoke, triggerAction: CodeActionTriggerSource.OnSave, filter: { include: codeActionKind, excludes: excludes, includeSourceActions: true }, }, progress, token); From 50941ef29ef3ac7349ec15a7069ad741569fc909 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Mon, 12 Jun 2023 15:47:06 -0500 Subject: [PATCH 072/128] fix #184951 --- .../workbench/contrib/accessibility/browser/accessibleView.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index c2153ac4878..21310db2aa0 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -98,10 +98,11 @@ class AccessibleView extends Disposable { } container.appendChild(domNode); this._layout(); - this._register(this._editorWidget.onKeyDown((e) => { + this._register(this._editorWidget.onKeyUp((e) => { if (e.keyCode === KeyCode.Escape) { this._contextViewService.hideContextView(); } + e.stopPropagation(); provider.onKeyDown?.(e); })); this._register(this._editorWidget.onDidBlurEditorText(() => this._contextViewService.hideContextView())); From 8b18ae5f9e35d052fd8665c8bc5b5036bef8524c Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Mon, 12 Jun 2023 16:04:59 -0500 Subject: [PATCH 073/128] Update src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts Co-authored-by: Daniel Imms <2193314+Tyriar@users.noreply.github.com> --- .../contrib/chat/browser/actions/chatAccessibilityHelp.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts index d7fbd840751..6651a454aa6 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts @@ -25,7 +25,7 @@ export function getAccessibilityHelpText(accessor: ServicesAccessor, type: 'chat content.push(descriptionForCommand('workbench.action.chat.clear', localize('workbench.action.chat.clear', 'The Chat Clear command ({0}) clears the request/response list.'), localize('workbench.action.chat.clearNoKb', 'The Chat Clear command clears the request/response list and is currently not triggerable by a keybinding.'), keybindingService)); } else { const startChatKeybininding = keybindingService.lookupKeybinding('inlineChat.start')?.getAriaLabel(); - content.push(localize('inlineChat.overview', "Inline chat occurs within a code editor and takes into account current selection. It is useful for refactoring, fixing, and more. Keep in mind that Copilot generated code may be incorrect.")); + content.push(localize('inlineChat.overview', "Inline chat occurs within a code editor, taking the current selection into account. It is useful for refactoring, fixing, and more. Keep in mind that Copilot generated code may be incorrect.")); content.push(localize('inlineChat.access', "It can be activated via the Fix and Explain with Copilot context menu actions or directly using the command: Inline Chat: Start Code Chat {0}.", startChatKeybininding)); content.push(localize('chat.requestHistoryInline', 'In the input box, use UpArrow/DownArrow to navigate your request history. Edit input and use enter or the make request button to run a new request.')); content.push(localize('inlineChat.contextActions', "Explain and Fix with Copilot actions run a request prefixed with /fix or /explain. These prefixes can be used directly in the input box to apply those specific actions.")); From 5c3c8a2698d7a0cf9e07a8b67956c49596a24c43 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Mon, 12 Jun 2023 16:05:08 -0500 Subject: [PATCH 074/128] Update src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts Co-authored-by: Daniel Imms <2193314+Tyriar@users.noreply.github.com> --- .../contrib/chat/browser/actions/chatAccessibilityHelp.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts index 6651a454aa6..db8a7f22ada 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts @@ -26,7 +26,7 @@ export function getAccessibilityHelpText(accessor: ServicesAccessor, type: 'chat } else { const startChatKeybininding = keybindingService.lookupKeybinding('inlineChat.start')?.getAriaLabel(); content.push(localize('inlineChat.overview', "Inline chat occurs within a code editor, taking the current selection into account. It is useful for refactoring, fixing, and more. Keep in mind that Copilot generated code may be incorrect.")); - content.push(localize('inlineChat.access', "It can be activated via the Fix and Explain with Copilot context menu actions or directly using the command: Inline Chat: Start Code Chat {0}.", startChatKeybininding)); + content.push(localize('inlineChat.access', "It can be activated via the Fix and Explain with the Copilot context menu actions or directly using the command: Inline Chat: Start Code Chat {0}.", startChatKeybininding)); content.push(localize('chat.requestHistoryInline', 'In the input box, use UpArrow/DownArrow to navigate your request history. Edit input and use enter or the make request button to run a new request.')); content.push(localize('inlineChat.contextActions', "Explain and Fix with Copilot actions run a request prefixed with /fix or /explain. These prefixes can be used directly in the input box to apply those specific actions.")); content.push(localize('inlineChat.fix', "When a request is prefixed with /fix, a response will indicate the problem with the current code. A diff editor will be rendered and can be reached by tabbing.")); From 571fbf44dffbd6ce5c412c9cdbc91a3a5c294143 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Mon, 12 Jun 2023 16:05:34 -0500 Subject: [PATCH 075/128] Update src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts Co-authored-by: Daniel Imms <2193314+Tyriar@users.noreply.github.com> --- .../contrib/chat/browser/actions/chatAccessibilityHelp.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts index db8a7f22ada..f775707a3e7 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts @@ -27,7 +27,7 @@ export function getAccessibilityHelpText(accessor: ServicesAccessor, type: 'chat const startChatKeybininding = keybindingService.lookupKeybinding('inlineChat.start')?.getAriaLabel(); content.push(localize('inlineChat.overview', "Inline chat occurs within a code editor, taking the current selection into account. It is useful for refactoring, fixing, and more. Keep in mind that Copilot generated code may be incorrect.")); content.push(localize('inlineChat.access', "It can be activated via the Fix and Explain with the Copilot context menu actions or directly using the command: Inline Chat: Start Code Chat {0}.", startChatKeybininding)); - content.push(localize('chat.requestHistoryInline', 'In the input box, use UpArrow/DownArrow to navigate your request history. Edit input and use enter or the make request button to run a new request.')); + content.push(localize('chat.requestHistoryInline', 'In the input box, use the up and down arrows to navigate your request history. Edit input and use enter or the make request button to run a new request.')); content.push(localize('inlineChat.contextActions', "Explain and Fix with Copilot actions run a request prefixed with /fix or /explain. These prefixes can be used directly in the input box to apply those specific actions.")); content.push(localize('inlineChat.fix', "When a request is prefixed with /fix, a response will indicate the problem with the current code. A diff editor will be rendered and can be reached by tabbing.")); const diffReviewKeybinding = keybindingService.lookupKeybinding('editor.action.diffReview.next')?.getAriaLabel(); From d2ca3e25fe2296bceef560db020061a4d84539e1 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Mon, 12 Jun 2023 16:12:53 -0500 Subject: [PATCH 076/128] fixes --- .../chat/browser/actions/chatAccessibilityHelp.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts index f775707a3e7..b9cc6dc5dac 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts @@ -24,14 +24,14 @@ export function getAccessibilityHelpText(accessor: ServicesAccessor, type: 'chat content.push(descriptionForCommand('workbench.action.chat.nextCodeBlock', localize('workbench.action.chat.nextCodeBlock', 'The Chat: Next Code Block command ({0}) focuses the next code block within a response.'), localize('workbench.action.chat.nextCodeBlockNoKb', 'The Chat: Next Code Block command focuses the next code block within a response and is currently not triggerable by a keybinding.'), keybindingService)); content.push(descriptionForCommand('workbench.action.chat.clear', localize('workbench.action.chat.clear', 'The Chat Clear command ({0}) clears the request/response list.'), localize('workbench.action.chat.clearNoKb', 'The Chat Clear command clears the request/response list and is currently not triggerable by a keybinding.'), keybindingService)); } else { - const startChatKeybininding = keybindingService.lookupKeybinding('inlineChat.start')?.getAriaLabel(); - content.push(localize('inlineChat.overview', "Inline chat occurs within a code editor, taking the current selection into account. It is useful for refactoring, fixing, and more. Keep in mind that Copilot generated code may be incorrect.")); - content.push(localize('inlineChat.access', "It can be activated via the Fix and Explain with the Copilot context menu actions or directly using the command: Inline Chat: Start Code Chat {0}.", startChatKeybininding)); - content.push(localize('chat.requestHistoryInline', 'In the input box, use the up and down arrows to navigate your request history. Edit input and use enter or the make request button to run a new request.')); + const startChatKeybinding = keybindingService.lookupKeybinding('inlineChat.start')?.getAriaLabel(); + content.push(localize('inlineChat.overview', "Inline chat occurs within a code editor and takes into account current selection. It is useful for refactoring, fixing, and more. Keep in mind that Copilot generated code may be incorrect.")); + content.push(localize('inlineChat.access', "It can be activated via the Fix and Explain with Copilot context menu actions or directly using the command: Inline Chat: Start Code Chat ({0}).", startChatKeybinding)); + content.push(localize('chat.requestHistoryInline', 'In the input box, use UpArrow/DownArrow to navigate your request history. Edit input and use enter or the make request button to run a new request.')); content.push(localize('inlineChat.contextActions', "Explain and Fix with Copilot actions run a request prefixed with /fix or /explain. These prefixes can be used directly in the input box to apply those specific actions.")); content.push(localize('inlineChat.fix', "When a request is prefixed with /fix, a response will indicate the problem with the current code. A diff editor will be rendered and can be reached by tabbing.")); const diffReviewKeybinding = keybindingService.lookupKeybinding('editor.action.diffReview.next')?.getAriaLabel(); - content.push(diffReviewKeybinding ? localize('inlineChat.diff', "Once in the diff editor, enter review mode with ({0}). Use Up/DownArrow to navigate lines with the proposed changes.", diffReviewKeybinding) : localize('inlineChat.diffNoKb', "Tab again to enter the Diff editor with the changes and enter review mode with the Go to Next Difference Command. Use Up/DownArrow to navigate lines with the proposed changes.")); + content.push(diffReviewKeybinding ? localize('inlineChat.diff', "Once in the diff editor, enter review mode with ({0}). Use up and down arrows to navigate lines with the proposed changes.", diffReviewKeybinding) : localize('inlineChat.diffNoKb', "Tab again to enter the Diff editor with the changes and enter review mode with the Go to Next Difference Command. Use Up/DownArrow to navigate lines with the proposed changes.")); content.push(localize('inlineChat.explain', "When a request is prefixed with /explain, a response will explain the code in the current selection and the chat view will be focused.")); content.push(localize('inlineChat.toolbar', "Use tab to reach conditional parts like commands, status, message responses and more.")); } From 9eb77afd62de46dd8b3f00c0871cb46b2f11f1ee Mon Sep 17 00:00:00 2001 From: meganrogge Date: Mon, 12 Jun 2023 16:13:44 -0500 Subject: [PATCH 077/128] arrows --- .../contrib/chat/browser/actions/chatAccessibilityHelp.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts index b9cc6dc5dac..65bbd5e8f97 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts @@ -18,7 +18,7 @@ export function getAccessibilityHelpText(accessor: ServicesAccessor, type: 'chat const content = []; if (type === 'chat') { content.push(localize('chat.overview', 'Chat responses will be announced as they come in. A response will indicate the number of code blocks, if any, and then the rest of the response.')); - content.push(localize('chat.requestHistory', 'In the input box, use UpArrow/DownArrow to navigate your request history. Edit input and use enter to run a new request.')); + content.push(localize('chat.requestHistory', 'In the input box, use up and down arrows to navigate your request history. Edit input and use enter to run a new request.')); content.push(descriptionForCommand('chat.action.focus', localize('workbench.action.chat.focus', 'The Focus Chat command ({0}) focuses the chat request/response list, which can be navigated with UpArrow/DownArrow.',), localize('workbench.action.chat.focusNoKb', 'The Focus Chat List command focuses the chat request/response list, which can be navigated with UpArrow/DownArrow and is currently not triggerable by a keybinding.'), keybindingService)); content.push(descriptionForCommand('workbench.action.chat.focusInput', localize('workbench.action.chat.focusInput', 'The Focus Chat Input command ({0}) focuses the input box for chat requests.'), localize('workbench.action.interactiveSession.focusInputNoKb', 'Focus Chat Input command focuses the input box for chat requests and is currently not triggerable by a keybinding.'), keybindingService)); content.push(descriptionForCommand('workbench.action.chat.nextCodeBlock', localize('workbench.action.chat.nextCodeBlock', 'The Chat: Next Code Block command ({0}) focuses the next code block within a response.'), localize('workbench.action.chat.nextCodeBlockNoKb', 'The Chat: Next Code Block command focuses the next code block within a response and is currently not triggerable by a keybinding.'), keybindingService)); @@ -27,7 +27,7 @@ export function getAccessibilityHelpText(accessor: ServicesAccessor, type: 'chat const startChatKeybinding = keybindingService.lookupKeybinding('inlineChat.start')?.getAriaLabel(); content.push(localize('inlineChat.overview', "Inline chat occurs within a code editor and takes into account current selection. It is useful for refactoring, fixing, and more. Keep in mind that Copilot generated code may be incorrect.")); content.push(localize('inlineChat.access', "It can be activated via the Fix and Explain with Copilot context menu actions or directly using the command: Inline Chat: Start Code Chat ({0}).", startChatKeybinding)); - content.push(localize('chat.requestHistoryInline', 'In the input box, use UpArrow/DownArrow to navigate your request history. Edit input and use enter or the make request button to run a new request.')); + content.push(localize('chat.requestHistoryInline', 'In the input box, use up and down arrows to navigate your request history. Edit input and use enter or the make request button to run a new request.')); content.push(localize('inlineChat.contextActions', "Explain and Fix with Copilot actions run a request prefixed with /fix or /explain. These prefixes can be used directly in the input box to apply those specific actions.")); content.push(localize('inlineChat.fix', "When a request is prefixed with /fix, a response will indicate the problem with the current code. A diff editor will be rendered and can be reached by tabbing.")); const diffReviewKeybinding = keybindingService.lookupKeybinding('editor.action.diffReview.next')?.getAriaLabel(); From a667642386cf4f3783c51d34413186396659753b Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 12 Jun 2023 15:42:28 -0700 Subject: [PATCH 078/128] Fix error in dispose from telemetry (#184957) --- src/vs/workbench/contrib/debug/browser/repl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index da7b3f03c17..19dc6cda053 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -753,7 +753,7 @@ export class Repl extends FilterViewPane implements IHistoryNavigationWidget { } override dispose(): void { - this.replInput.dispose(); + this.replInput?.dispose(); // Disposed before rendered? #174558 this.replElementsChangeListener?.dispose(); this.refreshScheduler.dispose(); this.modelChangeListener.dispose(); From ca3c3466344ee1ccd1ff7b2d9fdf417739aca7ea Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 12 Jun 2023 16:55:45 -0700 Subject: [PATCH 079/128] Don't auto-focus a "deemphasized" frame while debugging (#184962) Fix #184640 --- src/vs/workbench/contrib/debug/common/debugModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/common/debugModel.ts b/src/vs/workbench/contrib/debug/common/debugModel.ts index 51e5d6ed635..098f12be9bc 100644 --- a/src/vs/workbench/contrib/debug/common/debugModel.ts +++ b/src/vs/workbench/contrib/debug/common/debugModel.ts @@ -528,7 +528,7 @@ export class Thread implements IThread { const firstAvailableStackFrame = callStack.find(sf => !!(sf && ((this.stoppedDetails?.reason === 'instruction breakpoint' || (this.stoppedDetails?.reason === 'step' && this.lastSteppingGranularity === 'instruction')) && sf.instructionPointerReference) || (sf.source && sf.source.available && sf.source.presentationHint !== 'deemphasize'))); - return firstAvailableStackFrame || (callStack.length > 0 ? callStack[0] : undefined); + return firstAvailableStackFrame; } get stateLabel(): string { From 6e45786d0247566671f4310b47db9f12f0ddcde6 Mon Sep 17 00:00:00 2001 From: Bhavya U Date: Mon, 12 Jun 2023 18:00:03 -0700 Subject: [PATCH 080/128] Update quickpick on walkthrough additions (#184965) --- .../browser/gettingStarted.contribution.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.contribution.ts b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.contribution.ts index 977423bbe85..90788407bfd 100644 --- a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.contribution.ts +++ b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.contribution.ts @@ -251,10 +251,12 @@ registerAction2(class extends Action2 { quickPick.hide(); }); quickPick.onDidHide(() => quickPick.dispose()); - quickPick.show(); await extensionService.whenInstalledExtensionsRegistered(); + gettingStartedService.onDidAddWalkthrough(async () => { + quickPick.items = await this.getQuickPickItems(contextService, gettingStartedService); + }); + quickPick.show(); quickPick.busy = false; - quickPick.items = await this.getQuickPickItems(contextService, gettingStartedService); } }); From 79c4092768e41b16fd823e80c874dbfafdc08f55 Mon Sep 17 00:00:00 2001 From: Bhavya U Date: Mon, 12 Jun 2023 18:38:34 -0700 Subject: [PATCH 081/128] Register with editorResolver before attempting to open walkthrough (#184969) --- .../contrib/welcomeGettingStarted/browser/startupPage.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/browser/startupPage.ts b/src/vs/workbench/contrib/welcomeGettingStarted/browser/startupPage.ts index 857ae064148..c44e6ce9473 100644 --- a/src/vs/workbench/contrib/welcomeGettingStarted/browser/startupPage.ts +++ b/src/vs/workbench/contrib/welcomeGettingStarted/browser/startupPage.ts @@ -55,8 +55,6 @@ export class StartupPageContribution implements IWorkbenchContribution { @INotificationService private readonly notificationService: INotificationService, @IEditorResolverService editorResolverService: IEditorResolverService ) { - this.run().then(undefined, onUnexpectedError); - editorResolverService.registerEditor( `${GettingStartedInput.RESOURCE.scheme}:/**`, { @@ -80,6 +78,8 @@ export class StartupPageContribution implements IWorkbenchContribution { } } ); + + this.run().then(undefined, onUnexpectedError); } private async run() { From debcf16fcd8896f598aada07c19b4cc461bdbd18 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 12 Jun 2023 23:18:05 -0700 Subject: [PATCH 082/128] Mangle exported symbols (#182935) * Mangle exported functions For #180461 This prototype tries to mangle exported functions, saving a further 440kb from the bundle size * Fix missing call * Also try mangling top level exported consts too * Fixing errors * Don't run on build files * Skip a few more manglings and revert change to namespace * Skip a few more monaco files * Also mangle consts that shadow types This increases savings up to 3325 * Also mangle exported classes * Skip mangling more localization functions for now * Opt out pfs * Update build script * Run find locations task in parallel This should speed up compile * Cleanup before close * Limit workers to avoid hitting memory limit * Limit pool size * Skip one more mangling * Exclude entrypoints from mangling * Try to fix web build and clean up code * Exempt a few more projects * Exempt another file * Also exempt html * Skip mangling ext entrypoints * Use prefix that can't be confused with rpc calls * Fix max call stack error * Switch prefixes * Don't mangle ambient declarations * Use correct way of checking modifier flags * Workaround getCombinedModifierFlags not doing what I'd expect Maybe needs the checker to be enabled too? Just check parent chain instead for now * Clean up code and add logic showing how enum mangling could work * Remove a few more skipMangles Use entrypoints instead * Fix entrypoint name --- build/lib/compilation.js | 16 +- build/lib/compilation.ts | 15 +- build/lib/mangle/index.js | 665 ++++++++++++++++++ .../{mangleTypeScript.ts => mangle/index.ts} | 353 +++++++--- build/lib/mangle/renameWorker.js | 20 + build/lib/mangle/renameWorker.ts | 26 + build/lib/mangle/staticLanguageServiceHost.js | 65 ++ build/lib/mangle/staticLanguageServiceHost.ts | 62 ++ build/lib/mangleTypeScript.js | 191 ++++- build/package.json | 4 + build/yarn.lock | 12 + extensions/mangle-loader.js | 6 +- src/vs/base/common/errors.ts | 1 + src/vs/base/common/process.ts | 2 + src/vs/base/common/stripComments.d.ts | 2 +- src/vs/base/common/worker/simpleWorker.ts | 1 + src/vs/css.ts | 2 + .../browser/controller/textAreaHandler.ts | 7 +- .../test/browser/controller/imeTester.ts | 7 +- src/vs/nls.ts | 12 + .../electron-sandbox/profileAnalysisWorker.ts | 1 - src/vs/workbench/test/common/utils.ts | 2 + 22 files changed, 1338 insertions(+), 134 deletions(-) create mode 100644 build/lib/mangle/index.js rename build/lib/{mangleTypeScript.ts => mangle/index.ts} (63%) create mode 100644 build/lib/mangle/renameWorker.js create mode 100644 build/lib/mangle/renameWorker.ts create mode 100644 build/lib/mangle/staticLanguageServiceHost.js create mode 100644 build/lib/mangle/staticLanguageServiceHost.ts diff --git a/build/lib/compilation.js b/build/lib/compilation.js index 63ddeb2eabd..2270e054ba5 100644 --- a/build/lib/compilation.js +++ b/build/lib/compilation.js @@ -19,7 +19,7 @@ const os = require("os"); const ts = require("typescript"); const File = require("vinyl"); const task = require("./task"); -const mangleTypeScript_1 = require("./mangleTypeScript"); +const index_1 = require("./mangle/index"); const watch = require('./watch'); // --- gulp-tsb: compile and transpile -------------------------------- const reporter = (0, reporter_1.createReporter)(); @@ -105,20 +105,20 @@ function compileTask(src, out, build, options = {}) { // mangle: TypeScript to TypeScript let mangleStream = es.through(); if (build && !options.disableMangle) { - let ts2tsMangler = new mangleTypeScript_1.Mangler(compile.projectPath, (...data) => fancyLog(ansiColors.blue('[mangler]'), ...data)); + let ts2tsMangler = new index_1.Mangler(compile.projectPath, (...data) => fancyLog(ansiColors.blue('[mangler]'), ...data), { mangleExports: true, manglePrivateFields: true }); const newContentsByFileName = ts2tsMangler.computeNewFileContents(new Set(['saveState'])); - mangleStream = es.through(function write(data) { + mangleStream = es.through(async function write(data) { const tsNormalPath = ts.normalizePath(data.path); - const newContents = newContentsByFileName.get(tsNormalPath); + const newContents = (await newContentsByFileName).get(tsNormalPath); if (newContents !== undefined) { data.contents = Buffer.from(newContents.out); data.sourceMap = newContents.sourceMap && JSON.parse(newContents.sourceMap); } this.push(data); - }, function end() { - this.push(null); + }, async function end() { // free resources - newContentsByFileName.clear(); + (await newContentsByFileName).clear(); + this.push(null); ts2tsMangler = undefined; }); } @@ -281,4 +281,4 @@ exports.watchApiProposalNamesTask = task.define('watch-api-proposal-names', () = .pipe(util.debounce(task)) .pipe(gulp.dest('src')); }); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcGlsYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJjb21waWxhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztnR0FHZ0c7OztBQUVoRyxtQ0FBbUM7QUFDbkMseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3Qiw2QkFBNkI7QUFDN0IsMENBQTBDO0FBQzFDLDZCQUE2QjtBQUM3Qix5Q0FBNEM7QUFDNUMsK0JBQStCO0FBQy9CLHNDQUFzQztBQUN0QywwQ0FBMEM7QUFDMUMseUJBQXlCO0FBQ3pCLGlDQUFrQztBQUNsQyw4QkFBOEI7QUFDOUIsK0JBQStCO0FBQy9CLHlEQUE2QztBQUU3QyxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7QUFHakMsdUVBQXVFO0FBRXZFLE1BQU0sUUFBUSxHQUFHLElBQUEseUJBQWMsR0FBRSxDQUFDO0FBRWxDLFNBQVMsNEJBQTRCLENBQUMsR0FBVztJQUNoRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxTQUFTLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDckQsTUFBTSxPQUFPLEdBQXVCLEVBQUUsQ0FBQztJQUN2QyxPQUFPLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztJQUN4QixPQUFPLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztJQUN6QixJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMsRUFBRSxFQUFFLHNDQUFzQztRQUMvRSxPQUFPLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztLQUMxQjtJQUNELE9BQU8sQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0lBQzFCLE9BQU8sQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0lBQzFCLE9BQU8sQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM3QyxPQUFPLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxJQUFJ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 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcGlsYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJjb21waWxhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztnR0FHZ0c7OztBQUVoRyxtQ0FBbUM7QUFDbkMseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3Qiw2QkFBNkI7QUFDN0IsMENBQTBDO0FBQzFDLDZCQUE2QjtBQUM3Qix5Q0FBNEM7QUFDNUMsK0JBQStCO0FBQy9CLHNDQUFzQztBQUN0QywwQ0FBMEM7QUFDMUMseUJBQXlCO0FBQ3pCLGlDQUFrQztBQUNsQyw4QkFBOEI7QUFDOUIsK0JBQStCO0FBQy9CLDBDQUF5QztBQUV6QyxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7QUFHakMsdUVBQXVFO0FBRXZFLE1BQU0sUUFBUSxHQUFHLElBQUEseUJBQWMsR0FBRSxDQUFDO0FBRWxDLFNBQVMsNEJBQTRCLENBQUMsR0FBVztJQUNoRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxTQUFTLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDckQsTUFBTSxPQUFPLEdBQXVCLEVBQUUsQ0FBQztJQUN2QyxPQUFPLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztJQUN4QixPQUFPLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztJQUN6QixJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMsRUFBRSxFQUFFLHNDQUFzQztRQUMvRSxPQUFPLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztLQUMxQjtJQUNELE9BQU8sQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0lBQzFCLE9BQU8sQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0lBQzFCLE9BQU8sQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM3QyxPQUFPLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxJQUFJ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 \ No newline at end of file diff --git a/build/lib/compilation.ts b/build/lib/compilation.ts index d5cd1966221..d5da3f1cd89 100644 --- a/build/lib/compilation.ts +++ b/build/lib/compilation.ts @@ -17,7 +17,7 @@ import * as os from 'os'; import ts = require('typescript'); import * as File from 'vinyl'; import * as task from './task'; -import { Mangler } from './mangleTypeScript'; +import { Mangler } from './mangle/index'; import { RawSourceMap } from 'source-map'; const watch = require('./watch'); @@ -124,21 +124,22 @@ export function compileTask(src: string, out: string, build: boolean, options: { // mangle: TypeScript to TypeScript let mangleStream = es.through(); if (build && !options.disableMangle) { - let ts2tsMangler = new Mangler(compile.projectPath, (...data) => fancyLog(ansiColors.blue('[mangler]'), ...data)); + let ts2tsMangler = new Mangler(compile.projectPath, (...data) => fancyLog(ansiColors.blue('[mangler]'), ...data), { mangleExports: true, manglePrivateFields: true }); const newContentsByFileName = ts2tsMangler.computeNewFileContents(new Set(['saveState'])); - mangleStream = es.through(function write(data: File & { sourceMap?: RawSourceMap }) { + mangleStream = es.through(async function write(data: File & { sourceMap?: RawSourceMap }) { type TypeScriptExt = typeof ts & { normalizePath(path: string): string }; const tsNormalPath = (ts).normalizePath(data.path); - const newContents = newContentsByFileName.get(tsNormalPath); + const newContents = (await newContentsByFileName).get(tsNormalPath); if (newContents !== undefined) { data.contents = Buffer.from(newContents.out); data.sourceMap = newContents.sourceMap && JSON.parse(newContents.sourceMap); } this.push(data); - }, function end() { - this.push(null); + }, async function end() { // free resources - newContentsByFileName.clear(); + (await newContentsByFileName).clear(); + + this.push(null); (ts2tsMangler) = undefined; }); } diff --git a/build/lib/mangle/index.js b/build/lib/mangle/index.js new file mode 100644 index 00000000000..8d509b9590d --- /dev/null +++ b/build/lib/mangle/index.js @@ -0,0 +1,665 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Mangler = void 0; +const fs = require("fs"); +const path = require("path"); +const process_1 = require("process"); +const source_map_1 = require("source-map"); +const ts = require("typescript"); +const url_1 = require("url"); +const workerpool = require("workerpool"); +const staticLanguageServiceHost_1 = require("./staticLanguageServiceHost"); +const buildfile = require('../../../src/buildfile'); +class ShortIdent { + prefix; + static _keywords = new Set(['await', 'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger', + 'default', 'delete', 'do', 'else', 'export', 'extends', 'false', 'finally', 'for', 'function', 'if', + 'import', 'in', 'instanceof', 'let', 'new', 'null', 'return', 'static', 'super', 'switch', 'this', 'throw', + 'true', 'try', 'typeof', 'var', 'void', 'while', 'with', 'yield']); + static _alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890$_'.split(''); + _value = 0; + constructor(prefix) { + this.prefix = prefix; + } + next(isNameTaken) { + const candidate = this.prefix + ShortIdent.convert(this._value); + this._value++; + if (ShortIdent._keywords.has(candidate) || /^[_0-9]/.test(candidate) || isNameTaken?.(candidate)) { + // try again + return this.next(isNameTaken); + } + return candidate; + } + static convert(n) { + const base = this._alphabet.length; + let result = ''; + do { + const rest = n % base; + result += this._alphabet[rest]; + n = (n / base) | 0; + } while (n > 0); + return result; + } +} +var FieldType; +(function (FieldType) { + FieldType[FieldType["Public"] = 0] = "Public"; + FieldType[FieldType["Protected"] = 1] = "Protected"; + FieldType[FieldType["Private"] = 2] = "Private"; +})(FieldType || (FieldType = {})); +class ClassData { + fileName; + node; + fields = new Map(); + replacements; + parent; + children; + constructor(fileName, node) { + // analyse all fields (properties and methods). Find usages of all protected and + // private ones and keep track of all public ones (to prevent naming collisions) + this.fileName = fileName; + this.node = node; + const candidates = []; + for (const member of node.members) { + if (ts.isMethodDeclaration(member)) { + // method `foo() {}` + candidates.push(member); + } + else if (ts.isPropertyDeclaration(member)) { + // property `foo = 234` + candidates.push(member); + } + else if (ts.isGetAccessor(member)) { + // getter: `get foo() { ... }` + candidates.push(member); + } + else if (ts.isSetAccessor(member)) { + // setter: `set foo() { ... }` + candidates.push(member); + } + else if (ts.isConstructorDeclaration(member)) { + // constructor-prop:`constructor(private foo) {}` + for (const param of member.parameters) { + if (hasModifier(param, ts.SyntaxKind.PrivateKeyword) + || hasModifier(param, ts.SyntaxKind.ProtectedKeyword) + || hasModifier(param, ts.SyntaxKind.PublicKeyword) + || hasModifier(param, ts.SyntaxKind.ReadonlyKeyword)) { + candidates.push(param); + } + } + } + } + for (const member of candidates) { + const ident = ClassData._getMemberName(member); + if (!ident) { + continue; + } + const type = ClassData._getFieldType(member); + this.fields.set(ident, { type, pos: member.name.getStart() }); + } + } + static _getMemberName(node) { + if (!node.name) { + return undefined; + } + const { name } = node; + let ident = name.getText(); + if (name.kind === ts.SyntaxKind.ComputedPropertyName) { + if (name.expression.kind !== ts.SyntaxKind.StringLiteral) { + // unsupported: [Symbol.foo] or [abc + 'field'] + return; + } + // ['foo'] + ident = name.expression.getText().slice(1, -1); + } + return ident; + } + static _getFieldType(node) { + if (hasModifier(node, ts.SyntaxKind.PrivateKeyword)) { + return 2 /* FieldType.Private */; + } + else if (hasModifier(node, ts.SyntaxKind.ProtectedKeyword)) { + return 1 /* FieldType.Protected */; + } + else { + return 0 /* FieldType.Public */; + } + } + static _shouldMangle(type) { + return type === 2 /* FieldType.Private */ + || type === 1 /* FieldType.Protected */; + } + static makeImplicitPublicActuallyPublic(data, reportViolation) { + // TS-HACK + // A subtype can make an inherited protected field public. To prevent accidential + // mangling of public fields we mark the original (protected) fields as public... + for (const [name, info] of data.fields) { + if (info.type !== 0 /* FieldType.Public */) { + continue; + } + let parent = data.parent; + while (parent) { + if (parent.fields.get(name)?.type === 1 /* FieldType.Protected */) { + const parentPos = parent.node.getSourceFile().getLineAndCharacterOfPosition(parent.fields.get(name).pos); + const infoPos = data.node.getSourceFile().getLineAndCharacterOfPosition(info.pos); + reportViolation(name, `'${name}' from ${parent.fileName}:${parentPos.line + 1}`, `${data.fileName}:${infoPos.line + 1}`); + parent.fields.get(name).type = 0 /* FieldType.Public */; + } + parent = parent.parent; + } + } + } + static fillInReplacement(data) { + if (data.replacements) { + // already done + return; + } + // fill in parents first + if (data.parent) { + ClassData.fillInReplacement(data.parent); + } + data.replacements = new Map(); + const isNameTaken = (name) => { + // locally taken + if (data._isNameTaken(name)) { + return true; + } + // parents + let parent = data.parent; + while (parent) { + if (parent._isNameTaken(name)) { + return true; + } + parent = parent.parent; + } + // children + if (data.children) { + const stack = [...data.children]; + while (stack.length) { + const node = stack.pop(); + if (node._isNameTaken(name)) { + return true; + } + if (node.children) { + stack.push(...node.children); + } + } + } + return false; + }; + const identPool = new ShortIdent(''); + for (const [name, info] of data.fields) { + if (ClassData._shouldMangle(info.type)) { + const shortName = identPool.next(isNameTaken); + data.replacements.set(name, shortName); + } + } + } + // a name is taken when a field that doesn't get mangled exists or + // when the name is already in use for replacement + _isNameTaken(name) { + if (this.fields.has(name) && !ClassData._shouldMangle(this.fields.get(name).type)) { + // public field + return true; + } + if (this.replacements) { + for (const shortName of this.replacements.values()) { + if (shortName === name) { + // replaced already (happens wih super types) + return true; + } + } + } + if (isNameTakenInFile(this.node, name)) { + return true; + } + return false; + } + lookupShortName(name) { + let value = this.replacements.get(name); + let parent = this.parent; + while (parent) { + if (parent.replacements.has(name) && parent.fields.get(name)?.type === 1 /* FieldType.Protected */) { + value = parent.replacements.get(name) ?? value; + } + parent = parent.parent; + } + return value; + } + // --- parent chaining + addChild(child) { + this.children ??= []; + this.children.push(child); + child.parent = this; + } +} +function isNameTakenInFile(node, name) { + const identifiers = node.getSourceFile().identifiers; + if (identifiers instanceof Map) { + if (identifiers.has(name)) { + return true; + } + } + return false; +} +const fileIdents = new class { + idents = new ShortIdent('$'); + next() { + return this.idents.next(); + } +}; +const skippedExportMangledFiles = [ + // Build + 'css.build', + 'nls.build', + // Monaco + 'editorCommon', + 'editorOptions', + 'editorZoom', + 'standaloneEditor', + 'standaloneEnums', + 'standaloneLanguages', + // Generated + 'extensionsApiProposals', + // Module passed around as type + 'pfs', + // entry points + ...[ + buildfile.entrypoint('vs/server/node/server.main', []), + buildfile.entrypoint('vs/workbench/workbench.desktop.main', []), + buildfile.base, + buildfile.workerExtensionHost, + buildfile.workerNotebook, + buildfile.workerLanguageDetection, + buildfile.workerLocalFileSearch, + buildfile.workerProfileAnalysis, + buildfile.workbenchDesktop, + buildfile.workbenchWeb, + buildfile.code + ].flat().map(x => x.name), +]; +const skippedExportMangledProjects = [ + // Test projects + 'vscode-api-tests', + // These projects use webpack to dynamically rewrite imports, which messes up our mangling + 'configuration-editing', + 'microsoft-authentication', + 'github-authentication', + 'html-language-features/server', +]; +const skippedExportMangledSymbols = [ + // Don't mangle extension entry points + 'activate', + 'deactivate', +]; +class DeclarationData { + fileName; + node; + service; + replacementName; + constructor(fileName, node, service) { + this.fileName = fileName; + this.node = node; + this.service = service; + // Todo: generate replacement names based on usage count, with more used names getting shorter identifiers + this.replacementName = fileIdents.next(); + } + get locations() { + if (ts.isVariableDeclaration(this.node)) { + // If the const aliases any types, we need to rename those too + const definitionResult = this.service.getDefinitionAndBoundSpan(this.fileName, this.node.name.getStart()); + if (definitionResult?.definitions && definitionResult.definitions.length > 1) { + return definitionResult.definitions.map(x => ({ fileName: x.fileName, offset: x.textSpan.start })); + } + } + return [{ + fileName: this.fileName, + offset: this.node.name.getStart() + }]; + } + shouldMangle(newName) { + const currentName = this.node.name.getText(); + if (currentName.startsWith('$') || skippedExportMangledSymbols.includes(currentName)) { + return false; + } + // New name is longer the existing one :'( + if (newName.length >= currentName.length) { + return false; + } + // Don't mangle functions we've explicitly opted out + if (this.node.getFullText().includes('@skipMangle')) { + return false; + } + return true; + } +} +/** + * TypeScript2TypeScript transformer that mangles all private and protected fields + * + * 1. Collect all class fields (properties, methods) + * 2. Collect all sub and super-type relations between classes + * 3. Compute replacement names for each field + * 4. Lookup rename locations for these fields + * 5. Prepare and apply edits + */ +class Mangler { + projectPath; + log; + config; + allClassDataByKey = new Map(); + allExportedSymbols = new Set(); + service; + renameWorkerPool; + constructor(projectPath, log = () => { }, config) { + this.projectPath = projectPath; + this.log = log; + this.config = config; + this.service = ts.createLanguageService(new staticLanguageServiceHost_1.StaticLanguageServiceHost(projectPath)); + this.renameWorkerPool = workerpool.pool(path.join(__dirname, 'renameWorker.js'), { + maxWorkers: 2, + minWorkers: 'max' + }); + } + async computeNewFileContents(strictImplicitPublicHandling) { + // STEP: + // - Find all classes and their field info. + // - Find exported symbols. + const visit = (node) => { + if (this.config.manglePrivateFields) { + if (ts.isClassDeclaration(node) || ts.isClassExpression(node)) { + const anchor = node.name ?? node; + const key = `${node.getSourceFile().fileName}|${anchor.getStart()}`; + if (this.allClassDataByKey.has(key)) { + throw new Error('DUPE?'); + } + this.allClassDataByKey.set(key, new ClassData(node.getSourceFile().fileName, node)); + } + } + if (this.config.mangleExports) { + // Find exported classes, functions, and vars + if (( + // Exported class + ts.isClassDeclaration(node) + && hasModifier(node, ts.SyntaxKind.ExportKeyword) + && node.name) || ( + // Exported function + ts.isFunctionDeclaration(node) + && ts.isSourceFile(node.parent) + && hasModifier(node, ts.SyntaxKind.ExportKeyword) + && node.name && node.body // On named function and not on the overload + ) || ( + // Exported variable + ts.isVariableDeclaration(node) + && hasModifier(node.parent.parent, ts.SyntaxKind.ExportKeyword) // Variable statement is exported + && ts.isSourceFile(node.parent.parent.parent)) + // Disabled for now because we need to figure out how to handle + // enums that are used in monaco or extHost interfaces. + /* || ( + // Exported enum + ts.isEnumDeclaration(node) + && ts.isSourceFile(node.parent) + && hasModifier(node, ts.SyntaxKind.ExportKeyword) + && !hasModifier(node, ts.SyntaxKind.ConstKeyword) // Don't bother mangling const enums because these are inlined + && node.name + */ + ) { + if (isInAmbientContext(node)) { + return; + } + this.allExportedSymbols.add(new DeclarationData(node.getSourceFile().fileName, node, this.service)); + } + } + ts.forEachChild(node, visit); + }; + for (const file of this.service.getProgram().getSourceFiles()) { + if (!file.isDeclarationFile) { + ts.forEachChild(file, visit); + } + } + this.log(`Done collecting. Classes: ${this.allClassDataByKey.size}. Exported symbols: ${this.allExportedSymbols.size}`); + // STEP: connect sub and super-types + const setupParents = (data) => { + const extendsClause = data.node.heritageClauses?.find(h => h.token === ts.SyntaxKind.ExtendsKeyword); + if (!extendsClause) { + // no EXTENDS-clause + return; + } + const info = this.service.getDefinitionAtPosition(data.fileName, extendsClause.types[0].expression.getEnd()); + if (!info || info.length === 0) { + // throw new Error('SUPER type not found'); + return; + } + if (info.length !== 1) { + // inherits from declared/library type + return; + } + const [definition] = info; + const key = `${definition.fileName}|${definition.textSpan.start}`; + const parent = this.allClassDataByKey.get(key); + if (!parent) { + // throw new Error(`SUPER type not found: ${key}`); + return; + } + parent.addChild(data); + }; + for (const data of this.allClassDataByKey.values()) { + setupParents(data); + } + // STEP: make implicit public (actually protected) field really public + const violations = new Map(); + let violationsCauseFailure = false; + for (const data of this.allClassDataByKey.values()) { + ClassData.makeImplicitPublicActuallyPublic(data, (name, what, why) => { + const arr = violations.get(what); + if (arr) { + arr.push(why); + } + else { + violations.set(what, [why]); + } + if (strictImplicitPublicHandling && !strictImplicitPublicHandling.has(name)) { + violationsCauseFailure = true; + } + }); + } + for (const [why, whys] of violations) { + this.log(`WARN: ${why} became PUBLIC because of: ${whys.join(' , ')}`); + } + if (violationsCauseFailure) { + const message = 'Protected fields have been made PUBLIC. This hurts minification and is therefore not allowed. Review the WARN messages further above'; + this.log(`ERROR: ${message}`); + throw new Error(message); + } + // STEP: compute replacement names for each class + for (const data of this.allClassDataByKey.values()) { + ClassData.fillInReplacement(data); + } + this.log(`Done creating class replacements`); + // STEP: prepare rename edits + this.log(`Starting prepare rename edits`); + const editsByFile = new Map(); + const appendEdit = (fileName, edit) => { + const edits = editsByFile.get(fileName); + if (!edits) { + editsByFile.set(fileName, [edit]); + } + else { + edits.push(edit); + } + }; + const appendRename = (newText, loc) => { + appendEdit(loc.fileName, { + newText: (loc.prefixText || '') + newText + (loc.suffixText || ''), + offset: loc.textSpan.start, + length: loc.textSpan.length + }); + }; + const renameResults = []; + const queueRename = (fileName, pos, newName) => { + renameResults.push(Promise.resolve(this.renameWorkerPool.exec('findRenameLocations', [this.projectPath, fileName, pos])) + .then((locations) => ({ newName, locations }))); + }; + for (const data of this.allClassDataByKey.values()) { + if (hasModifier(data.node, ts.SyntaxKind.DeclareKeyword)) { + continue; + } + fields: for (const [name, info] of data.fields) { + if (!ClassData._shouldMangle(info.type)) { + continue fields; + } + // TS-HACK: protected became public via 'some' child + // and because of that we might need to ignore this now + let parent = data.parent; + while (parent) { + if (parent.fields.get(name)?.type === 0 /* FieldType.Public */) { + continue fields; + } + parent = parent.parent; + } + const newName = data.lookupShortName(name); + queueRename(data.fileName, info.pos, newName); + } + } + for (const data of this.allExportedSymbols.values()) { + if (data.fileName.endsWith('.d.ts') + || skippedExportMangledProjects.some(proj => data.fileName.includes(proj)) + || skippedExportMangledFiles.some(file => data.fileName.endsWith(file + '.ts'))) { + continue; + } + if (!data.shouldMangle(data.replacementName)) { + continue; + } + const newText = data.replacementName; + for (const { fileName, offset } of data.locations) { + queueRename(fileName, offset, newText); + } + } + await Promise.all(renameResults).then((result) => { + for (const { newName, locations } of result) { + for (const loc of locations) { + appendRename(newName, loc); + } + } + }); + await this.renameWorkerPool.terminate(); + this.log(`Done preparing edits: ${editsByFile.size} files`); + // STEP: apply all rename edits (per file) + const result = new Map(); + let savedBytes = 0; + for (const item of this.service.getProgram().getSourceFiles()) { + const { mapRoot, sourceRoot } = this.service.getProgram().getCompilerOptions(); + const projectDir = path.dirname(this.projectPath); + const sourceMapRoot = mapRoot ?? (0, url_1.pathToFileURL)(sourceRoot ?? projectDir).toString(); + // source maps + let generator; + let newFullText; + const edits = editsByFile.get(item.fileName); + if (!edits) { + // just copy + newFullText = item.getFullText(); + } + else { + // source map generator + const relativeFileName = normalize(path.relative(projectDir, item.fileName)); + const mappingsByLine = new Map(); + // apply renames + edits.sort((a, b) => b.offset - a.offset); + const characters = item.getFullText().split(''); + let lastEdit; + for (const edit of edits) { + if (lastEdit && lastEdit.offset === edit.offset) { + // + if (lastEdit.length !== edit.length || lastEdit.newText !== edit.newText) { + this.log('ERROR: Overlapping edit', item.fileName, edit.offset, edits); + throw new Error('OVERLAPPING edit'); + } + else { + continue; + } + } + lastEdit = edit; + const mangledName = characters.splice(edit.offset, edit.length, edit.newText).join(''); + savedBytes += mangledName.length - edit.newText.length; + // source maps + const pos = item.getLineAndCharacterOfPosition(edit.offset); + let mappings = mappingsByLine.get(pos.line); + if (!mappings) { + mappings = []; + mappingsByLine.set(pos.line, mappings); + } + mappings.unshift({ + source: relativeFileName, + original: { line: pos.line + 1, column: pos.character }, + generated: { line: pos.line + 1, column: pos.character }, + name: mangledName + }, { + source: relativeFileName, + original: { line: pos.line + 1, column: pos.character + edit.length }, + generated: { line: pos.line + 1, column: pos.character + edit.newText.length }, + }); + } + // source map generation, make sure to get mappings per line correct + generator = new source_map_1.SourceMapGenerator({ file: path.basename(item.fileName), sourceRoot: sourceMapRoot }); + generator.setSourceContent(relativeFileName, item.getFullText()); + for (const [, mappings] of mappingsByLine) { + let lineDelta = 0; + for (const mapping of mappings) { + generator.addMapping({ + ...mapping, + generated: { line: mapping.generated.line, column: mapping.generated.column - lineDelta } + }); + lineDelta += mapping.original.column - mapping.generated.column; + } + } + newFullText = characters.join(''); + } + result.set(item.fileName, { out: newFullText, sourceMap: generator?.toString() }); + } + this.log(`Done: ${savedBytes / 1000}kb saved`); + return result; + } +} +exports.Mangler = Mangler; +// --- ast utils +function hasModifier(node, kind) { + const modifiers = ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined; + return Boolean(modifiers?.find(mode => mode.kind === kind)); +} +function isInAmbientContext(node) { + for (let p = node.parent; p; p = p.parent) { + if (ts.isModuleDeclaration(p)) { + return true; + } + } + return false; +} +function normalize(path) { + return path.replace(/\\/g, '/'); +} +async function _run() { + const root = path.join(__dirname, '..', '..', '..'); + const projectBase = path.join(root, 'src'); + const projectPath = path.join(projectBase, 'tsconfig.json'); + const newProjectBase = path.join(path.dirname(projectBase), path.basename(projectBase) + '2'); + fs.cpSync(projectBase, newProjectBase, { recursive: true }); + const mangler = new Mangler(projectPath, console.log, { + mangleExports: true, + manglePrivateFields: true, + }); + for (const [fileName, contents] of await mangler.computeNewFileContents(new Set(['saveState']))) { + const newFilePath = path.join(newProjectBase, path.relative(projectBase, fileName)); + await fs.promises.mkdir(path.dirname(newFilePath), { recursive: true }); + await fs.promises.writeFile(newFilePath, contents.out); + if (contents.sourceMap) { + await fs.promises.writeFile(newFilePath + '.map', contents.sourceMap); + } + } +} +if (__filename === process_1.argv[1]) { + _run(); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztnR0FHZ0c7OztBQUVoRyx5QkFBeUI7QUFDekIsNkJBQTZCO0FBQzdCLHFDQUErQjtBQUMvQiwyQ0FBeUQ7QUFDekQsaUNBQWlDO0FBQ2pDLDZCQUFvQztBQUNwQyx5Q0FBeUM7QUFDekMsMkVBQXdFO0FBQ3hFLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO0FBRXBELE1BQU0sVUFBVTtJQVlHO0lBVlYsTUFBTSxDQUFDLFNBQVMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVO1FBQzlHLFNBQVMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxJQUFJO1FBQ25HLFFBQVEsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsT0FBTztRQUMxRyxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUU1RCxNQUFNLENBQUMsU0FBUyxHQUFHLGtFQUFrRSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUVoRyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBRW5CLFlBQ2tCLE1BQWM7UUFBZCxXQUFNLEdBQU4sTUFBTSxDQUFRO0lBQzVCLENBQUM7SUFFTCxJQUFJLENBQUMsV0FBdUM7UUFDM0Ms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 \ No newline at end of file diff --git a/build/lib/mangleTypeScript.ts b/build/lib/mangle/index.ts similarity index 63% rename from build/lib/mangleTypeScript.ts rename to build/lib/mangle/index.ts index f2707dd3238..c0bfdc9e3ed 100644 --- a/build/lib/mangleTypeScript.ts +++ b/build/lib/mangle/index.ts @@ -3,12 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as ts from 'typescript'; -import * as path from 'path'; import * as fs from 'fs'; +import * as path from 'path'; import { argv } from 'process'; import { Mapping, SourceMapGenerator } from 'source-map'; +import * as ts from 'typescript'; import { pathToFileURL } from 'url'; +import * as workerpool from 'workerpool'; +import { StaticLanguageServiceHost } from './staticLanguageServiceHost'; +const buildfile = require('../../../src/buildfile'); class ShortIdent { @@ -17,21 +20,20 @@ class ShortIdent { 'import', 'in', 'instanceof', 'let', 'new', 'null', 'return', 'static', 'super', 'switch', 'this', 'throw', 'true', 'try', 'typeof', 'var', 'void', 'while', 'with', 'yield']); - private static _alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''); + private static _alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890$_'.split(''); private _value = 0; - private readonly _isNameTaken: (name: string) => boolean; - constructor(isNameTaken: (name: string) => boolean) { - this._isNameTaken = name => ShortIdent._keywords.has(name) || isNameTaken(name); - } + constructor( + private readonly prefix: string + ) { } - next(): string { - const candidate = ShortIdent.convert(this._value); + next(isNameTaken?: (name: string) => boolean): string { + const candidate = this.prefix + ShortIdent.convert(this._value); this._value++; - if (this._isNameTaken(candidate)) { + if (ShortIdent._keywords.has(candidate) || /^[_0-9]/.test(candidate) || isNameTaken?.(candidate)) { // try again - return this.next(); + return this.next(isNameTaken); } return candidate; } @@ -181,8 +183,7 @@ class ClassData { data.replacements = new Map(); - const identPool = new ShortIdent(name => { - + const isNameTaken = (name: string) => { // locally taken if (data._isNameTaken(name)) { return true; @@ -212,11 +213,12 @@ class ClassData { } return false; - }); + }; + const identPool = new ShortIdent(''); for (const [name, info] of data.fields) { if (ClassData._shouldMangle(info.type)) { - const shortName = identPool.next(); + const shortName = identPool.next(isNameTaken); data.replacements.set(name, shortName); } } @@ -237,12 +239,11 @@ class ClassData { } } } - if ((this.node.getSourceFile()).identifiers instanceof Map) { - // taken by any other usage - if ((this.node.getSourceFile()).identifiers.has(name)) { - return true; - } + + if (isNameTakenInFile(this.node, name)) { + return true; } + return false; } @@ -267,59 +268,122 @@ class ClassData { } } -class StaticLanguageServiceHost implements ts.LanguageServiceHost { - - private readonly _cmdLine: ts.ParsedCommandLine; - private readonly _scriptSnapshots: Map = new Map(); - - constructor(readonly projectPath: string) { - const existingOptions: Partial = {}; - const parsed = ts.readConfigFile(projectPath, ts.sys.readFile); - if (parsed.error) { - throw parsed.error; - } - this._cmdLine = ts.parseJsonConfigFileContent(parsed.config, ts.sys, path.dirname(projectPath), existingOptions); - if (this._cmdLine.errors.length > 0) { - throw parsed.error; +function isNameTakenInFile(node: ts.Node, name: string): boolean { + const identifiers = (node.getSourceFile()).identifiers; + if (identifiers instanceof Map) { + if (identifiers.has(name)) { + return true; } } - getCompilationSettings(): ts.CompilerOptions { - return this._cmdLine.options; + return false; +} + +const fileIdents = new class { + private readonly idents = new ShortIdent('$'); + + next() { + return this.idents.next(); } - getScriptFileNames(): string[] { - return this._cmdLine.fileNames; +}; + +const skippedExportMangledFiles = [ + // Build + 'css.build', + 'nls.build', + + // Monaco + 'editorCommon', + 'editorOptions', + 'editorZoom', + 'standaloneEditor', + 'standaloneEnums', + 'standaloneLanguages', + + // Generated + 'extensionsApiProposals', + + // Module passed around as type + 'pfs', + + // entry points + ...[ + buildfile.entrypoint('vs/server/node/server.main', []), + buildfile.entrypoint('vs/workbench/workbench.desktop.main', []), + buildfile.base, + buildfile.workerExtensionHost, + buildfile.workerNotebook, + buildfile.workerLanguageDetection, + buildfile.workerLocalFileSearch, + buildfile.workerProfileAnalysis, + buildfile.workbenchDesktop, + buildfile.workbenchWeb, + buildfile.code + ].flat().map(x => x.name), +]; + +const skippedExportMangledProjects = [ + // Test projects + 'vscode-api-tests', + + // These projects use webpack to dynamically rewrite imports, which messes up our mangling + 'configuration-editing', + 'microsoft-authentication', + 'github-authentication', + 'html-language-features/server', +]; + +const skippedExportMangledSymbols = [ + // Don't mangle extension entry points + 'activate', + 'deactivate', +]; + +class DeclarationData { + + readonly replacementName: string; + + constructor( + readonly fileName: string, + readonly node: ts.FunctionDeclaration | ts.ClassDeclaration | ts.EnumDeclaration | ts.VariableDeclaration, + private readonly service: ts.LanguageService, + ) { + // Todo: generate replacement names based on usage count, with more used names getting shorter identifiers + this.replacementName = fileIdents.next(); } - getScriptVersion(_fileName: string): string { - return '1'; - } - getProjectVersion(): string { - return '1'; - } - getScriptSnapshot(fileName: string): ts.IScriptSnapshot | undefined { - let result: ts.IScriptSnapshot | undefined = this._scriptSnapshots.get(fileName); - if (result === undefined) { - const content = ts.sys.readFile(fileName); - if (content === undefined) { - return undefined; + + get locations(): Iterable<{ fileName: string; offset: number }> { + if (ts.isVariableDeclaration(this.node)) { + // If the const aliases any types, we need to rename those too + const definitionResult = this.service.getDefinitionAndBoundSpan(this.fileName, this.node.name.getStart()); + if (definitionResult?.definitions && definitionResult.definitions.length > 1) { + return definitionResult.definitions.map(x => ({ fileName: x.fileName, offset: x.textSpan.start })); } - result = ts.ScriptSnapshot.fromString(content); - this._scriptSnapshots.set(fileName, result); } - return result; + + return [{ + fileName: this.fileName, + offset: this.node.name!.getStart() + }]; } - getCurrentDirectory(): string { - return path.dirname(this.projectPath); + + shouldMangle(newName: string): boolean { + const currentName = this.node.name!.getText(); + if (currentName.startsWith('$') || skippedExportMangledSymbols.includes(currentName)) { + return false; + } + + // New name is longer the existing one :'( + if (newName.length >= currentName.length) { + return false; + } + + // Don't mangle functions we've explicitly opted out + if (this.node.getFullText().includes('@skipMangle')) { + return false; + } + + return true; } - getDefaultLibFileName(options: ts.CompilerOptions): string { - return ts.getDefaultLibFilePath(options); - } - directoryExists = ts.sys.directoryExists; - getDirectories = ts.sys.getDirectories; - fileExists = ts.sys.fileExists; - readFile = ts.sys.readFile; - readDirectory = ts.sys.readDirectory; - // this is necessary to make source references work. - realpath = ts.sys.realpath; } export interface MangleOutput { @@ -339,26 +403,82 @@ export interface MangleOutput { export class Mangler { private readonly allClassDataByKey = new Map(); + private readonly allExportedSymbols = new Set(); private readonly service: ts.LanguageService; + private readonly renameWorkerPool: workerpool.WorkerPool; - constructor(readonly projectPath: string, readonly log: typeof console.log = () => { }) { + constructor( + private readonly projectPath: string, + private readonly log: typeof console.log = () => { }, + private readonly config: { readonly manglePrivateFields: boolean; readonly mangleExports: boolean }, + ) { this.service = ts.createLanguageService(new StaticLanguageServiceHost(projectPath)); + + this.renameWorkerPool = workerpool.pool(path.join(__dirname, 'renameWorker.js'), { + maxWorkers: 2, + minWorkers: 'max' + }); } - computeNewFileContents(strictImplicitPublicHandling?: Set): Map { + async computeNewFileContents(strictImplicitPublicHandling?: Set): Promise> { - // STEP: find all classes and their field info + // STEP: + // - Find all classes and their field info. + // - Find exported symbols. const visit = (node: ts.Node): void => { - if (ts.isClassDeclaration(node) || ts.isClassExpression(node)) { - const anchor = node.name ?? node; - const key = `${node.getSourceFile().fileName}|${anchor.getStart()}`; - if (this.allClassDataByKey.has(key)) { - throw new Error('DUPE?'); + if (this.config.manglePrivateFields) { + if (ts.isClassDeclaration(node) || ts.isClassExpression(node)) { + const anchor = node.name ?? node; + const key = `${node.getSourceFile().fileName}|${anchor.getStart()}`; + if (this.allClassDataByKey.has(key)) { + throw new Error('DUPE?'); + } + this.allClassDataByKey.set(key, new ClassData(node.getSourceFile().fileName, node)); } - this.allClassDataByKey.set(key, new ClassData(node.getSourceFile().fileName, node)); } + + if (this.config.mangleExports) { + // Find exported classes, functions, and vars + if ( + ( + // Exported class + ts.isClassDeclaration(node) + && hasModifier(node, ts.SyntaxKind.ExportKeyword) + && node.name + ) || ( + // Exported function + ts.isFunctionDeclaration(node) + && ts.isSourceFile(node.parent) + && hasModifier(node, ts.SyntaxKind.ExportKeyword) + && node.name && node.body // On named function and not on the overload + ) || ( + // Exported variable + ts.isVariableDeclaration(node) + && hasModifier(node.parent.parent, ts.SyntaxKind.ExportKeyword) // Variable statement is exported + && ts.isSourceFile(node.parent.parent.parent) + ) + + // Disabled for now because we need to figure out how to handle + // enums that are used in monaco or extHost interfaces. + /* || ( + // Exported enum + ts.isEnumDeclaration(node) + && ts.isSourceFile(node.parent) + && hasModifier(node, ts.SyntaxKind.ExportKeyword) + && !hasModifier(node, ts.SyntaxKind.ConstKeyword) // Don't bother mangling const enums because these are inlined + && node.name + */ + ) { + if (isInAmbientContext(node)) { + return; + } + + this.allExportedSymbols.add(new DeclarationData(node.getSourceFile().fileName, node, this.service)); + } + } + ts.forEachChild(node, visit); }; @@ -367,7 +487,7 @@ export class Mangler { ts.forEachChild(file, visit); } } - this.log(`Done collecting classes: ${this.allClassDataByKey.size}`); + this.log(`Done collecting. Classes: ${this.allClassDataByKey.size}. Exported symbols: ${this.allExportedSymbols.size}`); // STEP: connect sub and super-types @@ -433,9 +553,11 @@ export class Mangler { for (const data of this.allClassDataByKey.values()) { ClassData.fillInReplacement(data); } - this.log(`Done creating replacements`); + this.log(`Done creating class replacements`); // STEP: prepare rename edits + this.log(`Starting prepare rename edits`); + type Edit = { newText: string; offset: number; length: number }; const editsByFile = new Map(); @@ -447,9 +569,24 @@ export class Mangler { edits.push(edit); } }; + const appendRename = (newText: string, loc: ts.RenameLocation) => { + appendEdit(loc.fileName, { + newText: (loc.prefixText || '') + newText + (loc.suffixText || ''), + offset: loc.textSpan.start, + length: loc.textSpan.length + }); + }; + + type RenameFn = (projectName: string, fileName: string, pos: number) => ts.RenameLocation[]; + + const renameResults: Array> = []; + + const queueRename = (fileName: string, pos: number, newName: string) => { + renameResults.push(Promise.resolve(this.renameWorkerPool.exec('findRenameLocations', [this.projectPath, fileName, pos])) + .then((locations) => ({ newName, locations }))); + }; for (const data of this.allClassDataByKey.values()) { - if (hasModifier(data.node, ts.SyntaxKind.DeclareKeyword)) { continue; } @@ -469,18 +606,39 @@ export class Mangler { parent = parent.parent; } - const newText = data.lookupShortName(name); - const locations = this.service.findRenameLocations(data.fileName, info.pos, false, false, true) ?? []; - for (const loc of locations) { - appendEdit(loc.fileName, { - newText: (loc.prefixText || '') + newText + (loc.suffixText || ''), - offset: loc.textSpan.start, - length: loc.textSpan.length - }); - } + const newName = data.lookupShortName(name); + queueRename(data.fileName, info.pos, newName); } } + for (const data of this.allExportedSymbols.values()) { + if (data.fileName.endsWith('.d.ts') + || skippedExportMangledProjects.some(proj => data.fileName.includes(proj)) + || skippedExportMangledFiles.some(file => data.fileName.endsWith(file + '.ts')) + ) { + continue; + } + + if (!data.shouldMangle(data.replacementName)) { + continue; + } + + const newText = data.replacementName; + for (const { fileName, offset } of data.locations) { + queueRename(fileName, offset, newText); + } + } + + await Promise.all(renameResults).then((result) => { + for (const { newName, locations } of result) { + for (const loc of locations) { + appendRename(newName, loc); + } + } + }); + + await this.renameWorkerPool.terminate(); + this.log(`Done preparing edits: ${editsByFile.size} files`); // STEP: apply all rename edits (per file) @@ -579,17 +737,32 @@ function hasModifier(node: ts.Node, kind: ts.SyntaxKind) { return Boolean(modifiers?.find(mode => mode.kind === kind)); } +function isInAmbientContext(node: ts.Node): boolean { + for (let p = node.parent; p; p = p.parent) { + if (ts.isModuleDeclaration(p)) { + return true; + } + } + return false; +} + function normalize(path: string): string { return path.replace(/\\/g, '/'); } async function _run() { - - const projectPath = path.join(__dirname, '../../src/tsconfig.json'); - const projectBase = path.dirname(projectPath); + const root = path.join(__dirname, '..', '..', '..'); + const projectBase = path.join(root, 'src'); + const projectPath = path.join(projectBase, 'tsconfig.json'); const newProjectBase = path.join(path.dirname(projectBase), path.basename(projectBase) + '2'); - for await (const [fileName, contents] of new Mangler(projectPath, console.log).computeNewFileContents(new Set(['saveState']))) { + fs.cpSync(projectBase, newProjectBase, { recursive: true }); + + const mangler = new Mangler(projectPath, console.log, { + mangleExports: true, + manglePrivateFields: true, + }); + for (const [fileName, contents] of await mangler.computeNewFileContents(new Set(['saveState']))) { const newFilePath = path.join(newProjectBase, path.relative(projectBase, fileName)); await fs.promises.mkdir(path.dirname(newFilePath), { recursive: true }); await fs.promises.writeFile(newFilePath, contents.out); diff --git a/build/lib/mangle/renameWorker.js b/build/lib/mangle/renameWorker.js new file mode 100644 index 00000000000..ce4b96275a3 --- /dev/null +++ b/build/lib/mangle/renameWorker.js @@ -0,0 +1,20 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +const ts = require("typescript"); +const workerpool = require("workerpool"); +const staticLanguageServiceHost_1 = require("./staticLanguageServiceHost"); +let service; // = ts.createLanguageService(new StaticLanguageServiceHost(projectPath)); +function findRenameLocations(projectPath, fileName, position) { + if (!service) { + service = ts.createLanguageService(new staticLanguageServiceHost_1.StaticLanguageServiceHost(projectPath)); + } + return service.findRenameLocations(fileName, position, false, false, true) ?? []; +} +workerpool.worker({ + findRenameLocations +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVuYW1lV29ya2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicmVuYW1lV29ya2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7QUFFaEcsaUNBQWlDO0FBQ2pDLHlDQUF5QztBQUN6QywyRUFBd0U7QUFFeEUsSUFBSSxPQUF1QyxDQUFDLENBQUEsMEVBQTBFO0FBRXRILFNBQVMsbUJBQW1CLENBQzNCLFdBQW1CLEVBQ25CLFFBQWdCLEVBQ2hCLFFBQWdCO0lBRWhCLElBQUksQ0FBQyxPQUFPLEVBQUU7UUFDYixPQUFPLEdBQUcsRUFBRSxDQUFDLHFCQUFxQixDQUFDLElBQUkscURBQXlCLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztLQUMvRTtJQUVELE9BQU8sT0FBTyxDQUFDLG1CQUFtQixDQUFDLFFBQVEsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7QUFDbEYsQ0FBQztBQUVELFVBQVUsQ0FBQyxNQUFNLENBQUM7SUFDakIsbUJBQW1CO0NBQ25CLENBQUMsQ0FBQyJ9 \ No newline at end of file diff --git a/build/lib/mangle/renameWorker.ts b/build/lib/mangle/renameWorker.ts new file mode 100644 index 00000000000..b5d6bcd5bc9 --- /dev/null +++ b/build/lib/mangle/renameWorker.ts @@ -0,0 +1,26 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as ts from 'typescript'; +import * as workerpool from 'workerpool'; +import { StaticLanguageServiceHost } from './staticLanguageServiceHost'; + +let service: ts.LanguageService | undefined;// = ts.createLanguageService(new StaticLanguageServiceHost(projectPath)); + +function findRenameLocations( + projectPath: string, + fileName: string, + position: number, +): readonly ts.RenameLocation[] { + if (!service) { + service = ts.createLanguageService(new StaticLanguageServiceHost(projectPath)); + } + + return service.findRenameLocations(fileName, position, false, false, true) ?? []; +} + +workerpool.worker({ + findRenameLocations +}); diff --git a/build/lib/mangle/staticLanguageServiceHost.js b/build/lib/mangle/staticLanguageServiceHost.js new file mode 100644 index 00000000000..acf48be8442 --- /dev/null +++ b/build/lib/mangle/staticLanguageServiceHost.js @@ -0,0 +1,65 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.StaticLanguageServiceHost = void 0; +const ts = require("typescript"); +const path = require("path"); +class StaticLanguageServiceHost { + projectPath; + _cmdLine; + _scriptSnapshots = new Map(); + constructor(projectPath) { + this.projectPath = projectPath; + const existingOptions = {}; + const parsed = ts.readConfigFile(projectPath, ts.sys.readFile); + if (parsed.error) { + throw parsed.error; + } + this._cmdLine = ts.parseJsonConfigFileContent(parsed.config, ts.sys, path.dirname(projectPath), existingOptions); + if (this._cmdLine.errors.length > 0) { + throw parsed.error; + } + } + getCompilationSettings() { + return this._cmdLine.options; + } + getScriptFileNames() { + return this._cmdLine.fileNames; + } + getScriptVersion(_fileName) { + return '1'; + } + getProjectVersion() { + return '1'; + } + getScriptSnapshot(fileName) { + let result = this._scriptSnapshots.get(fileName); + if (result === undefined) { + const content = ts.sys.readFile(fileName); + if (content === undefined) { + return undefined; + } + result = ts.ScriptSnapshot.fromString(content); + this._scriptSnapshots.set(fileName, result); + } + return result; + } + getCurrentDirectory() { + return path.dirname(this.projectPath); + } + getDefaultLibFileName(options) { + return ts.getDefaultLibFilePath(options); + } + directoryExists = ts.sys.directoryExists; + getDirectories = ts.sys.getDirectories; + fileExists = ts.sys.fileExists; + readFile = ts.sys.readFile; + readDirectory = ts.sys.readDirectory; + // this is necessary to make source references work. + realpath = ts.sys.realpath; +} +exports.StaticLanguageServiceHost = StaticLanguageServiceHost; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGljTGFuZ3VhZ2VTZXJ2aWNlSG9zdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInN0YXRpY0xhbmd1YWdlU2VydmljZUhvc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Z0dBR2dHOzs7QUFFaEcsaUNBQWlDO0FBQ2pDLDZCQUE2QjtBQUU3QixNQUFhLHlCQUF5QjtJQUtoQjtJQUhKLFFBQVEsQ0FBdUI7SUFDL0IsZ0JBQWdCLEdBQW9DLElBQUksR0FBRyxFQUFFLENBQUM7SUFFL0UsWUFBcUIsV0FBbUI7UUFBbkIsZ0JBQVcsR0FBWCxXQUFXLENBQVE7UUFDdkMsTUFBTSxlQUFlLEdBQWdDLEVBQUUsQ0FBQztRQUN4RCxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsY0FBYyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQy9ELElBQUksTUFBTSxDQUFDLEtBQUssRUFBRTtZQUNqQixNQUFNLE1BQU0sQ0FBQyxLQUFLLENBQUM7U0FDbkI7UUFDRCxJQUFJLENBQUMsUUFBUSxHQUFHLEVBQUUsQ0FBQywwQkFBMEIsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsRUFBRSxlQUFlLENBQUMsQ0FBQztRQUNqSCxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7WUFDcEMsTUFBTSxNQUFNLENBQUMsS0FBSyxDQUFDO1NBQ25CO0lBQ0YsQ0FBQztJQUNELHNCQUFzQjtRQUNyQixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0lBQzlCLENBQUM7SUFDRCxrQkFBa0I7UUFDakIsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQztJQUNoQyxDQUFDO0lBQ0QsZ0JBQWdCLENBQUMsU0FBaUI7UUFDakMsT0FBTyxHQUFHLENBQUM7SUFDWixDQUFDO0lBQ0QsaUJBQWlCO1FBQ2hCLE9BQU8sR0FBRyxDQUFDO0lBQ1osQ0FBQztJQUNELGlCQUFpQixDQUFDLFFBQWdCO1FBQ2pDLElBQUksTUFBTSxHQUFtQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2pGLElBQUksTUFBTSxLQUFLLFNBQVMsRUFBRTtZQUN6QixNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUMxQyxJQUFJLE9BQU8sS0FBSyxTQUFTLEVBQUU7Z0JBQzFCLE9BQU8sU0FBUyxDQUFDO2FBQ2pCO1lBQ0QsTUFBTSxHQUFHLEVBQUUsQ0FBQyxjQUFjLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQy9DLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1NBQzVDO1FBQ0QsT0FBTyxNQUFNLENBQUM7SUFDZixDQUFDO0lBQ0QsbUJBQW1CO1FBQ2xCLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUNELHFCQUFxQixDQUFDLE9BQTJCO1FBQ2hELE9BQU8sRUFBRSxDQUFDLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFDRCxlQUFlLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUM7SUFDekMsY0FBYyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDO0lBQ3ZDLFVBQVUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQztJQUMvQixRQUFRLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUM7SUFDM0IsYUFBYSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDO0lBQ3JDLG9EQUFvRDtJQUNwRCxRQUFRLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUM7Q0FDM0I7QUFyREQsOERBcURDIn0= \ No newline at end of file diff --git a/build/lib/mangle/staticLanguageServiceHost.ts b/build/lib/mangle/staticLanguageServiceHost.ts new file mode 100644 index 00000000000..c2793342ce3 --- /dev/null +++ b/build/lib/mangle/staticLanguageServiceHost.ts @@ -0,0 +1,62 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as ts from 'typescript'; +import * as path from 'path'; + +export class StaticLanguageServiceHost implements ts.LanguageServiceHost { + + private readonly _cmdLine: ts.ParsedCommandLine; + private readonly _scriptSnapshots: Map = new Map(); + + constructor(readonly projectPath: string) { + const existingOptions: Partial = {}; + const parsed = ts.readConfigFile(projectPath, ts.sys.readFile); + if (parsed.error) { + throw parsed.error; + } + this._cmdLine = ts.parseJsonConfigFileContent(parsed.config, ts.sys, path.dirname(projectPath), existingOptions); + if (this._cmdLine.errors.length > 0) { + throw parsed.error; + } + } + getCompilationSettings(): ts.CompilerOptions { + return this._cmdLine.options; + } + getScriptFileNames(): string[] { + return this._cmdLine.fileNames; + } + getScriptVersion(_fileName: string): string { + return '1'; + } + getProjectVersion(): string { + return '1'; + } + getScriptSnapshot(fileName: string): ts.IScriptSnapshot | undefined { + let result: ts.IScriptSnapshot | undefined = this._scriptSnapshots.get(fileName); + if (result === undefined) { + const content = ts.sys.readFile(fileName); + if (content === undefined) { + return undefined; + } + result = ts.ScriptSnapshot.fromString(content); + this._scriptSnapshots.set(fileName, result); + } + return result; + } + getCurrentDirectory(): string { + return path.dirname(this.projectPath); + } + getDefaultLibFileName(options: ts.CompilerOptions): string { + return ts.getDefaultLibFilePath(options); + } + directoryExists = ts.sys.directoryExists; + getDirectories = ts.sys.getDirectories; + fileExists = ts.sys.fileExists; + readFile = ts.sys.readFile; + readDirectory = ts.sys.readDirectory; + // this is necessary to make source references work. + realpath = ts.sys.realpath; +} diff --git a/build/lib/mangleTypeScript.js b/build/lib/mangleTypeScript.js index 7948e917e31..45b50148d12 100644 --- a/build/lib/mangleTypeScript.js +++ b/build/lib/mangleTypeScript.js @@ -16,18 +16,20 @@ class ShortIdent { 'default', 'delete', 'do', 'else', 'export', 'extends', 'false', 'finally', 'for', 'function', 'if', 'import', 'in', 'instanceof', 'let', 'new', 'null', 'return', 'static', 'super', 'switch', 'this', 'throw', 'true', 'try', 'typeof', 'var', 'void', 'while', 'with', 'yield']); - static _alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''); + static _alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890$_'.split(''); _value = 0; _isNameTaken; - constructor(isNameTaken) { - this._isNameTaken = name => ShortIdent._keywords.has(name) || isNameTaken(name); + prefix; + constructor(prefix, isNameTaken) { + this.prefix = prefix; + this._isNameTaken = name => ShortIdent._keywords.has(name) || /^[_0-9]/.test(name) || isNameTaken(name); } - next() { - const candidate = ShortIdent.convert(this._value); + next(localIsNameTaken) { + const candidate = this.prefix + ShortIdent.convert(this._value); this._value++; - if (this._isNameTaken(candidate)) { + if (this._isNameTaken(candidate) || localIsNameTaken?.(candidate)) { // try again - return this.next(); + return this.next(localIsNameTaken); } return candidate; } @@ -160,7 +162,7 @@ class ClassData { ClassData.fillInReplacement(data.parent); } data.replacements = new Map(); - const identPool = new ShortIdent(name => { + const identPool = new ShortIdent('', name => { // locally taken if (data._isNameTaken(name)) { return true; @@ -210,11 +212,8 @@ class ClassData { } } } - if (this.node.getSourceFile().identifiers instanceof Map) { - // taken by any other usage - if (this.node.getSourceFile().identifiers.has(name)) { - return true; - } + if (isNameTakenInFile(this.node, name)) { + return true; } return false; } @@ -236,6 +235,104 @@ class ClassData { child.parent = this; } } +function isNameTakenInFile(node, name) { + const identifiers = node.getSourceFile().identifiers; + if (identifiers instanceof Map) { + if (identifiers.has(name)) { + return true; + } + } + return false; +} +const fileIdents = new class { + idents = new ShortIdent('$', () => false); + next(file) { + return this.idents.next(name => isNameTakenInFile(file, name)); + } +}; +const skippedFiles = [ + // Build + 'css.build.ts', + 'nls.build.ts', + // Monaco + 'editorCommon.ts', + 'editorOptions.ts', + 'editorZoom.ts', + 'standaloneEditor.ts', + 'standaloneLanguages.ts', + // Generated + 'extensionsApiProposals.ts', + // Module passed around as type + 'pfs.ts', +]; +class DeclarationData { + fileName; + node; + replacementName; + constructor(fileName, node) { + this.fileName = fileName; + this.node = node; + this.replacementName = fileIdents.next(node.getSourceFile()); + } + get locations() { + return [{ + fileName: this.fileName, + offset: this.node.name.getStart() + }]; + } + shouldMangle(newName) { + // New name is longer the existing one :'( + if (newName.length >= this.node.name.getText().length) { + return false; + } + // Don't mangle functions we've explicitly opted out + if (this.node.getFullText().includes('@skipMangle')) { + return false; + } + // Don't mangle functions in the monaco editor API. + if (skippedFiles.some(file => this.node.getSourceFile().fileName.endsWith(file))) { + return false; + } + return true; + } +} +class ConstData { + fileName; + statement; + decl; + service; + replacementName; + constructor(fileName, statement, decl, service) { + this.fileName = fileName; + this.statement = statement; + this.decl = decl; + this.service = service; + this.replacementName = fileIdents.next(statement.getSourceFile()); + } + get locations() { + // If the const aliases any types, we need to rename those too + const definitionResult = this.service.getDefinitionAndBoundSpan(this.decl.getSourceFile().fileName, this.decl.name.getStart()); + if (definitionResult?.definitions && definitionResult.definitions.length > 1) { + return definitionResult.definitions.map(x => ({ fileName: x.fileName, offset: x.textSpan.start })); + } + return [{ fileName: this.fileName, offset: this.decl.name.getStart() }]; + } + shouldMangle(newName) { + // New name is longer the existing one :'( + if (newName.length >= this.decl.name.getText().length) { + return false; + } + // Don't mangle functions we've explicitly opted out + if (this.statement.getFullText().includes('@skipMangle')) { + return false; + } + // Don't mangle functions in some files + if (skippedFiles.some(file => this.decl.getSourceFile().fileName.endsWith(file))) { + return false; + } + return true; + } +} class StaticLanguageServiceHost { projectPath; _cmdLine; @@ -303,6 +400,7 @@ class Mangler { projectPath; log; allClassDataByKey = new Map(); + allExportedDeclarationsByKey = new Map(); service; constructor(projectPath, log = () => { }) { this.projectPath = projectPath; @@ -310,7 +408,7 @@ class Mangler { this.service = ts.createLanguageService(new StaticLanguageServiceHost(projectPath)); } computeNewFileContents(strictImplicitPublicHandling) { - // STEP: find all classes and their field info + // STEP find all classes and their field info. Find all exported consts and functions. const visit = (node) => { if (ts.isClassDeclaration(node) || ts.isClassExpression(node)) { const anchor = node.name ?? node; @@ -320,6 +418,39 @@ class Mangler { } this.allClassDataByKey.set(key, new ClassData(node.getSourceFile().fileName, node)); } + if (ts.isClassDeclaration(node) && hasModifier(node, ts.SyntaxKind.ExportKeyword)) { + if (node.name) { + const anchor = node.name; + const key = `${node.getSourceFile().fileName}|${anchor.getStart()}`; + if (this.allExportedDeclarationsByKey.has(key)) { + throw new Error('DUPE?'); + } + this.allExportedDeclarationsByKey.set(key, new DeclarationData(node.getSourceFile().fileName, node)); + } + } + if (ts.isFunctionDeclaration(node) + && ts.isSourceFile(node.parent) + && hasModifier(node, ts.SyntaxKind.ExportKeyword)) { + if (node.name && node.body) { // On named function and not on the overload + const anchor = node.name; + const key = `${node.getSourceFile().fileName}|${anchor.getStart()}`; + if (this.allExportedDeclarationsByKey.has(key)) { + throw new Error('DUPE?'); + } + this.allExportedDeclarationsByKey.set(key, new DeclarationData(node.getSourceFile().fileName, node)); + } + } + if (ts.isVariableStatement(node) + && ts.isSourceFile(node.parent) + && hasModifier(node, ts.SyntaxKind.ExportKeyword)) { + for (const decl of node.declarationList.declarations) { + const key = `${decl.getSourceFile().fileName}|${decl.name.getStart()}`; + if (this.allExportedDeclarationsByKey.has(key)) { + throw new Error('DUPE?'); + } + this.allExportedDeclarationsByKey.set(key, new ConstData(node.getSourceFile().fileName, node, decl, this.service)); + } + } ts.forEachChild(node, visit); }; for (const file of this.service.getProgram().getSourceFiles()) { @@ -327,7 +458,7 @@ class Mangler { ts.forEachChild(file, visit); } } - this.log(`Done collecting classes: ${this.allClassDataByKey.size}`); + this.log(`Done collecting. Classes: ${this.allClassDataByKey.size}. Exported const/fn: ${this.allExportedDeclarationsByKey.size}`); // STEP: connect sub and super-types const setupParents = (data) => { const extendsClause = data.node.heritageClauses?.find(h => h.token === ts.SyntaxKind.ExtendsKeyword); @@ -385,7 +516,7 @@ class Mangler { for (const data of this.allClassDataByKey.values()) { ClassData.fillInReplacement(data); } - this.log(`Done creating replacements`); + this.log(`Done creating class replacements`); const editsByFile = new Map(); const appendEdit = (fileName, edit) => { const edits = editsByFile.get(fileName); @@ -396,6 +527,13 @@ class Mangler { edits.push(edit); } }; + const appendRename = (newText, loc) => { + appendEdit(loc.fileName, { + newText: (loc.prefixText || '') + newText + (loc.suffixText || ''), + offset: loc.textSpan.start, + length: loc.textSpan.length + }); + }; for (const data of this.allClassDataByKey.values()) { if (hasModifier(data.node, ts.SyntaxKind.DeclareKeyword)) { continue; @@ -416,11 +554,19 @@ class Mangler { const newText = data.lookupShortName(name); const locations = this.service.findRenameLocations(data.fileName, info.pos, false, false, true) ?? []; for (const loc of locations) { - appendEdit(loc.fileName, { - newText: (loc.prefixText || '') + newText + (loc.suffixText || ''), - offset: loc.textSpan.start, - length: loc.textSpan.length - }); + appendRename(newText, loc); + } + } + } + for (const data of this.allExportedDeclarationsByKey.values()) { + if (!data.shouldMangle(data.replacementName)) { + continue; + } + const newText = data.replacementName; + for (const { fileName, offset } of data.locations) { + const locations = this.service.findRenameLocations(fileName, offset, false, false, true) ?? []; + for (const loc of locations) { + appendRename(newText, loc); } } } @@ -514,6 +660,7 @@ async function _run() { const projectPath = path.join(__dirname, '../../src/tsconfig.json'); const projectBase = path.dirname(projectPath); const newProjectBase = path.join(path.dirname(projectBase), path.basename(projectBase) + '2'); + fs.cpSync(projectBase, newProjectBase, { recursive: true }); for await (const [fileName, contents] of new Mangler(projectPath, console.log).computeNewFileContents(new Set(['saveState']))) { const newFilePath = path.join(newProjectBase, path.relative(projectBase, fileName)); await fs.promises.mkdir(path.dirname(newFilePath), { recursive: true }); @@ -526,4 +673,4 @@ async function _run() { if (__filename === process_1.argv[1]) { _run(); } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFuZ2xlVHlwZVNjcmlwdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm1hbmdsZVR5cGVTY3JpcHQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Z0dBR2dHOzs7QUFFaEcsaUNBQWlDO0FBQ2pDLDZCQUE2QjtBQUM3Qix5QkFBeUI7QUFDekIscUNBQStCO0FBQy9CLDJDQUF5RDtBQUN6RCw2QkFBb0M7QUFFcEMsTUFBTSxVQUFVO0lBRVAsTUFBTSxDQUFDLFNBQVMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVO1FBQzlHLFNBQVMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxJQUFJO1FBQ25HLFFBQVEsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsT0FBTztRQUMxRyxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUU1RCxNQUFNLENBQUMsU0FBUyxHQUFHLHNEQUFzRCxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUVwRixNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ0YsWUFBWSxDQUE0QjtJQUV6RCxZQUFZLFdBQXNDO1FBQ2pELElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxXQUFXLENBQUMsSUFB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 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFuZ2xlVHlwZVNjcmlwdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm1hbmdsZVR5cGVTY3JpcHQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Z0dBR2dHOzs7QUFFaEcsaUNBQWlDO0FBQ2pDLDZCQUE2QjtBQUM3Qix5QkFBeUI7QUFDekIscUNBQStCO0FBQy9CLDJDQUF5RDtBQUN6RCw2QkFBb0M7QUFFcEMsTUFBTSxVQUFVO0lBRVAsTUFBTSxDQUFDLFNBQVMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVO1FBQzlHLFNBQVMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxJQUFJO1FBQ25HLFFBQVEsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsT0FBTztRQUMxRyxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUU1RCxNQUFNLENBQUMsU0FBUyxHQUFHLGtFQUFrRSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUVoRyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ0YsWUFBWSxDQUE0QjtJQUN4QyxNQUFNLENBQVM7SUFFaEMsWUFBWSxNQUFjLEVBQUUsV0FBc0M7UUFDakUsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsRUFBRSxD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 \ No newline at end of file diff --git a/build/package.json b/build/package.json index 44eec832d64..df7b7799a24 100644 --- a/build/package.json +++ b/build/package.json @@ -38,6 +38,7 @@ "@types/through2": "^2.0.36", "@types/tmp": "^0.2.1", "@types/underscore": "^1.8.9", + "@types/workerpool": "^6.4.0", "@types/xml2js": "0.0.33", "@vscode/iconv-lite-umd": "0.7.0", "@vscode/vsce": "^2.16.0", @@ -70,5 +71,8 @@ "tree-sitter": "https://github.com/joaomoreno/node-tree-sitter/releases/download/v0.20.0/tree-sitter-0.20.0.tgz", "tree-sitter-typescript": "^0.20.1", "vscode-gulp-watch": "^5.0.3" + }, + "dependencies": { + "workerpool": "^6.4.0" } } diff --git a/build/yarn.lock b/build/yarn.lock index 8aa0f5f21cf..c29bf14c70a 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -646,6 +646,13 @@ dependencies: "@types/node" "*" +"@types/workerpool@^6.4.0": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@types/workerpool/-/workerpool-6.4.0.tgz#c79292915dd08350d10e78e74687b6f401f270b8" + integrity sha512-SIF2/169pDsLKeM8GQGHkOFifGalDbZgiBSaLUnnlVSRsAOenkAvQ6h4uhV2W+PZZczS+8LQxACwNkSykdT91A== + dependencies: + "@types/node" "*" + "@types/xml2js@0.0.33": version "0.0.33" resolved "https://registry.yarnpkg.com/@types/xml2js/-/xml2js-0.0.33.tgz#20c5dd6460245284d64a55690015b95e409fb7de" @@ -3017,6 +3024,11 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.2 || 2 || 3 || 4" +workerpool@^6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.4.0.tgz#f8d5cfb45fde32fa3b7af72ad617c3369567a462" + integrity sha512-i3KR1mQMNwY2wx20ozq2EjISGtQWDIfV56We+yGJ5yDs8jTwQiLLaqHlkBHITlCuJnYlVRmXegxFxZg7gqI++A== + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" diff --git a/extensions/mangle-loader.js b/extensions/mangle-loader.js index fa4fb1e36fc..46877444525 100644 --- a/extensions/mangle-loader.js +++ b/extensions/mangle-loader.js @@ -8,12 +8,12 @@ const fs = require('fs'); const webpack = require('webpack'); const fancyLog = require('fancy-log'); const ansiColors = require('ansi-colors'); -const { Mangler } = require('../build/lib/mangleTypeScript'); +const { Mangler } = require('../build/lib/mangle/index'); /** * Map of project paths to mangled file contents * - * @type {Map>} + * @type {Map>>} */ const mangleMap = new Map(); @@ -55,7 +55,7 @@ module.exports = async function (source, sourceMap, meta) { const callback = this.async(); - const fileContentsMap = getMangledFileContents(options.configFile); + const fileContentsMap = await getMangledFileContents(options.configFile); const newContents = fileContentsMap.get(this.resourcePath); callback(null, newContents?.out ?? source, sourceMap, meta); diff --git a/src/vs/base/common/errors.ts b/src/vs/base/common/errors.ts index 63f5a2f8c51..a558a0b06d8 100644 --- a/src/vs/base/common/errors.ts +++ b/src/vs/base/common/errors.ts @@ -74,6 +74,7 @@ export class ErrorHandler { export const errorHandler = new ErrorHandler(); +/** @skipMangle */ export function setUnexpectedErrorHandler(newUnexpectedErrorHandler: (e: any) => void): void { errorHandler.setUnexpectedErrorHandler(newUnexpectedErrorHandler); } diff --git a/src/vs/base/common/process.ts b/src/vs/base/common/process.ts index cfa3c1c5a41..a50f849b5af 100644 --- a/src/vs/base/common/process.ts +++ b/src/vs/base/common/process.ts @@ -48,6 +48,8 @@ else { * environments. * * Note: in web, this property is hardcoded to be `/`. + * + * @skipMangle */ export const cwd = safeProcess.cwd; diff --git a/src/vs/base/common/stripComments.d.ts b/src/vs/base/common/stripComments.d.ts index 69e662e9759..af5b182b5bf 100644 --- a/src/vs/base/common/stripComments.d.ts +++ b/src/vs/base/common/stripComments.d.ts @@ -10,5 +10,5 @@ * supported in JSON. * @param content the content to strip comments from * @returns the content without comments - */ +*/ export function stripComments(content: string): string; diff --git a/src/vs/base/common/worker/simpleWorker.ts b/src/vs/base/common/worker/simpleWorker.ts index deefcb96396..924dbf3ad7d 100644 --- a/src/vs/base/common/worker/simpleWorker.ts +++ b/src/vs/base/common/worker/simpleWorker.ts @@ -558,6 +558,7 @@ export class SimpleWorkerServer { /** * Called on the worker side + * @skipMangle */ export function create(postMessage: (msg: Message, transfer?: ArrayBuffer[]) => void): SimpleWorkerServer { return new SimpleWorkerServer(postMessage, null); diff --git a/src/vs/css.ts b/src/vs/css.ts index 4a5ea48d174..5337b4f2136 100644 --- a/src/vs/css.ts +++ b/src/vs/css.ts @@ -9,6 +9,8 @@ interface ICSSPluginConfig { /** * Invoked by the loader at run-time + * + * @skipMangle */ export function load(name: string, req: AMDLoader.IRelativeRequire, load: AMDLoader.IPluginLoadCallback, config: AMDLoader.IConfigurationOptions): void { config = config || {}; diff --git a/src/vs/editor/browser/controller/textAreaHandler.ts b/src/vs/editor/browser/controller/textAreaHandler.ts index 8c7a15121e9..0d5c3317051 100644 --- a/src/vs/editor/browser/controller/textAreaHandler.ts +++ b/src/vs/editor/browser/controller/textAreaHandler.ts @@ -297,7 +297,12 @@ export class TextAreaHandler extends ViewPart { }; const textAreaWrapper = this._register(new TextAreaWrapper(this.textArea.domNode)); - this._textAreaInput = this._register(new TextAreaInput(textAreaInputHost, textAreaWrapper, platform.OS, browser)); + this._textAreaInput = this._register(new TextAreaInput(textAreaInputHost, textAreaWrapper, platform.OS, { + isAndroid: browser.isAndroid, + isChrome: browser.isChrome, + isFirefox: browser.isFirefox, + isSafari: browser.isSafari, + })); this._register(this._textAreaInput.onKeyDown((e: IKeyboardEvent) => { this._viewController.emitKeyDown(e); diff --git a/src/vs/editor/test/browser/controller/imeTester.ts b/src/vs/editor/test/browser/controller/imeTester.ts index bf85dd9c5bf..b44da204b52 100644 --- a/src/vs/editor/test/browser/controller/imeTester.ts +++ b/src/vs/editor/test/browser/controller/imeTester.ts @@ -121,7 +121,12 @@ function doCreateTest(description: string, inputStr: string, expectedStr: string } }; - const handler = new TextAreaInput(textAreaInputHost, new TextAreaWrapper(input), platform.OS, browser); + const handler = new TextAreaInput(textAreaInputHost, new TextAreaWrapper(input), platform.OS, { + isAndroid: browser.isAndroid, + isFirefox: browser.isFirefox, + isChrome: browser.isChrome, + isSafari: browser.isSafari, + }); const output = document.createElement('pre'); output.className = 'output'; diff --git a/src/vs/nls.ts b/src/vs/nls.ts index 7ec0e246f8f..db57b98d67b 100644 --- a/src/vs/nls.ts +++ b/src/vs/nls.ts @@ -123,6 +123,9 @@ export function localize(info: ILocalizeInfo, message: string, ...args: (string */ export function localize(key: string, message: string, ...args: (string | number | boolean | undefined | null)[]): string; +/** + * @skipMangle + */ export function localize(data: ILocalizeInfo | string, message: string, ...args: (string | number | boolean | undefined | null)[]): string { return _format(message, args); } @@ -133,18 +136,25 @@ export function localize(data: ILocalizeInfo | string, message: string, ...args: * in order to ensure the loader plugin has been initialized before this function is called. */ export function getConfiguredDefaultLocale(stringFromLocalizeCall: string): string | undefined; +/** + * @skipMangle + */ export function getConfiguredDefaultLocale(_: string): string | undefined { // This returns undefined because this implementation isn't used and is overwritten by the loader // when loaded. return undefined; } +/** + * @skipMangle + */ export function setPseudoTranslation(value: boolean) { isPseudo = value; } /** * Invoked in a built product at run-time + * @skipMangle */ export function create(key: string, data: IBundledStrings & IConsumerAPI): IConsumerAPI { return { @@ -155,10 +165,12 @@ export function create(key: string, data: IBundledStrings & IConsumerAPI): ICons /** * Invoked by the loader at run-time + * @skipMangle */ export function load(name: string, req: AMDLoader.IRelativeRequire, load: AMDLoader.IPluginLoadCallback, config: AMDLoader.IConfigurationOptions): void { const pluginConfig: INLSPluginConfig = config['vs/nls'] ?? {}; if (!name || name.length === 0) { + // TODO: We need to give back the mangled names here return load({ localize: localize, getConfiguredDefaultLocale: () => pluginConfig.availableLanguages?.['*'] diff --git a/src/vs/platform/profiling/electron-sandbox/profileAnalysisWorker.ts b/src/vs/platform/profiling/electron-sandbox/profileAnalysisWorker.ts index 0d1ac1c4a65..14d6a473c09 100644 --- a/src/vs/platform/profiling/electron-sandbox/profileAnalysisWorker.ts +++ b/src/vs/platform/profiling/electron-sandbox/profileAnalysisWorker.ts @@ -11,7 +11,6 @@ import { IV8Profile, Utils } from 'vs/platform/profiling/common/profiling'; import { IProfileModel, BottomUpSample, buildModel, BottomUpNode, processNode, CdpCallFrame } from 'vs/platform/profiling/common/profilingModel'; import { BottomUpAnalysis, IProfileAnalysisWorker, ProfilingOutput } from 'vs/platform/profiling/electron-sandbox/profileAnalysisWorkerService'; - export function create(): IRequestHandler { return new ProfileAnalysisWorker(); } diff --git a/src/vs/workbench/test/common/utils.ts b/src/vs/workbench/test/common/utils.ts index c343653722c..498c5c499fe 100644 --- a/src/vs/workbench/test/common/utils.ts +++ b/src/vs/workbench/test/common/utils.ts @@ -12,6 +12,8 @@ import { LanguagesRegistry } from 'vs/editor/common/services/languagesRegistry'; * and can be used to add assertions. e.g. that registries are empty, etc. * * !! This is called directly by the testing framework. + * + * @skipMangle */ export function assertCleanState(): void { // If this test fails, it is a clear indication that From 5b2221330af196a151dd79e693cce6610136a6b9 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 13 Jun 2023 00:03:51 -0700 Subject: [PATCH 083/128] Add extra argument to Mangler (#184986) Missed updating this --- extensions/mangle-loader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/mangle-loader.js b/extensions/mangle-loader.js index 46877444525..b6b22ce3f1a 100644 --- a/extensions/mangle-loader.js +++ b/extensions/mangle-loader.js @@ -25,7 +25,7 @@ function getMangledFileContents(projectPath) { if (!entry) { const log = (...data) => fancyLog(ansiColors.blue('[mangler]'), ...data); log(`Mangling ${projectPath}`); - const ts2tsMangler = new Mangler(projectPath, log); + const ts2tsMangler = new Mangler(projectPath, log, { mangleExports: true, manglePrivateFields: true }); entry = ts2tsMangler.computeNewFileContents(); mangleMap.set(projectPath, entry); } From c591894e6c4e9813c4b70980d9a742bc29c862c9 Mon Sep 17 00:00:00 2001 From: Johannes Date: Tue, 13 Jun 2023 09:37:25 +0200 Subject: [PATCH 084/128] fixed flawed API deprecation warning We want to warn when extensions change `CompletionItem#insertText` during resolve but the check be better correct... --- src/vs/workbench/api/common/extHostLanguageFeatures.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 976490d0b64..7e88bc3c7fe 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -1040,7 +1040,7 @@ class CompletionsAdapter { additionalTextEdits: resolvedItem.additionalTextEdits }; - if (item.insertText !== resolvedItem.insertText) { + if (CompletionsAdapter._insertTextIdent(item.insertText) !== CompletionsAdapter._insertTextIdent(resolvedItem.insertText)) { this._apiDeprecation.report('CompletionItem.insertText', this._extension, 'extension MAY NOT change \'insertText\' of a CompletionItem during resolve'); enforcedResolvedItem.insertText = resolvedItem.insertText; } @@ -1048,6 +1048,14 @@ class CompletionsAdapter { return this._convertCompletionItem(enforcedResolvedItem, id); } + private static _insertTextIdent(insertText: string | vscode.SnippetString | undefined) { + switch (typeof insertText) { + case 'string': return insertText; + case 'undefined': return undefined; + case 'object': return insertText.value; + } + } + releaseCompletionItems(id: number): any { this._disposables.get(id)?.dispose(); this._disposables.delete(id); From fb973b6187b01962386d62c443456045d6e349d3 Mon Sep 17 00:00:00 2001 From: Johannes Date: Tue, 13 Jun 2023 09:43:49 +0200 Subject: [PATCH 085/128] add telemetry to know how often an item is inserted before resolve is done --- .../contrib/suggest/browser/suggestController.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/vs/editor/contrib/suggest/browser/suggestController.ts b/src/vs/editor/contrib/suggest/browser/suggestController.ts index 543b487b798..f8542015f45 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestController.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestController.ts @@ -332,6 +332,7 @@ export class SuggestController implements IEditorContribution { // keep item in memory this._memoryService.memorize(model, this.editor.getPosition(), item); + const isResolved = item.isResolved; if (Array.isArray(item.completion.additionalTextEdits)) { @@ -346,7 +347,7 @@ export class SuggestController implements IEditorContribution { ); scrollState.restoreRelativeVerticalPositionOfCursor(this.editor); - } else if (!item.isResolved) { + } else if (!isResolved) { // async additional edits const sw = new StopWatch(true); let position: IPosition | undefined; @@ -467,7 +468,7 @@ export class SuggestController implements IEditorContribution { // clear only now - after all tasks are done Promise.all(tasks).finally(() => { - this._reportSuggestionAcceptedTelemetry(item, model, event); + this._reportSuggestionAcceptedTelemetry(item, model, event, isResolved); this.model.clear(); cts.dispose(); @@ -475,12 +476,12 @@ export class SuggestController implements IEditorContribution { } private _telemetryGate: number = 0; - private _reportSuggestionAcceptedTelemetry(item: CompletionItem, model: ITextModel, acceptedSuggestion: ISelectedSuggestion) { + private _reportSuggestionAcceptedTelemetry(item: CompletionItem, model: ITextModel, acceptedSuggestion: ISelectedSuggestion, itemResolved: boolean) { if (this._telemetryGate++ % 100 !== 0) { return; } - type AcceptedSuggestion = { providerId: string; fileExtension: string; languageId: string; basenameHash: string; kind: number }; + type AcceptedSuggestion = { providerId: string; fileExtension: string; languageId: string; basenameHash: string; kind: number; itemResolved: boolean }; type AcceptedSuggestionClassification = { owner: 'jrieken'; comment: 'Information accepting completion items'; @@ -488,7 +489,8 @@ export class SuggestController implements IEditorContribution { basenameHash: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; comment: 'Hash of the basename of the file into which the completion was inserted' }; fileExtension: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'File extension of the file into which the completion was inserted' }; languageId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Language type of the file into which the completion was inserted' }; - kind: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The completion item kind' }; + kind: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'The completion item kind' }; + itemResolved: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'If the item was inserted before resolving was done' }; }; // _debugDisplayName looks like `vscode.css-language-features(/-:)`, where the last bit is the trigger chars // normalize it to just the extension ID and lowercase @@ -499,6 +501,7 @@ export class SuggestController implements IEditorContribution { basenameHash: hash(basename(model.uri)).toString(16), languageId: model.getLanguageId(), fileExtension: extname(model.uri), + itemResolved }); } From b8f0cf36c1f679bd17a9fe3e7976b5cb4cd0309e Mon Sep 17 00:00:00 2001 From: Johannes Date: Tue, 13 Jun 2023 09:48:00 +0200 Subject: [PATCH 086/128] add telemetry to measure how successful async additional edits can be applied --- .../contrib/suggest/browser/suggestController.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/vs/editor/contrib/suggest/browser/suggestController.ts b/src/vs/editor/contrib/suggest/browser/suggestController.ts index f8542015f45..695ade0e601 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestController.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestController.ts @@ -399,6 +399,18 @@ export class SuggestController implements IEditorContribution { return true; }).then(applied => { this._logService.trace('[suggest] async resolving of edits DONE (ms, applied?)', sw.elapsed(), applied); + type AsyncSuggestEdits = { providerId: string; applied: boolean }; + type AsyncSuggestEditsClassification = { + owner: 'jrieken'; + comment: 'Information about async additional text edits'; + providerId: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; comment: 'Provider of the completions item' }; + applied: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'If async additional text edits could be applied' }; + }; + this._telemetryService.publicLog2('suggest.asyncAdditionalEdits', { + providerId: item.extensionId?.value ?? 'unknown', + applied + }); + }).finally(() => { docListener.dispose(); typeListener.dispose(); })); From 6a805df6a4fbe54eddcea27f2c7472cdc06f903a Mon Sep 17 00:00:00 2001 From: Johannes Date: Tue, 13 Jun 2023 09:52:30 +0200 Subject: [PATCH 087/128] refine async edits telemetry --- .../contrib/suggest/browser/suggestController.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/vs/editor/contrib/suggest/browser/suggestController.ts b/src/vs/editor/contrib/suggest/browser/suggestController.ts index 695ade0e601..0341a938c24 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestController.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestController.ts @@ -379,7 +379,7 @@ export class SuggestController implements IEditorContribution { tasks.push(item.resolve(cts.token).then(() => { if (!item.completion.additionalTextEdits || cts.token.isCancellationRequested) { - return false; + return undefined; } if (position && item.completion.additionalTextEdits.some(edit => Position.isBefore(position!, Range.getStartPosition(edit.range)))) { return false; @@ -406,10 +406,12 @@ export class SuggestController implements IEditorContribution { providerId: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; comment: 'Provider of the completions item' }; applied: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'If async additional text edits could be applied' }; }; - this._telemetryService.publicLog2('suggest.asyncAdditionalEdits', { - providerId: item.extensionId?.value ?? 'unknown', - applied - }); + if (typeof applied === 'boolean') { + this._telemetryService.publicLog2('suggest.asyncAdditionalEdits', { + providerId: item.extensionId?.value ?? 'unknown', + applied + }); + } }).finally(() => { docListener.dispose(); typeListener.dispose(); From e82cbf80ba714ffc2265e84439b43d2f53f39335 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Tue, 13 Jun 2023 09:56:29 +0200 Subject: [PATCH 088/128] Git - only add --find-renames if the value is not the default one (#184992) --- extensions/git/src/git.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index f0e778ba9bc..2426563c671 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -2021,7 +2021,7 @@ export class Repository { } // --find-renames option is only available starting with git 2.18.0 - if (opts?.similarityThreshold && this._git.compareGitVersionTo('2.18.0') !== -1) { + if (opts?.similarityThreshold && opts.similarityThreshold !== 50 && this._git.compareGitVersionTo('2.18.0') !== -1) { args.push(`--find-renames=${opts.similarityThreshold}%`); } From 344768649969e72d2ba2fcbab235477faa8c7972 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Tue, 13 Jun 2023 11:25:00 +0200 Subject: [PATCH 089/128] Git - use close event when detecting git version (#184998) --- extensions/git/src/git.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index 2426563c671..a5a9589dcc4 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -73,7 +73,7 @@ function findSpecificGit(path: string, onValidate: (path: string) => boolean): P const child = cp.spawn(path, ['--version']); child.stdout.on('data', (b: Buffer) => buffers.push(b)); child.on('error', cpErrorHandler(e)); - child.on('exit', code => code ? e(new Error('Not found')) : c({ path, version: parseVersion(Buffer.concat(buffers).toString('utf8').trim()) })); + child.on('close', code => code ? e(new Error('Not found')) : c({ path, version: parseVersion(Buffer.concat(buffers).toString('utf8').trim()) })); }); } From 61eccf481c8f11634d3c63d340526c483b258f33 Mon Sep 17 00:00:00 2001 From: Johannes Date: Tue, 13 Jun 2023 12:49:48 +0200 Subject: [PATCH 090/128] fix formatting --- src/vs/workbench/api/common/extensionHostMain.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/api/common/extensionHostMain.ts b/src/vs/workbench/api/common/extensionHostMain.ts index 5422226e795..c2853d37302 100644 --- a/src/vs/workbench/api/common/extensionHostMain.ts +++ b/src/vs/workbench/api/common/extensionHostMain.ts @@ -103,7 +103,7 @@ abstract class ErrorHandler { prepareStackTraceAndFindExtension(error, stackTrace); return v.call(Error, error, stackTrace); }; - + Object.assign(_prepareStackTrace, { [_wasWrapped]: true }); }, }); From 66b54e16972c2139980e26bc840940eca4a37862 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 13 Jun 2023 12:53:41 +0200 Subject: [PATCH 091/128] joh/tasteless orca (#185006) * Add ability to rerun prompt Extract `SessionPrompt` with tries counter that, add rerun message that is listened on during WAIT_FOR_INPUT, read number of attempts during MAKE_REQUEST https://github.com/microsoft/vscode-copilot/issues/247 * renames --- .../browser/inlineChat.contribution.ts | 1 + .../inlineChat/browser/inlineChatActions.ts | 22 ++++++++++ .../browser/inlineChatController.ts | 33 ++++++++++---- .../browser/inlineChatLivePreviewWidget.ts | 12 ++++- .../inlineChat/browser/inlineChatSession.ts | 44 ++++++++++++++----- .../browser/inlineChatStrategies.ts | 28 ++++++++++-- 6 files changed, 116 insertions(+), 24 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChat.contribution.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChat.contribution.ts index 344670ab7ad..daef8334fe5 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChat.contribution.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChat.contribution.ts @@ -26,6 +26,7 @@ registerAction2(InlineChatActions.StartSessionAction); registerAction2(InlineChatActions.UnstashSessionAction); registerAction2(InlineChatActions.MakeRequestAction); registerAction2(InlineChatActions.StopRequestAction); +registerAction2(InlineChatActions.ReRunRequestAction); registerAction2(InlineChatActions.DiscardAction); registerAction2(InlineChatActions.DiscardToClipboardAction); registerAction2(InlineChatActions.DiscardUndoToNewFileAction); diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatActions.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatActions.ts index 918f1c7aecf..a29469d02b2 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatActions.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatActions.ts @@ -159,6 +159,28 @@ export class MakeRequestAction extends AbstractInlineChatAction { } } +export class ReRunRequestAction extends AbstractInlineChatAction { + + constructor() { + super({ + id: 'inlineChat.regenerate', + title: localize('rerun', 'Regenerate Response'), + icon: Codicon.refresh, + precondition: ContextKeyExpr.and(CTX_INLINE_CHAT_VISIBLE, CTX_INLINE_CHAT_EMPTY.negate(), CTX_INLINE_CHAT_LAST_RESPONSE_TYPE), + menu: { + id: MENU_INLINE_CHAT_WIDGET_STATUS, + group: '0_main', + order: 1, + } + }); + } + + override runInlineChatCommand(_accessor: ServicesAccessor, ctrl: InlineChatController): void { + ctrl.regenerate(); + } + +} + export class StopRequestAction extends AbstractInlineChatAction { constructor() { diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 16e5cc607f0..6bf262af6d1 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -28,7 +28,7 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ILogService } from 'vs/platform/log/common/log'; -import { EditResponse, EmptyResponse, ErrorResponse, ExpansionState, IInlineChatSessionService, MarkdownResponse, Session, SessionExchange } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession'; +import { EditResponse, EmptyResponse, ErrorResponse, ExpansionState, IInlineChatSessionService, MarkdownResponse, Session, SessionExchange, SessionPrompt } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession'; import { EditModeStrategy, LivePreviewStrategy, LiveStrategy, PreviewStrategy } from 'vs/workbench/contrib/inlineChat/browser/inlineChatStrategies'; import { InlineChatZoneWidget } from 'vs/workbench/contrib/inlineChat/browser/inlineChatWidget'; import { CTX_INLINE_CHAT_HAS_ACTIVE_REQUEST, CTX_INLINE_CHAT_LAST_FEEDBACK, IInlineChatRequest, IInlineChatResponse, INLINE_CHAT_ID, EditMode, InlineChatResponseFeedbackKind, CTX_INLINE_CHAT_LAST_RESPONSE_TYPE, InlineChatResponseType, CTX_INLINE_CHAT_DID_EDIT, CTX_INLINE_CHAT_HAS_STASHED_SESSION } from 'vs/workbench/contrib/inlineChat/common/inlineChat'; @@ -58,7 +58,8 @@ const enum Message { PAUSE_SESSION = 1 << 2, CANCEL_REQUEST = 1 << 3, CANCEL_INPUT = 1 << 4, - ACCEPT_INPUT = 1 << 5 + ACCEPT_INPUT = 1 << 5, + RERUN_INPUT = 1 << 6, } export interface InlineChatRunOptions { @@ -267,7 +268,7 @@ export class InlineChatController implements IEditorContribution { this._zone.value.widget.updateSlashCommands(this._activeSession.session.slashCommands ?? []); this._zone.value.widget.placeholder = this._getPlaceholderText(); - this._zone.value.widget.value = this._activeSession.lastInput ?? ''; + this._zone.value.widget.value = this._activeSession.lastInput?.value ?? ''; this._zone.value.widget.updateInfo(this._activeSession.session.message ?? localize('welcome.1', "AI-generated code may be incorrect")); this._zone.value.show(this._activeSession.wholeRange.value.getEndPosition()); this._zone.value.widget.preferredExpansionState = this._activeSession.lastExpansionState; @@ -357,6 +358,7 @@ export class InlineChatController implements IEditorContribution { private async [State.WAIT_FOR_INPUT](options: InlineChatRunOptions | undefined): Promise { assertType(this._activeSession); + assertType(this._strategy); this._zone.value.widget.placeholder = this._getPlaceholderText(); this._zone.value.show(this._activeSession.wholeRange.value.getEndPosition()); @@ -397,6 +399,15 @@ export class InlineChatController implements IEditorContribution { return State.PAUSE; } + if (message & Message.RERUN_INPUT && this._activeSession.lastExchange) { + const { lastExchange } = this._activeSession; + this._activeSession.addInput(lastExchange.prompt.retry()); + if (lastExchange.response instanceof EditResponse) { + await this._strategy.undoChanges(lastExchange.response); + } + return State.MAKE_REQUEST; + } + if (!this._zone.value.widget.value) { return State.WAIT_FOR_INPUT; } @@ -420,7 +431,7 @@ export class InlineChatController implements IEditorContribution { return State.WAIT_FOR_INPUT; } - this._activeSession.addInput(input); + this._activeSession.addInput(new SessionPrompt(input)); return State.MAKE_REQUEST; } @@ -444,10 +455,10 @@ export class InlineChatController implements IEditorContribution { const sw = StopWatch.create(); const request: IInlineChatRequest = { - prompt: this._activeSession.lastInput, + prompt: this._activeSession.lastInput.value, + attempt: this._activeSession.lastInput.attempt, selection: this._editor.getSelection(), wholeRange: this._activeSession.wholeRange.value, - attempt: 0, }; const task = this._activeSession.provider.provideResponse(this._activeSession.session, request, requestCts.token); this._log('request started', this._activeSession.provider.debugName, this._activeSession.session, request); @@ -463,7 +474,7 @@ export class InlineChatController implements IEditorContribution { if (reply?.type === 'message') { response = new MarkdownResponse(this._activeSession.textModelN.uri, reply); } else if (reply) { - response = new EditResponse(this._activeSession.textModelN.uri, reply); + response = new EditResponse(this._activeSession.textModelN.uri, this._activeSession.textModelN.getAlternativeVersionId(), reply); } else { response = new EmptyResponse(); } @@ -483,7 +494,7 @@ export class InlineChatController implements IEditorContribution { msgListener.dispose(); typeListener.dispose(); - this._activeSession.addExchange(new SessionExchange(request.prompt, response)); + this._activeSession.addExchange(new SessionExchange(this._activeSession.lastInput, response)); if (message & Message.CANCEL_SESSION) { return State.CANCEL; @@ -646,6 +657,10 @@ export class InlineChatController implements IEditorContribution { this._messages.fire(Message.ACCEPT_INPUT); } + regenerate(): void { + this._messages.fire(Message.RERUN_INPUT); + } + cancelCurrentRequest(): void { this._messages.fire(Message.CANCEL_INPUT | Message.CANCEL_REQUEST); } @@ -683,7 +698,7 @@ export class InlineChatController implements IEditorContribution { viewInChat() { if (this._activeSession?.lastExchange?.response instanceof MarkdownResponse) { - this._instaService.invokeFunction(showMessageResponse, this._activeSession.lastExchange.prompt, this._activeSession.lastExchange.response.raw.message.value); + this._instaService.invokeFunction(showMessageResponse, this._activeSession.lastExchange.prompt.value, this._activeSession.lastExchange.response.raw.message.value); } } diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatLivePreviewWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatLivePreviewWidget.ts index 121063c0f3d..4fedbe31063 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatLivePreviewWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatLivePreviewWidget.ts @@ -44,6 +44,7 @@ export class InlineChatLivePreviewWidget extends ZoneWidget { private readonly _inlineDiffDecorations: IEditorDecorationsCollection; private _dim: Dimension | undefined; private _isVisible: boolean = false; + private _isDiffLocked: boolean = false; constructor( editor: ICodeEditor, @@ -134,6 +135,8 @@ export class InlineChatLivePreviewWidget extends ZoneWidget { override show(): void { assertType(this.editor.hasModel()); this._sessionStore.clear(); + this._isDiffLocked = false; + this._isVisible = true; this._sessionStore.add(this._diffEditor.onDidUpdateDiff(() => { const result = this._diffEditor.getDiffComputationResult(); @@ -148,12 +151,19 @@ export class InlineChatLivePreviewWidget extends ZoneWidget { } })); this._updateFromChanges(this._session.wholeRange.value, this._session.lastTextModelChanges); - this._isVisible = true; + } + + lockToDiff(): void { + this._isDiffLocked = true; } private _updateFromChanges(range: Range, changes: readonly LineRangeMapping[]): void { assertType(this.editor.hasModel()); + if (this._isDiffLocked) { + return; + } + if (changes.length === 0 || this._session.textModel0.getValueLength() === 0) { // no change or changes to an empty file this._logService.debug('[IE] livePreview-mode: no diff'); diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts index fdf9dd3eb48..141b5911cff 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts @@ -108,7 +108,7 @@ class SessionWholeRange { export class Session { - private _lastInput: string | undefined; + private _lastInput: SessionPrompt | undefined; private _lastExpansionState: ExpansionState | undefined; private _lastTextModelChanges: readonly LineRangeMapping[] | undefined; private _isUnstashed: boolean = false; @@ -139,10 +139,14 @@ export class Session { }; } - addInput(input: string): void { + addInput(input: SessionPrompt): void { this._lastInput = input; } + get lastInput() { + return this._lastInput; + } + get isUnstashed(): boolean { return this._isUnstashed; } @@ -151,10 +155,6 @@ export class Session { this._isUnstashed = true; } - get lastInput() { - return this._lastInput; - } - get lastExpansionState(): ExpansionState | undefined { return this._lastExpansionState; } @@ -229,7 +229,7 @@ export class Session { for (const exchange of this._exchange) { const response = exchange.response; if (response instanceof MarkdownResponse || response instanceof EditResponse) { - result.exchanges.push({ prompt: exchange.prompt, res: response.raw }); + result.exchanges.push({ prompt: exchange.prompt.value, res: response.raw }); } } return result; @@ -237,9 +237,29 @@ export class Session { } -export class SessionExchange { +export class SessionPrompt { + + private _attempt: number = 0; + constructor( - readonly prompt: string, + readonly value: string, + ) { } + + get attempt() { + return this._attempt; + } + + retry() { + const result = new SessionPrompt(this.value); + result._attempt = this._attempt + 1; + return result; + } +} + +export class SessionExchange { + + constructor( + readonly prompt: SessionPrompt, readonly response: MarkdownResponse | EditResponse | EmptyResponse | ErrorResponse ) { } } @@ -275,7 +295,11 @@ export class EditResponse { readonly workspaceEdits: ResourceEdit[] | undefined; readonly workspaceEditsIncludeLocalEdits: boolean = false; - constructor(localUri: URI, readonly raw: IInlineChatBulkEditResponse | IInlineChatEditResponse) { + constructor( + localUri: URI, + readonly modelAltVersionId: number, + readonly raw: IInlineChatBulkEditResponse | IInlineChatEditResponse + ) { if (raw.type === 'editorEdit') { // this.localEdits = raw.edits; diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts index e8a718844da..03bb8f3e7ea 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts @@ -13,7 +13,7 @@ import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; import { IEditorDecorationsCollection } from 'vs/editor/common/editorCommon'; -import { ICursorStateComputer, IModelDecorationOptions, IModelDeltaDecoration, IValidEditOperation } from 'vs/editor/common/model'; +import { ICursorStateComputer, IModelDecorationOptions, IModelDeltaDecoration, ITextModel, IValidEditOperation } from 'vs/editor/common/model'; import { IEditorWorkerService } from 'vs/editor/common/services/editorWorker'; import { localize } from 'vs/nls'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; @@ -37,6 +37,8 @@ export abstract class EditModeStrategy { abstract makeChanges(edits: ISingleEditOperation[]): Promise; + abstract undoChanges(response: EditResponse): Promise; + abstract renderChanges(response: EditResponse): Promise; abstract toggleDiff(): void; @@ -110,6 +112,10 @@ export class PreviewStrategy extends EditModeStrategy { // nothing to do } + override async undoChanges(_response: EditResponse): Promise { + // nothing to do + } + override async renderChanges(response: EditResponse): Promise { if (response.localEdits.length > 0) { const edits = response.localEdits.map(edit => EditOperation.replace(Range.lift(edit.range), edit.text)); @@ -275,9 +281,7 @@ export class LiveStrategy extends EditModeStrategy { return; } const targetAltVersion = textModelNSnapshotAltVersion ?? textModelNAltVersion; - while (targetAltVersion < modelN.getAlternativeVersionId() && modelN.canUndo()) { - modelN.undo(); - } + LiveStrategy._undoModelUntil(modelN, targetAltVersion); } override async makeChanges(edits: ISingleEditOperation[], ignoreInlineDiff?: boolean): Promise { @@ -297,6 +301,11 @@ export class LiveStrategy extends EditModeStrategy { this._editor.executeEdits('inline-chat-live', edits, ignoreInlineDiff ? undefined : cursorStateComputerAndInlineDiffCollection); } + override async undoChanges(response: EditResponse): Promise { + const { textModelN } = this._session; + LiveStrategy._undoModelUntil(textModelN, response.modelAltVersionId); + } + override async renderChanges(response: EditResponse) { this._inlineDiffDecorations.update(); @@ -309,6 +318,12 @@ export class LiveStrategy extends EditModeStrategy { } } + private static _undoModelUntil(model: ITextModel, targetAltVersion: number): void { + while (targetAltVersion < model.getAlternativeVersionId() && model.canUndo()) { + model.undo(); + } + } + protected _updateSummaryMessage() { let linesChanged = 0; for (const change of this._session.lastTextModelChanges) { @@ -373,6 +388,11 @@ export class LivePreviewStrategy extends LiveStrategy { } } + override async undoChanges(response: EditResponse): Promise { + this._diffZone.lockToDiff(); + super.undoChanges(response); + } + protected override _doToggleDiff(): void { const scrollState = StableEditorScrollState.capture(this._editor); if (this._diffEnabled) { From c7d9530402aaa5bdc1601a1cf555d39d8c1b9242 Mon Sep 17 00:00:00 2001 From: Johannes Date: Tue, 13 Jun 2023 15:06:51 +0200 Subject: [PATCH 092/128] use equality check instead of Symbol, cache results and prevent double computation when "recursive" calls happen --- .../workbench/api/common/extensionHostMain.ts | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/api/common/extensionHostMain.ts b/src/vs/workbench/api/common/extensionHostMain.ts index c2853d37302..41308700711 100644 --- a/src/vs/workbench/api/common/extensionHostMain.ts +++ b/src/vs/workbench/api/common/extensionHostMain.ts @@ -65,12 +65,15 @@ abstract class ErrorHandler { const mainThreadErrors = rpcService.getProxy(MainContext.MainThreadErrors); const map = await extensionService.getExtensionPathIndex(); - const extensionErrors = new WeakMap(); + const extensionErrors = new WeakMap(); // PART 1 // set the prepareStackTrace-handle and use it as a side-effect to associate errors // with extensions - this works by looking up callsites in the extension path index function prepareStackTraceAndFindExtension(error: Error, stackTrace: errors.V8CallSite[]) { + if (extensionErrors.has(error)) { + return extensionErrors.get(error)!.stack; + } let stackTraceMessage = ''; let extension: IExtensionDescription | undefined; let fileName: string | null; @@ -81,20 +84,21 @@ abstract class ErrorHandler { extension = map.findSubstr(URI.file(fileName)); } } - extensionErrors.set(error, extension?.identifier); - return `${error.name || 'Error'}: ${error.message || ''}${stackTraceMessage}`; + const result = `${error.name || 'Error'}: ${error.message || ''}${stackTraceMessage}`; + extensionErrors.set(error, { extensionIdentifier: extension?.identifier, stack: result }); + return result; } - const _wasWrapped = Symbol('prepareStackTrace wrapped'); let _prepareStackTrace = prepareStackTraceAndFindExtension; - Object.assign(_prepareStackTrace, { [_wasWrapped]: true }); + Object.defineProperty(Error, 'prepareStackTrace', { configurable: false, get() { return _prepareStackTrace; }, set(v) { - if (v && (v as any)[_wasWrapped]) { + if (v === prepareStackTraceAndFindExtension) { + // back to default _prepareStackTrace = v; return; } @@ -103,8 +107,6 @@ abstract class ErrorHandler { prepareStackTraceAndFindExtension(error, stackTrace); return v.call(Error, error, stackTrace); }; - - Object.assign(_prepareStackTrace, { [_wasWrapped]: true }); }, }); @@ -115,16 +117,16 @@ abstract class ErrorHandler { errors.setUnexpectedErrorHandler(err => { logService.error(err); - const data = errors.transformErrorForSerialization(err); - const extension = extensionErrors.get(err); - if (!extension) { - mainThreadErrors.$onUnexpectedError(data); + const errorData = errors.transformErrorForSerialization(err); + const stackData = extensionErrors.get(err); + if (!stackData?.extensionIdentifier) { + mainThreadErrors.$onUnexpectedError(errorData); return; } - mainThreadExtensions.$onExtensionRuntimeError(extension, data); - const reported = extensionTelemetry.onExtensionError(extension, err); - logService.trace('forwarded error to extension?', reported, extension); + mainThreadExtensions.$onExtensionRuntimeError(stackData.extensionIdentifier, errorData); + const reported = extensionTelemetry.onExtensionError(stackData.extensionIdentifier, err); + logService.trace('forwarded error to extension?', reported, stackData); }); } } From ceb15e0fb7d81a9630598a9d0d5b7ac9b5955808 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 13 Jun 2023 15:13:58 +0200 Subject: [PATCH 093/128] Keyboard: the configure button in the notification pop is not accessible by tab key (fix #184711) (#185013) --- .../browser/parts/notifications/media/notificationsList.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/notifications/media/notificationsList.css b/src/vs/workbench/browser/parts/notifications/media/notificationsList.css index ddb96275cd2..475cc3a6f19 100644 --- a/src/vs/workbench/browser/parts/notifications/media/notificationsList.css +++ b/src/vs/workbench/browser/parts/notifications/media/notificationsList.css @@ -87,9 +87,9 @@ height: 22px; } +.monaco-workbench .notifications-list-container .monaco-list:focus-within .notification-list-item .notification-list-item-toolbar-container, .monaco-workbench .notifications-list-container .notification-list-item:hover .notification-list-item-toolbar-container, -.monaco-workbench .notifications-list-container .monaco-list-row.focused .notification-list-item .notification-list-item-toolbar-container, -.monaco-workbench .notifications-list-container .notification-list-item.expanded .notification-list-item-toolbar-container { +.monaco-workbench .notifications-list-container .monaco-list-row.focused .notification-list-item .notification-list-item-toolbar-container { display: block; } From 59ef7faef99b3ea21c22ee0b2f02c82679583dbb Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 13 Jun 2023 15:59:49 +0200 Subject: [PATCH 094/128] adding the changes from the review --- .../browser/inlineChatController.ts | 14 ++-- .../inlineChat/browser/inlineChatSession.ts | 3 +- .../browser/inlineChatStrategies.ts | 74 ++++++++----------- 3 files changed, 38 insertions(+), 53 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 47073adfb81..c9230fff33f 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -28,7 +28,7 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ILogService } from 'vs/platform/log/common/log'; -import { EditResponse, EmptyResponse, ErrorResponse, ExpansionState, IInlineChatSessionService, MarkdownResponse, Session, SessionExchange, SessionResponse } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession'; +import { EditResponse, EmptyResponse, ErrorResponse, ExpansionState, IInlineChatSessionService, MarkdownResponse, Session, SessionExchange } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession'; import { EditModeStrategy, LivePreviewStrategy, LiveStrategy, PreviewStrategy } from 'vs/workbench/contrib/inlineChat/browser/inlineChatStrategies'; import { InlineChatZoneWidget } from 'vs/workbench/contrib/inlineChat/browser/inlineChatWidget'; import { CTX_INLINE_CHAT_HAS_ACTIVE_REQUEST, CTX_INLINE_CHAT_LAST_FEEDBACK, IInlineChatRequest, IInlineChatResponse, INLINE_CHAT_ID, EditMode, InlineChatResponseFeedbackKind, CTX_INLINE_CHAT_LAST_RESPONSE_TYPE, InlineChatResponseType, CTX_INLINE_CHAT_DID_EDIT, CTX_INLINE_CHAT_HAS_STASHED_SESSION } from 'vs/workbench/contrib/inlineChat/common/inlineChat'; @@ -193,10 +193,10 @@ export class InlineChatController implements IEditorContribution { // ---- state machine - private _showWidget(initialRender: boolean = false, response?: SessionResponse) { + private _showWidget(initialRender: boolean = false) { assertType(this._activeSession); const selectionRange = this._activeSession.wholeRange.value; - const widgetPosition = this._strategy?.getWidgetPosition(initialRender, selectionRange, response); + const widgetPosition = this._strategy?.getWidgetPosition(initialRender, selectionRange); this._zone.value.show(widgetPosition ?? selectionRange.getEndPosition()); } @@ -241,14 +241,14 @@ export class InlineChatController implements IEditorContribution { switch (session.editMode) { case EditMode.Live: - this._strategy = this._instaService.createInstance(LiveStrategy, session, this._editor, this._zone.value.widget); + this._strategy = this._instaService.createInstance(LiveStrategy, this._editor, session, this._zone.value.widget); break; case EditMode.Preview: - this._strategy = this._instaService.createInstance(PreviewStrategy, session, this._editor, this._zone.value.widget); + this._strategy = this._instaService.createInstance(PreviewStrategy, this._editor, session, this._zone.value.widget); break; case EditMode.LivePreview: default: - this._strategy = this._instaService.createInstance(LivePreviewStrategy, session, this._editor, this._zone.value.widget); + this._strategy = this._instaService.createInstance(LivePreviewStrategy, this._editor, session, this._zone.value.widget); break; } @@ -543,7 +543,7 @@ export class InlineChatController implements IEditorContribution { assertType(this._strategy); const { response } = this._activeSession.lastExchange!; - this._showWidget(false, response); + this._showWidget(false); this._ctxLastResponseType.set(response instanceof EditResponse || response instanceof MarkdownResponse ? response.raw.type diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts index 3cdff58823c..fdf9dd3eb48 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts @@ -236,12 +236,11 @@ export class Session { } } -export type SessionResponse = EditResponse | MarkdownResponse | ErrorResponse | EmptyResponse; export class SessionExchange { constructor( readonly prompt: string, - readonly response: SessionResponse + readonly response: MarkdownResponse | EditResponse | EmptyResponse | ErrorResponse ) { } } diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts index 318fb90dc96..078826c49fe 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts @@ -5,7 +5,6 @@ import { Event } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; -import { assertType } from 'vs/base/common/types'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService'; import { StableEditorScrollState } from 'vs/editor/browser/stableEditorScroll'; @@ -21,14 +20,18 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { InlineChatFileCreatePreviewWidget, InlineChatLivePreviewWidget } from 'vs/workbench/contrib/inlineChat/browser/inlineChatLivePreviewWidget'; -import { EditResponse, Session, SessionResponse } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession'; +import { EditResponse, Session } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession'; import { InlineChatWidget } from 'vs/workbench/contrib/inlineChat/browser/inlineChatWidget'; import { CTX_INLINE_CHAT_SHOWING_DIFF, CTX_INLINE_CHAT_DOCUMENT_CHANGED } from 'vs/workbench/contrib/inlineChat/common/inlineChat'; import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; export abstract class EditModeStrategy { - protected _initialPosition: Position | undefined; + constructor(protected readonly _editor: ICodeEditor) { + this._initialPosition = this._editor.getPosition(); + } + + protected _initialPosition: Position | null; abstract dispose(): void; @@ -46,7 +49,7 @@ export abstract class EditModeStrategy { abstract hasFocus(): boolean; - abstract getWidgetPosition(initialRender: boolean, range?: Range, response?: SessionResponse): Position | undefined; + abstract getWidgetPosition(initialRender: boolean, range: Range): Position | null; } export class PreviewStrategy extends EditModeStrategy { @@ -55,14 +58,14 @@ export class PreviewStrategy extends EditModeStrategy { private readonly _listener: IDisposable; constructor( + _editor: ICodeEditor, private readonly _session: Session, - private readonly _editor: ICodeEditor, private readonly _widget: InlineChatWidget, @IContextKeyService contextKeyService: IContextKeyService, @IBulkEditService private readonly _bulkEditService: IBulkEditService, @IInstantiationService private readonly _instaService: IInstantiationService, ) { - super(); + super(_editor); this._ctxDocumentChanged = CTX_INLINE_CHAT_DOCUMENT_CHANGED.bindTo(contextKeyService); this._listener = Event.debounce(_session.textModelN.onDidChangeContent.bind(_session.textModelN), () => { }, 350)(_ => { @@ -135,12 +138,7 @@ export class PreviewStrategy extends EditModeStrategy { // nothing to do } - getWidgetPosition(initialRender: boolean, _range: Range, _response: SessionResponse): Position | undefined { - const viewModel = this._editor._getViewModel(); - assertType(viewModel); - if (initialRender) { - this._initialPosition = viewModel.getPrimaryCursorState().viewState.position; - } + getWidgetPosition(_initialRender: boolean, _range: Range): Position | null { return this._initialPosition; } @@ -227,8 +225,8 @@ export class LiveStrategy extends EditModeStrategy { private _editCount: number = 0; constructor( + _editor: ICodeEditor, protected readonly _session: Session, - protected readonly _editor: ICodeEditor, protected readonly _widget: InlineChatWidget, @IContextKeyService contextKeyService: IContextKeyService, @IStorageService protected _storageService: IStorageService, @@ -236,7 +234,7 @@ export class LiveStrategy extends EditModeStrategy { @IEditorWorkerService protected readonly _editorWorkerService: IEditorWorkerService, @IInstantiationService private readonly _instaService: IInstantiationService, ) { - super(); + super(_editor); this._diffEnabled = _storageService.getBoolean(LiveStrategy._inlineDiffStorageKey, StorageScope.PROFILE, true); this._inlineDiffDecorations = new InlineDiffDecorations(this._editor, this._diffEnabled); @@ -340,36 +338,26 @@ export class LiveStrategy extends EditModeStrategy { this._widget.updateStatus(message); } - private _findEditsMaxLineNumber(response: EditResponse): number | void { - const edits = response.localEdits; - if (edits.length) { - let editsMaxLineNumber = 0; - for (const edit of edits) { - const editStartLine = edit.range.startLineNumber; - const editNumberOfLines = (edit.text.match(/\n/g) || []).length; - const endLine = editStartLine + editNumberOfLines - 1; - if (endLine > editsMaxLineNumber) { - editsMaxLineNumber = endLine; - } + private _lastLineOfLocalEdits(): number | undefined { + const lastTextModelChanges = this._session.lastTextModelChanges; + let lastLineOfLocalEdits: number | undefined; + for (const change of lastTextModelChanges) { + const changeEndLineNumber = change.modifiedRange.endLineNumberExclusive - 1; + if (!lastLineOfLocalEdits || lastLineOfLocalEdits < changeEndLineNumber) { + lastLineOfLocalEdits = changeEndLineNumber; } - return editsMaxLineNumber; } + return lastLineOfLocalEdits; } - override getWidgetPosition(initialRender: boolean, _range: Range, response: SessionResponse): Position | undefined { - const viewModel = this._editor._getViewModel(); - assertType(viewModel); + override getWidgetPosition(initialRender: boolean, _range: Range): Position | null { if (initialRender) { - this._initialPosition = viewModel.getPrimaryCursorState().viewState.position; return this._initialPosition; } else { - if (response instanceof EditResponse) { - const editsMaxLineNumber = this._findEditsMaxLineNumber(response); - if (editsMaxLineNumber) { - return new Position(editsMaxLineNumber, 1); - } else { - return this._initialPosition; - } + const isEditResponse = this._session.lastExchange?.response instanceof EditResponse; + if (isEditResponse) { + const lastLineOfLocalEdits = this._lastLineOfLocalEdits(); + return lastLineOfLocalEdits ? new Position(lastLineOfLocalEdits, 1) : this._initialPosition; } else { return this._initialPosition; } @@ -387,8 +375,8 @@ export class LivePreviewStrategy extends LiveStrategy { private readonly _previewZone: InlineChatFileCreatePreviewWidget; constructor( - session: Session, editor: ICodeEditor, + session: Session, widget: InlineChatWidget, @IContextKeyService contextKeyService: IContextKeyService, @IStorageService storageService: IStorageService, @@ -396,7 +384,7 @@ export class LivePreviewStrategy extends LiveStrategy { @IEditorWorkerService editorWorkerService: IEditorWorkerService, @IInstantiationService instaService: IInstantiationService, ) { - super(session, editor, widget, contextKeyService, storageService, bulkEditService, editorWorkerService, instaService); + super(editor, session, widget, contextKeyService, storageService, bulkEditService, editorWorkerService, instaService); this._diffZone = instaService.createInstance(InlineChatLivePreviewWidget, editor, session); this._previewZone = instaService.createInstance(InlineChatFileCreatePreviewWidget, editor); @@ -434,14 +422,12 @@ export class LivePreviewStrategy extends LiveStrategy { scrollState.restore(this._editor); } - override getWidgetPosition(initialRender: boolean, range: Range, response: SessionResponse): Position | undefined { + override getWidgetPosition(initialRender: boolean, range: Range): Position | null { if (initialRender) { - const viewModel = this._editor._getViewModel(); - assertType(viewModel); - this._initialPosition = viewModel.getPrimaryCursorState().viewState.position; return this._initialPosition; } else { - if (range && response instanceof EditResponse) { + const isEditResponse = this._session.lastExchange?.response instanceof EditResponse; + if (range && isEditResponse) { return range.getEndPosition(); } else { return this._initialPosition; From 0e8491bec7071ce74059560526c5619719fc3c58 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 13 Jun 2023 16:05:49 +0200 Subject: [PATCH 095/128] changing the check to typeof undefined --- .../contrib/inlineChat/browser/inlineChatStrategies.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts index 078826c49fe..b3e1f00194d 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts @@ -343,7 +343,7 @@ export class LiveStrategy extends EditModeStrategy { let lastLineOfLocalEdits: number | undefined; for (const change of lastTextModelChanges) { const changeEndLineNumber = change.modifiedRange.endLineNumberExclusive - 1; - if (!lastLineOfLocalEdits || lastLineOfLocalEdits < changeEndLineNumber) { + if (typeof lastLineOfLocalEdits === 'undefined' || lastLineOfLocalEdits < changeEndLineNumber) { lastLineOfLocalEdits = changeEndLineNumber; } } From 00b14b2c62db7074e97c1ba77775df4779c889aa Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 13 Jun 2023 16:19:30 +0200 Subject: [PATCH 096/128] update list of repos (#185019) --- .vscode/notebooks/my-work.github-issues | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/notebooks/my-work.github-issues b/.vscode/notebooks/my-work.github-issues index bf86a804dff..99932de7f26 100644 --- a/.vscode/notebooks/my-work.github-issues +++ b/.vscode/notebooks/my-work.github-issues @@ -7,7 +7,7 @@ { "kind": 2, "language": "github-issues", - "value": "// list of repos we work in\n$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-python repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-markdown-languageservice\n\n// current milestone name\n$milestone=milestone:\"June 2023\"" + "value": "// list of repos we work in\n$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-python repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release\n\n// current milestone name\n$milestone=milestone:\"June 2023\"" }, { "kind": 1, From c3275e4dd5b1c21496feba14164d018d4d100c2e Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 13 Jun 2023 17:23:47 +0200 Subject: [PATCH 097/128] changes from review --- .../inlineChat/browser/inlineChatController.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index c9230fff33f..b5c3d8f695d 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -195,9 +195,15 @@ export class InlineChatController implements IEditorContribution { private _showWidget(initialRender: boolean = false) { assertType(this._activeSession); - const selectionRange = this._activeSession.wholeRange.value; - const widgetPosition = this._strategy?.getWidgetPosition(initialRender, selectionRange); - this._zone.value.show(widgetPosition ?? selectionRange.getEndPosition()); + assertType(this._strategy); + + let widgetPosition: Position | null; + if (initialRender) { + widgetPosition = this._editor.getPosition(); + } else { + widgetPosition = this._strategy.getWidgetPosition(); + } + this._zone.value.show((widgetPosition ?? this._zone.value.position) ?? this._activeSession.wholeRange.value.getEndPosition()); } protected async _nextState(state: State, options: InlineChatRunOptions | undefined): Promise { @@ -241,14 +247,14 @@ export class InlineChatController implements IEditorContribution { switch (session.editMode) { case EditMode.Live: - this._strategy = this._instaService.createInstance(LiveStrategy, this._editor, session, this._zone.value.widget); + this._strategy = this._instaService.createInstance(LiveStrategy, session, this._editor, this._zone.value.widget); break; case EditMode.Preview: - this._strategy = this._instaService.createInstance(PreviewStrategy, this._editor, session, this._zone.value.widget); + this._strategy = this._instaService.createInstance(PreviewStrategy, session, this._zone.value.widget); break; case EditMode.LivePreview: default: - this._strategy = this._instaService.createInstance(LivePreviewStrategy, this._editor, session, this._zone.value.widget); + this._strategy = this._instaService.createInstance(LivePreviewStrategy, session, this._editor, this._zone.value.widget); break; } From eb98edb838dc0b01550fdef26377e79688f3f9fd Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 13 Jun 2023 17:23:55 +0200 Subject: [PATCH 098/128] changes from review --- .../browser/inlineChatStrategies.ts | 55 +++++++------------ 1 file changed, 19 insertions(+), 36 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts index b3e1f00194d..921e07e44f6 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts @@ -27,12 +27,6 @@ import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/ export abstract class EditModeStrategy { - constructor(protected readonly _editor: ICodeEditor) { - this._initialPosition = this._editor.getPosition(); - } - - protected _initialPosition: Position | null; - abstract dispose(): void; abstract checkChanges(response: EditResponse): boolean; @@ -49,7 +43,7 @@ export abstract class EditModeStrategy { abstract hasFocus(): boolean; - abstract getWidgetPosition(initialRender: boolean, range: Range): Position | null; + abstract getWidgetPosition(): Position | null; } export class PreviewStrategy extends EditModeStrategy { @@ -58,14 +52,13 @@ export class PreviewStrategy extends EditModeStrategy { private readonly _listener: IDisposable; constructor( - _editor: ICodeEditor, private readonly _session: Session, private readonly _widget: InlineChatWidget, @IContextKeyService contextKeyService: IContextKeyService, @IBulkEditService private readonly _bulkEditService: IBulkEditService, @IInstantiationService private readonly _instaService: IInstantiationService, ) { - super(_editor); + super(); this._ctxDocumentChanged = CTX_INLINE_CHAT_DOCUMENT_CHANGED.bindTo(contextKeyService); this._listener = Event.debounce(_session.textModelN.onDidChangeContent.bind(_session.textModelN), () => { }, 350)(_ => { @@ -138,8 +131,8 @@ export class PreviewStrategy extends EditModeStrategy { // nothing to do } - getWidgetPosition(_initialRender: boolean, _range: Range): Position | null { - return this._initialPosition; + getWidgetPosition(): Position | null { + return null; } hasFocus(): boolean { @@ -225,8 +218,8 @@ export class LiveStrategy extends EditModeStrategy { private _editCount: number = 0; constructor( - _editor: ICodeEditor, protected readonly _session: Session, + protected readonly _editor: ICodeEditor, protected readonly _widget: InlineChatWidget, @IContextKeyService contextKeyService: IContextKeyService, @IStorageService protected _storageService: IStorageService, @@ -234,7 +227,7 @@ export class LiveStrategy extends EditModeStrategy { @IEditorWorkerService protected readonly _editorWorkerService: IEditorWorkerService, @IInstantiationService private readonly _instaService: IInstantiationService, ) { - super(_editor); + super(); this._diffEnabled = _storageService.getBoolean(LiveStrategy._inlineDiffStorageKey, StorageScope.PROFILE, true); this._inlineDiffDecorations = new InlineDiffDecorations(this._editor, this._diffEnabled); @@ -350,18 +343,13 @@ export class LiveStrategy extends EditModeStrategy { return lastLineOfLocalEdits; } - override getWidgetPosition(initialRender: boolean, _range: Range): Position | null { - if (initialRender) { - return this._initialPosition; - } else { - const isEditResponse = this._session.lastExchange?.response instanceof EditResponse; - if (isEditResponse) { - const lastLineOfLocalEdits = this._lastLineOfLocalEdits(); - return lastLineOfLocalEdits ? new Position(lastLineOfLocalEdits, 1) : this._initialPosition; - } else { - return this._initialPosition; - } + override getWidgetPosition(): Position | null { + const isEditResponse = this._session.lastExchange?.response instanceof EditResponse; + if (isEditResponse) { + const lastLineOfLocalEdits = this._lastLineOfLocalEdits(); + return lastLineOfLocalEdits ? new Position(lastLineOfLocalEdits, 1) : null; } + return null; } hasFocus(): boolean { @@ -375,8 +363,8 @@ export class LivePreviewStrategy extends LiveStrategy { private readonly _previewZone: InlineChatFileCreatePreviewWidget; constructor( - editor: ICodeEditor, session: Session, + editor: ICodeEditor, widget: InlineChatWidget, @IContextKeyService contextKeyService: IContextKeyService, @IStorageService storageService: IStorageService, @@ -384,7 +372,7 @@ export class LivePreviewStrategy extends LiveStrategy { @IEditorWorkerService editorWorkerService: IEditorWorkerService, @IInstantiationService instaService: IInstantiationService, ) { - super(editor, session, widget, contextKeyService, storageService, bulkEditService, editorWorkerService, instaService); + super(session, editor, widget, contextKeyService, storageService, bulkEditService, editorWorkerService, instaService); this._diffZone = instaService.createInstance(InlineChatLivePreviewWidget, editor, session); this._previewZone = instaService.createInstance(InlineChatFileCreatePreviewWidget, editor); @@ -422,17 +410,12 @@ export class LivePreviewStrategy extends LiveStrategy { scrollState.restore(this._editor); } - override getWidgetPosition(initialRender: boolean, range: Range): Position | null { - if (initialRender) { - return this._initialPosition; - } else { - const isEditResponse = this._session.lastExchange?.response instanceof EditResponse; - if (range && isEditResponse) { - return range.getEndPosition(); - } else { - return this._initialPosition; - } + override getWidgetPosition(): Position | null { + const isEditResponse = this._session.lastExchange?.response instanceof EditResponse; + if (isEditResponse) { + return this._session.wholeRange.value.getEndPosition(); } + return null; } override hasFocus(): boolean { From d85ee0f6c52bedf7e2936af22cf1ee83dce537d5 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 13 Jun 2023 17:48:23 +0200 Subject: [PATCH 099/128] the margins are not set when not an initial render --- .../contrib/inlineChat/browser/inlineChatController.ts | 6 +++++- .../contrib/inlineChat/browser/inlineChatWidget.ts | 3 +-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index b5c3d8f695d..45ab5461a97 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -203,7 +203,11 @@ export class InlineChatController implements IEditorContribution { } else { widgetPosition = this._strategy.getWidgetPosition(); } - this._zone.value.show((widgetPosition ?? this._zone.value.position) ?? this._activeSession.wholeRange.value.getEndPosition()); + const position = ((widgetPosition ?? this._zone.value.position) ?? this._activeSession.wholeRange.value.getEndPosition()); + this._zone.value.show(position); + if (initialRender) { + this._zone.value.setMargins(position); + } } protected async _nextState(state: State, options: InlineChatRunOptions | undefined): Promise { diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index 53ffd4ace2e..f25ef458cfe 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -795,10 +795,9 @@ export class InlineChatZoneWidget extends ZoneWidget { super.show(position, this._computeHeightInLines()); this.widget.focus(); this._ctxVisible.set(true); - this._setMargins(position); } - private _setMargins(position: Position): void { + public setMargins(position: Position): void { const viewModel = this.editor._getViewModel(); if (!viewModel) { return; From 9f70132f21603bc2e3dc8f47ec661c28715b375b Mon Sep 17 00:00:00 2001 From: Joyce Er Date: Tue, 13 Jun 2023 09:08:49 -0700 Subject: [PATCH 100/128] Fix storing cloud changes with deleted file (#185037) --- .../browser/editSessions.contribution.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/editSessions/browser/editSessions.contribution.ts b/src/vs/workbench/contrib/editSessions/browser/editSessions.contribution.ts index 84c1bd8f1d7..33850a1817c 100644 --- a/src/vs/workbench/contrib/editSessions/browser/editSessions.contribution.ts +++ b/src/vs/workbench/contrib/editSessions/browser/editSessions.contribution.ts @@ -707,14 +707,15 @@ export class EditSessionsContribution extends Disposable implements IWorkbenchCo hasEdits = true; - const contents = encodeBase64((await this.fileService.readFile(uri)).value); - editSessionSize += contents.length; - if (editSessionSize > this.editSessionsStorageService.SIZE_LIMIT) { - this.notificationService.error(localize('payload too large', 'Your working changes exceed the size limit and cannot be stored.')); - return undefined; - } if (await this.fileService.exists(uri)) { + const contents = encodeBase64((await this.fileService.readFile(uri)).value); + editSessionSize += contents.length; + if (editSessionSize > this.editSessionsStorageService.SIZE_LIMIT) { + this.notificationService.error(localize('payload too large', 'Your working changes exceed the size limit and cannot be stored.')); + return undefined; + } + workingChanges.push({ type: ChangeType.Addition, fileType: FileType.File, contents: contents, relativeFilePath: relativeFilePath }); } else { // Assume it's a deletion From d037fad5895e2a4a39611aaa299374f98cbd7e3e Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 13 Jun 2023 18:29:50 +0200 Subject: [PATCH 101/128] changes from review --- .../browser/inlineChatController.ts | 7 ++--- .../browser/inlineChatStrategies.ts | 27 ++++--------------- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index b5c3d8f695d..0c668574ec1 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -196,14 +196,15 @@ export class InlineChatController implements IEditorContribution { private _showWidget(initialRender: boolean = false) { assertType(this._activeSession); assertType(this._strategy); + assertType(this._editor.hasModel()); - let widgetPosition: Position | null; + let widgetPosition: Position | undefined; if (initialRender) { widgetPosition = this._editor.getPosition(); } else { - widgetPosition = this._strategy.getWidgetPosition(); + widgetPosition = this._strategy.getWidgetPosition() ?? this._zone.value.position ?? this._activeSession.wholeRange.value.getEndPosition(); } - this._zone.value.show((widgetPosition ?? this._zone.value.position) ?? this._activeSession.wholeRange.value.getEndPosition()); + this._zone.value.show(widgetPosition); } protected async _nextState(state: State, options: InlineChatRunOptions | undefined): Promise { diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts index 921e07e44f6..3182adaf006 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts @@ -43,7 +43,7 @@ export abstract class EditModeStrategy { abstract hasFocus(): boolean; - abstract getWidgetPosition(): Position | null; + abstract getWidgetPosition(): Position | undefined; } export class PreviewStrategy extends EditModeStrategy { @@ -131,8 +131,8 @@ export class PreviewStrategy extends EditModeStrategy { // nothing to do } - getWidgetPosition(): Position | null { - return null; + getWidgetPosition(): Position | undefined { + return; } hasFocus(): boolean { @@ -331,7 +331,7 @@ export class LiveStrategy extends EditModeStrategy { this._widget.updateStatus(message); } - private _lastLineOfLocalEdits(): number | undefined { + override getWidgetPosition(): Position | undefined { const lastTextModelChanges = this._session.lastTextModelChanges; let lastLineOfLocalEdits: number | undefined; for (const change of lastTextModelChanges) { @@ -340,16 +340,7 @@ export class LiveStrategy extends EditModeStrategy { lastLineOfLocalEdits = changeEndLineNumber; } } - return lastLineOfLocalEdits; - } - - override getWidgetPosition(): Position | null { - const isEditResponse = this._session.lastExchange?.response instanceof EditResponse; - if (isEditResponse) { - const lastLineOfLocalEdits = this._lastLineOfLocalEdits(); - return lastLineOfLocalEdits ? new Position(lastLineOfLocalEdits, 1) : null; - } - return null; + return lastLineOfLocalEdits ? new Position(lastLineOfLocalEdits, 1) : undefined; } hasFocus(): boolean { @@ -410,14 +401,6 @@ export class LivePreviewStrategy extends LiveStrategy { scrollState.restore(this._editor); } - override getWidgetPosition(): Position | null { - const isEditResponse = this._session.lastExchange?.response instanceof EditResponse; - if (isEditResponse) { - return this._session.wholeRange.value.getEndPosition(); - } - return null; - } - override hasFocus(): boolean { return super.hasFocus() || this._diffZone.hasFocus() || this._previewZone.hasFocus(); } From 4b939d0a0e4ad5d11170ba1a8cea8051f284791b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 13 Jun 2023 19:56:46 +0200 Subject: [PATCH 102/128] unc - fix path traversal bypass (#185048) --- build/gulpfile.reh.js | 2 +- build/lib/electron.js | 4 ++-- build/lib/electron.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/gulpfile.reh.js b/build/gulpfile.reh.js index e3d9a477437..a930ce09492 100644 --- a/build/gulpfile.reh.js +++ b/build/gulpfile.reh.js @@ -165,7 +165,7 @@ function nodejs(platform, arch) { if (platform === 'win32') { if (product.nodejsRepository) { log(`Downloading node.js ${nodeVersion} ${platform} ${arch} from ${product.nodejsRepository}...`); - return assetFromGithub(product.nodejsRepository, nodeVersion, name => name === `win-${arch}-node.exe`) + return assetFromGithub(product.nodejsRepository, nodeVersion, name => name === `win-${arch}-node-patched.exe`) .pipe(rename('node.exe')); } log(`Downloading node.js ${nodeVersion} ${platform} ${arch} from https://nodejs.org`); diff --git a/build/lib/electron.js b/build/lib/electron.js index 4a51a8f254e..5cf792c491c 100644 --- a/build/lib/electron.js +++ b/build/lib/electron.js @@ -76,7 +76,7 @@ function darwinBundleDocumentTypes(types, icon) { }); } exports.config = { - version: product.electronRepository ? '22.5.5' : util.getElectronVersion(), + version: product.electronRepository ? '22.5.7' : util.getElectronVersion(), productAppName: product.nameLong, companyName: 'Microsoft Corporation', copyright: 'Copyright (C) 2023 Microsoft. All rights reserved', @@ -193,7 +193,7 @@ function getElectron(arch) { }; } async function main(arch = process.arch) { - const version = product.electronRepository ? '22.5.5' : util.getElectronVersion(); + const version = product.electronRepository ? '22.5.7' : util.getElectronVersion(); const electronPath = path.join(root, '.build', 'electron'); const versionFile = path.join(electronPath, 'version'); const isUpToDate = fs.existsSync(versionFile) && fs.readFileSync(versionFile, 'utf8') === `${version}`; diff --git a/build/lib/electron.ts b/build/lib/electron.ts index dfc74c01658..1d11429e586 100644 --- a/build/lib/electron.ts +++ b/build/lib/electron.ts @@ -91,7 +91,7 @@ function darwinBundleDocumentTypes(types: { [name: string]: string | string[] }, } export const config = { - version: product.electronRepository ? '22.5.5' : util.getElectronVersion(), + version: product.electronRepository ? '22.5.7' : util.getElectronVersion(), productAppName: product.nameLong, companyName: 'Microsoft Corporation', copyright: 'Copyright (C) 2023 Microsoft. All rights reserved', @@ -212,7 +212,7 @@ function getElectron(arch: string): () => NodeJS.ReadWriteStream { } async function main(arch = process.arch): Promise { - const version = product.electronRepository ? '22.5.5' : util.getElectronVersion(); + const version = product.electronRepository ? '22.5.7' : util.getElectronVersion(); const electronPath = path.join(root, '.build', 'electron'); const versionFile = path.join(electronPath, 'version'); const isUpToDate = fs.existsSync(versionFile) && fs.readFileSync(versionFile, 'utf8') === `${version}`; From 470b6efc0c5783a687f3ac1aa11befd89c463a57 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Tue, 13 Jun 2023 20:16:39 +0200 Subject: [PATCH 103/128] diff editor v2: sync update (#185039) --- .../diffEditorWidget2/diffEditorWidget2.ts | 2 - .../widget/diffEditorWidget2/diffModel.ts | 150 +++++++++++------- .../diffEditorWidget2/unchangedRanges.ts | 8 +- .../editor/common/diff/linesDiffComputer.ts | 16 ++ src/vs/monaco.d.ts | 4 + 5 files changed, 120 insertions(+), 60 deletions(-) diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts index 74346212f94..a4c4cc5821e 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts @@ -306,7 +306,6 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { if (!m) { return; } const movedText = m.diff.get()!.movedTexts.find(m => m.lineRangeMapping.originalRange.contains(e.position.lineNumber)); - m.syncedMovedTexts.set(movedText, undefined); })); return editor; @@ -322,7 +321,6 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { if (!m) { return; } const movedText = m.diff.get()!.movedTexts.find(m => m.lineRangeMapping.modifiedRange.contains(e.position.lineNumber)); - m.syncedMovedTexts.set(movedText, undefined); })); // Revert change when an arrow is clicked. diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffModel.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffModel.ts index cfab19c8ed4..4ef2d808a89 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffModel.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffModel.ts @@ -7,25 +7,30 @@ import { RunOnceScheduler } from 'vs/base/common/async'; import { Disposable } from 'vs/base/common/lifecycle'; import { IObservable, IReader, ITransaction, derived, observableSignal, observableSignalFromEvent, observableValue, transaction } from 'vs/base/common/observable'; import { autorunWithStore2 } from 'vs/base/common/observableImpl/autorun'; +import { isDefined } from 'vs/base/common/types'; import { LineRange } from 'vs/editor/common/core/lineRange'; import { Range } from 'vs/editor/common/core/range'; import { IDocumentDiff, IDocumentDiffProvider } from 'vs/editor/common/diff/documentDiffProvider'; -import { LineRangeMapping, MovedText, RangeMapping } from 'vs/editor/common/diff/linesDiffComputer'; +import { LineRangeMapping, MovedText, RangeMapping, SimpleLineRangeMapping } from 'vs/editor/common/diff/linesDiffComputer'; import { lineRangeMappingFromRangeMappings } from 'vs/editor/common/diff/standardLinesDiffComputer'; import { IDiffEditorModel } from 'vs/editor/common/editorCommon'; import { ITextModel } from 'vs/editor/common/model'; import { TextEditInfo } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/beforeEditPositionMapper'; import { combineTextEditInfos } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/combineTextEditInfos'; -import { lengthAdd, lengthDiffNonNegative, lengthOfRange, lengthToPosition, lengthZero, positionToLength } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/length'; +import { lengthAdd, lengthDiffNonNegative, lengthGetLineCount, lengthOfRange, lengthToPosition, lengthZero, positionToLength } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/length'; export class DiffModel extends Disposable { private readonly _isDiffUpToDate = observableValue('isDiffUpToDate', false); public readonly isDiffUpToDate: IObservable = this._isDiffUpToDate; + private _lastDiff: IDocumentDiff | undefined; private readonly _diff = observableValue('diff', undefined); public readonly diff: IObservable = this._diff; - private readonly _unchangedRegions = observableValue<{ regions: UnchangedRegion[]; originalDecorationIds: string[]; modifiedDecorationIds: string[] }>('unchangedRegion', { regions: [], originalDecorationIds: [], modifiedDecorationIds: [] }); + private readonly _unchangedRegions = observableValue<{ regions: UnchangedRegion[]; originalDecorationIds: string[]; modifiedDecorationIds: string[] }>( + 'unchangedRegion', + { regions: [], originalDecorationIds: [], modifiedDecorationIds: [] } + ); public readonly unchangedRegions: IObservable = derived('unchangedRegions', r => this._hideUnchangedRegions.read(r) ? this._unchangedRegions.read(r).regions : [] ); @@ -50,11 +55,14 @@ export class DiffModel extends Disposable { if (!diff) { return; } - /*const textEdits = TextEditInfo.fromModelContentChanges(e.changes); - this._diff.set( - applyModifiedEdits(diff, textEdits, model.original, model.modified), - undefined - );*/ + if (!this._showMoves.get()) { + const textEdits = TextEditInfo.fromModelContentChanges(e.changes); + this._lastDiff = applyModifiedEdits(this._lastDiff!, textEdits, model.original, model.modified); + this._diff.set(DiffState.fromDiffResult(this._lastDiff), undefined); + const currentSyncedMovedText = this.syncedMovedTexts.get(); + this.syncedMovedTexts.set(currentSyncedMovedText ? this._lastDiff.moves.find(m => m.lineRangeMapping.modifiedRange.intersect(currentSyncedMovedText.lineRangeMapping.modifiedRange)) : undefined, undefined); + } + debouncer.schedule(); })); this._register(model.original.onDidChangeContent((e) => { @@ -62,11 +70,13 @@ export class DiffModel extends Disposable { if (!diff) { return; } - /*const textEdits = TextEditInfo.fromModelContentChanges(e.changes); - this._diff.set( - applyOriginalEdits(diff, textEdits, model.original, model.modified), - undefined - );*/ + if (!this._showMoves.get()) { + const textEdits = TextEditInfo.fromModelContentChanges(e.changes); + this._lastDiff = applyOriginalEdits(this._lastDiff!, textEdits, model.original, model.modified); + this._diff.set(DiffState.fromDiffResult(this._lastDiff), undefined); + const currentSyncedMovedText = this.syncedMovedTexts.get(); + this.syncedMovedTexts.set(currentSyncedMovedText ? this._lastDiff.moves.find(m => m.lineRangeMapping.modifiedRange.intersect(currentSyncedMovedText.lineRangeMapping.modifiedRange)) : undefined, undefined); + } debouncer.schedule(); })); @@ -137,8 +147,11 @@ export class DiffModel extends Disposable { ); transaction(tx => { + this._lastDiff = result; this._diff.set(DiffState.fromDiffResult(result), tx); this._isDiffUpToDate.set(true, tx); + const currentSyncedMovedText = this.syncedMovedTexts.get(); + this.syncedMovedTexts.set(currentSyncedMovedText ? this._lastDiff.moves.find(m => m.lineRangeMapping.modifiedRange.intersect(currentSyncedMovedText.lineRangeMapping.modifiedRange)) : undefined, tx); this._unchangedRegions.set( { @@ -152,7 +165,7 @@ export class DiffModel extends Disposable { })); } - public revealModifiedLine(lineNumber: number, tx: ITransaction): void { + public ensureModifiedLineIsVisible(lineNumber: number, tx: ITransaction): void { const unchangedRegions = this._unchangedRegions.get().regions; for (const r of unchangedRegions) { if (r.getHiddenModifiedRange(undefined).contains(lineNumber)) { @@ -162,7 +175,7 @@ export class DiffModel extends Disposable { } } - public revealOriginalLine(lineNumber: number, tx: ITransaction): void { + public ensureOriginalLineIsVisible(lineNumber: number, tx: ITransaction): void { const unchangedRegions = this._unchangedRegions.get().regions; for (const r of unchangedRegions) { if (r.getHiddenOriginalRange(undefined).contains(lineNumber)) { @@ -315,38 +328,17 @@ function applyOriginalEdits(diff: IDocumentDiff, textEdits: TextEditInfo[], orig return diff; } - const diffTextEdits = diff.changes.flatMap(c => c.innerChanges!.map(c => new TextEditInfo( - positionToLength(c.modifiedRange.getStartPosition()), - positionToLength(c.modifiedRange.getEndPosition()), - lengthOfRange(c.originalRange).toLength(), - ))); - - const combined = combineTextEditInfos(diffTextEdits, textEdits); - - let lastModifiedEndOffset = lengthZero; - let lastOriginalEndOffset = lengthZero; - const rangeMappings = combined.map(c => { - const originalStartOffset = lengthAdd(lastOriginalEndOffset, lengthDiffNonNegative(lastModifiedEndOffset, c.startOffset)); - lastModifiedEndOffset = c.endOffset; - lastOriginalEndOffset = lengthAdd(originalStartOffset, c.newLength); - - return new RangeMapping( - Range.fromPositions(lengthToPosition(originalStartOffset), lengthToPosition(lastOriginalEndOffset)), - Range.fromPositions(lengthToPosition(c.startOffset), lengthToPosition(c.endOffset)), - ); - }); - - const changes = lineRangeMappingFromRangeMappings( - rangeMappings, - originalTextModel.getLinesContent(), - modifiedTextModel.getLinesContent(), - ); + const diff2 = flip(diff); + const diff3 = applyModifiedEdits(diff2, textEdits, modifiedTextModel, originalTextModel); + return flip(diff3); +} +function flip(diff: IDocumentDiff): IDocumentDiff { return { - identical: false, - quitEarly: false, - changes, - moves: [], + changes: diff.changes.map(c => c.flip()), + moves: diff.moves.map(m => m.flip()), + identical: diff.identical, + quitEarly: diff.quitEarly, }; } @@ -355,7 +347,63 @@ function applyModifiedEdits(diff: IDocumentDiff, textEdits: TextEditInfo[], orig return diff; } - const diffTextEdits = diff.changes.flatMap(c => c.innerChanges!.map(c => new TextEditInfo( + const changes = applyModifiedEditsToLineRangeMappings(diff.changes, textEdits, originalTextModel, modifiedTextModel); + + const moves = diff.moves.map(m => { + const newModifiedRange = applyEditToLineRange(m.lineRangeMapping.modifiedRange, textEdits); + return newModifiedRange ? new MovedText( + new SimpleLineRangeMapping(m.lineRangeMapping.originalRange, newModifiedRange), + applyModifiedEditsToLineRangeMappings(m.changes, textEdits, originalTextModel, modifiedTextModel), + ) : undefined; + }).filter(isDefined); + + return { + identical: false, + quitEarly: false, + changes, + moves, + }; +} + +function applyEditToLineRange(range: LineRange, textEdits: TextEditInfo[]): LineRange | undefined { + let rangeStartLineNumber = range.startLineNumber; + let rangeEndLineNumberEx = range.endLineNumberExclusive; + + for (let i = textEdits.length - 1; i >= 0; i--) { + const textEdit = textEdits[i]; + const textEditStartLineNumber = lengthGetLineCount(textEdit.startOffset) + 1; + const textEditEndLineNumber = lengthGetLineCount(textEdit.endOffset) + 1; + const newLengthLineCount = lengthGetLineCount(textEdit.newLength); + const delta = newLengthLineCount - (textEditEndLineNumber - textEditStartLineNumber); + + if (textEditEndLineNumber < rangeStartLineNumber) { + // the text edit is before us + rangeStartLineNumber += delta; + rangeEndLineNumberEx += delta; + } else if (textEditStartLineNumber > rangeEndLineNumberEx) { + // the text edit is after us + // NOOP + } else if (textEditStartLineNumber < rangeStartLineNumber && rangeEndLineNumberEx < textEditEndLineNumber) { + // the range is fully contained in the text edit + return undefined; + } else if (textEditStartLineNumber < rangeStartLineNumber && textEditEndLineNumber <= rangeEndLineNumberEx) { + // the text edit ends inside our range + rangeStartLineNumber = textEditEndLineNumber + 1; + rangeStartLineNumber += delta; + rangeEndLineNumberEx += delta; + } else if (rangeStartLineNumber <= textEditStartLineNumber && textEditEndLineNumber < rangeStartLineNumber) { + // the text edit starts inside our range + rangeEndLineNumberEx = textEditStartLineNumber; + } else { + rangeEndLineNumberEx += delta; + } + } + + return new LineRange(rangeStartLineNumber, rangeEndLineNumberEx); +} + +function applyModifiedEditsToLineRangeMappings(changes: readonly LineRangeMapping[], textEdits: TextEditInfo[], originalTextModel: ITextModel, modifiedTextModel: ITextModel): LineRangeMapping[] { + const diffTextEdits = changes.flatMap(c => c.innerChanges!.map(c => new TextEditInfo( positionToLength(c.originalRange.getStartPosition()), positionToLength(c.originalRange.getEndPosition()), lengthOfRange(c.modifiedRange).toLength(), @@ -376,16 +424,10 @@ function applyModifiedEdits(diff: IDocumentDiff, textEdits: TextEditInfo[], orig ); }); - const changes = lineRangeMappingFromRangeMappings( + const newChanges = lineRangeMappingFromRangeMappings( rangeMappings, originalTextModel.getLinesContent(), modifiedTextModel.getLinesContent(), ); - - return { - identical: false, - quitEarly: false, - changes, - moves: [], - }; + return newChanges; } diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/unchangedRanges.ts b/src/vs/editor/browser/widget/diffEditorWidget2/unchangedRanges.ts index a979ecf78ca..e2d5bebe6f0 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/unchangedRanges.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/unchangedRanges.ts @@ -28,8 +28,8 @@ export class UnchangedRangesFeature extends Disposable { const m = this._diffModel.get(); transaction(tx => { for (const s of this._originalEditor.getSelections() || []) { - m?.revealOriginalLine(s.getStartPosition().lineNumber, tx); - m?.revealOriginalLine(s.getEndPosition().lineNumber, tx); + m?.ensureOriginalLineIsVisible(s.getStartPosition().lineNumber, tx); + m?.ensureOriginalLineIsVisible(s.getEndPosition().lineNumber, tx); } }); })); @@ -38,8 +38,8 @@ export class UnchangedRangesFeature extends Disposable { const m = this._diffModel.get(); transaction(tx => { for (const s of this._modifiedEditor.getSelections() || []) { - m?.revealModifiedLine(s.getStartPosition().lineNumber, tx); - m?.revealModifiedLine(s.getEndPosition().lineNumber, tx); + m?.ensureModifiedLineIsVisible(s.getStartPosition().lineNumber, tx); + m?.ensureModifiedLineIsVisible(s.getEndPosition().lineNumber, tx); } }); })); diff --git a/src/vs/editor/common/diff/linesDiffComputer.ts b/src/vs/editor/common/diff/linesDiffComputer.ts index e8fddf830a9..a096042419f 100644 --- a/src/vs/editor/common/diff/linesDiffComputer.ts +++ b/src/vs/editor/common/diff/linesDiffComputer.ts @@ -102,6 +102,10 @@ export class LineRangeMapping { public get changedLineCount() { return Math.max(this.originalRange.length, this.modifiedRange.length); } + + public flip(): LineRangeMapping { + return new LineRangeMapping(this.modifiedRange, this.originalRange, this.innerChanges?.map(c => c.flip())); + } } /** @@ -130,6 +134,10 @@ export class RangeMapping { public toString(): string { return `{${this.originalRange.toString()}->${this.modifiedRange.toString()}}`; } + + public flip(): RangeMapping { + return new RangeMapping(this.modifiedRange, this.originalRange); + } } export class SimpleLineRangeMapping { @@ -142,6 +150,10 @@ export class SimpleLineRangeMapping { public toString(): string { return `{${this.originalRange.toString()}->${this.modifiedRange.toString()}}`; } + + public flip(): SimpleLineRangeMapping { + return new SimpleLineRangeMapping(this.modifiedRange, this.originalRange); + } } export class MovedText { @@ -161,4 +173,8 @@ export class MovedText { this.lineRangeMapping = lineRangeMapping; this.changes = changes; } + + public flip(): MovedText { + return new MovedText(this.lineRangeMapping.flip(), this.changes.map(c => c.flip())); + } } diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index f4f733504e9..e19a539a1f2 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -2501,6 +2501,7 @@ declare namespace monaco.editor { constructor(originalRange: LineRange, modifiedRange: LineRange, innerChanges: RangeMapping[] | undefined); toString(): string; get changedLineCount(): any; + flip(): LineRangeMapping; } /** @@ -2517,6 +2518,7 @@ declare namespace monaco.editor { readonly modifiedRange: Range; constructor(originalRange: Range, modifiedRange: Range); toString(): string; + flip(): RangeMapping; } export class MovedText { @@ -2528,6 +2530,7 @@ declare namespace monaco.editor { */ readonly changes: readonly LineRangeMapping[]; constructor(lineRangeMapping: SimpleLineRangeMapping, changes: readonly LineRangeMapping[]); + flip(): MovedText; } export class SimpleLineRangeMapping { @@ -2535,6 +2538,7 @@ declare namespace monaco.editor { readonly modifiedRange: LineRange; constructor(originalRange: LineRange, modifiedRange: LineRange); toString(): string; + flip(): SimpleLineRangeMapping; } export interface IDimension { width: number; From f1b2a3a77faedb737630bf8a0e4df6bf00b276a0 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 13 Jun 2023 20:16:58 +0200 Subject: [PATCH 104/128] Use `Lazy` for creating diff and preview zone so that they don't block startup (#185041) https://github.com/microsoft/vscode/issues/185034 --- .../browser/inlineChatStrategies.ts | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts index 03bb8f3e7ea..d498c1f1c3a 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Event } from 'vs/base/common/event'; +import { Lazy } from 'vs/base/common/lazy'; import { IDisposable } from 'vs/base/common/lifecycle'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService'; @@ -347,8 +348,8 @@ export class LiveStrategy extends EditModeStrategy { export class LivePreviewStrategy extends LiveStrategy { - private readonly _diffZone: InlineChatLivePreviewWidget; - private readonly _previewZone: InlineChatFileCreatePreviewWidget; + private readonly _diffZone: Lazy; + private readonly _previewZone: Lazy; constructor( session: Session, @@ -362,15 +363,15 @@ export class LivePreviewStrategy extends LiveStrategy { ) { super(session, editor, widget, contextKeyService, storageService, bulkEditService, editorWorkerService, instaService); - this._diffZone = instaService.createInstance(InlineChatLivePreviewWidget, editor, session); - this._previewZone = instaService.createInstance(InlineChatFileCreatePreviewWidget, editor); + this._diffZone = new Lazy(() => instaService.createInstance(InlineChatLivePreviewWidget, editor, session)); + this._previewZone = new Lazy(() => instaService.createInstance(InlineChatFileCreatePreviewWidget, editor)); } override dispose(): void { - this._diffZone.hide(); - this._diffZone.dispose(); - this._previewZone.hide(); - this._previewZone.dispose(); + this._diffZone.rawValue?.hide(); + this._diffZone.rawValue?.dispose(); + this._previewZone.rawValue?.hide(); + this._previewZone.rawValue?.dispose(); super.dispose(); } @@ -378,33 +379,33 @@ export class LivePreviewStrategy extends LiveStrategy { this._updateSummaryMessage(); if (this._diffEnabled) { - this._diffZone.show(); + this._diffZone.value.show(); } if (response.singleCreateFileEdit) { - this._previewZone.showCreation(this._session.wholeRange.value, response.singleCreateFileEdit.uri, await Promise.all(response.singleCreateFileEdit.edits)); + this._previewZone.value.showCreation(this._session.wholeRange.value, response.singleCreateFileEdit.uri, await Promise.all(response.singleCreateFileEdit.edits)); } else { - this._previewZone.hide(); + this._previewZone.value.hide(); } } override async undoChanges(response: EditResponse): Promise { - this._diffZone.lockToDiff(); + this._diffZone.value.lockToDiff(); super.undoChanges(response); } protected override _doToggleDiff(): void { const scrollState = StableEditorScrollState.capture(this._editor); if (this._diffEnabled) { - this._diffZone.show(); + this._diffZone.value.show(); } else { - this._diffZone.hide(); + this._diffZone.value.hide(); } scrollState.restore(this._editor); } override hasFocus(): boolean { - return super.hasFocus() || this._diffZone.hasFocus() || this._previewZone.hasFocus(); + return super.hasFocus() || this._diffZone.value.hasFocus() || this._previewZone.value.hasFocus(); } } From 2e335d2df2001439b09483e7fcff8379ac1a7a16 Mon Sep 17 00:00:00 2001 From: Joyce Er Date: Tue, 13 Jun 2023 11:46:04 -0700 Subject: [PATCH 105/128] Update payload size limit (#185052) --- .../contrib/editSessions/browser/editSessionsStorageService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/editSessions/browser/editSessionsStorageService.ts b/src/vs/workbench/contrib/editSessions/browser/editSessionsStorageService.ts index 2f63475b58a..c7389a1b224 100644 --- a/src/vs/workbench/contrib/editSessions/browser/editSessionsStorageService.ts +++ b/src/vs/workbench/contrib/editSessions/browser/editSessionsStorageService.ts @@ -33,7 +33,7 @@ export class EditSessionsWorkbenchService extends Disposable implements IEditSes declare _serviceBrand: undefined; - public readonly SIZE_LIMIT = 1024 * 1024 * 2; // 2 MB + public readonly SIZE_LIMIT = Math.floor(1024 * 1024 * 1.9); // 2 MB private serverConfiguration = this.productService['editSessions.store']; private machineClient: IUserDataSyncMachinesService | undefined; From b42cfb963cdb75b7be347f62ac38395b1a40c8e8 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 13 Jun 2023 15:38:16 -0500 Subject: [PATCH 106/128] rm copilot term --- .../browser/actions/chatAccessibilityHelp.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts index 65bbd5e8f97..76e92276042 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts @@ -13,22 +13,26 @@ import { IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat'; import { IAccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView'; import { InlineChatController } from 'vs/workbench/contrib/inlineChat/browser/inlineChatController'; + +const inputBox = localize('chat.requestHistory', 'In the input box, use up and down arrows to navigate your request history. Edit input and use enter or the submit button to run a new request.'); + export function getAccessibilityHelpText(accessor: ServicesAccessor, type: 'chat' | 'inline'): string { const keybindingService = accessor.get(IKeybindingService); const content = []; if (type === 'chat') { - content.push(localize('chat.overview', 'Chat responses will be announced as they come in. A response will indicate the number of code blocks, if any, and then the rest of the response.')); - content.push(localize('chat.requestHistory', 'In the input box, use up and down arrows to navigate your request history. Edit input and use enter to run a new request.')); - content.push(descriptionForCommand('chat.action.focus', localize('workbench.action.chat.focus', 'The Focus Chat command ({0}) focuses the chat request/response list, which can be navigated with UpArrow/DownArrow.',), localize('workbench.action.chat.focusNoKb', 'The Focus Chat List command focuses the chat request/response list, which can be navigated with UpArrow/DownArrow and is currently not triggerable by a keybinding.'), keybindingService)); + content.push(localize('chat.overview', 'The chat view is comprised of an input box and a request/response list. The input box is used to make requests and the list is used to display responses.')); + content.push(inputBox); + content.push(localize('chat.announcement', 'Chat responses will be announced as they come in. A response will indicate the number of code blocks, if any, and then the rest of the response.')); + content.push(descriptionForCommand('chat.action.focus', localize('workbench.action.chat.focus', 'The Focus Chat command ({0}) focuses the chat request/response list, which can be navigated with up and down arrows.',), localize('workbench.action.chat.focusNoKb', 'The Focus Chat List command focuses the chat request/response list, which can be navigated with UpArrow/DownArrow and is currently not triggerable by a keybinding.'), keybindingService)); content.push(descriptionForCommand('workbench.action.chat.focusInput', localize('workbench.action.chat.focusInput', 'The Focus Chat Input command ({0}) focuses the input box for chat requests.'), localize('workbench.action.interactiveSession.focusInputNoKb', 'Focus Chat Input command focuses the input box for chat requests and is currently not triggerable by a keybinding.'), keybindingService)); content.push(descriptionForCommand('workbench.action.chat.nextCodeBlock', localize('workbench.action.chat.nextCodeBlock', 'The Chat: Next Code Block command ({0}) focuses the next code block within a response.'), localize('workbench.action.chat.nextCodeBlockNoKb', 'The Chat: Next Code Block command focuses the next code block within a response and is currently not triggerable by a keybinding.'), keybindingService)); content.push(descriptionForCommand('workbench.action.chat.clear', localize('workbench.action.chat.clear', 'The Chat Clear command ({0}) clears the request/response list.'), localize('workbench.action.chat.clearNoKb', 'The Chat Clear command clears the request/response list and is currently not triggerable by a keybinding.'), keybindingService)); } else { const startChatKeybinding = keybindingService.lookupKeybinding('inlineChat.start')?.getAriaLabel(); - content.push(localize('inlineChat.overview', "Inline chat occurs within a code editor and takes into account current selection. It is useful for refactoring, fixing, and more. Keep in mind that Copilot generated code may be incorrect.")); - content.push(localize('inlineChat.access', "It can be activated via the Fix and Explain with Copilot context menu actions or directly using the command: Inline Chat: Start Code Chat ({0}).", startChatKeybinding)); - content.push(localize('chat.requestHistoryInline', 'In the input box, use up and down arrows to navigate your request history. Edit input and use enter or the make request button to run a new request.')); - content.push(localize('inlineChat.contextActions', "Explain and Fix with Copilot actions run a request prefixed with /fix or /explain. These prefixes can be used directly in the input box to apply those specific actions.")); + content.push(localize('inlineChat.overview', "Inline chat occurs within a code editor and takes into account the current selection. It is useful for refactoring, fixing, and more. Keep in mind that AI generated code may be incorrect.")); + content.push(localize('inlineChat.access', "It can be activated via quick fix actions or directly using the command: Inline Chat: Start Code Chat ({0}).", startChatKeybinding)); + content.push(inputBox); + content.push(localize('inlineChat.contextActions', "Context menu actions may run a request prefixed with /fix or /explain. These prefixes can be used directly in the input box to apply those specific actions.")); content.push(localize('inlineChat.fix', "When a request is prefixed with /fix, a response will indicate the problem with the current code. A diff editor will be rendered and can be reached by tabbing.")); const diffReviewKeybinding = keybindingService.lookupKeybinding('editor.action.diffReview.next')?.getAriaLabel(); content.push(diffReviewKeybinding ? localize('inlineChat.diff', "Once in the diff editor, enter review mode with ({0}). Use up and down arrows to navigate lines with the proposed changes.", diffReviewKeybinding) : localize('inlineChat.diffNoKb', "Tab again to enter the Diff editor with the changes and enter review mode with the Go to Next Difference Command. Use Up/DownArrow to navigate lines with the proposed changes.")); From 34911a262b2d658b5050f67510a72669e8cc0a39 Mon Sep 17 00:00:00 2001 From: cadinsl <46573438+cadinsl@users.noreply.github.com> Date: Tue, 13 Jun 2023 17:06:45 -0400 Subject: [PATCH 107/128] Edited user and workspace tab to only display the name for accessibility #184530 (#184627) --- .../preferences/browser/preferencesWidgets.ts | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts b/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts index 067e5110b60..c4f4a6b1fdd 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesWidgets.ts @@ -33,7 +33,6 @@ import { ThemeIcon } from 'vs/base/common/themables'; import { isWorkspaceFolder, IWorkspaceContextService, IWorkspaceFolder, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { settingsEditIcon, settingsScopeDropDownIcon } from 'vs/workbench/contrib/preferences/browser/preferencesIcons'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; import { ILanguageService } from 'vs/editor/common/languages/language'; import { CONTEXT_SETTINGS_EDITOR_IN_USER_TAB } from 'vs/workbench/contrib/preferences/common/preferences'; @@ -52,7 +51,6 @@ export class FolderSettingsActionViewItem extends BaseActionViewItem { action: IAction, @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, @IContextMenuService private readonly contextMenuService: IContextMenuService, - @IPreferencesService private readonly preferencesService: IPreferencesService, ) { super(null, action); const workspace = this.contextService.getWorkspace(); @@ -142,14 +140,14 @@ export class FolderSettingsActionViewItem extends BaseActionViewItem { } } - private async update(): Promise { + private update(): void { let total = 0; this._folderSettingCounts.forEach(n => total += n); const workspace = this.contextService.getWorkspace(); if (this._folder) { this.labelElement.textContent = this._folder.name; - this.anchorElement.title = (await this.preferencesService.getEditableSettingsURI(ConfigurationTarget.WORKSPACE_FOLDER, this._folder.uri))?.fsPath || ''; + this.anchorElement.title = this._folder.name; const detailsText = this.labelWithCount(this._action.label, total); this.detailsElement.textContent = detailsText; this.dropDownElement.classList.toggle('hide', workspace.folders.length === 1 || !this._action.checked); @@ -233,7 +231,6 @@ export class SettingsTargetsWidget extends Widget { @IInstantiationService private readonly instantiationService: IInstantiationService, @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, @ILabelService private readonly labelService: ILabelService, - @IPreferencesService private readonly preferencesService: IPreferencesService, @ILanguageService private readonly languageService: ILanguageService, @IContextKeyService contextKeyService: IContextKeyService, ) { @@ -265,15 +262,12 @@ export class SettingsTargetsWidget extends Widget { })); this.userLocalSettings = new Action('userSettings', '', '.settings-tab', true, () => this.updateTarget(ConfigurationTarget.USER_LOCAL)); - this.preferencesService.getEditableSettingsURI(ConfigurationTarget.USER_LOCAL).then(uri => { - // Don't wait to create UI on resolving remote - this.userLocalSettings.tooltip = uri?.fsPath ?? ''; - }); + this.userLocalSettings.tooltip = localize('userSettings', "User"); this.userRemoteSettings = new Action('userSettingsRemote', '', '.settings-tab', true, () => this.updateTarget(ConfigurationTarget.USER_REMOTE)); - this.preferencesService.getEditableSettingsURI(ConfigurationTarget.USER_REMOTE).then(uri => { - this.userRemoteSettings.tooltip = uri?.fsPath ?? ''; - }); + const remoteAuthority = this.environmentService.remoteAuthority; + const hostLabel = remoteAuthority && this.labelService.getHostLabel(Schemas.vscodeRemote, remoteAuthority); + this.userRemoteSettings.tooltip = localize('userSettingsRemote', "Remote") + (hostLabel ? ` [${hostLabel}]` : ''); this.workspaceSettings = new Action('workspaceSettings', '', '.settings-tab', false, () => this.updateTarget(ConfigurationTarget.WORKSPACE)); @@ -368,7 +362,7 @@ export class SettingsTargetsWidget extends Widget { this.workspaceSettings.enabled = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY; this.folderSettings.action.enabled = this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE && this.contextService.getWorkspace().folders.length > 0; - this.workspaceSettings.tooltip = (await this.preferencesService.getEditableSettingsURI(ConfigurationTarget.WORKSPACE))?.fsPath || ''; + this.workspaceSettings.tooltip = localize('workspaceSettings', "Workspace"); } } From 20d8459c1d98798429d70fae6da34ca556210eff Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Tue, 13 Jun 2023 23:38:24 +0200 Subject: [PATCH 108/128] Implements simple caching for diff editor v2 (#185060) --- src/vs/editor/browser/editorBrowser.ts | 4 +- .../editor/browser/widget/codeEditorWidget.ts | 2 +- .../editor/browser/widget/diffEditorWidget.ts | 15 ++++++- .../diffEditorWidget2/delegatingEditorImpl.ts | 4 +- .../diffEditorWidget2/diffEditorWidget2.ts | 42 ++++++++++++------- .../widget/diffEditorWidget2/diffModel.ts | 10 +++-- .../diffEditorWidget2/movedBlocksLines.ts | 5 +-- .../widget/workerBasedDocumentDiffProvider.ts | 15 +++++++ src/vs/editor/common/editorCommon.ts | 8 +++- src/vs/monaco.d.ts | 10 ++++- .../browser/parts/editor/textDiffEditor.ts | 7 +++- 11 files changed, 92 insertions(+), 30 deletions(-) diff --git a/src/vs/editor/browser/editorBrowser.ts b/src/vs/editor/browser/editorBrowser.ts index 836448dac93..c85f63877e5 100644 --- a/src/vs/editor/browser/editorBrowser.ts +++ b/src/vs/editor/browser/editorBrowser.ts @@ -1157,6 +1157,8 @@ export interface IDiffEditor extends editorCommon.IEditor { */ getModel(): editorCommon.IDiffEditorModel | null; + createViewModel(model: editorCommon.IDiffEditorModel): editorCommon.IDiffEditorViewModel; + /** * Sets the current model attached to this editor. * If the previous model was created by the editor via the value key in the options @@ -1165,7 +1167,7 @@ export interface IDiffEditor extends editorCommon.IEditor { * will not be destroyed. * It is safe to call setModel(null) to simply detach the current model from the editor. */ - setModel(model: editorCommon.IDiffEditorModel | null): void; + setModel(model: editorCommon.IDiffEditorModel | editorCommon.IDiffEditorViewModel | null): void; /** * Get the `original` editor. diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index 181b2c279e4..dedb0237589 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -488,7 +488,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE return this._modelData.model; } - public setModel(_model: ITextModel | editorCommon.IDiffEditorModel | null = null): void { + public setModel(_model: ITextModel | editorCommon.IDiffEditorModel | editorCommon.IDiffEditorViewModel | null = null): void { const model = _model; if (this._modelData === null && model === null) { // Current model is the new model diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index e9d3e2d1ec1..f25d9b3f9b4 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -829,7 +829,20 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE }; } - public setModel(model: editorCommon.IDiffEditorModel | null): void { + public createViewModel(model: editorCommon.IDiffEditorModel): editorCommon.IDiffEditorViewModel { + return { + model, + async waitForDiff() { + // noop + }, + }; + } + + public setModel(model: editorCommon.IDiffEditorModel | editorCommon.IDiffEditorViewModel | null): void { + if (model && 'model' in model) { + model = model.model; + } + // Guard us against partial null model if (model && (!model.original || !model.modified)) { throw new Error(!model.original ? 'DiffEditorWidget.setModel: Original model is null' : 'DiffEditorWidget.setModel: Modified model is null'); diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/delegatingEditorImpl.ts b/src/vs/editor/browser/widget/diffEditorWidget2/delegatingEditorImpl.ts index 70d9fe58399..4ab6f4201b8 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/delegatingEditorImpl.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/delegatingEditorImpl.ts @@ -11,7 +11,7 @@ import { IDimension } from 'vs/editor/common/core/dimension'; import { IPosition, Position } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; import { ISelection, Selection } from 'vs/editor/common/core/selection'; -import { IEditor, IEditorAction, IEditorDecorationsCollection, IEditorModel, IEditorViewState, ScrollType } from 'vs/editor/common/editorCommon'; +import { IDiffEditorViewModel, IEditor, IEditorAction, IEditorDecorationsCollection, IEditorModel, IEditorViewState, ScrollType } from 'vs/editor/common/editorCommon'; import { IModelDecorationsChangeAccessor, IModelDeltaDecoration } from 'vs/editor/common/model'; export abstract class DelegatingEditor extends Disposable implements IEditor { @@ -34,7 +34,7 @@ export abstract class DelegatingEditor extends Disposable implements IEditor { abstract saveViewState(): IEditorViewState | null; abstract restoreViewState(state: IEditorViewState | null): void; abstract getModel(): IEditorModel | null; - abstract setModel(model: IEditorModel | null): void; + abstract setModel(model: IEditorModel | null | IDiffEditorViewModel): void; // #region editorBrowser.IDiffEditor: Delegating to modified Editor diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts index a4c4cc5821e..c4c9edf6990 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts @@ -7,8 +7,8 @@ import { IBoundarySashes } from 'vs/base/browser/ui/sash/sash'; import { findLast } from 'vs/base/common/arrays'; import { onUnexpectedError } from 'vs/base/common/errors'; import { Emitter, Event } from 'vs/base/common/event'; -import { IObservable, ISettableObservable, autorun, derived, keepAlive, observableValue, waitForState } from 'vs/base/common/observable'; -import { disposableObservableValue } from 'vs/base/common/observableImpl/base'; +import { IObservable, ISettableObservable, autorun, derived, keepAlive, observableValue } from 'vs/base/common/observable'; +import { disposableObservableValue, transaction } from 'vs/base/common/observableImpl/base'; import { derivedWithStore } from 'vs/base/common/observableImpl/derived'; import { isDefined } from 'vs/base/common/types'; import { Constants } from 'vs/base/common/uint'; @@ -32,7 +32,7 @@ import { IDimension } from 'vs/editor/common/core/dimension'; import { LineRange } from 'vs/editor/common/core/lineRange'; import { Position } from 'vs/editor/common/core/position'; import { IDiffComputationResult, ILineChange } from 'vs/editor/common/diff/smartLinesDiffComputer'; -import { EditorType, IContentSizeChangedEvent, IDiffEditorModel, IDiffEditorViewState } from 'vs/editor/common/editorCommon'; +import { EditorType, IContentSizeChangedEvent, IDiffEditorModel, IDiffEditorViewModel, IDiffEditorViewState } from 'vs/editor/common/editorCommon'; import { IModelDeltaDecoration } from 'vs/editor/common/model'; import { localize } from 'vs/nls'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; @@ -482,22 +482,27 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { } } - override getModel(): IDiffEditorModel | null { return this._model.get(); } - - override setModel(model: IDiffEditorModel | null): void { - this._originalEditor.setModel(model ? model.original : null); - this._modifiedEditor.setModel(model ? model.modified : null); - - this._model.set(model, undefined); - - this._diffModel.set(model ? new DiffModel( + public createViewModel(model: IDiffEditorModel): IDiffEditorViewModel { + return new DiffModel( model, this._options.map(o => o.ignoreTrimWhitespace), this._options.map(o => o.maxComputationTime), this._options.map(o => o.experimental.collapseUnchangedRegions!), this._options.map(o => o.experimental.showMoves! && o.renderSideBySide), this._instantiationService.createInstance(WorkerBasedDocumentDiffProvider, this._options.get()) - ) : undefined, undefined); + ); + } + + override getModel(): IDiffEditorModel | null { return this._model.get(); } + + override setModel(model: IDiffEditorModel | null | IDiffEditorViewModel): void { + const vm = model ? ('model' in model) ? model : this.createViewModel(model) : undefined; + this._originalEditor.setModel(vm ? vm.model.original : null); + this._modifiedEditor.setModel(vm ? vm.model.modified : null); + transaction(tx => { + this._model.set(vm?.model ?? null, tx); + this._diffModel.set(vm as (DiffModel | undefined), tx); + }); } override updateOptions(_newOptions: IDiffEditorOptions): void { @@ -639,7 +644,7 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { return; } // wait for the diff computation to finish - waitForState(diffModel.isDiffUpToDate, s => s).then(() => { + this.waitForDiff().then(() => { const diffs = diffModel.diff.get()?.mappings; if (!diffs || diffs.length === 0) { return; @@ -647,6 +652,15 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { this._goTo(diffs[0]); }); } + + + public async waitForDiff(): Promise { + const diffModel = this._diffModel.get(); + if (!diffModel) { + return; + } + await diffModel.waitForDiff(); + } } function validateDiffEditorOptions(options: Readonly, defaults: ValidDiffEditorBaseOptions): ValidDiffEditorBaseOptions { diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffModel.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffModel.ts index 4ef2d808a89..6094cee8684 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffModel.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffModel.ts @@ -5,7 +5,7 @@ import { RunOnceScheduler } from 'vs/base/common/async'; import { Disposable } from 'vs/base/common/lifecycle'; -import { IObservable, IReader, ITransaction, derived, observableSignal, observableSignalFromEvent, observableValue, transaction } from 'vs/base/common/observable'; +import { IObservable, IReader, ITransaction, derived, observableSignal, observableSignalFromEvent, observableValue, transaction, waitForState } from 'vs/base/common/observable'; import { autorunWithStore2 } from 'vs/base/common/observableImpl/autorun'; import { isDefined } from 'vs/base/common/types'; import { LineRange } from 'vs/editor/common/core/lineRange'; @@ -13,13 +13,13 @@ import { Range } from 'vs/editor/common/core/range'; import { IDocumentDiff, IDocumentDiffProvider } from 'vs/editor/common/diff/documentDiffProvider'; import { LineRangeMapping, MovedText, RangeMapping, SimpleLineRangeMapping } from 'vs/editor/common/diff/linesDiffComputer'; import { lineRangeMappingFromRangeMappings } from 'vs/editor/common/diff/standardLinesDiffComputer'; -import { IDiffEditorModel } from 'vs/editor/common/editorCommon'; +import { IDiffEditorModel, IDiffEditorViewModel } from 'vs/editor/common/editorCommon'; import { ITextModel } from 'vs/editor/common/model'; import { TextEditInfo } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/beforeEditPositionMapper'; import { combineTextEditInfos } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/combineTextEditInfos'; import { lengthAdd, lengthDiffNonNegative, lengthGetLineCount, lengthOfRange, lengthToPosition, lengthZero, positionToLength } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/length'; -export class DiffModel extends Disposable { +export class DiffModel extends Disposable implements IDiffEditorViewModel { private readonly _isDiffUpToDate = observableValue('isDiffUpToDate', false); public readonly isDiffUpToDate: IObservable = this._isDiffUpToDate; @@ -184,6 +184,10 @@ export class DiffModel extends Disposable { } } } + + public async waitForDiff(): Promise { + await waitForState(this.isDiffUpToDate, s => s); + } } export class DiffState { diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts b/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts index 5502568cc69..3df9808e6b0 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts @@ -42,8 +42,9 @@ export class MovedBlocksLinesPart extends Disposable { const originalScrollTop = observableFromEvent(this._originalEditor.onDidScrollChange, () => this._originalEditor.getScrollTop()); const modifiedScrollTop = observableFromEvent(this._modifiedEditor.onDidScrollChange, () => this._modifiedEditor.getScrollTop()); - this._register(autorun('update', (reader) => { + element.replaceChildren(); + const info = this._originalEditorLayoutInfo.read(reader); const info2 = this._modifiedEditorLayoutInfo.read(reader); if (!info || !info2) { @@ -56,8 +57,6 @@ export class MovedBlocksLinesPart extends Disposable { return; } - element.replaceChildren(); - let idx = 0; for (const m of moves) { function computeLineStart(range: LineRange, editor: ICodeEditor) { diff --git a/src/vs/editor/browser/widget/workerBasedDocumentDiffProvider.ts b/src/vs/editor/browser/widget/workerBasedDocumentDiffProvider.ts index a2fc75d5296..eddfb9c0ad9 100644 --- a/src/vs/editor/browser/widget/workerBasedDocumentDiffProvider.ts +++ b/src/vs/editor/browser/widget/workerBasedDocumentDiffProvider.ts @@ -20,6 +20,8 @@ export class WorkerBasedDocumentDiffProvider implements IDocumentDiffProvider, I private diffAlgorithm: DiffAlgorithmName | IDocumentDiffProvider = 'advanced'; private diffAlgorithmOnDidChangeSubscription: IDisposable | undefined = undefined; + private static readonly diffCache = new Map(); + constructor( options: IWorkerBasedDocumentDiffProviderOptions, @IEditorWorkerService private readonly editorWorkerService: IEditorWorkerService, @@ -58,6 +60,13 @@ export class WorkerBasedDocumentDiffProvider implements IDocumentDiffProvider, I }; } + const uriKey = JSON.stringify([original.uri.toString(), modified.uri.toString()]); + const context = JSON.stringify([original.id, modified.id, original.getAlternativeVersionId(), modified.getAlternativeVersionId(), JSON.stringify(options)]); + const c = WorkerBasedDocumentDiffProvider.diffCache.get(uriKey); + if (c && c.context === context) { + return c.result; + } + const sw = StopWatch.create(true); const result = await this.editorWorkerService.computeDiff(original.uri, modified.uri, options, this.diffAlgorithm); const timeMs = sw.elapsed(); @@ -81,6 +90,12 @@ export class WorkerBasedDocumentDiffProvider implements IDocumentDiffProvider, I throw new Error('no diff result available'); } + // max 10 items in cache + if (WorkerBasedDocumentDiffProvider.diffCache.size > 10) { + WorkerBasedDocumentDiffProvider.diffCache.delete(WorkerBasedDocumentDiffProvider.diffCache.keys().next().value); + } + + WorkerBasedDocumentDiffProvider.diffCache.set(uriKey, { result, context }); return result; } diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 2f735614140..e3b7854e21d 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -104,6 +104,12 @@ export interface IDiffEditorModel { modified: ITextModel; } +export interface IDiffEditorViewModel { + readonly model: IDiffEditorModel; + + waitForDiff(): Promise; +} + /** * An event describing that an editor has had its model reset (i.e. `editor.setModel()`). */ @@ -153,7 +159,7 @@ export interface IEditorAction { run(args?: unknown): Promise; } -export type IEditorModel = ITextModel | IDiffEditorModel; +export type IEditorModel = ITextModel | IDiffEditorModel | IDiffEditorViewModel; /** * A (serializable) state of the cursors. diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index e19a539a1f2..07aec862a82 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -2623,6 +2623,11 @@ declare namespace monaco.editor { modified: ITextModel; } + export interface IDiffEditorViewModel { + readonly model: IDiffEditorModel; + waitForDiff(): Promise; + } + /** * An event describing that an editor has had its model reset (i.e. `editor.setModel()`). */ @@ -2657,7 +2662,7 @@ declare namespace monaco.editor { run(args?: unknown): Promise; } - export type IEditorModel = ITextModel | IDiffEditorModel; + export type IEditorModel = ITextModel | IDiffEditorModel | IDiffEditorViewModel; /** * A (serializable) state of the cursors. @@ -6026,6 +6031,7 @@ declare namespace monaco.editor { * Type the getModel() of IEditor. */ getModel(): IDiffEditorModel | null; + createViewModel(model: IDiffEditorModel): IDiffEditorViewModel; /** * Sets the current model attached to this editor. * If the previous model was created by the editor via the value key in the options @@ -6034,7 +6040,7 @@ declare namespace monaco.editor { * will not be destroyed. * It is safe to call setModel(null) to simply detach the current model from the editor. */ - setModel(model: IDiffEditorModel | null): void; + setModel(model: IDiffEditorModel | IDiffEditorViewModel | null): void; /** * Get the `original` editor. */ diff --git a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts index 2ce5f1694c8..e5918fb80ca 100644 --- a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts @@ -5,7 +5,7 @@ import { localize } from 'vs/nls'; import { deepClone } from 'vs/base/common/objects'; -import { isObject, assertIsDefined, withUndefinedAsNull, withNullAsUndefined } from 'vs/base/common/types'; +import { isObject, assertIsDefined, withNullAsUndefined } from 'vs/base/common/types'; import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser'; import { IDiffEditorOptions, IEditorOptions as ICodeEditorOptions } from 'vs/editor/common/config/editorOptions'; import { AbstractTextEditor, IEditorConfiguration } from 'vs/workbench/browser/parts/editor/textEditor'; @@ -133,7 +133,10 @@ export class TextDiffEditor extends AbstractTextEditor imp // Set Editor Model const control = assertIsDefined(this.diffEditorControl); const resolvedDiffEditorModel = resolvedModel as TextDiffEditorModel; - control.setModel(withUndefinedAsNull(resolvedDiffEditorModel.textDiffEditorModel)); + + const vm = resolvedDiffEditorModel.textDiffEditorModel ? control.createViewModel(resolvedDiffEditorModel.textDiffEditorModel) : null; + await vm?.waitForDiff(); + control.setModel(vm); // Restore view state (unless provided by options) let hasPreviousViewState = false; From 990d40aad4e5fe57500132cae7ad8c69950399b0 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 13 Jun 2023 15:53:21 -0700 Subject: [PATCH 109/128] Fix highlight on chat thumbs buttons (#185063) The parent element used to also have the 'checked' class, now it doesn't, bisecting to figure out what happened Fix microsoft/vscode-copilot-release#242 --- src/vs/workbench/contrib/chat/browser/media/chat.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/media/chat.css b/src/vs/workbench/contrib/chat/browser/media/chat.css index d32c164481f..6796d8436a8 100644 --- a/src/vs/workbench/contrib/chat/browser/media/chat.css +++ b/src/vs/workbench/contrib/chat/browser/media/chat.css @@ -82,8 +82,8 @@ padding: 2px; } -.interactive-item-container .header .monaco-toolbar .checked .action-label, -.interactive-item-container .header .monaco-toolbar .checked .action-label:hover { +.interactive-item-container .header .monaco-toolbar .checked.action-label, +.interactive-item-container .header .monaco-toolbar .checked.action-label:hover { color: var(--vscode-inputOption-activeForeground) !important; border-color: var(--vscode-inputOption-activeBorder); background-color: var(--vscode-inputOption-activeBackground); From df2952cc9be54bd0b3450cca00dfe7bf7058499d Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Wed, 14 Jun 2023 10:25:15 +1000 Subject: [PATCH 110/128] Revert changes to listWidtget (#185071) --- src/vs/base/browser/ui/list/listWidget.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index 2a282e9f1a3..d039f788cca 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -152,7 +152,8 @@ class Trait implements ISpliceable, IDisposable { const length = this.length + diff; if (this.sortedIndexes.length > 0 && sortedIndexes.length === 0 && length > 0) { - sortedIndexes.push(Math.min(firstSortedIndex ?? length - 1, length - 1)); + const first = this.sortedIndexes.find(index => index >= start) ?? length - 1; + sortedIndexes.push(Math.min(first, length - 1)); } this.renderer.splice(start, deleteCount, elements.length); From 352d2d3934fd0d2e62cd3992038cc6476f7e8b45 Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Tue, 13 Jun 2023 17:45:22 -0700 Subject: [PATCH 111/128] Fix #184606. Fix updateCellMetadata incremental update. (#184964) --- src/vs/workbench/api/common/extHostTypes.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index f414312d433..e90c15ce050 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -17,7 +17,7 @@ import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensio import { FileSystemProviderErrorCode, markAsFileSystemProviderError } from 'vs/platform/files/common/files'; import { RemoteAuthorityResolverErrorCode } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { IRelativePatternDto } from 'vs/workbench/api/common/extHost.protocol'; -import { CellEditType, ICellPartialMetadataEdit, IDocumentMetadataEdit, isTextStreamMime } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellEditType, ICellMetadataEdit, IDocumentMetadataEdit, isTextStreamMime } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions'; import type * as vscode from 'vscode'; @@ -775,7 +775,7 @@ export interface IFileSnippetTextEdit { export interface IFileCellEdit { readonly _type: FileEditType.Cell; readonly uri: URI; - readonly edit?: ICellPartialMetadataEdit | IDocumentMetadataEdit; + readonly edit?: ICellMetadataEdit | IDocumentMetadataEdit; readonly notebookMetadata?: Record; readonly metadata?: vscode.WorkspaceEditEntryMetadata; } @@ -832,7 +832,7 @@ export class WorkspaceEdit implements vscode.WorkspaceEdit { } private replaceNotebookCellMetadata(uri: URI, index: number, cellMetadata: Record, metadata?: vscode.WorkspaceEditEntryMetadata): void { - this._edits.push({ _type: FileEditType.Cell, metadata, uri, edit: { editType: CellEditType.PartialMetadata, index, metadata: cellMetadata } }); + this._edits.push({ _type: FileEditType.Cell, metadata, uri, edit: { editType: CellEditType.Metadata, index, metadata: cellMetadata } }); } // --- text From bf5419f02d146b4359c32fa0748f8ba47adf118c Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Tue, 13 Jun 2023 21:24:18 -0700 Subject: [PATCH 112/128] Update execution timer priorty to reserve some room. (#185076) --- .../contrib/cellStatusBar/executionStatusBarItemController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/executionStatusBarItemController.ts b/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/executionStatusBarItemController.ts index c09f41176fa..3aa72fc3bfb 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/executionStatusBarItemController.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/executionStatusBarItemController.ts @@ -321,7 +321,7 @@ class TimerCellStatusBarItem extends Disposable { return { text: formatCellDuration(duration, false), alignment: CellStatusbarAlignment.Left, - priority: Number.MAX_SAFE_INTEGER - 1, + priority: Number.MAX_SAFE_INTEGER - 5, tooltip }; } From 8e26c332debacb3c06a36fee410723e71700528a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 14 Jun 2023 08:43:26 +0200 Subject: [PATCH 113/128] Warning message doesn't show up when code-insiders --status is run while no instances are open (#185080) * Warning message doesn't show up when `code-insiders --status` is run while no instances are open (fix #185069) * :lipstick: --- src/vs/code/electron-main/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index adc1cba1945..6e960fc47c7 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -382,7 +382,7 @@ class CodeMain { // Print --status usage info if (environmentMainService.args.status) { - logService.warn(localize('statusWarning', "Warning: The --status argument can only be used if {0} is already running. Please run it again after {0} has started.", productService.nameShort)); + console.log(localize('statusWarning', "Warning: The --status argument can only be used if {0} is already running. Please run it again after {0} has started.", productService.nameShort)); throw new ExpectedError('Terminating...'); } From a1e93027e40462ea03c146fd83ef9c18e5326a49 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Wed, 14 Jun 2023 09:31:48 +0200 Subject: [PATCH 114/128] removing the useless variable --- .../contrib/inlineChat/browser/inlineChatController.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 98d7c67a461..d9f703d4c72 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -205,10 +205,9 @@ export class InlineChatController implements IEditorContribution { } else { widgetPosition = this._strategy.getWidgetPosition() ?? this._zone.value.position ?? this._activeSession.wholeRange.value.getEndPosition(); } - const position = (widgetPosition); - this._zone.value.show(position); + this._zone.value.show(widgetPosition); if (initialRender) { - this._zone.value.setMargins(position); + this._zone.value.setMargins(widgetPosition); } } From 79c611d7b7a542a1ab86b2eca07bf55e82736e07 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Wed, 14 Jun 2023 09:33:54 +0200 Subject: [PATCH 115/128] setting the margins inside of the case of initial render --- .../contrib/inlineChat/browser/inlineChatController.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index d9f703d4c72..e28b8cfc171 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -202,13 +202,11 @@ export class InlineChatController implements IEditorContribution { let widgetPosition: Position | undefined; if (initialRender) { widgetPosition = this._editor.getPosition(); + this._zone.value.setMargins(widgetPosition); } else { widgetPosition = this._strategy.getWidgetPosition() ?? this._zone.value.position ?? this._activeSession.wholeRange.value.getEndPosition(); } this._zone.value.show(widgetPosition); - if (initialRender) { - this._zone.value.setMargins(widgetPosition); - } } protected async _nextState(state: State, options: InlineChatRunOptions | undefined): Promise { From 04f7885c54e3cfe777344a57401f0a0b6133022d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 14 Jun 2023 10:25:30 +0200 Subject: [PATCH 116/128] UNC allow list checks cannot be disabled in extension host (#184989) (#185083) * UNC allow list checks cannot be disabled in extension host (#184989) * Update src/vs/base/node/unc.js Co-authored-by: Robo --------- Co-authored-by: Robo --- src/vs/base/node/unc.d.ts | 5 +++++ src/vs/base/node/unc.js | 11 ++++++++++- .../utilityProcess/electron-main/utilityProcess.ts | 8 ++++++-- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/vs/base/node/unc.d.ts b/src/vs/base/node/unc.d.ts index 75e53310c8c..d131bba5d85 100644 --- a/src/vs/base/node/unc.d.ts +++ b/src/vs/base/node/unc.d.ts @@ -23,3 +23,8 @@ export function addUNCHostToAllowlist(allowedHost: string | string[]): void; * path validation. */ export function disableUNCAccessRestrictions(): void; + +/** + * Whether UNC Host allow list in node.js is disabled. + */ +export function isUNCAccessRestrictionsDisabled(): boolean; diff --git a/src/vs/base/node/unc.js b/src/vs/base/node/unc.js index 71bd2fbcbbf..4e774d1114a 100644 --- a/src/vs/base/node/unc.js +++ b/src/vs/base/node/unc.js @@ -117,11 +117,20 @@ process.enableUNCAccessChecks = false; } + function isUNCAccessRestrictionsDisabled() { + if (process.platform !== 'win32') { + return true; + } + + return process.enableUNCAccessChecks === false; + } + return { getUNCHostAllowlist, addUNCHostToAllowlist, getUNCHost, - disableUNCAccessRestrictions + disableUNCAccessRestrictions, + isUNCAccessRestrictionsDisabled }; } diff --git a/src/vs/platform/utilityProcess/electron-main/utilityProcess.ts b/src/vs/platform/utilityProcess/electron-main/utilityProcess.ts index 522956e5b07..f2276db0396 100644 --- a/src/vs/platform/utilityProcess/electron-main/utilityProcess.ts +++ b/src/vs/platform/utilityProcess/electron-main/utilityProcess.ts @@ -17,7 +17,7 @@ import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifec import { removeDangerousEnvVariables } from 'vs/base/common/processes'; import { deepClone } from 'vs/base/common/objects'; import { isWindows } from 'vs/base/common/platform'; -import { getUNCHostAllowlist } from 'vs/base/node/unc'; +import { isUNCAccessRestrictionsDisabled, getUNCHostAllowlist } from 'vs/base/node/unc'; export interface IUtilityProcessConfiguration { @@ -259,7 +259,11 @@ export class UtilityProcess extends Disposable { } env['VSCODE_CRASH_REPORTER_PROCESS_TYPE'] = configuration.type; if (isWindows) { - env['NODE_UNC_HOST_ALLOWLIST'] = getUNCHostAllowlist().join('\\'); + if (isUNCAccessRestrictionsDisabled()) { + env['NODE_DISABLE_UNC_ACCESS_CHECKS'] = '1'; + } else { + env['NODE_UNC_HOST_ALLOWLIST'] = getUNCHostAllowlist().join('\\'); + } } // Remove any environment variables that are not allowed From f3aa9a201b2455e6556797e8ffb7145d77adb792 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 14 Jun 2023 10:29:39 +0200 Subject: [PATCH 117/128] fix #165202 (#185016) --- .../abstractExtensionManagementService.ts | 81 +++++++++++++---- .../common/extensionManagement.ts | 4 + .../common/extensionManagementIpc.ts | 11 ++- .../node/extensionManagementService.ts | 14 ++- .../userDataSync/common/extensionsSync.ts | 49 +++++----- ...ensionRecommendationNotificationService.ts | 6 +- .../extensions/browser/extensionsViews.ts | 2 +- .../common/extensionManagement.ts | 2 - .../common/extensionManagementService.ts | 91 +++++++++++++------ .../common/webExtensionManagementService.ts | 11 ++- .../browser/extensionsResource.ts | 27 ++++-- .../test/browser/workbenchTestServices.ts | 9 +- 12 files changed, 213 insertions(+), 94 deletions(-) diff --git a/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts b/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts index f681fc5b653..cc9c6d87d95 100644 --- a/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts +++ b/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts @@ -16,9 +16,9 @@ import * as nls from 'vs/nls'; import { ExtensionManagementError, IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementParticipant, IGalleryExtension, ILocalExtension, InstallOperation, IExtensionsControlManifest, StatisticType, isTargetPlatformCompatible, TargetPlatformToString, ExtensionManagementErrorCode, - InstallOptions, InstallVSIXOptions, UninstallOptions, Metadata, InstallExtensionEvent, DidUninstallExtensionEvent, InstallExtensionResult, UninstallExtensionEvent, IExtensionManagementService + InstallOptions, InstallVSIXOptions, UninstallOptions, Metadata, InstallExtensionEvent, DidUninstallExtensionEvent, InstallExtensionResult, UninstallExtensionEvent, IExtensionManagementService, InstallExtensionInfo } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { areSameExtensions, ExtensionKey, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { areSameExtensions, ExtensionKey, getGalleryExtensionId, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { ExtensionType, IExtensionManifest, isApplicationScopedExtension, TargetPlatform } from 'vs/platform/extensions/common/extensions'; import { ILogService } from 'vs/platform/log/common/log'; import { IProductService } from 'vs/platform/product/common/productService'; @@ -26,6 +26,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile'; export type ExtensionVerificationStatus = boolean | string; +export type InstallableExtension = { readonly manifest: IExtensionManifest; extension: IGalleryExtension | URI; options: InstallOptions & InstallVSIXOptions }; export type InstallExtensionTaskOptions = InstallOptions & InstallVSIXOptions & { readonly profileLocation: URI }; export interface IInstallExtensionTask { @@ -93,19 +94,54 @@ export abstract class AbstractExtensionManagementService extends Disposable impl async installFromGallery(extension: IGalleryExtension, options: InstallOptions = {}): Promise { try { - if (!this.galleryService.isEnabled()) { - throw new ExtensionManagementError(nls.localize('MarketPlaceDisabled', "Marketplace is not enabled"), ExtensionManagementErrorCode.Internal); + const results = await this.installGalleryExtensions([{ extension, options }]); + const result = results.find(({ identifier }) => areSameExtensions(identifier, extension.identifier)); + if (result?.local) { + return result?.local; } - const compatible = await this.checkAndGetCompatibleVersion(extension, !!options.installGivenVersion, !!options.installPreReleaseVersion); - return await this.installExtension(compatible.manifest, compatible.extension, options); + if (result?.error) { + throw result.error; + } + throw toExtensionManagementError(new Error(`Unknown error while installing extension ${extension.identifier.id}`)); } catch (error) { - reportTelemetry(this.telemetryService, 'extensionGallery:install', { extensionData: getGalleryExtensionTelemetryData(extension), error }); - this.logService.error(`Failed to install extension.`, extension.identifier.id); - this.logService.error(error); throw toExtensionManagementError(error); } } + async installGalleryExtensions(extensions: InstallExtensionInfo[]): Promise { + if (!this.galleryService.isEnabled()) { + throw new ExtensionManagementError(nls.localize('MarketPlaceDisabled', "Marketplace is not enabled"), ExtensionManagementErrorCode.Internal); + } + + const results: InstallExtensionResult[] = []; + const installableExtensions: InstallableExtension[] = []; + + await Promise.allSettled(extensions.map(async ({ extension, options }) => { + try { + const compatible = await this.checkAndGetCompatibleVersion(extension, !!options?.installGivenVersion, !!options?.installPreReleaseVersion); + installableExtensions.push({ ...compatible, options }); + } catch (error) { + results.push({ identifier: extension.identifier, operation: InstallOperation.Install, source: extension, error }); + } + })); + + if (installableExtensions.length) { + results.push(...await this.installExtensions(installableExtensions)); + } + + for (const result of results) { + if (result.error) { + this.logService.error(`Failed to install extension.`, result.identifier.id); + this.logService.error(result.error); + if (result.source && !URI.isUri(result.source)) { + reportTelemetry(this.telemetryService, 'extensionGallery:install', { extensionData: getGalleryExtensionTelemetryData(result.source), error: result.error }); + } + } + } + + return results; + } + async uninstall(extension: ILocalExtension, options: UninstallOptions = {}): Promise { this.logService.trace('ExtensionManagementService#uninstall', extension.identifier.id); return this.uninstallExtension(extension, options); @@ -126,7 +162,21 @@ export abstract class AbstractExtensionManagementService extends Disposable impl this.participants.push(participant); } - protected async installExtension(manifest: IExtensionManifest, extension: URI | IGalleryExtension, options: InstallOptions & InstallVSIXOptions): Promise { + protected async installExtensions(extensions: InstallableExtension[]): Promise { + const results: InstallExtensionResult[] = []; + await Promise.allSettled(extensions.map(async e => { + try { + const result = await this.installExtension(e); + results.push(...result); + } catch (error) { + results.push({ identifier: { id: getGalleryExtensionId(e.manifest.publisher, e.manifest.name) }, operation: InstallOperation.Install, source: e.extension, error }); + } + })); + this._onDidInstallExtensions.fire(results); + return results; + } + + private async installExtension({ manifest, extension, options }: InstallableExtension): Promise { const isApplicationScoped = options.isApplicationScoped || options.isBuiltin || isApplicationScopedExtension(manifest); const installExtensionTaskOptions: InstallExtensionTaskOptions = { @@ -142,7 +192,8 @@ export abstract class AbstractExtensionManagementService extends Disposable impl const installingExtension = this.installingExtensions.get(getInstallExtensionTaskKey(extension)); if (installingExtension) { this.logService.info('Extensions is already requested to install', extension.identifier.id); - return installingExtension.task.waitUntilTaskIsFinished(); + await installingExtension.task.waitUntilTaskIsFinished(); + return []; } } @@ -272,8 +323,7 @@ export abstract class AbstractExtensionManagementService extends Disposable impl } installResults.forEach(({ identifier }) => this.logService.info(`Extension installed successfully:`, identifier.id)); - this._onDidInstallExtensions.fire(installResults); - return installResults.filter(({ identifier }) => areSameExtensions(identifier, installExtensionTask.identifier))[0].local; + return installResults; } catch (error) { @@ -299,8 +349,7 @@ export abstract class AbstractExtensionManagementService extends Disposable impl } } - this._onDidInstallExtensions.fire(allInstallExtensionTasks.map(({ task }) => ({ identifier: task.identifier, operation: InstallOperation.Install, source: task.source, context: installExtensionTaskOptions.context, profileLocation: installExtensionTaskOptions.profileLocation }))); - throw error; + return allInstallExtensionTasks.map(({ task }) => ({ identifier: task.identifier, operation: InstallOperation.Install, source: task.source, context: installExtensionTaskOptions.context, profileLocation: installExtensionTaskOptions.profileLocation, error })); } finally { // Finally, remove all the tasks from the cache for (const { task } of allInstallExtensionTasks) { @@ -678,7 +727,7 @@ export function joinErrors(errorOrErrors: (Error | string) | (Array; readonly profileLocation?: URI; readonly applicationScoped?: boolean; @@ -450,6 +451,8 @@ export interface IExtensionManagementParticipant { postUninstall(local: ILocalExtension, options: UninstallOptions, token: CancellationToken): Promise; } +export type InstallExtensionInfo = { readonly extension: IGalleryExtension; readonly options: InstallOptions }; + export const IExtensionManagementService = createDecorator('extensionManagementService'); export interface IExtensionManagementService { readonly _serviceBrand: undefined; @@ -466,6 +469,7 @@ export interface IExtensionManagementService { install(vsix: URI, options?: InstallVSIXOptions): Promise; canInstall(extension: IGalleryExtension): Promise; installFromGallery(extension: IGalleryExtension, options?: InstallOptions): Promise; + installGalleryExtensions(extensions: InstallExtensionInfo[]): Promise; installFromLocation(location: URI, profileLocation: URI): Promise; installExtensionsFromProfile(extensions: IExtensionIdentifier[], fromProfileLocation: URI, toProfileLocation: URI): Promise; uninstall(extension: ILocalExtension, options?: UninstallOptions): Promise; diff --git a/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts b/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts index 712e7fc22f9..c1d91312b45 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts @@ -9,7 +9,7 @@ import { cloneAndChange } from 'vs/base/common/objects'; import { URI, UriComponents } from 'vs/base/common/uri'; import { DefaultURITransformer, IURITransformer, transformAndReviveIncomingURIs } from 'vs/base/common/uriIpc'; import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; -import { IExtensionIdentifier, IExtensionTipsService, IGalleryExtension, ILocalExtension, IExtensionsControlManifest, isTargetPlatformCompatible, InstallOptions, InstallVSIXOptions, UninstallOptions, Metadata, IExtensionManagementService, DidUninstallExtensionEvent, InstallExtensionEvent, InstallExtensionResult, UninstallExtensionEvent, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { IExtensionIdentifier, IExtensionTipsService, IGalleryExtension, ILocalExtension, IExtensionsControlManifest, isTargetPlatformCompatible, InstallOptions, InstallVSIXOptions, UninstallOptions, Metadata, IExtensionManagementService, DidUninstallExtensionEvent, InstallExtensionEvent, InstallExtensionResult, UninstallExtensionEvent, InstallOperation, InstallExtensionInfo } from 'vs/platform/extensionManagement/common/extensionManagement'; import { ExtensionType, IExtensionManifest, TargetPlatform } from 'vs/platform/extensions/common/extensions'; function transformIncomingURI(uri: UriComponents, transformer: IURITransformer | null): URI; @@ -128,6 +128,10 @@ export class ExtensionManagementChannel implements IServerChannel { case 'installFromGallery': { return this.service.installFromGallery(args[0], transformIncomingOptions(args[1], uriTransformer)); } + case 'installGalleryExtensions': { + const arg: InstallExtensionInfo[] = args[0]; + return this.service.installGalleryExtensions(arg.map(({ extension, options }) => ({ extension, options: transformIncomingOptions(options, uriTransformer) ?? {} }))); + } case 'uninstall': { return this.service.uninstall(transformIncomingExtension(args[0], uriTransformer), transformIncomingOptions(args[1], uriTransformer)); } @@ -250,6 +254,11 @@ export class ExtensionManagementChannelClient extends Disposable implements IExt return Promise.resolve(this.channel.call('installFromGallery', [extension, installOptions])).then(local => transformIncomingExtension(local, null)); } + async installGalleryExtensions(extensions: InstallExtensionInfo[]): Promise { + const results = await this.channel.call('installGalleryExtensions', [extensions]); + return results.map(e => ({ ...e, local: e.local ? transformIncomingExtension(e.local, null) : e.local, source: this.isUriComponents(e.source) ? URI.revive(e.source) : e.source, profileLocation: URI.revive(e.profileLocation) })); + } + uninstall(extension: ILocalExtension, options?: UninstallOptions): Promise { return Promise.resolve(this.channel.call('uninstall', [extension!, options])); } diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts index 840f47e3b22..dff38faf6f5 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts @@ -25,7 +25,7 @@ import { extract, ExtractError, IFile, zip } from 'vs/base/node/zip'; import * as nls from 'vs/nls'; import { IDownloadService } from 'vs/platform/download/common/download'; import { INativeEnvironmentService } from 'vs/platform/environment/common/environment'; -import { AbstractExtensionManagementService, AbstractExtensionTask, ExtensionVerificationStatus, IInstallExtensionTask, InstallExtensionTaskOptions, IUninstallExtensionTask, joinErrors, UninstallExtensionTaskOptions } from 'vs/platform/extensionManagement/common/abstractExtensionManagementService'; +import { AbstractExtensionManagementService, AbstractExtensionTask, ExtensionVerificationStatus, IInstallExtensionTask, InstallExtensionTaskOptions, IUninstallExtensionTask, joinErrors, toExtensionManagementError, UninstallExtensionTaskOptions } from 'vs/platform/extensionManagement/common/abstractExtensionManagementService'; import { ExtensionManagementError, ExtensionManagementErrorCode, IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementService, IGalleryExtension, ILocalExtension, InstallOperation, Metadata, InstallVSIXOptions @@ -148,11 +148,19 @@ export class ExtensionManagementService extends AbstractExtensionManagementServi try { const manifest = await getManifest(path.resolve(location.fsPath)); + const extensionId = getGalleryExtensionId(manifest.publisher, manifest.name); if (manifest.engines && manifest.engines.vscode && !isEngineValid(manifest.engines.vscode, this.productService.version, this.productService.date)) { - throw new Error(nls.localize('incompatible', "Unable to install extension '{0}' as it is not compatible with VS Code '{1}'.", getGalleryExtensionId(manifest.publisher, manifest.name), this.productService.version)); + throw new Error(nls.localize('incompatible', "Unable to install extension '{0}' as it is not compatible with VS Code '{1}'.", extensionId, this.productService.version)); } - return await this.installExtension(manifest, location, options); + const result = await this.installExtensions([{ manifest, extension: location, options }]); + if (result[0]?.local) { + return result[0]?.local; + } + if (result[0]?.error) { + throw result[0].error; + } + throw toExtensionManagementError(new Error(`Unknown error while installing extension ${extensionId}`)); } finally { await cleanup(); } diff --git a/src/vs/platform/userDataSync/common/extensionsSync.ts b/src/vs/platform/userDataSync/common/extensionsSync.ts index 5bbed1cfb93..d898288a41e 100644 --- a/src/vs/platform/userDataSync/common/extensionsSync.ts +++ b/src/vs/platform/userDataSync/common/extensionsSync.ts @@ -15,7 +15,7 @@ import { URI } from 'vs/base/common/uri'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { GlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService'; -import { IExtensionGalleryService, IExtensionManagementService, IGlobalExtensionEnablementService, ILocalExtension, ExtensionManagementError, ExtensionManagementErrorCode, IGalleryExtension, DISABLED_EXTENSIONS_STORAGE_PATH, EXTENSION_INSTALL_SKIP_WALKTHROUGH_CONTEXT, EXTENSION_INSTALL_SYNC_CONTEXT } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { IExtensionGalleryService, IExtensionManagementService, IGlobalExtensionEnablementService, ILocalExtension, ExtensionManagementError, ExtensionManagementErrorCode, IGalleryExtension, DISABLED_EXTENSIONS_STORAGE_PATH, EXTENSION_INSTALL_SKIP_WALKTHROUGH_CONTEXT, EXTENSION_INSTALL_SYNC_CONTEXT, InstallExtensionInfo } from 'vs/platform/extensionManagement/common/extensionManagement'; import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { ExtensionStorageService, IExtensionStorageService } from 'vs/platform/extensionManagement/common/extensionStorage'; import { ExtensionType, IExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; @@ -405,7 +405,8 @@ export class LocalExtensionsProvider { async updateLocalExtensions(added: ISyncExtension[], removed: IExtensionIdentifier[], updated: ISyncExtension[], skippedExtensions: ISyncExtension[], profile: IUserDataProfile): Promise { const syncResourceLogLabel = getSyncResourceLogLabel(SyncResource.Extensions, profile); - const extensionsToInstall: [ISyncExtension, IGalleryExtension][] = []; + const extensionsToInstall: InstallExtensionInfo[] = []; + const syncExtensionsToInstall = new Map(); const removeFromSkipped: IExtensionIdentifier[] = []; const addToSkipped: ISyncExtension[] = []; const installedExtensions = await this.extensionManagementService.getInstalled(undefined, profile.extensionsResource); @@ -473,7 +474,17 @@ export class LocalExtensionsProvider { || (version && installedExtension.manifest.version !== version) // Install if the extension version has changed ) { if (await this.extensionManagementService.canInstall(extension)) { - extensionsToInstall.push([e, extension]); + extensionsToInstall.push({ + extension, options: { + isMachineScoped: false /* set isMachineScoped value to prevent install and sync dialog in web */, + donotIncludePackAndDependencies: true, + installGivenVersion: e.pinned && !!e.version, + installPreReleaseVersion: e.preRelease, + profileLocation: profile.extensionsResource, + context: { [EXTENSION_INSTALL_SKIP_WALKTHROUGH_CONTEXT]: true, [EXTENSION_INSTALL_SYNC_CONTEXT]: true } + } + }); + syncExtensionsToInstall.set(extension.identifier.id.toLowerCase(), e); } else { this.logService.info(`${syncResourceLogLabel}: Skipped synchronizing extension because it cannot be installed.`, extension.displayName || extension.identifier.id); addToSkipped.push(e); @@ -504,26 +515,22 @@ export class LocalExtensionsProvider { } // 3. Install extensions at the end - for (const [e, extension] of extensionsToInstall) { - try { - this.logService.trace(`${syncResourceLogLabel}: Installing extension...`, extension.identifier.id, extension.version); - await this.extensionManagementService.installFromGallery(extension, { - isMachineScoped: false /* set isMachineScoped value to prevent install and sync dialog in web */, - donotIncludePackAndDependencies: true, - installGivenVersion: e.pinned && !!e.version, - installPreReleaseVersion: e.preRelease, - profileLocation: profile.extensionsResource, - context: { [EXTENSION_INSTALL_SKIP_WALKTHROUGH_CONTEXT]: true, [EXTENSION_INSTALL_SYNC_CONTEXT]: true } - }); - this.logService.info(`${syncResourceLogLabel}: Installed extension.`, extension.identifier.id, extension.version); - removeFromSkipped.push(extension.identifier); - } catch (error) { - addToSkipped.push(e); + const results = await this.extensionManagementService.installGalleryExtensions(extensionsToInstall); + for (const { identifier, local, error, source } of results) { + const gallery = source as IGalleryExtension; + if (local) { + this.logService.info(`${syncResourceLogLabel}: Installed extension.`, identifier.id, gallery.version); + removeFromSkipped.push(identifier); + } else { + const e = syncExtensionsToInstall.get(identifier.id.toLowerCase()); + if (e) { + addToSkipped.push(e); + this.logService.info(`${syncResourceLogLabel}: Skipped synchronizing extension`, gallery.displayName || gallery.identifier.id); + } if (error instanceof ExtensionManagementError && [ExtensionManagementErrorCode.Incompatible, ExtensionManagementErrorCode.IncompatiblePreRelease, ExtensionManagementErrorCode.IncompatibleTargetPlatform].includes(error.code)) { - this.logService.info(`${syncResourceLogLabel}: Skipped synchronizing extension because the compatible extension is not found.`, extension.displayName || extension.identifier.id); - } else { + this.logService.info(`${syncResourceLogLabel}: Skipped synchronizing extension because the compatible extension is not found.`, gallery.displayName || gallery.identifier.id); + } else if (error) { this.logService.error(error); - this.logService.info(`${syncResourceLogLabel}: Skipped synchronizing extension`, extension.displayName || extension.identifier.id); } } } diff --git a/src/vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService.ts b/src/vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService.ts index 7c6c2132599..c08110b911b 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService.ts @@ -267,17 +267,17 @@ export class ExtensionRecommendationNotificationService implements IExtensionRec return createCancelablePromise(async token => { let accepted = false; const choices: (IPromptChoice | IPromptChoiceWithMenu)[] = []; - const installExtensions = async (isMachineScoped?: boolean) => { + const installExtensions = async (isMachineScoped: boolean) => { this.runAction(this.instantiationService.createInstance(SearchExtensionsAction, searchValue)); onDidInstallRecommendedExtensions(extensions); await Promises.settled([ Promises.settled(extensions.map(extension => this.extensionsWorkbenchService.open(extension, { pinned: true }))), - this.extensionManagementService.installExtensions(extensions.map(e => e.gallery!), { isMachineScoped }) + this.extensionManagementService.installGalleryExtensions(extensions.map(e => ({ extension: e.gallery!, options: { isMachineScoped } }))) ]); }; choices.push({ label: localize('install', "Install"), - run: () => installExtensions(), + run: () => installExtensions(false), menu: this.userDataSyncEnablementService.isEnabled() && this.userDataSyncEnablementService.isResourceEnabled(SyncResource.Extensions) ? [{ label: localize('install and do no sync', "Install (Do not sync)"), run: () => installExtensions(true) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts index 36f2491569c..84497ffe878 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts @@ -1447,7 +1447,7 @@ export class WorkspaceRecommendedExtensionsView extends ExtensionsListView imple async installWorkspaceRecommendations(): Promise { const installableRecommendations = await this.getInstallableWorkspaceRecommendations(); if (installableRecommendations.length) { - await this.extensionManagementService.installExtensions(installableRecommendations.map(i => i.gallery!)); + await this.extensionManagementService.installGalleryExtensions(installableRecommendations.map(i => ({ extension: i.gallery!, options: {} }))); } else { this.notificationService.notify({ severity: Severity.Info, diff --git a/src/vs/workbench/services/extensionManagement/common/extensionManagement.ts b/src/vs/workbench/services/extensionManagement/common/extensionManagement.ts index 2c15566fffc..362e485948a 100644 --- a/src/vs/workbench/services/extensionManagement/common/extensionManagement.ts +++ b/src/vs/workbench/services/extensionManagement/common/extensionManagement.ts @@ -58,9 +58,7 @@ export interface IWorkbenchExtensionManagementService extends IProfileAwareExten installVSIX(location: URI, manifest: IExtensionManifest, installOptions?: InstallVSIXOptions): Promise; installFromLocation(location: URI): Promise; - installExtensions(extensions: IGalleryExtension[], installOptions?: InstallOptions): Promise; updateFromGallery(gallery: IGalleryExtension, extension: ILocalExtension, installOptions?: InstallOptions): Promise; - getExtensionManagementServerToInstall(manifest: IExtensionManifest): IExtensionManagementServer | null; } export const enum EnablementState { diff --git a/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts b/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts index b29c51da2d5..b21e6f845d4 100644 --- a/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts +++ b/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts @@ -5,7 +5,7 @@ import { Event, EventMultiplexer } from 'vs/base/common/event'; import { - ILocalExtension, IGalleryExtension, IExtensionIdentifier, IExtensionsControlManifest, IExtensionGalleryService, InstallOptions, UninstallOptions, InstallVSIXOptions, InstallExtensionResult, ExtensionManagementError, ExtensionManagementErrorCode, Metadata, InstallOperation, EXTENSION_INSTALL_SYNC_CONTEXT + ILocalExtension, IGalleryExtension, IExtensionIdentifier, IExtensionsControlManifest, IExtensionGalleryService, InstallOptions, UninstallOptions, InstallVSIXOptions, InstallExtensionResult, ExtensionManagementError, ExtensionManagementErrorCode, Metadata, InstallOperation, EXTENSION_INSTALL_SYNC_CONTEXT, InstallExtensionInfo } from 'vs/platform/extensionManagement/common/extensionManagement'; import { DidChangeProfileForServerEvent, DidUninstallExtensionOnServerEvent, IExtensionManagementServer, IExtensionManagementServerService, InstallExtensionOnServerEvent, IWorkbenchExtensionManagementService, UninstallExtensionOnServerEvent } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { ExtensionType, isLanguagePackExtension, IExtensionManifest, getWorkspaceSupportTypeMessage, TargetPlatform } from 'vs/platform/extensions/common/extensions'; @@ -296,15 +296,56 @@ export class ExtensionManagementService extends Disposable implements IWorkbench return Promises.settled(servers.map(server => server.extensionManagementService.installFromGallery(gallery, installOptions))).then(([local]) => local); } - async installExtensions(extensions: IGalleryExtension[], installOptions?: InstallOptions): Promise { - if (!installOptions) { - const isMachineScoped = await this.hasToFlagExtensionsMachineScoped(extensions); - installOptions = { isMachineScoped, isBuiltin: false }; - } - return Promises.settled(extensions.map(extension => this.installFromGallery(extension, installOptions))); + async installGalleryExtensions(extensions: InstallExtensionInfo[]): Promise { + const results = new Map(); + + const extensionsByServer = new Map(); + await Promise.all(extensions.map(async ({ extension, options }) => { + try { + const servers = await this.validateAndGetExtensionManagementServersToInstall(extension, options); + if (!options.isMachineScoped && this.isExtensionsSyncEnabled()) { + if (this.extensionManagementServerService.localExtensionManagementServer && !servers.includes(this.extensionManagementServerService.localExtensionManagementServer) && (await this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.canInstall(extension))) { + servers.push(this.extensionManagementServerService.localExtensionManagementServer); + } + } + for (const server of servers) { + let exensions = extensionsByServer.get(server); + if (!exensions) { + extensionsByServer.set(server, exensions = []); + } + exensions.push({ extension, options }); + } + } catch (error) { + results.set(extension.identifier.id.toLowerCase(), { identifier: extension.identifier, source: extension, error, operation: InstallOperation.Install }); + } + })); + + await Promise.all([...extensionsByServer.entries()].map(async ([server, extensions]) => { + const serverResults = await server.extensionManagementService.installGalleryExtensions(extensions); + for (const result of serverResults) { + results.set(result.identifier.id.toLowerCase(), result); + } + })); + + return [...results.values()]; } async installFromGallery(gallery: IGalleryExtension, installOptions?: InstallOptions): Promise { + const servers = await this.validateAndGetExtensionManagementServersToInstall(gallery, installOptions); + if (!installOptions || isUndefined(installOptions.isMachineScoped)) { + const isMachineScoped = await this.hasToFlagExtensionsMachineScoped([gallery]); + installOptions = { ...(installOptions || {}), isMachineScoped }; + } + + if (!installOptions.isMachineScoped && this.isExtensionsSyncEnabled()) { + if (this.extensionManagementServerService.localExtensionManagementServer && !servers.includes(this.extensionManagementServerService.localExtensionManagementServer) && (await this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.canInstall(gallery))) { + servers.push(this.extensionManagementServerService.localExtensionManagementServer); + } + } + return Promises.settled(servers.map(server => server.extensionManagementService.installFromGallery(gallery, installOptions))).then(([local]) => local); + } + + private async validateAndGetExtensionManagementServersToInstall(gallery: IGalleryExtension, installOptions?: InstallOptions): Promise { const manifest = await this.extensionGalleryService.getManifest(gallery, CancellationToken.None); if (!manifest) { @@ -323,32 +364,24 @@ export class ExtensionManagementService extends Disposable implements IWorkbench } } - if (servers.length) { - if (!installOptions || isUndefined(installOptions.isMachineScoped)) { - const isMachineScoped = await this.hasToFlagExtensionsMachineScoped([gallery]); - installOptions = { ...(installOptions || {}), isMachineScoped }; - } - if (!installOptions.isMachineScoped && this.isExtensionsSyncEnabled()) { - if (this.extensionManagementServerService.localExtensionManagementServer && !servers.includes(this.extensionManagementServerService.localExtensionManagementServer) && (await this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.canInstall(gallery))) { - servers.push(this.extensionManagementServerService.localExtensionManagementServer); - } - } - if (!installOptions.context?.[EXTENSION_INSTALL_SYNC_CONTEXT]) { - await this.checkForWorkspaceTrust(manifest); - } - if (!installOptions.donotIncludePackAndDependencies) { - await this.checkInstallingExtensionOnWeb(gallery, manifest); - } - return Promises.settled(servers.map(server => server.extensionManagementService.installFromGallery(gallery, installOptions))).then(([local]) => local); + if (!servers.length) { + const error = new Error(localize('cannot be installed', "Cannot install the '{0}' extension because it is not available in this setup.", gallery.displayName || gallery.name)); + error.name = ExtensionManagementErrorCode.Unsupported; + throw error; } - const error = new Error(localize('cannot be installed', "Cannot install the '{0}' extension because it is not available in this setup.", gallery.displayName || gallery.name)); - error.name = ExtensionManagementErrorCode.Unsupported; - return Promise.reject(error); + if (!installOptions?.context?.[EXTENSION_INSTALL_SYNC_CONTEXT]) { + await this.checkForWorkspaceTrust(manifest); + } + + if (!installOptions?.donotIncludePackAndDependencies) { + await this.checkInstallingExtensionOnWeb(gallery, manifest); + } + + return servers; } - getExtensionManagementServerToInstall(manifest: IExtensionManifest): IExtensionManagementServer | null { - + private getExtensionManagementServerToInstall(manifest: IExtensionManifest): IExtensionManagementServer | null { // Only local server if (this.servers.length === 1 && this.extensionManagementServerService.localExtensionManagementServer) { return this.extensionManagementServerService.localExtensionManagementServer; diff --git a/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts b/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts index c59003dc9b1..9f0064d709d 100644 --- a/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts +++ b/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts @@ -11,7 +11,7 @@ import { areSameExtensions, getGalleryExtensionId } from 'vs/platform/extensionM import { IProfileAwareExtensionManagementService, IScannedExtension, IWebExtensionsScannerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { ILogService } from 'vs/platform/log/common/log'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { AbstractExtensionManagementService, AbstractExtensionTask, IInstallExtensionTask, InstallExtensionTaskOptions, IUninstallExtensionTask, UninstallExtensionTaskOptions } from 'vs/platform/extensionManagement/common/abstractExtensionManagementService'; +import { AbstractExtensionManagementService, AbstractExtensionTask, IInstallExtensionTask, InstallExtensionTaskOptions, IUninstallExtensionTask, toExtensionManagementError, UninstallExtensionTaskOptions } from 'vs/platform/extensionManagement/common/abstractExtensionManagementService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IExtensionManifestPropertiesService } from 'vs/workbench/services/extensions/common/extensionManifestPropertiesService'; import { IProductService } from 'vs/platform/product/common/productService'; @@ -105,7 +105,14 @@ export class WebExtensionManagementService extends AbstractExtensionManagementSe if (!manifest) { throw new Error(`Cannot find packageJSON from the location ${location.toString()}`); } - return this.installExtension(manifest, location, options); + const result = await this.installExtensions([{ manifest, extension: location, options }]); + if (result[0]?.local) { + return result[0]?.local; + } + if (result[0]?.error) { + throw result[0].error; + } + throw toExtensionManagementError(new Error(`Unknown error while installing extension ${getGalleryExtensionId(manifest.publisher, manifest.name)}`)); } installFromLocation(location: URI, profileLocation: URI): Promise { diff --git a/src/vs/workbench/services/userDataProfile/browser/extensionsResource.ts b/src/vs/workbench/services/userDataProfile/browser/extensionsResource.ts index 3585557e837..3940f2a06b7 100644 --- a/src/vs/workbench/services/userDataProfile/browser/extensionsResource.ts +++ b/src/vs/workbench/services/userDataProfile/browser/extensionsResource.ts @@ -7,7 +7,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { localize } from 'vs/nls'; import { GlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService'; -import { EXTENSION_INSTALL_SKIP_WALKTHROUGH_CONTEXT, IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementService, IGlobalExtensionEnablementService, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { EXTENSION_INSTALL_SKIP_WALKTHROUGH_CONTEXT, IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementService, IGlobalExtensionEnablementService, ILocalExtension, InstallExtensionInfo } from 'vs/platform/extensionManagement/common/extensionManagement'; import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; @@ -143,27 +143,34 @@ export class ExtensionsResource implements IProfileResource { } } if (extensionsToInstall.length) { + this.logService.info(`Importing Profile (${profile.name}): Started installing extensions.`); const galleryExtensions = await this.extensionGalleryService.getExtensions(extensionsToInstall.map(e => ({ ...e.identifier, version: e.version, hasPreRelease: e.version ? undefined : e.preRelease })), CancellationToken.None); + const installExtensionInfos: InstallExtensionInfo[] = []; await Promise.all(extensionsToInstall.map(async e => { const extension = galleryExtensions.find(galleryExtension => areSameExtensions(galleryExtension.identifier, e.identifier)); if (!extension) { return; } if (await this.extensionManagementService.canInstall(extension)) { - this.logService.trace(`Importing Profile (${profile.name}): Installing extension...`, extension.identifier.id, extension.version); - await this.extensionManagementService.installFromGallery(extension, { - isMachineScoped: false,/* set isMachineScoped value to prevent install and sync dialog in web */ - donotIncludePackAndDependencies: true, - installGivenVersion: !!e.version, - installPreReleaseVersion: e.preRelease, - profileLocation: profile.extensionsResource, - context: { [EXTENSION_INSTALL_SKIP_WALKTHROUGH_CONTEXT]: true } + installExtensionInfos.push({ + extension, + options: { + isMachineScoped: false,/* set isMachineScoped value to prevent install and sync dialog in web */ + donotIncludePackAndDependencies: true, + installGivenVersion: !!e.version, + installPreReleaseVersion: e.preRelease, + profileLocation: profile.extensionsResource, + context: { [EXTENSION_INSTALL_SKIP_WALKTHROUGH_CONTEXT]: true } + } }); - this.logService.info(`Importing Profile (${profile.name}): Installed extension...`, extension.identifier.id, extension.version); } else { this.logService.info(`Importing Profile (${profile.name}): Skipped installing extension because it cannot be installed.`, extension.identifier.id); } })); + if (installExtensionInfos.length) { + await this.extensionManagementService.installGalleryExtensions(installExtensionInfos); + } + this.logService.info(`Importing Profile (${profile.name}): Finished installing extensions.`); } if (extensionsToUninstall.length) { await Promise.all(extensionsToUninstall.map(e => this.extensionManagementService.uninstall(e))); diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index 68191eae2f6..7fe99b5f2cb 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -161,8 +161,8 @@ import { ILayoutOffsetInfo } from 'vs/platform/layout/browser/layoutService'; import { IUserDataProfile, IUserDataProfilesService, toUserDataProfile, UserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile'; import { UserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfileService'; import { IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile'; -import { EnablementState, IExtensionManagementServer, IScannedExtension, IWebExtensionsScannerService, IWorkbenchExtensionEnablementService, IWorkbenchExtensionManagementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; -import { InstallVSIXOptions, ILocalExtension, IGalleryExtension, InstallOptions, IExtensionIdentifier, UninstallOptions, IExtensionsControlManifest, IGalleryMetadata, IExtensionManagementParticipant, Metadata } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { EnablementState, IScannedExtension, IWebExtensionsScannerService, IWorkbenchExtensionEnablementService, IWorkbenchExtensionManagementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; +import { InstallVSIXOptions, ILocalExtension, IGalleryExtension, InstallOptions, IExtensionIdentifier, UninstallOptions, IExtensionsControlManifest, IGalleryMetadata, IExtensionManagementParticipant, Metadata, InstallExtensionResult, InstallExtensionInfo } from 'vs/platform/extensionManagement/common/extensionManagement'; import { Codicon } from 'vs/base/common/codicons'; import { IHoverOptions, IHoverService, IHoverWidget } from 'vs/workbench/services/hover/browser/hover'; import { IRemoteExtensionsScannerService } from 'vs/platform/remote/common/remoteExtensionsScanner'; @@ -1993,13 +1993,10 @@ export class TestWorkbenchExtensionManagementService implements IWorkbenchExtens installFromLocation(location: URI): Promise { throw new Error('Method not implemented.'); } - installExtensions(extensions: IGalleryExtension[], installOptions?: InstallOptions | undefined): Promise { + installGalleryExtensions(extensions: InstallExtensionInfo[]): Promise { throw new Error('Method not implemented.'); } async updateFromGallery(gallery: IGalleryExtension, extension: ILocalExtension, installOptions?: InstallOptions | undefined): Promise { return extension; } - getExtensionManagementServerToInstall(manifest: Readonly): IExtensionManagementServer | null { - throw new Error('Method not implemented.'); - } zip(extension: ILocalExtension): Promise { throw new Error('Method not implemented.'); } From 6dc3d6c60e3d22c726e65e694d5afa366bf285a6 Mon Sep 17 00:00:00 2001 From: Johannes Date: Wed, 14 Jun 2023 12:03:16 +0200 Subject: [PATCH 118/128] return `_wasWrapped` symbol but it only for wrapped functions, not the "original" handler, add unit tests --- .../workbench/api/common/extensionHostMain.ts | 8 +- .../api/test/common/extensionHostMain.test.ts | 218 ++++++++++++++++++ 2 files changed, 223 insertions(+), 3 deletions(-) create mode 100644 src/vs/workbench/api/test/common/extensionHostMain.test.ts diff --git a/src/vs/workbench/api/common/extensionHostMain.ts b/src/vs/workbench/api/common/extensionHostMain.ts index 41308700711..ee87ff55b64 100644 --- a/src/vs/workbench/api/common/extensionHostMain.ts +++ b/src/vs/workbench/api/common/extensionHostMain.ts @@ -32,7 +32,7 @@ export interface IConsolePatchFn { (mainThreadConsole: MainThreadConsoleShape): any; } -abstract class ErrorHandler { +export abstract class ErrorHandler { static { // increase number of stack frames (from 10, https://github.com/v8/v8/wiki/Stack-Trace-API) @@ -89,6 +89,7 @@ abstract class ErrorHandler { return result; } + const _wasWrapped = Symbol('prepareStackTrace wrapped'); let _prepareStackTrace = prepareStackTraceAndFindExtension; Object.defineProperty(Error, 'prepareStackTrace', { @@ -97,8 +98,7 @@ abstract class ErrorHandler { return _prepareStackTrace; }, set(v) { - if (v === prepareStackTraceAndFindExtension) { - // back to default + if (v === prepareStackTraceAndFindExtension || v[_wasWrapped]) { _prepareStackTrace = v; return; } @@ -107,6 +107,8 @@ abstract class ErrorHandler { prepareStackTraceAndFindExtension(error, stackTrace); return v.call(Error, error, stackTrace); }; + + Object.assign(_prepareStackTrace, { [_wasWrapped]: true }); }, }); diff --git a/src/vs/workbench/api/test/common/extensionHostMain.test.ts b/src/vs/workbench/api/test/common/extensionHostMain.test.ts new file mode 100644 index 00000000000..7fda5758766 --- /dev/null +++ b/src/vs/workbench/api/test/common/extensionHostMain.test.ts @@ -0,0 +1,218 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { SerializedError, errorHandler, onUnexpectedError } from 'vs/base/common/errors'; +import { TernarySearchTree } from 'vs/base/common/ternarySearchTree'; +import { URI } from 'vs/base/common/uri'; +import { mock } from 'vs/base/test/common/mock'; +import { ExtensionIdentifier, IExtensionDescription, IRelaxedExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; +import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; +import { ILogService, NullLogService } from 'vs/platform/log/common/log'; +import { MainThreadExtensionServiceShape } from 'vs/workbench/api/common/extHost.protocol'; +import { ExtensionPaths, IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService'; +import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; +import { IExtHostTelemetry } from 'vs/workbench/api/common/extHostTelemetry'; +import { ErrorHandler } from 'vs/workbench/api/common/extensionHostMain'; +import { nullExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; +import { ProxyIdentifier, Proxied } from 'vs/workbench/services/extensions/common/proxyIdentifier'; + + +suite('ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 ', function () { + + const extensionsIndex = TernarySearchTree.forUris(); + const mainThreadExtensionsService = new class extends mock() { + override $onExtensionRuntimeError(extensionId: ExtensionIdentifier, data: SerializedError): void { + + } + }; + + const collection = new ServiceCollection( + [ILogService, new NullLogService()], + [IExtHostTelemetry, new class extends mock() { + declare readonly _serviceBrand: undefined; + override onExtensionError(extension: ExtensionIdentifier, error: Error): boolean { + return true; + } + }], + [IExtHostExtensionService, new class extends mock() { + declare readonly _serviceBrand: undefined; + getExtensionPathIndex() { + return new class extends ExtensionPaths { + override findSubstr(key: URI): Readonly | undefined { + findSubstrCount++; + return nullExtensionDescription; + } + + }(extensionsIndex); + } + }], + [IExtHostRpcService, new class extends mock() { + declare readonly _serviceBrand: undefined; + override getProxy(identifier: ProxyIdentifier): Proxied { + return mainThreadExtensionsService; + } + }] + ); + + const insta = new InstantiationService(collection, false); + + let existingErrorHandler: (e: any) => void; + let findSubstrCount = 0; + + suiteSetup(async function () { + existingErrorHandler = errorHandler.getUnexpectedErrorHandler(); + await insta.invokeFunction(ErrorHandler.installFullHandler); + }); + + suiteTeardown(function () { + errorHandler.setUnexpectedErrorHandler(existingErrorHandler); + }); + + setup(async function () { + findSubstrCount = 0; + }); + + test('basics', function () { + + const err = new Error('test1'); + + onUnexpectedError(err); + + assert.strictEqual(findSubstrCount, 1); + + }); + + test('set/reset prepareStackTrace-callback', function () { + + const original = Error.prepareStackTrace; + Error.prepareStackTrace = (_error, _stack) => 'stack'; + const probeErr = new Error(); + const stack = probeErr.stack; + assert.ok(stack); + Error.prepareStackTrace = original; + assert.strictEqual(findSubstrCount, 1); + + // already checked + onUnexpectedError(probeErr); + assert.strictEqual(findSubstrCount, 1); + + // one more error + const err = new Error('test2'); + onUnexpectedError(err); + + assert.strictEqual(findSubstrCount, 2); + }); + + test('wrap prepareStackTrace-callback', function () { + + function do_something_else(params: string) { + return params; + } + + const original = Error.prepareStackTrace; + Error.prepareStackTrace = (...args) => { + return do_something_else(original?.(...args)); + }; + const probeErr = new Error(); + const stack = probeErr.stack; + assert.ok(stack); + + + onUnexpectedError(probeErr); + assert.strictEqual(findSubstrCount, 1); + }); + + test('prevent rewrapping', function () { + + let do_something_count = 0; + function do_something(params: any) { + do_something_count++; + } + + Error.prepareStackTrace = (result, stack) => { + do_something(stack); + return 'fakestack'; + }; + + for (let i = 0; i < 2_500; ++i) { + Error.prepareStackTrace = Error.prepareStackTrace; + } + + const probeErr = new Error(); + const stack = probeErr.stack; + assert.strictEqual(stack, 'fakestack'); + + onUnexpectedError(probeErr); + assert.strictEqual(findSubstrCount, 1); + + const probeErr2 = new Error(); + onUnexpectedError(probeErr2); + assert.strictEqual(findSubstrCount, 2); + assert.strictEqual(do_something_count, 2); + }); +}); + +suite('ExtensionHostMain#ErrorHandler - from https://gist.github.com/thecrypticace/f0f2e182082072efdaf0f8e1537d2cce', function () { + + test("Restored, separate operations", () => { + // Actual Test + let original; + + // Operation 1 + original = Error.prepareStackTrace; + for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } + assert.ok(new Error().stack); + Error.prepareStackTrace = original; + + // Operation 2 + original = Error.prepareStackTrace; + for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } + assert.ok(new Error().stack); + Error.prepareStackTrace = original; + + // Operation 3 + original = Error.prepareStackTrace; + for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } + assert.ok(new Error().stack); + Error.prepareStackTrace = original; + + // Operation 4 + original = Error.prepareStackTrace; + for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } + assert.ok(new Error().stack); + Error.prepareStackTrace = original; + }); + + test("Never restored, separate operations", () => { + // Operation 1 + for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } + assert.ok(new Error().stack); + + // Operation 2 + for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } + assert.ok(new Error().stack); + + // Operation 3 + for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } + assert.ok(new Error().stack); + + // Operation 4 + for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } + assert.ok(new Error().stack); + }); + + test("Restored, too many uses before restoration", async () => { + const original = Error.prepareStackTrace; + Error.prepareStackTrace = (_, stack) => stack; + + // Operation 1 — more uses of `prepareStackTrace` + for (let i = 0; i < 10_000; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } + assert.ok(new Error().stack); + + Error.prepareStackTrace = original; + }); +}); From 35c1f3e9982dd5e1a0c5abcb5ac09ad4417ebc37 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 14 Jun 2023 12:08:36 +0200 Subject: [PATCH 119/128] notifications - go back to showing toolbar in expanded notifications (#185094) Otherwise hovering over long notifications can result in ugly flicker. --- .../browser/parts/notifications/media/notificationsList.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/notifications/media/notificationsList.css b/src/vs/workbench/browser/parts/notifications/media/notificationsList.css index 475cc3a6f19..354164660d0 100644 --- a/src/vs/workbench/browser/parts/notifications/media/notificationsList.css +++ b/src/vs/workbench/browser/parts/notifications/media/notificationsList.css @@ -89,7 +89,8 @@ .monaco-workbench .notifications-list-container .monaco-list:focus-within .notification-list-item .notification-list-item-toolbar-container, .monaco-workbench .notifications-list-container .notification-list-item:hover .notification-list-item-toolbar-container, -.monaco-workbench .notifications-list-container .monaco-list-row.focused .notification-list-item .notification-list-item-toolbar-container { +.monaco-workbench .notifications-list-container .monaco-list-row.focused .notification-list-item .notification-list-item-toolbar-container, +.monaco-workbench .notifications-list-container .notification-list-item.expanded .notification-list-item-toolbar-container { display: block; } From 498bf5cc33f4ef145d40a07e3bf3675934434846 Mon Sep 17 00:00:00 2001 From: Johannes Date: Wed, 14 Jun 2023 12:10:01 +0200 Subject: [PATCH 120/128] run gist test under the actual handler... --- .../api/test/common/extensionHostMain.test.ts | 104 ++++++++++-------- 1 file changed, 57 insertions(+), 47 deletions(-) diff --git a/src/vs/workbench/api/test/common/extensionHostMain.test.ts b/src/vs/workbench/api/test/common/extensionHostMain.test.ts index 7fda5758766..0fe1f5b783d 100644 --- a/src/vs/workbench/api/test/common/extensionHostMain.test.ts +++ b/src/vs/workbench/api/test/common/extensionHostMain.test.ts @@ -154,65 +154,75 @@ suite('ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slo assert.strictEqual(findSubstrCount, 2); assert.strictEqual(do_something_count, 2); }); -}); -suite('ExtensionHostMain#ErrorHandler - from https://gist.github.com/thecrypticace/f0f2e182082072efdaf0f8e1537d2cce', function () { - test("Restored, separate operations", () => { - // Actual Test - let original; + suite('https://gist.github.com/thecrypticace/f0f2e182082072efdaf0f8e1537d2cce', function () { - // Operation 1 - original = Error.prepareStackTrace; - for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } - assert.ok(new Error().stack); - Error.prepareStackTrace = original; + test("Restored, separate operations", () => { + // Actual Test + let original; - // Operation 2 - original = Error.prepareStackTrace; - for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } - assert.ok(new Error().stack); - Error.prepareStackTrace = original; + // Operation 1 + original = Error.prepareStackTrace; + for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } + const err1 = new Error(); + assert.ok(err1.stack); + assert.strictEqual(findSubstrCount, 1); + Error.prepareStackTrace = original; - // Operation 3 - original = Error.prepareStackTrace; - for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } - assert.ok(new Error().stack); - Error.prepareStackTrace = original; + // Operation 2 + original = Error.prepareStackTrace; + for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } + assert.ok(new Error().stack); + assert.strictEqual(findSubstrCount, 2); + Error.prepareStackTrace = original; - // Operation 4 - original = Error.prepareStackTrace; - for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } - assert.ok(new Error().stack); - Error.prepareStackTrace = original; - }); + // Operation 3 + original = Error.prepareStackTrace; + for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } + assert.ok(new Error().stack); + assert.strictEqual(findSubstrCount, 3); + Error.prepareStackTrace = original; - test("Never restored, separate operations", () => { - // Operation 1 - for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } - assert.ok(new Error().stack); + // Operation 4 + original = Error.prepareStackTrace; + for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } + assert.ok(new Error().stack); + assert.strictEqual(findSubstrCount, 4); + Error.prepareStackTrace = original; - // Operation 2 - for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } - assert.ok(new Error().stack); + // Back to Operation 1 + assert.ok(err1.stack); + assert.strictEqual(findSubstrCount, 4); + }); - // Operation 3 - for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } - assert.ok(new Error().stack); + test("Never restored, separate operations", () => { + // Operation 1 + for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } + assert.ok(new Error().stack); - // Operation 4 - for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } - assert.ok(new Error().stack); - }); + // Operation 2 + for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } + assert.ok(new Error().stack); - test("Restored, too many uses before restoration", async () => { - const original = Error.prepareStackTrace; - Error.prepareStackTrace = (_, stack) => stack; + // Operation 3 + for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } + assert.ok(new Error().stack); - // Operation 1 — more uses of `prepareStackTrace` - for (let i = 0; i < 10_000; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } - assert.ok(new Error().stack); + // Operation 4 + for (let i = 0; i < 12_500; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } + assert.ok(new Error().stack); + }); - Error.prepareStackTrace = original; + test("Restored, too many uses before restoration", async () => { + const original = Error.prepareStackTrace; + Error.prepareStackTrace = (_, stack) => stack; + + // Operation 1 — more uses of `prepareStackTrace` + for (let i = 0; i < 10_000; ++i) { Error.prepareStackTrace = Error.prepareStackTrace; } + assert.ok(new Error().stack); + + Error.prepareStackTrace = original; + }); }); }); From d983c8498a2ee7ae937f20bbaaf84c0bb3e79827 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Wed, 14 Jun 2023 12:40:59 +0200 Subject: [PATCH 121/128] review changes --- .../inlineChat/browser/inlineChatController.ts | 4 ++++ .../inlineChat/browser/inlineChatStrategies.ts | 10 ++++++++++ .../inlineChat/browser/inlineChatWidget.ts | 15 ++++++++++++--- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index e28b8cfc171..fedfdeeb3c2 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -205,6 +205,10 @@ export class InlineChatController implements IEditorContribution { this._zone.value.setMargins(widgetPosition); } else { widgetPosition = this._strategy.getWidgetPosition() ?? this._zone.value.position ?? this._activeSession.wholeRange.value.getEndPosition(); + const needsMargin = this._strategy.needsMargin(); + if (!needsMargin) { + this._zone.value.setMargins(widgetPosition, 0); + } } this._zone.value.show(widgetPosition); } diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts index 6effff16c18..cc9836e8f8a 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts @@ -47,6 +47,8 @@ export abstract class EditModeStrategy { abstract hasFocus(): boolean; abstract getWidgetPosition(): Position | undefined; + + abstract needsMargin(): boolean; } export class PreviewStrategy extends EditModeStrategy { @@ -145,6 +147,10 @@ export class PreviewStrategy extends EditModeStrategy { hasFocus(): boolean { return this._widget.hasFocus(); } + + needsMargin(): boolean { + return true; + } } class InlineDiffDecorations { @@ -359,6 +365,10 @@ export class LiveStrategy extends EditModeStrategy { return lastLineOfLocalEdits ? new Position(lastLineOfLocalEdits, 1) : undefined; } + override needsMargin(): boolean { + return Boolean(this._session.lastTextModelChanges.length); + } + hasFocus(): boolean { return this._widget.hasFocus(); } diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index f25ef458cfe..da046893374 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -797,10 +797,10 @@ export class InlineChatZoneWidget extends ZoneWidget { this._ctxVisible.set(true); } - public setMargins(position: Position): void { + private _calculateIndentationWidth(position: Position): number { const viewModel = this.editor._getViewModel(); if (!viewModel) { - return; + return 0; } const visibleRange = viewModel.getCompletelyVisibleViewRange(); const startLineVisibleRange = visibleRange.startLineNumber; @@ -815,7 +815,16 @@ export class InlineChatZoneWidget extends ZoneWidget { break; } } - this._indentationWidth = this.editor.getOffsetForColumn(indentationLineNumber ?? positionLine, indentationLevel ?? viewModel.getLineFirstNonWhitespaceColumn(positionLine)); + return this.editor.getOffsetForColumn(indentationLineNumber ?? positionLine, indentationLevel ?? viewModel.getLineFirstNonWhitespaceColumn(positionLine)); + } + + setMargins(position: Position, indentationWidth?: number): void { + if (indentationWidth === undefined) { + indentationWidth = this._calculateIndentationWidth(position); + } + if (this._indentationWidth === indentationWidth) { + return; + } const info = this.editor.getLayoutInfo(); const marginWithoutIndentation = info.glyphMarginWidth + info.decorationsWidth + info.lineNumbersWidth; const marginWithIndentation = marginWithoutIndentation + this._indentationWidth; From 13b1b90a8366d02f5929e673e227ec1a4d09f534 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Wed, 14 Jun 2023 07:34:03 -0700 Subject: [PATCH 122/128] tunnel: fix keyring panic on Linux (#185066) tunnel: fix keyring panic on Linxu Fixes #184792 Reported on https://github.com/hwchen/keyring-rs/issues/132 --- cli/src/auth.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/cli/src/auth.rs b/cli/src/auth.rs index d9089940730..604b1a6ced7 100644 --- a/cli/src/auth.rs +++ b/cli/src/auth.rs @@ -20,7 +20,7 @@ use async_trait::async_trait; use chrono::{DateTime, Duration, Utc}; use gethostname::gethostname; use serde::{de::DeserializeOwned, Deserialize, Serialize}; -use std::{cell::Cell, fmt::Display, path::PathBuf, sync::Arc}; +use std::{cell::Cell, fmt::Display, path::PathBuf, sync::Arc, thread}; use tokio::time::sleep; use tunnels::{ contracts::PROD_FIRST_PARTY_APP_ID, @@ -210,6 +210,48 @@ const KEYCHAIN_ENTRY_LIMIT: usize = 128 * 1024; const CONTINUE_MARKER: &str = ""; +/// Implementation that wraps the KeyringStorage on Linux to avoid +/// https://github.com/hwchen/keyring-rs/issues/132 +struct ThreadKeyringStorage { + s: Option, +} + +impl ThreadKeyringStorage { + fn thread_op(&mut self, f: Fn) -> R + where + Fn: 'static + Send + FnOnce(&mut KeyringStorage) -> R, + R: 'static + Send, + { + let mut s = self.s.take().unwrap(); + let handler = thread::spawn(move || (f(&mut s), s)); + let (r, s) = handler.join().unwrap(); + self.s = Some(s); + r + } +} + +impl Default for ThreadKeyringStorage { + fn default() -> Self { + Self { + s: Some(KeyringStorage::default()), + } + } +} + +impl StorageImplementation for ThreadKeyringStorage { + fn read(&mut self) -> Result, WrappedError> { + self.thread_op(|s| s.read()) + } + + fn store(&mut self, value: StoredCredential) -> Result<(), WrappedError> { + self.thread_op(move |s| s.store(value)) + } + + fn clear(&mut self) -> Result<(), WrappedError> { + self.thread_op(|s| s.clear()) + } +} + #[derive(Default)] struct KeyringStorage { // keywring storage can be split into multiple entries due to entry length limits @@ -325,7 +367,10 @@ impl Auth { return op(s); } + #[cfg(not(target_os = "linux"))] let mut keyring_storage = KeyringStorage::default(); + #[cfg(target_os = "linux")] + let mut keyring_storage = ThreadKeyringStorage::default(); let mut file_storage = FileStorage(PersistedState::new(self.file_storage_path.clone())); let keyring_storage_result = match std::env::var("VSCODE_CLI_USE_FILE_KEYCHAIN") { From 21952a58bce59ea52bd131f8ad18532102240ba6 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Wed, 14 Jun 2023 16:41:42 +0200 Subject: [PATCH 123/128] simplifying the css --- src/vs/workbench/contrib/inlineChat/browser/inlineChat.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChat.css b/src/vs/workbench/contrib/inlineChat/browser/inlineChat.css index d19609b2bdb..6a377fac227 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChat.css +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChat.css @@ -206,6 +206,10 @@ font-size: 14px; } +.monaco-editor .inline-chat .status .monaco-toolbar .action-item.button-item .action-label:hover { + background-color: var(--vscode-button-hoverBackground); +} + /* preview */ .monaco-editor .inline-chat .preview { From 8afb685c9bfcf510d7d992f65d30201840ae6b51 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 14 Jun 2023 16:57:06 +0200 Subject: [PATCH 124/128] eng - add `checksum` validation support to `nodejs` and `extensions` (#184877) * eng - add `checksum` validation support to `remote` * eng - wire in more `checksum` support * eng - renames for remote fetching * eng - renames for remote fetching * eng - disable verbose * eng - always fetch verbose in CI * eng - :lipstick: * eng - add checksums for node * eng - report checksum matches * eng - fix build * eng - warn when not being able to check sum * eng - support checksums for built in extensions * eng - clear todo * eng - add nodejs metadata to product.json * :up: version * :up: distro * update distro * eng - switch to checksum file * cleanup alpine * fix alpine * fix bug * eng - fetch all from remote * eng - :lipstick: * eng - print checksums * eng - fix missing import * :up: distro * undo version change --- build/checksums/nodejs.txt | 34 +++++ build/gulpfile.reh.js | 102 ++++++++++----- build/lib/builtInExtensions.js | 2 +- build/lib/builtInExtensions.ts | 1 + build/lib/extensions.js | 29 +++-- build/lib/extensions.ts | 41 +++--- build/lib/fetch.js | 136 ++++++++++++++++++++ build/lib/fetch.ts | 147 ++++++++++++++++++++++ build/lib/github.js | 48 ------- build/lib/github.ts | 47 ------- build/lib/gulpRemoteSource.js | 84 ------------- build/lib/gulpRemoteSource.ts | 95 -------------- product.json | 9 +- src/vs/platform/product/common/product.ts | 2 +- 14 files changed, 434 insertions(+), 343 deletions(-) create mode 100644 build/checksums/nodejs.txt create mode 100644 build/lib/fetch.js create mode 100644 build/lib/fetch.ts delete mode 100644 build/lib/github.js delete mode 100644 build/lib/github.ts delete mode 100644 build/lib/gulpRemoteSource.js delete mode 100644 build/lib/gulpRemoteSource.ts diff --git a/build/checksums/nodejs.txt b/build/checksums/nodejs.txt new file mode 100644 index 00000000000..edc1af90cd9 --- /dev/null +++ b/build/checksums/nodejs.txt @@ -0,0 +1,34 @@ +dfb37570ef34ac04f34c26d0ec558df60a9665df5961c01c1657c0ca495f2f01 node-v16.17.1-aix-ppc64.tar.gz +f9f02f7872e2e8ee54320fce13deb9d56904f32bb0615b6e21aa3371d8899150 node-v16.17.1-darwin-arm64.tar.gz +09a45f60bfb9dfbea4f69044dc733ef983945acd92ca89ccccac267f3d71bd44 node-v16.17.1-darwin-arm64.tar.xz +3db26761ad8493b894d42260d7e65094b7af9bc473588739e61bc1c32d6ff955 node-v16.17.1-darwin-x64.tar.gz +8e7089956fa01cf7d0045945c0863d282dc6818fb0476237c1396497e29a4254 node-v16.17.1-darwin-x64.tar.xz +35ccb95caf02cda3bd680da4350a8ae5d666a7a9eae3afe5c2a1b3ef29aef108 node-v16.17.1-headers.tar.gz +554c8d1b4b16e0f4c073b9df7c49c893716a3a533f25ac646f23619f5ccee7df node-v16.17.1-headers.tar.xz +adc7032888d4e672a4aac886baede8c04fccdd1a2e7ab4bcf325e3f336f44a3d node-v16.17.1-linux-arm64.tar.gz +3dfb8fd8f6b97df69cdc56524abc906c50ef1d0bf091188616802e6c7c731389 node-v16.17.1-linux-arm64.tar.xz +aeab05e35f1d2824ecfb88ca321f1408b44d292b2775f2890972c828e00216d0 node-v16.17.1-linux-armv7l.tar.gz +a035ceefb5e16f5fce98c8ddfdf721b96eec20542c72fb8781bcbb6ef20c5550 node-v16.17.1-linux-armv7l.tar.xz +1f48de7bed99e973c4c50f1b7fc99fc9af5144d093fd6d2b50a1e43b5818bf05 node-v16.17.1-linux-ppc64le.tar.gz +70305934661f89fca64053b85317a75f233d5e3fdb2caa6546a19262a519cf20 node-v16.17.1-linux-ppc64le.tar.xz +029dad48018bda07b481213816549b632059fc673c30fdc7a353e04619128344 node-v16.17.1-linux-s390x.tar.gz +1a47f604944c6aff37cb7483503155671cdb34bda9bfb8962007bc440fa04d77 node-v16.17.1-linux-s390x.tar.xz +da5658693243b3ecf6a4cba6751a71df1eb9e9703ca93b42a9404aed85f58ad0 node-v16.17.1-linux-x64.tar.gz +06ba2eb34aa385967f5f58c87a44753f83212f6cccea892b33f80a2e7fda8384 node-v16.17.1-linux-x64.tar.xz +12d10476ea7483298364c810c037b9316d1a73dc8c81cfeff7d794aecadde498 node-v16.17.1.pkg +e423985f6019b2026f9a191adb56a96ae83ecd56cdf839cf94aa980168b7a90f node-v16.17.1.tar.gz +6721feb4152d56d2c6b358ce397abd5a7f1daf09ee2e25c5021b9b4d3f86a330 node-v16.17.1.tar.xz +9777e8c4b2864c5b54a0e4e9400f14887db68560a09b94b4113b560a64d1e680 node-v16.17.1-win-x64.7z +ed290151efb417262b9808a70738d4ab79e9d53653a6a9f4b8dd97912e279dce node-v16.17.1-win-x64.zip +0f8101648d5c9e49e89fee541da9e574f899716c32b7c51a732b1766b9fc4526 node-v16.17.1-win-x86.7z +189b5e8b23226403e7b07a46614de19b444d369e694901e3668e2f549799cbcd node-v16.17.1-win-x86.zip +1bdff65fb7642425c0d6826084d63c4be43520316f0ea0b46e6a51999a0ed7fc node-v16.17.1-x64.msi +b737eb23a2c67c253b9364b5284123faf5220d567615bebd4ec4b81070e4d177 node-v16.17.1-x86.msi +f518a70dcab7c3fac5b2e1ef100b4f628edfb160f4fafa9a94ef222da8a6e9ab win-x64/node.exe +2f459a64647db493da63c790ce368ad54f59f086d9f22f59c5018680420197b3 win-x64/node.lib +23215ce7d1e9de9777c3407239e7cf18d29d60f757b772219421ab361ac67c74 win-x64/node_pdb.7z +8e32ec12028fd3e3147435be79a858ed9c870aaafa1fcb291362307ef3c47547 win-x64/node_pdb.zip +2393aff88be19dbe0205cbde4ff0c1d89911b15de5c99c80f6e5e29604eecd12 win-x86/node.exe +5018c3d42f3fbacbd06cb943b3f2696c8e67ca9bdf6864d0e263d6d6911dffd2 win-x86/node.lib +05a4db56444a60ee70b0d2642d7f2d82a33339894d2d73bd07b1a41d6c869e04 win-x86/node_pdb.7z +8f86eacb7f13a1bf6738cb0819d7854a2abca40fc2e9e1f91421e44ba52cad7e win-x86/node_pdb.zip diff --git a/build/gulpfile.reh.js b/build/gulpfile.reh.js index a930ce09492..53ac36242aa 100644 --- a/build/gulpfile.reh.js +++ b/build/gulpfile.reh.js @@ -17,7 +17,6 @@ const rename = require('gulp-rename'); const replace = require('gulp-replace'); const filter = require('gulp-filter'); const { getProductionDependencies } = require('./lib/dependencies'); -const { assetFromGithub } = require('./lib/github'); const vfs = require('vinyl-fs'); const packageJson = require('../package.json'); const flatmap = require('gulp-flatmap'); @@ -43,7 +42,6 @@ const BUILD_TARGETS = [ { platform: 'win32', arch: 'x64' }, { platform: 'darwin', arch: 'x64' }, { platform: 'darwin', arch: 'arm64' }, - { platform: 'linux', arch: 'ia32' }, { platform: 'linux', arch: 'x64' }, { platform: 'linux', arch: 'armhf' }, { platform: 'linux', arch: 'arm64' }, @@ -131,6 +129,33 @@ function getNodeVersion() { return target; } +function getNodeChecksum(nodeVersion, platform, arch) { + let expectedName; + switch (platform) { + case 'win32': + expectedName = `win-${arch}/node.exe`; + break; + + case 'darwin': + case 'linux': + expectedName = `node-v${nodeVersion}-${platform}-${arch}.tar.gz`; + break; + + case 'alpine': + expectedName = `${platform}-${arch}/node`; + break; + } + + const nodeJsChecksums = fs.readFileSync(path.join(REPO_ROOT, 'build', 'checksums', 'nodejs.txt'), 'utf8'); + for (const line of nodeJsChecksums.split('\n')) { + const [checksum, name] = line.split(/\s+/); + if (name === expectedName) { + return checksum; + } + } + return undefined; +} + const nodeVersion = getNodeVersion(); BUILD_TARGETS.forEach(({ platform, arch }) => { @@ -155,40 +180,57 @@ if (defaultNodeTask) { } function nodejs(platform, arch) { - const { remote } = require('./lib/gulpRemoteSource'); + const { fetchUrls, fetchGithub } = require('./lib/fetch'); const untar = require('gulp-untar'); + const crypto = require('crypto'); if (arch === 'ia32') { arch = 'x86'; - } - - if (platform === 'win32') { - if (product.nodejsRepository) { - log(`Downloading node.js ${nodeVersion} ${platform} ${arch} from ${product.nodejsRepository}...`); - return assetFromGithub(product.nodejsRepository, nodeVersion, name => name === `win-${arch}-node-patched.exe`) - .pipe(rename('node.exe')); - } - log(`Downloading node.js ${nodeVersion} ${platform} ${arch} from https://nodejs.org`); - return remote(`/dist/v${nodeVersion}/win-${arch}/node.exe`, { base: 'https://nodejs.org', verbose: true }) - .pipe(rename('node.exe')); - } - - if (arch === 'alpine' || platform === 'alpine') { - const imageName = arch === 'arm64' ? 'arm64v8/node' : 'node'; - log(`Downloading node.js ${nodeVersion} ${platform} ${arch} from docker image ${imageName}`); - const contents = cp.execSync(`docker run --rm ${imageName}:${nodeVersion}-alpine /bin/sh -c 'cat \`which node\`'`, { maxBuffer: 100 * 1024 * 1024, encoding: 'buffer' }); - return es.readArray([new File({ path: 'node', contents, stat: { mode: parseInt('755', 8) } })]); - } - - if (arch === 'armhf') { + } else if (arch === 'armhf') { arch = 'armv7l'; + } else if (arch === 'alpine') { + platform = 'alpine'; + arch = 'x64'; + } + + log(`Downloading node.js ${nodeVersion} ${platform} ${arch} from ${product.nodejs.repository}...`); + + const checksumSha256 = getNodeChecksum(nodeVersion, platform, arch); + + if (checksumSha256) { + log(`Using SHA256 checksum for checking integrity: ${checksumSha256}`); + } else { + log.warn(`Unable to verify integrity of downloaded node.js binary because no SHA256 checksum was found!`); + } + + switch (platform) { + case 'win32': + return (product.nodejs.repository !== 'https://nodejs.org' ? + fetchGithub(product.nodejs.repository, { version: product.nodejs.version, name: `win-${arch}-node.exe`, checksumSha256 }) : + fetchUrls(`/dist/v${nodeVersion}/win-${arch}/node.exe`, { base: 'https://nodejs.org', checksumSha256 })) + .pipe(rename('node.exe')); + case 'darwin': + case 'linux': + return (product.nodejs.repository !== 'https://nodejs.org' ? + fetchGithub(product.nodejs.repository, { version: product.nodejs.version, name: `node-v${nodeVersion}-${platform}-${arch}.tar.gz`, checksumSha256 }) : + fetchUrls(`/dist/v${nodeVersion}/node-v${nodeVersion}-${platform}-${arch}.tar.gz`, { base: 'https://nodejs.org', checksumSha256 }) + ).pipe(flatmap(stream => stream.pipe(gunzip()).pipe(untar()))) + .pipe(filter('**/node')) + .pipe(util.setExecutableBit('**')) + .pipe(rename('node')); + case 'alpine': { + const imageName = arch === 'arm64' ? 'arm64v8/node' : 'node'; + log(`Downloading node.js ${nodeVersion} ${platform} ${arch} from docker image ${imageName}`); + const contents = cp.execSync(`docker run --rm ${imageName}:${nodeVersion}-alpine /bin/sh -c 'cat \`which node\`'`, { maxBuffer: 100 * 1024 * 1024, encoding: 'buffer' }); + if (checksumSha256) { + const actualSHA256Checksum = crypto.createHash('sha256').update(contents).digest('hex'); + if (actualSHA256Checksum !== checksumSha256) { + throw new Error(`Checksum mismatch for node.js from docker image (expected ${options.checksumSha256}, actual ${actualSHA256Checksum}))`); + } + } + return es.readArray([new File({ path: 'node', contents, stat: { mode: parseInt('755', 8) } })]); + } } - log(`Downloading node.js ${nodeVersion} ${platform} ${arch} from https://nodejs.org`); - return remote(`/dist/v${nodeVersion}/node-v${nodeVersion}-${platform}-${arch}.tar.gz`, { base: 'https://nodejs.org', verbose: true }) - .pipe(flatmap(stream => stream.pipe(gunzip()).pipe(untar()))) - .pipe(filter('**/node')) - .pipe(util.setExecutableBit('**')) - .pipe(rename('node')); } function packageTask(type, platform, arch, sourceFolderName, destinationFolderName) { diff --git a/build/lib/builtInExtensions.js b/build/lib/builtInExtensions.js index 5f0e483ea08..222a3c014b2 100644 --- a/build/lib/builtInExtensions.js +++ b/build/lib/builtInExtensions.js @@ -134,4 +134,4 @@ if (require.main === module) { process.exit(1); }); } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbHRJbkV4dGVuc2lvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJidWlsdEluRXh0ZW5zaW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztnR0FHZ0c7OztBQUVoRyx5QkFBeUI7QUFDekIsNkJBQTZCO0FBQzdCLHlCQUF5QjtBQUN6QixpQ0FBaUM7QUFDakMsbUNBQW1DO0FBQ25DLHNDQUFzQztBQUN0QyxnQ0FBZ0M7QUFDaEMsb0NBQW9DO0FBQ3BDLHNDQUFzQztBQUN0QywwQ0FBMEM7QUFHMUMsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBbUJqQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztBQUNuRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsb0JBQW9CLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0FBQ3BHLE1BQU0saUJBQWlCLEdBQTJCLFdBQVcsQ0FBQyxpQkFBaUIsSUFBSSxFQUFFLENBQUM7QUFDdEYsTUFBTSxvQkFBb0IsR0FBMkIsV0FBVyxDQUFDLG9CQUFvQixJQUFJLEVBQUUsQ0FBQztBQUM1RixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxpQkFBaUIsRUFBRSxZQUFZLEVBQUUsY0FBYyxDQUFDLENBQUM7QUFDakcsTUFBTSxjQUFjLEdBQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGdEQUFnRCxDQUFDLENBQUM7QUFFdEYsU0FBUyxHQUFHLENBQUMsR0FBRyxRQUFrQjtJQUNqQyxJQUFJLGNBQWMsRUFBRTtRQUNuQixRQUFRLENBQUMsR0FBRyxRQUFRLENBQUMsQ0FBQztLQUN0QjtBQUNGLENB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 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbHRJbkV4dGVuc2lvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJidWlsdEluRXh0ZW5zaW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztnR0FHZ0c7OztBQUVoRyx5QkFBeUI7QUFDekIsNkJBQTZCO0FBQzdCLHlCQUF5QjtBQUN6QixpQ0FBaUM7QUFDakMsbUNBQW1DO0FBQ25DLHNDQUFzQztBQUN0QyxnQ0FBZ0M7QUFDaEMsb0NBQW9DO0FBQ3BDLHNDQUFzQztBQUN0QywwQ0FBMEM7QUFHMUMsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBb0JqQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztBQUNuRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsb0JBQW9CLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0FBQ3BHLE1BQU0saUJBQWlCLEdBQTJCLFdBQVcsQ0FBQyxpQkFBaUIsSUFBSSxFQUFFLENBQUM7QUFDdEYsTUFBTSxvQkFBb0IsR0FBMkIsV0FBVyxDQUFDLG9CQUFvQixJQUFJLEVBQUUsQ0FBQztBQUM1RixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxpQkFBaUIsRUFBRSxZQUFZLEVBQUUsY0FBYyxDQUFDLENBQUM7QUFDakcsTUFBTSxjQUFjLEdBQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGdEQUFnRCxDQUFDLENBQUM7QUFFdEYsU0FBUyxHQUFHLENBQUMsR0FBRyxRQUFrQjtJQUNqQyxJQUFJLGNBQWMsRUFBRTtRQUNuQixRQUFRLENBQUMsR0FBRyxRQUFRLENBQUMsQ0FBQztLQUN0QjtBQUNGLENB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 \ No newline at end of file diff --git a/build/lib/builtInExtensions.ts b/build/lib/builtInExtensions.ts index 912e05653ac..fefed436bb9 100644 --- a/build/lib/builtInExtensions.ts +++ b/build/lib/builtInExtensions.ts @@ -20,6 +20,7 @@ const mkdirp = require('mkdirp'); export interface IExtensionDefinition { name: string; version: string; + sha256: string; repo: string; platforms?: string[]; metadata: { diff --git a/build/lib/extensions.js b/build/lib/extensions.js index 0dc532b25bf..5f6718411a5 100644 --- a/build/lib/extensions.js +++ b/build/lib/extensions.js @@ -24,8 +24,7 @@ const jsoncParser = require("jsonc-parser"); const dependencies_1 = require("./dependencies"); const builtInExtensions_1 = require("./builtInExtensions"); const getVersion_1 = require("./getVersion"); -const gulpRemoteSource_1 = require("./gulpRemoteSource"); -const github_1 = require("./github"); +const fetch_1 = require("./fetch"); const root = path.dirname(path.dirname(__dirname)); const commit = (0, getVersion_1.getVersion)(root); const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${commit}`; @@ -193,19 +192,19 @@ const baseHeaders = { 'User-Agent': userAgent, 'X-Market-User-Id': '291C1CD0-051A-4123-9B4B-30D60EF52EE2', }; -function fromMarketplace(serviceUrl, { name: extensionName, version, metadata }) { +function fromMarketplace(serviceUrl, { name: extensionName, version, sha256, metadata }) { const json = require('gulp-json-editor'); const [publisher, name] = extensionName.split('.'); const url = `${serviceUrl}/publishers/${publisher}/vsextensions/${name}/${version}/vspackage`; fancyLog('Downloading extension:', ansiColors.yellow(`${extensionName}@${version}`), '...'); - const options = { - base: url, - fetchOptions: { - headers: baseHeaders - } - }; const packageJsonFilter = filter('package.json', { restore: true }); - return (0, gulpRemoteSource_1.remote)('', options) + return (0, fetch_1.fetchUrls)('', { + base: url, + nodeFetchOptions: { + headers: baseHeaders + }, + checksumSha256: sha256 + }) .pipe(vzip.src()) .pipe(filter('extension/**')) .pipe(rename(p => p.dirname = p.dirname.replace(/^extension\/?/, ''))) @@ -215,11 +214,15 @@ function fromMarketplace(serviceUrl, { name: extensionName, version, metadata }) .pipe(packageJsonFilter.restore); } exports.fromMarketplace = fromMarketplace; -function fromGithub({ name, version, repo, metadata }) { +function fromGithub({ name, version, repo, sha256, metadata }) { const json = require('gulp-json-editor'); fancyLog('Downloading extension from GH:', ansiColors.yellow(`${name}@${version}`), '...'); const packageJsonFilter = filter('package.json', { restore: true }); - return (0, github_1.assetFromGithub)(new URL(repo).pathname, version, name => name.endsWith('.vsix')) + return (0, fetch_1.fetchGithub)(new URL(repo).pathname, { + version, + name: name => name.endsWith('.vsix'), + checksumSha256: sha256 + }) .pipe(buffer()) .pipe(vzip.src()) .pipe(filter('extension/**')) @@ -498,4 +501,4 @@ async function buildExtensionMedia(isWatch, outputRoot) { }))); } exports.buildExtensionMedia = buildExtensionMedia; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXh0ZW5zaW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImV4dGVuc2lvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Z0dBR2dHOzs7QUFFaEcsbUNBQW1DO0FBQ25DLHlCQUF5QjtBQUN6QixvQ0FBb0M7QUFDcEMsNkJBQTZCO0FBQzdCLDZCQUE2QjtBQUM3Qiw2QkFBNkI7QUFFN0IsOEJBQThCO0FBQzlCLG1DQUE0QztBQUM1QyxnQ0FBZ0M7QUFDaEMsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUM7QUFDdkMsc0NBQXVDO0FBQ3ZDLHNDQUF1QztBQUN2QyxzQ0FBc0M7QUFDdEMsMENBQTBDO0FBQzFDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQztBQUN0Qyw0Q0FBNEM7QUFFNUMsaURBQTJEO0FBQzNELDJEQUF5RDtBQUN6RCw2Q0FBMEM7QUFDMUMseURBQTJFO0FBQzNFLHFDQUEyQztBQUUzQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztBQUNuRCxNQUFNLE1BQU0sR0FBRyxJQUFBLHVCQUFVLEVBQUMsSUFBSSxDQUFDLENBQUM7QUFDaEMsTUFBTSxvQkFBb0IsR0FBRyxtREFBbUQsTUFBTSxFQUFFLENBQUM7QUFFekYsU0FBUyx3QkFBd0IsQ0FBQyxLQUFhO0lBQzlDLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxDQUFDLFdBQVcsRUFBRSxvQkFBb0IsQ0FBQyxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7SUFDbEYsT0FBTyxLQUFLO1NBQ1YsSUFBSSxDQUFDLFVBQVUsQ0FBQztTQUNoQixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7U0FDZCxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQU8sRUFBRSxFQUFFO1FBQzVCLE1BQU0sTUFBTSxHQUE2QixFQUFFLENBQUM7UUFDNUMsTUFBTSxLQUFLLEdBQUcsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRSxrQkFBa0IsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ25HLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDeEIsbUVBQW1FO1lBQ25FLENBQUMsQ0FBQyxRQUFRLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7U0FDaEQ7UUFDRCxPQUFPLENBQUMsQ0FBQztJQUNWLENBQUMsQ0FBQyxDQUFDO1NBQ0YsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUM1QixDQUFDO0FBRUQsU0FBUywwQkFBMEIsQ0FBQyxLQUFhLEVBQUUsTUFBMEI7SUFDNUUsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLENBQUMsMkJBQTJCLEVBQUUsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUNqRixPQUFPLEtBQUs7U0FDVixJQUFJLENBQUMsaUJBQWlCLENBQUM7U0FDdkIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1NBQ2QsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFPLEVBQUUsRUFBRTtRQUM1QixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDckQsQ0FBQyxDQUFDLFFBQVEsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2RCxPQUFPLENBQUMsQ0FBQztJQUNWLENBQUMsQ0FBQyxDQUFDO1NBQ0YsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQ25DLENBQUM7QUFFRCxTQUFTLFNBQVMsQ0FBQyxhQUFxQixFQUFFLE1BQWUsRUFBRSxhQUFzQjtJQUNoRixNQUFNLHFCQUFxQixHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMscUNBQXFDLENBQUMsQ0FBQyxDQUFDLDZCQUE2QixDQUFDO0lBRTdHLE1BQU0sV0FBVyxHQUFHLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUscUJBQXFCLENBQUMsQ0FBQyxDQUFDO0lBQ25GLElBQUksS0FBSyxHQUFHLFdBQVc7UUFDdEIsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLGFBQWEsRUFBRSxxQkFBcUIsRUFBRSxhQUFhLENBQUM7UUFDdkUsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUVsQyxJQUFJLFdBQVcsRUFBRTtRQUNoQixLQUFLLEdBQUcsMEJBQTBCLENBQUMsS0FBSyxFQUFFLENBQUMsSUFBUyxFQUFFLEVBQUU7WUFDdkQsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDO1lBQ3BCLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQztZQUN6QixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUM7WUFDNUIsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFO2dCQUNkLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDO2FBQ2pEO1lBQ0QsT0FBTyxJQUFJLENBQUM7UUFDYixDQUFDLENBQUMsQ0FBQztLQUNIO0lBRUQsT0FBTyxLQUFLLENBQUM7QUFDZCxDQUFDO0FBR0QsU0FBUyxnQkFBZ0IsQ0FBQyxhQUFxQixFQUFFLHFCQUE2QixFQUFFLGFBQXNCO0lBQ3JHLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQWtDLENBQUM7SUFDdEUsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ25DLE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBQzlDLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUU1QixNQUFNLG9CQUFvQixHQUFhLEVBQUUsQ0FBQztJQUMxQyxNQUFNLGlCQUFpQixHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxjQUFjLENBQUMsQ0FBQyxDQUFDO0lBQzVFLElBQUksaUJBQWlCLENBQUMsWUFBWSxFQUFFO1FBQ25DLE1BQU0saUJBQWlCLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLHFCQUFxQixDQUFDLENBQUMsQ0FBQztRQUNuRixLQUFLLE1BQU0sR0FBRyxJQUFJLGlCQUFpQixDQUFDLFNBQVMsRUFBRTtZQUM5QyxJQUFJLEdBQUcsSUFBSSxpQkFBaUIsQ0FBQyxZQUFZLEVBQUU7Z0JBQzFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQzthQUMvQjtTQUNEO0tBQ0Q7SUFFRCxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsR0FBRyxFQUFFLGFBQWEsRUFBRSxjQUFjLEVBQUUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsb0JBQW9CLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRTtRQUN2SCxNQUFNLEtBQUssR0FBRyxTQUFTO2FBQ3JCLEdBQUcsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLFFBQVEsQ0FBQyxDQUFDO2FBQ25ELEdBQUcsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLElBQUksSUFBSSxDQUFDO1lBQ3pCLElBQUksRUFBRSxRQUFRO1lBQ2QsSUFBSSxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDO1lBQzNCLElBQUksRUFBRSxhQUFhO1lBQ25CLFFBQVEsRUFBRSxFQUFFLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFRO1NBQzlDLENBQUMsQ0FBQyxDQUFDO1FBRUwsK0RBQStEO1FBQy9ELDhDQUE4QztRQUM5QyxNQUFNLHNCQUFzQixHQUFjLElBQUksQ0FBQyxJQUFJLENBQ2xELElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLElBQUksRUFBRSxxQkFBcUIsQ0FBQyxFQUNyRCxFQUFFLE1BQU0sRUFBRSxDQUFDLGlCQUFpQixDQUFDLEVBQUUsQ0FDOUIsQ0FBQztRQUVILE1BQU0sY0FBYyxHQUFHLHNCQUFzQixDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFO1lBRXpFLE1BQU0sV0FBVyxHQUFHLENBQUMsR0FBUSxFQUFFLEtBQVUsRUFBRSxFQUFFO2dCQUM1QyxRQUFRLENBQUMsc0JBQXNCLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxFQUFFLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDakosSUFBSSxHQUFHLEVBQUU7b0JBQ1IsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUM7aUJBQzFCO2dCQUNELE1BQU0sRUFBRSxXQUFXLEVBQUUsR0FBRyxLQUFLLENBQUM7Z0JBQzlCLElBQUksV0FBVyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO29CQUNsQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO2lCQUNwRDtnQkFDRCxJQUFJLFdBQVcsQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtvQkFDcEMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsV0FBVyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztpQkFDdEQ7WUFDRixDQUFDLENBQUM7WUFFRixNQUFNLGNBQWMsR0FBRyxPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUNsRCxPQUFPLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFO2dCQUN2RixNQUFNLGFBQWEsR0FBRztvQkFDckIsR0FBRyxNQUFNO29CQUNULEdBQUcsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFO2lCQUN6QixDQUFDO2dCQUNGLElBQUksYUFBYSxFQUFFO29CQUNsQixJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRTt3QkFDdkMsS0FBSyxNQUFNLElBQUksSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRTs0QkFDdkMsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRTtnQ0FDNUIsS0FBSyxNQUFNLEdBQUcsSUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFO29DQUMzQixJQUFJLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsUUFBUSxDQUFDLGtCQUFrQixDQUFDLEVBQUU7d0NBQ3BELEdBQUcsQ0FBQyxPQUFPLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztxQ0FDNUI7aUNBQ0Q7NkJBQ0Q7eUJBQ0Q7cUJBQ0Q7aUJBQ0Q7Z0JBQ0QsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxhQUFhLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUVuRixPQUFPLFdBQVcsQ0FBQyxhQUFhLEVBQUUsT0FBTyxFQUFFLFdBQVcsQ0FBQztxQkFDckQsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsVUFBVSxJQUFJO29CQUM5QixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDO29CQUM1QixJQUFJLENBQUMsSUFBSSxHQUFHLGFBQWEsQ0FBQztvQkFDMUIsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQ3pCLENBQUMsQ0FBQyxDQUFDO3FCQUNGLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQVUsSUFBVTtvQkFDcEMsdUJBQXVCO29CQUN2Qiw2QkFBNkI7b0JBQzdCLG1EQUFtRDtvQkFDbkQsTUFBTSxRQUFRLEdBQVksSUFBSSxDQUFDLFFBQVMsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7b0JBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLGtDQUFrQyxFQUFFLFVBQVUsRUFBRSxFQUFFLEVBQUU7d0JBQ2hHLE9BQU8sMEJBQTBCLG9CQUFvQixlQUFlLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLElBQUksa0JBQWtCLElBQUksRUFBRSxFQUFFLENBQUM7b0JBQ2hJLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO29CQUVaLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUN6QixDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ04sQ0FBQyxDQUFDLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxjQUFjLEVBQUUsRUFBRSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUMvQyxxQ0FBcUM7WUFDckMsWUFBWTtZQUNaLHdEQUF3RDtZQUN4RCw0QkFBNEI7WUFDNUIsTUFBTTthQUNMLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUVoQixDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUU7UUFDZCxPQUFPLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQzdCLE9BQU8sQ0FBQyxLQUFLLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUNwQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsQ0FBQztJQUMzQixDQUFDLENBQUMsQ0FBQztJQUVILE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFBLHlCQUFpQixFQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3JFLENBQUM7QUFFRCxTQUFTLGVBQWUsQ0FBQyxhQUFxQjtJQUM3QyxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFrQyxDQUFDO0lBQ3RFLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUU1QixJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsR0FBRyxFQUFFLGFBQWEsRUFBRSxjQUFjLEVBQUUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztTQUM5RSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUU7UUFDakIsTUFBTSxLQUFLLEdBQUcsU0FBUzthQUNyQixHQUFHLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxRQUFRLENBQUMsQ0FBQzthQUNuRCxHQUFHLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxJQUFJLElBQUksQ0FBQztZQUN6QixJQUFJLEVBQUUsUUFBUTtZQUNkLElBQUksRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQztZQUMzQixJQUFJLEVBQUUsYUFBYTtZQUNuQixRQUFRLEVBQUUsRUFBRSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBUTtTQUM5QyxDQUFDLENBQUMsQ0FBQztRQUVMLEVBQUUsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2xDLENBQUMsQ0FBQztTQUNELEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFFMUMsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUEseUJBQWlCLEVBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDckUsQ0FBQztBQUVELE1BQU0sU0FBUyxHQUFHLGNBQWMsQ0FBQztBQUNqQyxNQUFNLFdBQVcsR0FBRztJQUNuQixvQkFBb0IsRUFBRSxjQUFjO0lBQ3BDLFlBQVksRUFBRSxTQUFTO0lBQ3ZCLGtCQUFrQixFQUFFLHNDQUFzQztDQUMxRCxDQUFDO0FBRUYsU0FBZ0IsZUFBZSxDQUFDLFVBQWtCLEVBQUUsRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQXFCO0lBQ2hILE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBc0MsQ0FBQztJQUU5RSxNQUFNLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxHQUFHLGFBQWEsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbkQsTUFBTSxHQUFHLEdBQUcsR0FBRyxVQUFVLGVBQWUsU0FBUyxpQkFBaUIsSUFBSSxJQUFJLE9BQU8sWUFBWSxDQUFDO0lBRTlGLFFBQVEsQ0FBQyx3QkFBd0IsRUFBRSxVQUFVLENBQUMsTUFBTSxDQUFDLEdBQUcsYUFBYSxJQUFJLE9BQU8sRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFFNUYsTUFBTSxPQUFPLEdBQXNCO1FBQ2xDLElBQUksRUFBRSxHQUFHO1FBQ1QsWUFBWSxFQUFFO1lBQ2IsT0FBTyxFQUFFLFdBQVc7U0FDcEI7S0FDRCxDQUFDO0lBRUYsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLENBQUMsY0FBYyxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7SUFFcEUsT0FBTyxJQUFBLHlCQUFNLEVBQUMsRUFBRSxFQUFFLE9BQU8sQ0FBQztTQUN4QixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2hCLElBQUksQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUM7U0FDNUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDLE9BQVEsQ0FBQyxPQUFPLENBQUMsZUFBZSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7U0FDdEUsSUFBSSxDQUFDLGlCQUFpQixDQUFDO1NBQ3ZCLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztTQUNkLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztTQUNwQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDbkMsQ0FBQztBQXpCRCwwQ0F5QkM7QUFHRCxTQUFnQixVQUFVLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQXFCO0lBQzlFLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBc0MsQ0FBQztJQUU5RSxRQUFRLENBQUMsZ0NBQWdDLEVBQUUsVUFBVSxDQUFDLE1BQU0sQ0FBQyxHQUFHLElBQUksSUFBSSxPQUFPLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBRTNGLE1BQU0saUJBQWlCLEdBQUcsTUFBTSxDQUFDLGNBQWMsRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBRXBFLE9BQU8sSUFBQSx3QkFBZSxFQUFDLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1NBQ3JGLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztTQUNkLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7U0FDaEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztTQUM1QixJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUMsT0FBUSxDQUFDLE9BQU8sQ0FBQyxlQUFlLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztTQUN0RSxJQUFJLENBQUMsaUJBQWlCLENBQUM7U0FDdkIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1NBQ2QsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO1NBQ3BDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUNuQyxDQUFDO0FBaEJELGdDQWdCQztBQUVELE1BQU0sa0JBQWtCLEdBQUc7SUFDMUIsa0JBQWtCO0lBQ2xCLHVCQUF1QjtJQUN2QixzQkFBc0I7SUFDdEIsc0JBQXNCO0lBQ3RCLHVCQUF1QjtDQUN2QixDQUFDO0FBRUYsTUFBTSwrQkFBK0IsR0FBRyxJQUFJLEdBQUcsQ0FBQztJQUMvQyxzQkFBc0I7SUFDdEIsdUJBQXVCO0lBQ3ZCLDhCQUE4QjtJQUM5QixvQkFBb0I7SUFDcEIsbUNBQW1DO0NBQ25DLENBQUMsQ0FBQztBQVNILE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxvQkFBb0IsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7QUFDcEcsTUFBTSxpQkFBaUIsR0FBd0IsV0FBVyxDQUFDLGlCQUFpQixJQUFJLEVBQUUsQ0FBQztBQUNuRixNQUFNLG9CQUFvQixHQUF3QixXQUFXLENBQUMsb0JBQW9CLElBQUksRUFBRSxDQUFDO0FBV3pGOztHQUVHO0FBQ0gsU0FBUyxjQUFjLENBQUMsUUFBNEI7SUFDbkQsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQzlCLE9BQU8sSUFBSSxDQUFDO0tBQ1o7SUFDRCxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUU7UUFDM0IsT0FBTyxLQUFLLENBQUM7S0FDYjtJQUNELDJCQUEyQjtJQUMzQixJQUFJLE9BQU8sUUFBUSxDQUFDLGFBQWEsS0FBSyxXQUFXLEVBQUU7UUFDbEQsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ2hILElBQUksYUFBYSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDdEMsT0FBTyxJQUFJLENBQUM7U0FDWjtLQUNEO0lBQ0QsSUFBSSxPQUFPLFFBQVEsQ0FBQyxXQUFXLEtBQUssV0FBVyxFQUFFO1FBQ2hELEtBQUssTUFBTSxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUUsVUFBVSxFQUFFLHlCQUF5QixDQUFDLEVBQUU7WUFDdEUsSUFBSSxRQUFRLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUMsRUFBRTtnQkFDNUMsT0FBTyxLQUFLLENBQUM7YUFDYjtTQUNEO0tBQ0Q7SUFDRCxPQUFPLElBQUksQ0FBQztBQUNiLENBQUM7QUFFRCxTQUFnQiw0QkFBNEIsQ0FBQyxNQUFlLEVBQUUsYUFBc0I7SUFDbkYsTUFBTSwyQkFBMkIsR0FBRyxDQUN4QixJQUFJLENBQUMsSUFBSSxDQUFDLDJCQUEyQixDQUFFO1NBQ2hELEdBQUcsQ0FBQyxZQUFZLENBQUMsRUFBRTtRQUNuQixNQUFNLG9CQUFvQixHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQzNELE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQztRQUNsRSxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ25ELE9BQU8sRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLG9CQUFvQixFQUFFLENBQUM7SUFDekYsQ0FBQyxDQUFDO1NBQ0QsTUFBTSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUMsa0JBQWtCLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1NBQzdELE1BQU0sQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLENBQUM7U0FDbkUsTUFBTSxDQUFDLENBQUMsRUFBRSxZQUFZLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FDdkYsQ0FBQztJQUNGLE1BQU0scUJBQXFCLEdBQUcsd0JBQXdCLENBQ3JELEVBQUUsQ0FBQyxLQUFLLENBQ1AsR0FBRywyQkFBMkIsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLEVBQUU7UUFDOUMsT0FBTyxTQUFTLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsYUFBYSxDQUFDO2FBQ3JELElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxHQUFHLGNBQWMsU0FBUyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzlFLENBQUMsQ0FBQyxDQUNGLENBQ0QsQ0FBQztJQUVGLElBQUksTUFBYyxDQUFDO0lBQ25CLElBQUksTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLHFCQUFxQixDQUFDO0tBQy9CO1NBQU07UUFDTiw4Q0FBOEM7UUFDOUMsTUFBTSxzQkFBc0IsR0FBRyxJQUFBLHdDQUF5QixFQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ3hFLE1BQU0sZUFBZSxHQUFHLHNCQUFzQixDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO1FBRTlJLE1BQU0sR0FBRyxFQUFFLENBQUMsS0FBSyxDQUNoQixxQkFBcUIsRUFDckIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxlQUFlLEVBQUUsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUM7YUFDdEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsZUFBZSxDQUFDLENBQUMsQ0FBQzthQUN2RSxJQUFJLENBQUMsS0FBSyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE9BQU8sRUFBRSxpQkFBaUIsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7S0FDaEc7SUFFRCxPQUFPLENBQ04sTUFBTTtTQUNKLElBQUksQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQzNDLENBQUM7QUFDSCxDQUFDO0FBekNELG9FQXlDQztBQUVELFNBQWdCLGtDQUFrQyxDQUFDLE1BQWU7SUFDakUsTUFBTSxpQ0FBaUMsR0FBRztRQUN6QyxHQUFHLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLCtCQUErQixDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdkcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztLQUN2QyxDQUFDO0lBQ0YsTUFBTSwyQkFBMkIsR0FBRyx3QkFBd0IsQ0FDM0QsRUFBRSxDQUFDLEtBQUssQ0FDUCxHQUFHLGlDQUFpQztTQUNsQyxHQUFHLENBQUMsU0FBUyxDQUFDLEVBQUU7UUFDaEIsTUFBTSxHQUFHLEdBQUcsSUFBQSxzQ0FBa0IsRUFBQyxTQUFTLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sR0FBRyxjQUFjLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDbkcsT0FBTywwQkFBMEIsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFTLEVBQUUsRUFBRTtZQUNwRCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7WUFDcEIsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO1lBQ3pCLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQztZQUM1QixPQUFPLElBQUksQ0FBQztRQUNiLENBQUMsQ0FBQyxDQUFDO0lBQ0osQ0FBQyxDQUFDLENBQ0gsQ0FDRCxDQUFDO0lBRUYsT0FBTyxDQUNOLDJCQUEyQjtTQUN6QixJQUFJLENBQUMsS0FBSyxDQUFDLGdCQUFnQixDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUMzQyxDQUFDO0FBQ0gsQ0FBQztBQXhCRCxnRkF3QkM7QUFVRCxTQUFnQixxQkFBcUIsQ0FBQyxjQUFzQixFQUFFLFVBQW9CLEVBQUU7SUFDbkYsTUFBTSxpQkFBaUIsR0FBK0IsRUFBRSxDQUFDO0lBRXpELElBQUk7UUFDSCxNQUFNLGlCQUFpQixHQUFHLEVBQUUsQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDekQsS0FBSyxNQUFNLGVBQWUsSUFBSSxpQkFBaUIsRUFBRTtZQUNoRCxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxFQUFFO2dCQUMxQyxTQUFTO2FBQ1Q7WUFDRCxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxlQUFlLEVBQUUsY0FBYyxDQUFDLENBQUM7WUFDbkYsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsZUFBZSxDQUFDLEVBQUU7Z0JBQ3BDLFNBQVM7YUFDVDtZQUNELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxlQUFlLENBQUMsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztZQUNsRixJQUFJLENBQUMsY0FBYyxDQUFDLFdBQVcsQ0FBQyxFQUFFO2dCQUNqQyxTQUFTO2FBQ1Q7WUFDRCxNQUFNLFFBQVEsR0FBRyxFQUFFLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLGVBQWUsQ0FBQyxDQUFDLENBQUM7WUFDNUUsTUFBTSxjQUFjLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssS0FBSyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2pGLE1BQU0sVUFBVSxHQUFHLGNBQWMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLGVBQWUsRUFBRSxjQUFjLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztZQUNuSixNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDakYsTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLDJCQUEyQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRXZGLGlCQUFpQixDQUFDLElBQUksQ0FBQztnQkFDdEIsYUFBYSxFQUFFLGVBQWU7Z0JBQzlCLFdBQVc7Z0JBQ1gsVUFBVTtnQkFDVixVQUFVLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUztnQkFDbkUsYUFBYSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVM7YUFDNUUsQ0FBQyxDQUFDO1NBQ0g7UUFDRCxPQUFPLGlCQUFpQixDQUFDO0tBQ3pCO0lBQUMsT0FBTyxFQUFFLEVBQUU7UUFDWixPQUFPLGlCQUFpQixDQUFDO0tBQ3pCO0FBQ0YsQ0FBQztBQW5DRCxzREFtQ0M7QUFFRCxTQUFnQixvQkFBb0IsQ0FBQyxXQUFtQixFQUFFLGNBQXNCO0lBSS9FLE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdEMsTUFBTSxVQUFVLEdBQWMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLGNBQWMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDckYsTUFBTSxTQUFTLEdBQUcsQ0FBQyxHQUFRLEVBQUUsRUFBRTtRQUM5QixLQUFLLE1BQU0sR0FBRyxJQUFJLEdBQUcsRUFBRTtZQUN0QixNQUFNLEdBQUcsR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDckIsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFO2dCQUN2QixHQUFHLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO2FBQ3ZCO2lCQUFNLElBQUksR0FBRyxJQUFJLE9BQU8sR0FBRyxLQUFLLFFBQVEsRUFBRTtnQkFDMUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2FBQ2Y7aUJBQU0sSUFBSSxPQUFPLEdBQUcsS0FBSyxRQUFRLElBQUksR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsS0FBSyxXQUFXLElBQUksR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxLQUFLLFdBQVcsRUFBRTtnQkFDMUgsTUFBTSxVQUFVLEdBQUcsVUFBVSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDN0QsSUFBSSxVQUFVLEVBQUU7b0JBQ2YsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLE9BQU8sVUFBVSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sVUFBVSxDQUFDLE9BQU8sS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2lCQUM3SDthQUNEO1NBQ0Q7SUFDRixDQUFDLENBQUM7SUFDRixTQUFTLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDdkIsT0FBTyxXQUFXLENBQUM7QUFDcEIsQ0FBQztBQXZCRCxvREF1QkM7QUFFRCxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxZQUFZLENBQUMsQ0FBQztBQUVyRCxpRkFBaUY7QUFDakYsTUFBTSxtQkFBbUIsR0FBRztJQUMzQixnREFBZ0Q7SUFDaEQsK0NBQStDO0lBQy9DLDBCQUEwQjtJQUMxQiwrQkFBK0I7SUFDL0Isa0JBQWtCO0lBQ2xCLG1DQUFtQztDQUNuQyxDQUFDO0FBRUssS0FBSyxVQUFVLGlCQUFpQixDQUFDLFFBQWdCLEVBQUUsT0FBZ0IsRUFBRSxzQkFBcUU7SUFDaEosTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBNkIsQ0FBQztJQUUvRCxNQUFNLGNBQWMsR0FBNEIsRUFBRSxDQUFDO0lBRW5ELEtBQUssTUFBTSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsSUFBSSxzQkFBc0IsRUFBRTtRQUNoRSxNQUFNLGlCQUFpQixHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUM5QyxTQUFTLFNBQVMsQ0FBQyxpQkFBNkg7WUFDL0ksS0FBSyxNQUFNLFVBQVUsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxDQUFDLGlCQUFpQixDQUFDLEVBQUU7Z0JBQ3BHLE1BQU0sTUFBTSxHQUFHLE9BQU8sVUFBVSxLQUFLLFVBQVUsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDO2dCQUNsRixJQUFJLFVBQVUsRUFBRTtvQkFDZixNQUFNLENBQUMsTUFBTyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUUsTUFBTSxDQUFDLE1BQU8sQ0FBQyxJQUFLLENBQUMsQ0FBQyxDQUFDO2lCQUMzRztnQkFDRCxjQUFjLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO2FBQzVCO1FBQ0YsQ0FBQztRQUNELFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0tBQzdCO0lBQ0QsU0FBUyxRQUFRLENBQUMsU0FBYztRQUMvQixJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxFQUFFO1lBQ3RDLEtBQUssTUFBTSxLQUFLLElBQUksU0FBUyxDQUFDLFFBQVEsRUFBRTtnQkFDdkMsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQztnQkFDcEMsSUFBSSxVQUFVLEVBQUU7b0JBQ2YsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxjQUFjLEVBQUUsVUFBVSxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQztvQkFDbkYsTUFBTSxLQUFLLEdBQUcsWUFBWSxDQUFDLEtBQUssQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO29CQUMvRCxRQUFRLENBQUMsWUFBWSxVQUFVLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLFVBQVUsQ0FBQyxDQUFDO2lCQUNySDtnQkFDRCxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxFQUFFO29CQUNoQyxLQUFLLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQVUsRUFBRSxFQUFFO3dCQUNuQyxRQUFRLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUN2QixDQUFDLENBQUMsQ0FBQztpQkFDSDtnQkFDRCxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxFQUFFO29CQUNsQyxLQUFLLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE9BQVksRUFBRSxFQUFFO3dCQUN2QyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO29CQUN4QixDQUFDLENBQUMsQ0FBQztpQkFDSDthQUNEO1NBQ0Q7SUFDRixDQUFDO0lBQ0QsT0FBTyxJQUFJLE9BQU8sQ0FBTyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtRQUM1QyxJQUFJLE9BQU8sRUFBRTtZQUNaLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxFQUFFO2dCQUNoRCxJQUFJLEdBQUcsRUFBRTtvQkFDUixNQUFNLEVBQUUsQ0FBQztpQkFDVDtxQkFBTTtvQkFDTixRQUFRLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7aUJBQzFCO1lBQ0YsQ0FBQyxDQUFDLENBQUM7U0FDSDthQUFNO1lBQ04sT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsRUFBRTtnQkFDMUMsSUFBSSxHQUFHLEVBQUU7b0JBQ1IsUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztvQkFDcEIsTUFBTSxFQUFFLENBQUM7aUJBQ1Q7cUJBQU07b0JBQ04sUUFBUSxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO29CQUMxQixPQUFPLEVBQUUsQ0FBQztpQkFDVjtZQUNGLENBQUMsQ0FBQyxDQUFDO1NBQ0g7SUFDRixDQUFDLENBQUMsQ0FBQztBQUNKLENBQUM7QUE3REQsOENBNkRDO0FBRUQsS0FBSyxVQUFVLGlCQUFpQixDQUFDLFFBQWdCLEVBQUUsT0FBZ0IsRUFBRSxPQUFrRDtJQUN0SCxTQUFTLFFBQVEsQ0FBQyxRQUFnQixFQUFFLE1BQWM7UUFDakQsTUFBTSxPQUFPLEdBQUcsQ0FBQyxRQUFRLElBQUksRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLHdCQUF3QixDQUFDLENBQUM7UUFDakUsUUFBUSxDQUFDLFlBQVksVUFBVSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxNQUFNLFNBQVMsT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQzFHLEtBQUssTUFBTSxLQUFLLElBQUksT0FBTyxJQUFJLEVBQUUsRUFBRTtZQUNsQyxRQUFRLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQ3RCO0lBQ0YsQ0FBQztJQUVELE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFO1FBQ3BELE9BQU8sSUFBSSxPQUFPLENBQU8sQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDNUMsTUFBTSxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN0QixJQUFJLE9BQU8sRUFBRTtnQkFDWixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2FBQ3JCO1lBQ0QsSUFBSSxVQUFVLEVBQUU7Z0JBQ2YsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsVUFBVSxDQUFDLENBQUM7YUFDdEM7WUFDRCxNQUFNLElBQUksR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7Z0JBQzlFLElBQUksS0FBSyxFQUFFO29CQUNWLE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO2lCQUNyQjtnQkFDRCxRQUFRLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFDO2dCQUN6QixJQUFJLE1BQU0sRUFBRTtvQkFDWCxPQUFPLE1BQU0sRUFBRSxDQUFDO2lCQUNoQjtnQkFDRCxPQUFPLE9BQU8sRUFBRSxDQUFDO1lBQ2xCLENBQUMsQ0FBQyxDQUFDO1lBRUgsSUFBSSxDQUFDLE1BQU8sQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLEVBQUU7Z0JBQ2hDLFFBQVEsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDckUsQ0FBQyxDQUFDLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzNCLENBQUM7QUFFTSxLQUFLLFVBQVUsbUJBQW1CLENBQUMsT0FBZ0IsRUFBRSxVQUFtQjtJQUM5RSxPQUFPLGlCQUFpQixDQUFDLDRCQUE0QixFQUFFLE9BQU8sRUFBRSxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQzdGLE1BQU0sRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUM7UUFDcEMsVUFBVSxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUztLQUNqRixDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ04sQ0FBQztBQUxELGtEQUtDIn0= \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXh0ZW5zaW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImV4dGVuc2lvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Z0dBR2dHOzs7QUFFaEcsbUNBQW1DO0FBQ25DLHlCQUF5QjtBQUN6QixvQ0FBb0M7QUFDcEMsNkJBQTZCO0FBQzdCLDZCQUE2QjtBQUM3Qiw2QkFBNkI7QUFFN0IsOEJBQThCO0FBQzlCLG1DQUE0QztBQUM1QyxnQ0FBZ0M7QUFDaEMsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUM7QUFDdkMsc0NBQXVDO0FBQ3ZDLHNDQUF1QztBQUN2QyxzQ0FBc0M7QUFDdEMsMENBQTBDO0FBQzFDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQztBQUN0Qyw0Q0FBNEM7QUFFNUMsaURBQTJEO0FBQzNELDJEQUErRTtBQUMvRSw2Q0FBMEM7QUFDMUMsbUNBQWlEO0FBRWpELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0FBQ25ELE1BQU0sTUFBTSxHQUFHLElBQUEsdUJBQVUsRUFBQyxJQUFJLENBQUMsQ0FBQztBQUNoQyxNQUFNLG9CQUFvQixHQUFHLG1EQUFtRCxNQUFNLEVBQUUsQ0FBQztBQUV6RixTQUFTLHdCQUF3QixDQUFDLEtBQWE7SUFDOUMsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLENBQUMsV0FBVyxFQUFFLG9CQUFvQixDQUFDLEVBQUUsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUNsRixPQUFPLEtBQUs7U0FDVixJQUFJLENBQUMsVUFBVSxDQUFDO1NBQ2hCLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztTQUNkLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBTyxFQUFFLEVBQUU7UUFDNUIsTUFBTSxNQUFNLEdBQTZC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 \ No newline at end of file diff --git a/build/lib/extensions.ts b/build/lib/extensions.ts index b72ef4e6a1a..6edfdcb63fb 100644 --- a/build/lib/extensions.ts +++ b/build/lib/extensions.ts @@ -22,10 +22,9 @@ const buffer = require('gulp-buffer'); import * as jsoncParser from 'jsonc-parser'; import webpack = require('webpack'); import { getProductionDependencies } from './dependencies'; -import { getExtensionStream } from './builtInExtensions'; +import { IExtensionDefinition, getExtensionStream } from './builtInExtensions'; import { getVersion } from './getVersion'; -import { remote, IOptions as IRemoteSrcOptions } from './gulpRemoteSource'; -import { assetFromGithub } from './github'; +import { fetchUrls, fetchGithub } from './fetch'; const root = path.dirname(path.dirname(__dirname)); const commit = getVersion(root); @@ -222,7 +221,7 @@ const baseHeaders = { 'X-Market-User-Id': '291C1CD0-051A-4123-9B4B-30D60EF52EE2', }; -export function fromMarketplace(serviceUrl: string, { name: extensionName, version, metadata }: IBuiltInExtension): Stream { +export function fromMarketplace(serviceUrl: string, { name: extensionName, version, sha256, metadata }: IExtensionDefinition): Stream { const json = require('gulp-json-editor') as typeof import('gulp-json-editor'); const [publisher, name] = extensionName.split('.'); @@ -230,16 +229,15 @@ export function fromMarketplace(serviceUrl: string, { name: extensionName, versi fancyLog('Downloading extension:', ansiColors.yellow(`${extensionName}@${version}`), '...'); - const options: IRemoteSrcOptions = { - base: url, - fetchOptions: { - headers: baseHeaders - } - }; - const packageJsonFilter = filter('package.json', { restore: true }); - return remote('', options) + return fetchUrls('', { + base: url, + nodeFetchOptions: { + headers: baseHeaders + }, + checksumSha256: sha256 + }) .pipe(vzip.src()) .pipe(filter('extension/**')) .pipe(rename(p => p.dirname = p.dirname!.replace(/^extension\/?/, ''))) @@ -250,14 +248,18 @@ export function fromMarketplace(serviceUrl: string, { name: extensionName, versi } -export function fromGithub({ name, version, repo, metadata }: IBuiltInExtension): Stream { +export function fromGithub({ name, version, repo, sha256, metadata }: IExtensionDefinition): Stream { const json = require('gulp-json-editor') as typeof import('gulp-json-editor'); fancyLog('Downloading extension from GH:', ansiColors.yellow(`${name}@${version}`), '...'); const packageJsonFilter = filter('package.json', { restore: true }); - return assetFromGithub(new URL(repo).pathname, version, name => name.endsWith('.vsix')) + return fetchGithub(new URL(repo).pathname, { + version, + name: name => name.endsWith('.vsix'), + checksumSha256: sha256 + }) .pipe(buffer()) .pipe(vzip.src()) .pipe(filter('extension/**')) @@ -284,16 +286,9 @@ const marketplaceWebExtensionsExclude = new Set([ 'ms-vscode.vscode-js-profile-table' ]); -interface IBuiltInExtension { - name: string; - version: string; - repo: string; - metadata: any; -} - const productJson = JSON.parse(fs.readFileSync(path.join(__dirname, '../../product.json'), 'utf8')); -const builtInExtensions: IBuiltInExtension[] = productJson.builtInExtensions || []; -const webBuiltInExtensions: IBuiltInExtension[] = productJson.webBuiltInExtensions || []; +const builtInExtensions: IExtensionDefinition[] = productJson.builtInExtensions || []; +const webBuiltInExtensions: IExtensionDefinition[] = productJson.webBuiltInExtensions || []; type ExtensionKind = 'ui' | 'workspace' | 'web'; interface IExtensionManifest { diff --git a/build/lib/fetch.js b/build/lib/fetch.js new file mode 100644 index 00000000000..e9a1362b50c --- /dev/null +++ b/build/lib/fetch.js @@ -0,0 +1,136 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.fetchGithub = exports.fetchUrl = exports.fetchUrls = void 0; +const es = require("event-stream"); +const node_fetch_1 = require("node-fetch"); +const VinylFile = require("vinyl"); +const log = require("fancy-log"); +const ansiColors = require("ansi-colors"); +const crypto = require("crypto"); +const through2 = require("through2"); +function fetchUrls(urls, options) { + if (options === undefined) { + options = {}; + } + if (typeof options.base !== 'string' && options.base !== null) { + options.base = '/'; + } + if (!Array.isArray(urls)) { + urls = [urls]; + } + return es.readArray(urls).pipe(es.map((data, cb) => { + const url = [options.base, data].join(''); + fetchUrl(url, options).then(file => { + cb(undefined, file); + }, error => { + cb(error); + }); + })); +} +exports.fetchUrls = fetchUrls; +async function fetchUrl(url, options, retries = 10, retryDelay = 1000) { + const verbose = !!options.verbose ?? (!!process.env['CI'] || !!process.env['BUILD_ARTIFACTSTAGINGDIRECTORY']); + try { + let startTime = 0; + if (verbose) { + log(`Start fetching ${ansiColors.magenta(url)}${retries !== 10 ? `(${10 - retries} retry}` : ''}`); + startTime = new Date().getTime(); + } + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 30 * 1000); + try { + const response = await (0, node_fetch_1.default)(url, { + ...options.nodeFetchOptions, + signal: controller.signal /* Typings issue with lib.dom.d.ts */ + }); + if (verbose) { + log(`Fetch completed: Status ${response.status}. Took ${ansiColors.magenta(`${new Date().getTime() - startTime} ms`)}`); + } + if (response.ok && (response.status >= 200 && response.status < 300)) { + const contents = await response.buffer(); + if (options.checksumSha256) { + const actualSHA256Checksum = crypto.createHash('sha256').update(contents).digest('hex'); + if (actualSHA256Checksum !== options.checksumSha256) { + throw new Error(`Checksum mismatch for ${ansiColors.cyan(url)} (expected ${options.checksumSha256}, actual ${actualSHA256Checksum}))`); + } + else if (verbose) { + log(`Verified SHA256 checksums match for ${ansiColors.cyan(url)}`); + } + } + else if (verbose) { + log(`Skipping checksum verification for ${ansiColors.cyan(url)} because no expected checksum was provided`); + } + if (verbose) { + log(`Fetched response body buffer: ${ansiColors.magenta(`${contents.byteLength} bytes`)}`); + } + return new VinylFile({ + cwd: '/', + base: options.base, + path: url, + contents + }); + } + throw new Error(`Request ${ansiColors.magenta(url)} failed with status code: ${response.status}`); + } + finally { + clearTimeout(timeout); + } + } + catch (e) { + if (verbose) { + log(`Fetching ${ansiColors.cyan(url)} failed: ${e}`); + } + if (retries > 0) { + await new Promise(resolve => setTimeout(resolve, retryDelay)); + return fetchUrl(url, options, retries - 1, retryDelay); + } + throw e; + } +} +exports.fetchUrl = fetchUrl; +const ghApiHeaders = { + Accept: 'application/vnd.github.v3+json', + 'User-Agent': 'VSCode Build', +}; +if (process.env.GITHUB_TOKEN) { + ghApiHeaders.Authorization = 'Basic ' + Buffer.from(process.env.GITHUB_TOKEN).toString('base64'); +} +const ghDownloadHeaders = { + ...ghApiHeaders, + Accept: 'application/octet-stream', +}; +/** + * @param repo for example `Microsoft/vscode` + * @param version for example `16.17.1` - must be a valid releases tag + * @param assetName for example (name) => name === `win-x64-node.exe` - must be an asset that exists + * @returns a stream with the asset as file + */ +function fetchGithub(repo, options) { + return fetchUrls(`/repos/${repo.replace(/^\/|\/$/g, '')}/releases/tags/v${options.version}`, { + base: 'https://api.github.com', + verbose: options.verbose, + nodeFetchOptions: { headers: ghApiHeaders } + }).pipe(through2.obj(async function (file, _enc, callback) { + const assetFilter = typeof options.name === 'string' ? (name) => name === options.name : options.name; + const asset = JSON.parse(file.contents.toString()).assets.find((a) => assetFilter(a.name)); + if (!asset) { + return callback(new Error(`Could not find asset in release of ${repo} @ ${options.version}`)); + } + try { + callback(null, await fetchUrl(asset.url, { + nodeFetchOptions: { headers: ghDownloadHeaders }, + verbose: options.verbose, + checksumSha256: options.checksumSha256 + })); + } + catch (error) { + callback(error); + } + })); +} +exports.fetchGithub = fetchGithub; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmV0Y2guanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJmZXRjaC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztnR0FHZ0c7OztBQUVoRyxtQ0FBbUM7QUFDbkMsMkNBQWdEO0FBQ2hELG1DQUFtQztBQUNuQyxpQ0FBaUM7QUFDakMsMENBQTBDO0FBQzFDLGlDQUFpQztBQUNqQyxxQ0FBcUM7QUFVckMsU0FBZ0IsU0FBUyxDQUFDLElBQXVCLEVBQUUsT0FBc0I7SUFDeEUsSUFBSSxPQUFPLEtBQUssU0FBUyxFQUFFO1FBQzFCLE9BQU8sR0FBRyxFQUFFLENBQUM7S0FDYjtJQUVELElBQUksT0FBTyxPQUFPLENBQUMsSUFBSSxLQUFLLFFBQVEsSUFBSSxPQUFPLENBQUMsSUFBSSxLQUFLLElBQUksRUFBRTtRQUM5RCxPQUFPLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQztLQUNuQjtJQUVELElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFO1FBQ3pCLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0tBQ2Q7SUFFRCxPQUFPLEVBQUUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQTJCLENBQUMsSUFBWSxFQUFFLEVBQUUsRUFBRSxFQUFFO1FBQ3BGLE1BQU0sR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDMUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDbEMsRUFBRSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNyQixDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUU7WUFDVixFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDWCxDQUFDLENBQUMsQ0FBQztJQUNKLENBQUMs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 \ No newline at end of file diff --git a/build/lib/fetch.ts b/build/lib/fetch.ts new file mode 100644 index 00000000000..238f0ac4228 --- /dev/null +++ b/build/lib/fetch.ts @@ -0,0 +1,147 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as es from 'event-stream'; +import fetch, { RequestInit } from 'node-fetch'; +import * as VinylFile from 'vinyl'; +import * as log from 'fancy-log'; +import * as ansiColors from 'ansi-colors'; +import * as crypto from 'crypto'; +import * as through2 from 'through2'; +import { Stream } from 'stream'; + +export interface IFetchOptions { + base?: string; + nodeFetchOptions?: RequestInit; + verbose?: boolean; + checksumSha256?: string; +} + +export function fetchUrls(urls: string[] | string, options: IFetchOptions): es.ThroughStream { + if (options === undefined) { + options = {}; + } + + if (typeof options.base !== 'string' && options.base !== null) { + options.base = '/'; + } + + if (!Array.isArray(urls)) { + urls = [urls]; + } + + return es.readArray(urls).pipe(es.map((data: string, cb) => { + const url = [options.base, data].join(''); + fetchUrl(url, options).then(file => { + cb(undefined, file); + }, error => { + cb(error); + }); + })); +} + +export async function fetchUrl(url: string, options: IFetchOptions, retries = 10, retryDelay = 1000): Promise { + const verbose = !!options.verbose ?? (!!process.env['CI'] || !!process.env['BUILD_ARTIFACTSTAGINGDIRECTORY']); + try { + let startTime = 0; + if (verbose) { + log(`Start fetching ${ansiColors.magenta(url)}${retries !== 10 ? `(${10 - retries} retry}` : ''}`); + startTime = new Date().getTime(); + } + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 30 * 1000); + try { + const response = await fetch(url, { + ...options.nodeFetchOptions, + signal: controller.signal as any /* Typings issue with lib.dom.d.ts */ + }); + if (verbose) { + log(`Fetch completed: Status ${response.status}. Took ${ansiColors.magenta(`${new Date().getTime() - startTime} ms`)}`); + } + if (response.ok && (response.status >= 200 && response.status < 300)) { + const contents = await response.buffer(); + if (options.checksumSha256) { + const actualSHA256Checksum = crypto.createHash('sha256').update(contents).digest('hex'); + if (actualSHA256Checksum !== options.checksumSha256) { + throw new Error(`Checksum mismatch for ${ansiColors.cyan(url)} (expected ${options.checksumSha256}, actual ${actualSHA256Checksum}))`); + } else if (verbose) { + log(`Verified SHA256 checksums match for ${ansiColors.cyan(url)}`); + } + } else if (verbose) { + log(`Skipping checksum verification for ${ansiColors.cyan(url)} because no expected checksum was provided`); + } + if (verbose) { + log(`Fetched response body buffer: ${ansiColors.magenta(`${(contents as Buffer).byteLength} bytes`)}`); + } + return new VinylFile({ + cwd: '/', + base: options.base, + path: url, + contents + }); + } + throw new Error(`Request ${ansiColors.magenta(url)} failed with status code: ${response.status}`); + } finally { + clearTimeout(timeout); + } + } catch (e) { + if (verbose) { + log(`Fetching ${ansiColors.cyan(url)} failed: ${e}`); + } + if (retries > 0) { + await new Promise(resolve => setTimeout(resolve, retryDelay)); + return fetchUrl(url, options, retries - 1, retryDelay); + } + throw e; + } +} + +const ghApiHeaders: Record = { + Accept: 'application/vnd.github.v3+json', + 'User-Agent': 'VSCode Build', +}; +if (process.env.GITHUB_TOKEN) { + ghApiHeaders.Authorization = 'Basic ' + Buffer.from(process.env.GITHUB_TOKEN).toString('base64'); +} +const ghDownloadHeaders = { + ...ghApiHeaders, + Accept: 'application/octet-stream', +}; + +export interface IGitHubAssetOptions { + version: string; + name: string | ((name: string) => boolean); + checksumSha256?: string; + verbose?: boolean; +} + +/** + * @param repo for example `Microsoft/vscode` + * @param version for example `16.17.1` - must be a valid releases tag + * @param assetName for example (name) => name === `win-x64-node.exe` - must be an asset that exists + * @returns a stream with the asset as file + */ +export function fetchGithub(repo: string, options: IGitHubAssetOptions): Stream { + return fetchUrls(`/repos/${repo.replace(/^\/|\/$/g, '')}/releases/tags/v${options.version}`, { + base: 'https://api.github.com', + verbose: options.verbose, + nodeFetchOptions: { headers: ghApiHeaders } + }).pipe(through2.obj(async function (file, _enc, callback) { + const assetFilter = typeof options.name === 'string' ? (name: string) => name === options.name : options.name; + const asset = JSON.parse(file.contents.toString()).assets.find((a: { name: string }) => assetFilter(a.name)); + if (!asset) { + return callback(new Error(`Could not find asset in release of ${repo} @ ${options.version}`)); + } + try { + callback(null, await fetchUrl(asset.url, { + nodeFetchOptions: { headers: ghDownloadHeaders }, + verbose: options.verbose, + checksumSha256: options.checksumSha256 + })); + } catch (error) { + callback(error); + } + })); +} diff --git a/build/lib/github.js b/build/lib/github.js deleted file mode 100644 index 01b2cd2e3d1..00000000000 --- a/build/lib/github.js +++ /dev/null @@ -1,48 +0,0 @@ -"use strict"; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.assetFromGithub = void 0; -const node_fetch_1 = require("node-fetch"); -const gulpRemoteSource_1 = require("./gulpRemoteSource"); -const through2 = require("through2"); -const ghApiHeaders = { - Accept: 'application/vnd.github.v3+json', - 'User-Agent': 'VSCode Build', -}; -if (process.env.GITHUB_TOKEN) { - ghApiHeaders.Authorization = 'Basic ' + Buffer.from(process.env.GITHUB_TOKEN).toString('base64'); -} -const ghDownloadHeaders = { - ...ghApiHeaders, - Accept: 'application/octet-stream', -}; -/** - * @param repo for example `Microsoft/vscode` - * @param version for example `16.17.1` - must be a valid releases tag - * @param assetName for example (name) => name === `win-x64-node.exe` - must be an asset that exists - * @returns a stream with the asset as file - */ -function assetFromGithub(repo, version, assetFilter) { - return (0, gulpRemoteSource_1.remote)(`/repos/${repo.replace(/^\/|\/$/g, '')}/releases/tags/v${version}`, { - base: 'https://api.github.com', - fetchOptions: { headers: ghApiHeaders } - }).pipe(through2.obj(async function (file, _enc, callback) { - const asset = JSON.parse(file.contents.toString()).assets.find((a) => assetFilter(a.name)); - if (!asset) { - return callback(new Error(`Could not find asset in release of ${repo} @ ${version}`)); - } - const response = await (0, node_fetch_1.default)(asset.url, { headers: ghDownloadHeaders }); - if (response.ok) { - file.contents = response.body.pipe(through2()); - callback(null, file); - } - else { - return callback(new Error(`Request ${response.url} failed with status code: ${response.status}`)); - } - })); -} -exports.assetFromGithub = assetFromGithub; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2l0aHViLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZ2l0aHViLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7O0FBR2hHLDJDQUErQjtBQUMvQix5REFBNEM7QUFDNUMscUNBQXFDO0FBRXJDLE1BQU0sWUFBWSxHQUEyQjtJQUM1QyxNQUFNLEVBQUUsZ0NBQWdDO0lBQ3hDLFlBQVksRUFBRSxjQUFjO0NBQzVCLENBQUM7QUFDRixJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFO0lBQzdCLFlBQVksQ0FBQyxhQUFhLEdBQUcsUUFBUSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7Q0FDakc7QUFDRCxNQUFNLGlCQUFpQixHQUFHO0lBQ3pCLEdBQUcsWUFBWTtJQUNmLE1BQU0sRUFBRSwwQkFBMEI7Q0FDbEMsQ0FBQztBQUVGOzs7OztHQUtHO0FBQ0gsU0FBZ0IsZUFBZSxDQUFDLElBQVksRUFBRSxPQUFlLEVBQUUsV0FBc0M7SUFDcEcsT0FBTyxJQUFBLHlCQUFNLEVBQUMsVUFBVSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsbUJBQW1CLE9BQU8sRUFBRSxFQUFFO1FBQ2pGLElBQUksRUFBRSx3QkFBd0I7UUFDOUIsWUFBWSxFQUFFLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRTtLQUN2QyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsS0FBSyxXQUFXLElBQUksRUFBRSxJQUFJLEVBQUUsUUFBUTtRQUN4RCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBbUIsRUFBRSxFQUFFLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQzdHLElBQUksQ0FBQyxLQUFLLEVBQUU7WUFDWCxPQUFPLFFBQVEsQ0FBQyxJQUFJLEtBQUssQ0FBQyxzQ0FBc0MsSUFBSSxNQUFNLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQztTQUN0RjtRQUNELE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBQSxvQkFBSyxFQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsRUFBRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsQ0FBQyxDQUFDO1FBQ3hFLElBQUksUUFBUSxDQUFDLEVBQUUsRUFBRTtZQUNoQixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7WUFDL0MsUUFBUSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztTQUNyQjthQUFNO1lBQ04sT0FBTyxRQUFRLENBQUMsSUFBSSxLQUFLLENBQUMsV0FBVyxRQUFRLENBQUMsR0FBRyw2QkFBNkIsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztTQUNsRztJQUVGLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBbEJELDBDQWtCQyJ9 \ No newline at end of file diff --git a/build/lib/github.ts b/build/lib/github.ts deleted file mode 100644 index c9a457e49ab..00000000000 --- a/build/lib/github.ts +++ /dev/null @@ -1,47 +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 { Stream } from 'stream'; -import fetch from 'node-fetch'; -import { remote } from './gulpRemoteSource'; -import * as through2 from 'through2'; - -const ghApiHeaders: Record = { - Accept: 'application/vnd.github.v3+json', - 'User-Agent': 'VSCode Build', -}; -if (process.env.GITHUB_TOKEN) { - ghApiHeaders.Authorization = 'Basic ' + Buffer.from(process.env.GITHUB_TOKEN).toString('base64'); -} -const ghDownloadHeaders = { - ...ghApiHeaders, - Accept: 'application/octet-stream', -}; - -/** - * @param repo for example `Microsoft/vscode` - * @param version for example `16.17.1` - must be a valid releases tag - * @param assetName for example (name) => name === `win-x64-node.exe` - must be an asset that exists - * @returns a stream with the asset as file - */ -export function assetFromGithub(repo: string, version: string, assetFilter: (name: string) => boolean): Stream { - return remote(`/repos/${repo.replace(/^\/|\/$/g, '')}/releases/tags/v${version}`, { - base: 'https://api.github.com', - fetchOptions: { headers: ghApiHeaders } - }).pipe(through2.obj(async function (file, _enc, callback) { - const asset = JSON.parse(file.contents.toString()).assets.find((a: { name: string }) => assetFilter(a.name)); - if (!asset) { - return callback(new Error(`Could not find asset in release of ${repo} @ ${version}`)); - } - const response = await fetch(asset.url, { headers: ghDownloadHeaders }); - if (response.ok) { - file.contents = response.body.pipe(through2()); - callback(null, file); - } else { - return callback(new Error(`Request ${response.url} failed with status code: ${response.status}`)); - } - - })); -} diff --git a/build/lib/gulpRemoteSource.js b/build/lib/gulpRemoteSource.js deleted file mode 100644 index 25258f3c1e4..00000000000 --- a/build/lib/gulpRemoteSource.js +++ /dev/null @@ -1,84 +0,0 @@ -"use strict"; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.remote = void 0; -const es = require("event-stream"); -const node_fetch_1 = require("node-fetch"); -const VinylFile = require("vinyl"); -const through2 = require("through2"); -const log = require("fancy-log"); -const ansiColors = require("ansi-colors"); -function remote(urls, options) { - if (options === undefined) { - options = {}; - } - if (typeof options.base !== 'string' && options.base !== null) { - options.base = '/'; - } - if (typeof options.buffer !== 'boolean') { - options.buffer = true; - } - if (!Array.isArray(urls)) { - urls = [urls]; - } - return es.readArray(urls).pipe(es.map((data, cb) => { - const url = [options.base, data].join(''); - fetchWithRetry(url, options).then(file => { - cb(undefined, file); - }, error => { - cb(error); - }); - })); -} -exports.remote = remote; -async function fetchWithRetry(url, options, retries = 10, retryDelay = 1000) { - try { - let startTime = 0; - if (options.verbose) { - log(`Start fetching ${ansiColors.magenta(url)}${retries !== 10 ? `(${10 - retries} retry}` : ''}`); - startTime = new Date().getTime(); - } - const controller = new AbortController(); - const timeout = setTimeout(() => controller.abort(), 30 * 1000); - try { - const response = await (0, node_fetch_1.default)(url, { - ...options.fetchOptions, - signal: controller.signal /* Typings issue with lib.dom.d.ts */ - }); - if (options.verbose) { - log(`Fetch completed: Status ${response.status}. Took ${ansiColors.magenta(`${new Date().getTime() - startTime} ms`)}`); - } - if (response.ok && (response.status >= 200 && response.status < 300)) { - // request must be piped out once created, or we'll get this error: "You cannot pipe after data has been emitted from the response." - const contents = options.buffer ? await response.buffer() : response.body.pipe(through2()); - if (options.buffer && options.verbose) { - log(`Fetched response body buffer: ${ansiColors.magenta(`${contents.byteLength} bytes`)}`); - } - return new VinylFile({ - cwd: '/', - base: options.base, - path: url, - contents - }); - } - throw new Error(`Request ${ansiColors.magenta(url)} failed with status code: ${response.status}`); - } - finally { - clearTimeout(timeout); - } - } - catch (e) { - if (options.verbose) { - log(`Fetching ${ansiColors.cyan(url)} failed: ${e}`); - } - if (retries > 0) { - await new Promise(resolve => setTimeout(resolve, retryDelay)); - return fetchWithRetry(url, options, retries - 1, retryDelay); - } - throw e; - } -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3VscFJlbW90ZVNvdXJjZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImd1bHBSZW1vdGVTb3VyY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Z0dBR2dHOzs7QUFFaEcsbUNBQW1DO0FBQ25DLDJDQUFnRDtBQUNoRCxtQ0FBbUM7QUFDbkMscUNBQXFDO0FBQ3JDLGlDQUFpQztBQUNqQywwQ0FBMEM7QUFTMUMsU0FBZ0IsTUFBTSxDQUFDLElBQXVCLEVBQUUsT0FBaUI7SUFDaEUsSUFBSSxPQUFPLEtBQUssU0FBUyxFQUFFO1FBQzFCLE9BQU8sR0FBRyxFQUFFLENBQUM7S0FDYjtJQUVELElBQUksT0FBTyxPQUFPLENBQUMsSUFBSSxLQUFLLFFBQVEsSUFBSSxPQUFPLENBQUMsSUFBSSxLQUFLLElBQUksRUFBRTtRQUM5RCxPQUFPLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQztLQUNuQjtJQUVELElBQUksT0FBTyxPQUFPLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRTtRQUN4QyxPQUFPLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztLQUN0QjtJQUVELElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFO1FBQ3pCLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0tBQ2Q7SUFFRCxPQUFPLEVBQUUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQTJCLENBQUMsSUFBWSxFQUFFLEVBQUUsRUFBRSxFQUFFO1FBQ3BGLE1BQU0sR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDMUMsY0FBYyxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDeEMsRUFBRSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMs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 \ No newline at end of file diff --git a/build/lib/gulpRemoteSource.ts b/build/lib/gulpRemoteSource.ts deleted file mode 100644 index c39891a60b1..00000000000 --- a/build/lib/gulpRemoteSource.ts +++ /dev/null @@ -1,95 +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 * as es from 'event-stream'; -import fetch, { RequestInit } from 'node-fetch'; -import * as VinylFile from 'vinyl'; -import * as through2 from 'through2'; -import * as log from 'fancy-log'; -import * as ansiColors from 'ansi-colors'; - -export interface IOptions { - base?: string; - buffer?: boolean; - fetchOptions?: RequestInit; - verbose?: boolean; -} - -export function remote(urls: string[] | string, options: IOptions): es.ThroughStream { - if (options === undefined) { - options = {}; - } - - if (typeof options.base !== 'string' && options.base !== null) { - options.base = '/'; - } - - if (typeof options.buffer !== 'boolean') { - options.buffer = true; - } - - if (!Array.isArray(urls)) { - urls = [urls]; - } - - return es.readArray(urls).pipe(es.map((data: string, cb) => { - const url = [options.base, data].join(''); - fetchWithRetry(url, options).then(file => { - cb(undefined, file); - }, error => { - cb(error); - }); - })); -} - -async function fetchWithRetry(url: string, options: IOptions, retries = 10, retryDelay = 1000): Promise { - try { - let startTime = 0; - if (options.verbose) { - log(`Start fetching ${ansiColors.magenta(url)}${retries !== 10 ? `(${10 - retries} retry}` : ''}`); - startTime = new Date().getTime(); - } - const controller = new AbortController(); - const timeout = setTimeout(() => controller.abort(), 30 * 1000); - try { - const response = await fetch(url, { - ...options.fetchOptions, - signal: controller.signal as any /* Typings issue with lib.dom.d.ts */ - }); - if (options.verbose) { - log(`Fetch completed: Status ${response.status}. Took ${ansiColors.magenta(`${new Date().getTime() - startTime} ms`)}`); - } - if (response.ok && (response.status >= 200 && response.status < 300)) { - // request must be piped out once created, or we'll get this error: "You cannot pipe after data has been emitted from the response." - const contents = options.buffer ? await response.buffer() : response.body.pipe(through2()); - if (options.buffer && options.verbose) { - log(`Fetched response body buffer: ${ansiColors.magenta(`${(contents as Buffer).byteLength} bytes`)}`); - } - return new VinylFile({ - cwd: '/', - base: options.base, - path: url, - contents - }); - } - throw new Error(`Request ${ansiColors.magenta(url)} failed with status code: ${response.status}`); - } finally { - clearTimeout(timeout); - } - } catch (e) { - if (options.verbose) { - log(`Fetching ${ansiColors.cyan(url)} failed: ${e}`); - } - if (retries > 0) { - await new Promise(resolve => setTimeout(resolve, retryDelay)); - return fetchWithRetry(url, options, retries - 1, retryDelay); - } - throw e; - } -} - - - - diff --git a/product.json b/product.json index f801597290e..51d2bfe00d6 100644 --- a/product.json +++ b/product.json @@ -36,6 +36,7 @@ { "name": "ms-vscode.js-debug-companion", "version": "1.0.18", + "sha256": "b49ee134f452c88fe3de09ae62b7f77aa66d1d6dcd794c48e065bdc2c74d4a30", "repo": "https://github.com/microsoft/vscode-js-debug-companion", "metadata": { "id": "99cb0b7f-7354-4278-b8da-6cc79972169d", @@ -51,6 +52,7 @@ { "name": "ms-vscode.js-debug", "version": "1.78.0", + "sha256": "9fbf0c15394fb436a4079b5f704d2718d305828be178b1219db85a9287e24870", "repo": "https://github.com/microsoft/vscode-js-debug", "metadata": { "id": "25629058-ddac-4e17-abba-74678e126c5d", @@ -66,6 +68,7 @@ { "name": "ms-vscode.vscode-js-profile-table", "version": "1.0.3", + "sha256": "b9dab017506d9e6a469a0f82b392e4cb1d7a25a4843f1db8ba396cbee209cfc5", "repo": "https://github.com/microsoft/vscode-js-profile-visualizer", "metadata": { "id": "7e52b41b-71ad-457b-ab7e-0620f1fc4feb", @@ -78,5 +81,9 @@ "publisherDisplayName": "Microsoft" } } - ] + ], + "nodejs": { + "repository": "https://nodejs.org", + "version": "16.17.1" + } } diff --git a/src/vs/platform/product/common/product.ts b/src/vs/platform/product/common/product.ts index 51a55e1b840..3be5dc01184 100644 --- a/src/vs/platform/product/common/product.ts +++ b/src/vs/platform/product/common/product.ts @@ -58,7 +58,7 @@ else { // Running out of sources if (Object.keys(product).length === 0) { Object.assign(product, { - version: '1.78.0-dev', + version: '1.80.0-dev', nameShort: 'Code - OSS Dev', nameLong: 'Code - OSS Dev', applicationName: 'code-oss', From e1d89c9e9d41ccee135e03d892cd5c3ac4028143 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 14 Jun 2023 17:24:15 +0200 Subject: [PATCH 125/128] :up: distro (#185133) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 412d99ebf22..2acdfbe5926 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.80.0", - "distro": "c523cf770e3f05498d5d51a3d7d1dd2d04375276", + "distro": "a44605dbeeed7ad5c41513260004329c4f502793", "author": { "name": "Microsoft Corporation" }, From e209a1c94ab97ef74b23ea22019b3ef699b94240 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 14 Jun 2023 17:40:33 +0200 Subject: [PATCH 126/128] skip `Error.prepareStackTrace` unit test for firefox and safari that don't support this (#185134) --- src/vs/workbench/api/test/common/extensionHostMain.test.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vs/workbench/api/test/common/extensionHostMain.test.ts b/src/vs/workbench/api/test/common/extensionHostMain.test.ts index 0fe1f5b783d..52b49352d81 100644 --- a/src/vs/workbench/api/test/common/extensionHostMain.test.ts +++ b/src/vs/workbench/api/test/common/extensionHostMain.test.ts @@ -5,6 +5,7 @@ import * as assert from 'assert'; import { SerializedError, errorHandler, onUnexpectedError } from 'vs/base/common/errors'; +import { isFirefox, isSafari } from 'vs/base/common/platform'; import { TernarySearchTree } from 'vs/base/common/ternarySearchTree'; import { URI } from 'vs/base/common/uri'; import { mock } from 'vs/base/test/common/mock'; @@ -23,6 +24,10 @@ import { ProxyIdentifier, Proxied } from 'vs/workbench/services/extensions/commo suite('ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 ', function () { + if (isFirefox || isSafari) { + return; + } + const extensionsIndex = TernarySearchTree.forUris(); const mainThreadExtensionsService = new class extends mock() { override $onExtensionRuntimeError(extensionId: ExtensionIdentifier, data: SerializedError): void { From 9130ebd22aa208dacc6fc12ccc84317ac5a15e4c Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 14 Jun 2023 10:08:17 -0700 Subject: [PATCH 127/128] Ensure pty host only adds --inspect when a port is set Fixes #185033 --- .../electron-main/electronPtyHostStarter.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/vs/platform/terminal/electron-main/electronPtyHostStarter.ts b/src/vs/platform/terminal/electron-main/electronPtyHostStarter.ts index 963ed887aa7..72ab9b51824 100644 --- a/src/vs/platform/terminal/electron-main/electronPtyHostStarter.ts +++ b/src/vs/platform/terminal/electron-main/electronPtyHostStarter.ts @@ -42,15 +42,10 @@ export class ElectronPtyHostStarter implements IPtyHostStarter { this.utilityProcess = new UtilityProcess(this._logService, NullTelemetryService, this._lifecycleMainService); const inspectParams = parsePtyHostDebugPort(this._environmentService.args, this._environmentService.isBuilt); - let execArgv: string[] | undefined = undefined; - if (inspectParams) { - execArgv = ['--nolazy']; - if (inspectParams.break) { - execArgv.push(`--inspect-brk=${inspectParams.port}`); - } else if (!inspectParams.break) { - execArgv.push(`--inspect=${inspectParams.port}`); - } - } + const execArgv = inspectParams.port ? [ + '--nolazy', + `--inspect${inspectParams.break ? '-brk' : ''}=${inspectParams.port}` + ] : undefined; this.utilityProcess.start({ type: 'ptyHost', From 9e5edb7d9ab64e0c5fec481e6b6320aa093a9de0 Mon Sep 17 00:00:00 2001 From: John Murray Date: Wed, 14 Jun 2023 18:23:37 +0100 Subject: [PATCH 128/128] Allow downloads from pages viewed in Simple Browser (#185117) --- extensions/simple-browser/src/simpleBrowserView.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/simple-browser/src/simpleBrowserView.ts b/extensions/simple-browser/src/simpleBrowserView.ts index eb842f6f104..5725dcf4f9b 100644 --- a/extensions/simple-browser/src/simpleBrowserView.ts +++ b/extensions/simple-browser/src/simpleBrowserView.ts @@ -165,7 +165,7 @@ export class SimpleBrowserView extends Disposable {
${vscode.l10n.t("Focus Lock")}
- +