Merge from vscode 79a1f5a5ca0c6c53db617aa1fa5a2396d2caebe2

This commit is contained in:
ADS Merger
2020-05-31 19:47:51 +00:00
parent 84492049e8
commit 28be33cfea
913 changed files with 28242 additions and 15549 deletions

View File

@@ -6,7 +6,7 @@
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { NativeBackupTracker } from 'vs/workbench/contrib/backup/electron-browser/backupTracker';
import { NativeBackupTracker } from 'vs/workbench/contrib/backup/electron-sandbox/backupTracker';
// Register Backup Tracker
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(NativeBackupTracker, LifecyclePhase.Starting);

View File

@@ -14,7 +14,7 @@ import Severity from 'vs/base/common/severity';
import { WorkbenchState, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { isMacintosh } from 'vs/base/common/platform';
import { HotExitConfiguration } from 'vs/platform/files/common/files';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
import { BackupTracker } from 'vs/workbench/contrib/backup/common/backupTracker';
import { ILogService } from 'vs/platform/log/common/log';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';

View File

@@ -13,7 +13,7 @@ import { createTextBufferFactory } from 'vs/editor/common/model/textModel';
import { getRandomTestPath } from 'vs/base/test/node/testUtils';
import { DefaultEndOfLine } from 'vs/editor/common/model';
import { hashPath } from 'vs/workbench/services/backup/node/backupFileService';
import { NativeBackupTracker } from 'vs/workbench/contrib/backup/electron-browser/backupTracker';
import { NativeBackupTracker } from 'vs/workbench/contrib/backup/electron-sandbox/backupTracker';
import { workbenchInstantiationService } from 'vs/workbench/test/electron-browser/workbenchTestServices';
import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';

View File

@@ -11,7 +11,7 @@ import * as pfs from 'vs/base/node/pfs';
import { URI } from 'vs/base/common/uri';
import { getRandomTestPath } from 'vs/base/test/node/testUtils';
import { hashPath } from 'vs/workbench/services/backup/node/backupFileService';
import { NativeBackupTracker } from 'vs/workbench/contrib/backup/electron-browser/backupTracker';
import { NativeBackupTracker } from 'vs/workbench/contrib/backup/electron-sandbox/backupTracker';
import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart';
@@ -34,7 +34,7 @@ import { HotExitConfiguration } from 'vs/platform/files/common/files';
import { ShutdownReason, ILifecycleService, BeforeShutdownEvent } from 'vs/platform/lifecycle/common/lifecycle';
import { IFileDialogService, ConfirmResult, IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IWorkspaceContextService, Workspace } from 'vs/platform/workspace/common/workspace';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
import { BackupTracker } from 'vs/workbench/contrib/backup/common/backupTracker';
import { workbenchInstantiationService, TestServiceAccessor } from 'vs/workbench/test/electron-browser/workbenchTestServices';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';

View File

@@ -70,10 +70,10 @@
min-width: 16px;
}
.vs-dark .monaco-workbench .bulk-edit-panel .monaco-tl-contents.category .uri-icon,
.hc-black .monaco-workbench .bulk-edit-panel .monaco-tl-contents.category .uri-icon,
.vs-dark .monaco-workbench .bulk-edit-panel .monaco-tl-contents.textedit .uri-icon,
.hc-black .monaco-workbench .bulk-edit-panel .monaco-tl-contents.textedit .uri-icon
.monaco-workbench.vs-dark .bulk-edit-panel .monaco-tl-contents.category .uri-icon,
.monaco-workbench.hc-black .bulk-edit-panel .monaco-tl-contents.category .uri-icon,
.monaco-workbench.vs-dark .bulk-edit-panel .monaco-tl-contents.textedit .uri-icon,
.monaco-workbench.hc-black .bulk-edit-panel .monaco-tl-contents.textedit .uri-icon
{
background-image: var(--background-dark);
}

View File

@@ -20,6 +20,7 @@ import { IIdentifiedSingleEditOperation } from 'vs/editor/common/model';
import { ConflictDetector } from 'vs/workbench/services/bulkEdit/browser/conflicts';
import { ResourceMap } from 'vs/base/common/map';
import { localize } from 'vs/nls';
import { extUri } from 'vs/base/common/resources';
export class CheckedStates<T extends object> {
@@ -209,13 +210,13 @@ export class BulkFileOperations {
}
const insert = (uri: URI, map: Map<string, BulkFileOperation>) => {
let key = uri.toString();
let key = extUri.getComparisonKey(uri, true);
let operation = map.get(key);
// rename
if (!operation && newToOldUri.has(uri)) {
uri = newToOldUri.get(uri)!;
key = uri.toString();
key = extUri.getComparisonKey(uri, true);
operation = map.get(key);
}

View File

@@ -350,6 +350,10 @@ export abstract class SimpleFindReplaceWidget extends Widget {
}, 0);
}
public focus(): void {
this._findInput.focus();
}
public show(initialInput?: string): void {
if (initialInput && !this._isVisible) {
this._findInput.setValue(initialInput);
@@ -361,6 +365,8 @@ export abstract class SimpleFindReplaceWidget extends Widget {
dom.addClass(this._domNode, 'visible');
dom.addClass(this._domNode, 'visible-transition');
this._domNode.setAttribute('aria-hidden', 'false');
this.focus();
}, 0);
}

View File

@@ -14,17 +14,18 @@ import { AbstractGotoSymbolQuickAccessProvider, IGotoSymbolQuickPickItem } from
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IWorkbenchEditorConfiguration, IEditorPane } from 'vs/workbench/common/editor';
import { ITextModel } from 'vs/editor/common/model';
import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { DisposableStore, IDisposable, toDisposable, Disposable } from 'vs/base/common/lifecycle';
import { timeout } from 'vs/base/common/async';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { Action } from 'vs/base/common/actions';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { registerAction2, Action2 } from 'vs/platform/actions/common/actions';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { prepareQuery } from 'vs/base/common/fuzzyScorer';
import { SymbolKind } from 'vs/editor/common/modes';
import { fuzzyScore, createMatches } from 'vs/base/common/filters';
import { onUnexpectedError } from 'vs/base/common/errors';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccessProvider {
@@ -41,6 +42,13 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess
//#region DocumentSymbols (text editor required)
protected provideWithTextEditor(editor: IEditor, picker: IQuickPick<IGotoSymbolQuickPickItem>, token: CancellationToken): IDisposable {
if (this.canPickFromTableOfContents()) {
return this.doGetTableOfContentsPicks(picker);
}
return super.provideWithTextEditor(editor, picker, token);
}
private get configuration() {
const editorConfig = this.configurationService.getValue<IWorkbenchEditorConfiguration>().workbench.editor;
@@ -106,12 +114,21 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess
//#endregion
protected provideWithoutTextEditor(picker: IQuickPick<IGotoSymbolQuickPickItem>): IDisposable {
const pane = this.editorService.activeEditorPane;
if (!pane || !TableOfContentsProviderRegistry.has(pane.getId())) {
//
return super.provideWithoutTextEditor(picker);
if (this.canPickFromTableOfContents()) {
return this.doGetTableOfContentsPicks(picker);
}
return super.provideWithoutTextEditor(picker);
}
private canPickFromTableOfContents(): boolean {
return this.editorService.activeEditorPane ? TableOfContentsProviderRegistry.has(this.editorService.activeEditorPane.getId()) : false;
}
private doGetTableOfContentsPicks(picker: IQuickPick<IGotoSymbolQuickPickItem>): IDisposable {
const pane = this.editorService.activeEditorPane;
if (!pane) {
return Disposable.None;
}
const provider = TableOfContentsProviderRegistry.get(pane.getId())!;
const cts = new CancellationTokenSource();
@@ -133,7 +150,8 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess
kind: SymbolKind.File,
index: idx,
score: 0,
label: entry.label,
label: entry.icon ? `$(${entry.icon.id}) ${entry.label}` : entry.label,
ariaLabel: entry.detail ? `${entry.label}, ${entry.detail}` : entry.label,
detail: entry.detail,
description: entry.description,
};
@@ -142,7 +160,7 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess
disposables.add(picker.onDidAccept(() => {
picker.hide();
const [entry] = picker.selectedItems;
entries[entry.index]?.reveal();
entries[entry.index]?.pick();
}));
const updatePickerItems = () => {
@@ -175,14 +193,11 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess
let ignoreFirstActiveEvent = true;
disposables.add(picker.onDidChangeActive(() => {
const [entry] = picker.activeItems;
if (entry && entries[entry.index]) {
if (ignoreFirstActiveEvent) {
ignoreFirstActiveEvent = false;
return;
if (!ignoreFirstActiveEvent) {
entries[entry.index]?.preview();
}
entries[entry.index]?.reveal();
ignoreFirstActiveEvent = false;
}
}));
@@ -206,36 +221,38 @@ Registry.as<IQuickAccessRegistry>(QuickaccessExtensions.Quickaccess).registerQui
]
});
export class GotoSymbolAction extends Action {
registerAction2(class GotoSymbolAction extends Action2 {
static readonly ID = 'workbench.action.gotoSymbol';
static readonly LABEL = localize('gotoSymbol', "Go to Symbol in Editor...");
constructor(
id: string,
label: string,
@IQuickInputService private readonly quickInputService: IQuickInputService
) {
super(id, label);
constructor() {
super({
id: 'workbench.action.gotoSymbol',
title: {
value: localize('gotoSymbol', "Go to Symbol in Editor..."),
original: 'Go to Symbol in Editor...'
},
f1: true,
keybinding: {
when: undefined,
weight: KeybindingWeight.WorkbenchContrib,
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_O
}
});
}
async run(): Promise<void> {
this.quickInputService.quickAccess.show(GotoSymbolQuickAccessProvider.PREFIX);
run(accessor: ServicesAccessor) {
accessor.get(IQuickInputService).quickAccess.show(GotoSymbolQuickAccessProvider.PREFIX);
}
}
Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions).registerWorkbenchAction(SyncActionDescriptor.from(GotoSymbolAction, {
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_O
}), 'Go to Symbol in Editor...');
});
//#region toc definition and logic
export interface ITableOfContentsEntry {
icon?: ThemeIcon;
label: string;
detail?: string;
description?: string;
reveal(): any;
pick(): any;
preview(): any;
}
export interface ITableOfContentsProvider<T extends IEditorPane = IEditorPane> {

View File

@@ -311,7 +311,7 @@ function getSuggestEnabledInputOptions(ariaLabel?: string): IEditorOptions {
roundedSelection: false,
renderIndentGuides: false,
cursorWidth: 1,
fontFamily: ' -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif',
fontFamily: ' system-ui, -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif',
ariaLabel: ariaLabel || '',
snippetSuggestions: 'none',

View File

@@ -47,31 +47,31 @@ export class ToggleColumnSelectionAction extends Action {
if (!codeEditor || codeEditor !== this._getCodeEditor() || oldValue === newValue || !codeEditor.hasModel()) {
return;
}
const cursors = codeEditor._getCursors();
const viewModel = codeEditor._getViewModel();
if (codeEditor.getOption(EditorOption.columnSelection)) {
const selection = codeEditor.getSelection();
const modelSelectionStart = new Position(selection.selectionStartLineNumber, selection.selectionStartColumn);
const viewSelectionStart = cursors.context.convertModelPositionToViewPosition(modelSelectionStart);
const viewSelectionStart = viewModel.coordinatesConverter.convertModelPositionToViewPosition(modelSelectionStart);
const modelPosition = new Position(selection.positionLineNumber, selection.positionColumn);
const viewPosition = cursors.context.convertModelPositionToViewPosition(modelPosition);
const viewPosition = viewModel.coordinatesConverter.convertModelPositionToViewPosition(modelPosition);
CoreNavigationCommands.MoveTo.runCoreEditorCommand(cursors, {
CoreNavigationCommands.MoveTo.runCoreEditorCommand(viewModel, {
position: modelSelectionStart,
viewPosition: viewSelectionStart
});
const visibleColumn = CursorColumns.visibleColumnFromColumn2(cursors.context.config, cursors.context.viewModel, viewPosition);
CoreNavigationCommands.ColumnSelect.runCoreEditorCommand(cursors, {
const visibleColumn = CursorColumns.visibleColumnFromColumn2(viewModel.cursorConfig, viewModel, viewPosition);
CoreNavigationCommands.ColumnSelect.runCoreEditorCommand(viewModel, {
position: modelPosition,
viewPosition: viewPosition,
doColumnSelect: true,
mouseColumn: visibleColumn + 1
});
} else {
const columnSelectData = cursors.getColumnSelectData();
const fromViewColumn = CursorColumns.columnFromVisibleColumn2(cursors.context.config, cursors.context.viewModel, columnSelectData.fromViewLineNumber, columnSelectData.fromViewVisualColumn);
const fromPosition = cursors.context.convertViewPositionToModelPosition(columnSelectData.fromViewLineNumber, fromViewColumn);
const toViewColumn = CursorColumns.columnFromVisibleColumn2(cursors.context.config, cursors.context.viewModel, columnSelectData.toViewLineNumber, columnSelectData.toViewVisualColumn);
const toPosition = cursors.context.convertViewPositionToModelPosition(columnSelectData.toViewLineNumber, toViewColumn);
const columnSelectData = viewModel.getCursorColumnSelectData();
const fromViewColumn = CursorColumns.columnFromVisibleColumn2(viewModel.cursorConfig, viewModel, columnSelectData.fromViewLineNumber, columnSelectData.fromViewVisualColumn);
const fromPosition = viewModel.coordinatesConverter.convertViewPositionToModelPosition(new Position(columnSelectData.fromViewLineNumber, fromViewColumn));
const toViewColumn = CursorColumns.columnFromVisibleColumn2(viewModel.cursorConfig, viewModel, columnSelectData.toViewLineNumber, columnSelectData.toViewVisualColumn);
const toPosition = viewModel.coordinatesConverter.convertViewPositionToModelPosition(new Position(columnSelectData.toViewLineNumber, toViewColumn));
codeEditor.setSelection(new Selection(fromPosition.lineNumber, fromPosition.column, toPosition.lineNumber, toPosition.column));
}

View File

@@ -3,7 +3,4 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import './inputClipboardActions';
import './sleepResumeRepaintMinimap';
import './selectionClipboard';
import './startDebugTextMate';

View File

@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import * as os from 'os';
import * as path from 'path';
import * as nls from 'vs/nls';
import { Range } from 'vs/editor/common/core/range';
@@ -22,6 +21,7 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService
import { ITextModel } from 'vs/editor/common/model';
import { Constants } from 'vs/base/common/uint';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { join } from 'vs/base/common/path';
class StartDebugTextMate extends Action {
@@ -59,7 +59,7 @@ class StartDebugTextMate extends Action {
}
public async run(): Promise<any> {
const pathInTemp = path.join(os.tmpdir(), `vcode-tm-log-${generateUuid()}.txt`);
const pathInTemp = join(os.tmpdir(), `vcode-tm-log-${generateUuid()}.txt`);
const logger = createRotatingLogger(`tm-log`, pathInTemp, 1024 * 1024 * 30, 1);
const model = this._getOrCreateModel();
const append = (str: string) => {

View File

@@ -0,0 +1,8 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import './inputClipboardActions';
import './selectionClipboard';
import './sleepResumeRepaintMinimap';

View File

@@ -6,7 +6,7 @@
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { Registry } from 'vs/platform/registry/common/platform';
import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import { ipcRenderer as ipc } from 'electron';
import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
class SleepResumeRepaintMinimap implements IWorkbenchContribution {
@@ -14,7 +14,7 @@ class SleepResumeRepaintMinimap implements IWorkbenchContribution {
constructor(
@ICodeEditorService codeEditorService: ICodeEditorService
) {
ipc.on('vscode:osResume', () => {
ipcRenderer.on('vscode:osResume', () => {
codeEditorService.listCodeEditors().forEach(editor => editor.render(true));
});
}

View File

@@ -33,6 +33,7 @@ import { ContextAwareMenuEntryActionViewItem } from 'vs/platform/actions/browser
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { CommentFormActions } from 'vs/workbench/contrib/comments/browser/commentFormActions';
import { MOUSE_CURSOR_TEXT_CSS_CLASS_NAME } from 'vs/base/browser/ui/mouseCursor/mouseCursor';
export class CommentNode extends Disposable {
private _domNode: HTMLElement;
@@ -100,7 +101,7 @@ export class CommentNode extends Disposable {
this.createHeader(this._commentDetailsContainer);
this._body = dom.append(this._commentDetailsContainer, dom.$('div.comment-body'));
this._body = dom.append(this._commentDetailsContainer, dom.$(`div.comment-body.${MOUSE_CURSOR_TEXT_CSS_CLASS_NAME}`));
this._md = this.markdownRenderer.render(comment.body).element;
this._body.appendChild(this._md);
@@ -120,7 +121,7 @@ export class CommentNode extends Disposable {
}
private createHeader(commentDetailsContainer: HTMLElement): void {
const header = dom.append(commentDetailsContainer, dom.$('div.comment-title'));
const header = dom.append(commentDetailsContainer, dom.$(`div.comment-title.${MOUSE_CURSOR_TEXT_CSS_CLASS_NAME}`));
const author = dom.append(header, dom.$('strong.author'));
author.innerText = this.comment.userName;

View File

@@ -48,6 +48,7 @@ import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { KeyCode } from 'vs/base/common/keyCodes';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { MOUSE_CURSOR_TEXT_CSS_CLASS_NAME } from 'vs/base/browser/ui/mouseCursor/mouseCursor';
export const COMMENTEDITOR_DECORATION_KEY = 'commenteditordecoration';
const COLLAPSE_ACTION_CLASS = 'expand-review-action codicon-chevron-up';
@@ -720,7 +721,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
}
private createReplyButton() {
this._reviewThreadReplyButton = <HTMLButtonElement>dom.append(this._commentForm, dom.$('button.review-thread-reply-button'));
this._reviewThreadReplyButton = <HTMLButtonElement>dom.append(this._commentForm, dom.$(`button.review-thread-reply-button.${MOUSE_CURSOR_TEXT_CSS_CLASS_NAME}`));
this._reviewThreadReplyButton.title = this._commentOptions?.prompt || nls.localize('reply', "Reply...");
this._reviewThreadReplyButton.textContent = this._commentOptions?.prompt || nls.localize('reply', "Reply...");

View File

@@ -257,7 +257,6 @@
line-height: 20px;
white-space: nowrap;
border: 0px;
cursor: text;
outline: 1px solid transparent;
}

View File

@@ -61,7 +61,8 @@ export class DefaultConfigurationExportHelper {
const processProperty = (name: string, prop: IConfigurationPropertySchema) => {
if (processedNames.has(name)) {
throw new Error('Setting is registered twice: ' + name);
console.warn('Setting is registered twice: ' + name);
return;
}
processedNames.add(name);

View File

@@ -97,9 +97,8 @@ export class CustomEditorInputFactory extends WebviewEditorInputFactory {
const webview = webviewService.createWebviewOverlay(data.id, {
enableFindWidget: data.options.enableFindWidget,
retainContextWhenHidden: data.options.retainContextWhenHidden
}, data.options);
}, data.options, data.extension);
webview.state = data.state;
webview.extension = data.extension;
return webview;
});
}

View File

@@ -17,9 +17,9 @@ import { EditorActivation, IEditorOptions, ITextEditorOptions } from 'vs/platfor
import { FileOperation, IFileService } from 'vs/platform/files/common/files';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
import { IStorageService } from 'vs/platform/storage/common/storage';
import * as colorRegistry from 'vs/platform/theme/common/colorRegistry';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { EditorServiceImpl } from 'vs/workbench/browser/parts/editor/editor';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { EditorInput, EditorOptions, GroupIdentifier, IEditorInput, IEditorPane } from 'vs/workbench/common/editor';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
@@ -37,7 +37,7 @@ import { CustomEditorInput } from './customEditorInput';
export class CustomEditorService extends Disposable implements ICustomEditorService, ICustomEditorViewTypesHandler {
_serviceBrand: any;
private readonly _contributedEditors = this._register(new ContributedCustomEditors());
private readonly _contributedEditors: ContributedCustomEditors;
private readonly _editorCapabilities = new Map<string, CustomEditorCapabilities>();
private readonly _models = new CustomEditorModelManager();
@@ -51,6 +51,7 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
constructor(
@IContextKeyService contextKeyService: IContextKeyService,
@IFileService fileService: IFileService,
@IStorageService storageService: IStorageService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IEditorService private readonly editorService: IEditorService,
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
@@ -64,11 +65,13 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
this._focusedCustomEditorIsEditable = CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE.bindTo(contextKeyService);
this._webviewHasOwnEditFunctions = webviewHasOwnEditFunctionsContext.bindTo(contextKeyService);
this._register(this.editorService.registerCustomEditorViewTypesHandler('Custom Editor', this));
this._contributedEditors = this._register(new ContributedCustomEditors(storageService));
this._register(this._contributedEditors.onChange(() => {
this.updateContexts();
this._onDidChangeViewTypes.fire();
}));
this._register(this.editorService.registerCustomEditorViewTypesHandler('Custom Editor', this));
this._register(this.editorService.onDidActiveEditorChange(() => this.updateContexts()));
this._register(fileService.onDidRunOperation(e => {
@@ -231,7 +234,7 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
const id = generateUuid();
const webview = new Lazy(() => {
return this.webviewService.createWebviewOverlay(id, { customClasses: options?.customClasses }, {});
return this.webviewService.createWebviewOverlay(id, { customClasses: options?.customClasses }, {}, undefined);
});
const input = this.instantiationService.createInstance(CustomEditorInput, resource, viewType, id, webview, {});
if (typeof group !== 'undefined') {
@@ -418,19 +421,23 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
export class CustomEditorContribution extends Disposable implements IWorkbenchContribution {
constructor(
@IEditorService private readonly editorService: EditorServiceImpl,
@IEditorService private readonly editorService: IEditorService,
@ICustomEditorService private readonly customEditorService: ICustomEditorService,
) {
super();
this._register(this.editorService.overrideOpenEditor({
open: (editor, options, group, id) => {
open: (editor, options, group, context, id) => {
return this.onEditorOpening(editor, options, group, id);
},
getEditorOverrides: (resource: URI, _options: IEditorOptions | undefined, group: IEditorGroup | undefined): IOpenEditorOverrideEntry[] => {
const currentEditor = group?.editors.find(editor => isEqual(editor.resource, resource));
const customEditors = this.customEditorService.getAllCustomEditors(resource);
if (!customEditors.length) {
return [];
}
return [
{
...defaultEditorOverrideEntry,

View File

@@ -8,9 +8,12 @@ import { Disposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import * as nls from 'vs/nls';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { CustomEditorInfo, CustomEditorPriority } from 'vs/workbench/contrib/customEditor/common/customEditor';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { Memento } from 'vs/workbench/common/memento';
import { CustomEditorDescriptor, CustomEditorInfo, CustomEditorPriority } from 'vs/workbench/contrib/customEditor/common/customEditor';
import { customEditorsExtensionPoint, ICustomEditorsExtensionPoint } from 'vs/workbench/contrib/customEditor/common/extensionPoint';
import { DEFAULT_EDITOR_ID } from 'vs/workbench/contrib/files/common/files';
import { IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry';
const builtinProviderDisplayName = nls.localize('builtinProviderDisplayName', "Built-in");
@@ -26,32 +29,52 @@ export const defaultCustomEditor = new CustomEditorInfo({
export class ContributedCustomEditors extends Disposable {
private readonly _editors = new Map<string, CustomEditorInfo>();
private static readonly CUSTOM_EDITORS_STORAGE_ID = 'customEditors';
private static readonly CUSTOM_EDITORS_ENTRY_ID = 'editors';
constructor() {
private readonly _editors = new Map<string, CustomEditorInfo>();
private readonly _memento: Memento;
constructor(storageService: IStorageService) {
super();
customEditorsExtensionPoint.setHandler(extensions => {
this._editors.clear();
this._memento = new Memento(ContributedCustomEditors.CUSTOM_EDITORS_STORAGE_ID, storageService);
for (const extension of extensions) {
for (const webviewEditorContribution of extension.value) {
this.add(new CustomEditorInfo({
id: webviewEditorContribution.viewType,
displayName: webviewEditorContribution.displayName,
providerDisplayName: extension.description.isBuiltin ? builtinProviderDisplayName : extension.description.displayName || extension.description.identifier.value,
selector: webviewEditorContribution.selector || [],
priority: getPriorityFromContribution(webviewEditorContribution, extension.description),
}));
}
}
this._onChange.fire();
const mementoObject = this._memento.getMemento(StorageScope.GLOBAL);
for (const info of (mementoObject[ContributedCustomEditors.CUSTOM_EDITORS_ENTRY_ID] || []) as CustomEditorDescriptor[]) {
this.add(new CustomEditorInfo(info));
}
customEditorsExtensionPoint.setHandler(extensions => {
this.update(extensions);
});
}
private readonly _onChange = this._register(new Emitter<void>());
public readonly onChange = this._onChange.event;
private update(extensions: readonly IExtensionPointUser<ICustomEditorsExtensionPoint[]>[]) {
this._editors.clear();
for (const extension of extensions) {
for (const webviewEditorContribution of extension.value) {
this.add(new CustomEditorInfo({
id: webviewEditorContribution.viewType,
displayName: webviewEditorContribution.displayName,
providerDisplayName: extension.description.isBuiltin ? builtinProviderDisplayName : extension.description.displayName || extension.description.identifier.value,
selector: webviewEditorContribution.selector || [],
priority: getPriorityFromContribution(webviewEditorContribution, extension.description),
}));
}
}
const mementoObject = this._memento.getMemento(StorageScope.GLOBAL);
mementoObject[ContributedCustomEditors.CUSTOM_EDITORS_ENTRY_ID] = Array.from(this._editors.values());
this._memento.saveMemento();
this._onChange.fire();
}
public [Symbol.iterator](): Iterator<CustomEditorInfo> {
return this._editors.values();
}

View File

@@ -79,7 +79,15 @@ export interface CustomEditorSelector {
readonly filenamePattern?: string;
}
export class CustomEditorInfo {
export interface CustomEditorDescriptor {
readonly id: string;
readonly displayName: string;
readonly providerDisplayName: string;
readonly priority: CustomEditorPriority;
readonly selector: readonly CustomEditorSelector[];
}
export class CustomEditorInfo implements CustomEditorDescriptor {
public readonly id: string;
public readonly displayName: string;
@@ -87,13 +95,7 @@ export class CustomEditorInfo {
public readonly priority: CustomEditorPriority;
public readonly selector: readonly CustomEditorSelector[];
constructor(descriptor: {
readonly id: string;
readonly displayName: string;
readonly providerDisplayName: string;
readonly priority: CustomEditorPriority;
readonly selector: readonly CustomEditorSelector[];
}) {
constructor(descriptor: CustomEditorDescriptor) {
this.id = descriptor.id;
this.displayName = descriptor.displayName;
this.providerDisplayName = descriptor.providerDisplayName;

View File

@@ -61,6 +61,7 @@ export class BreakpointsView extends ViewPane {
private list!: WorkbenchList<BreakpointItem>;
private needsRefresh = false;
private ignoreLayout = false;
constructor(
options: IViewletViewOptions,
@@ -79,7 +80,6 @@ export class BreakpointsView extends ViewPane {
) {
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
this.updateSize();
this._register(this.debugService.getModel().onDidChangeBreakpoints(() => this.onBreakpointsChange()));
}
@@ -164,10 +164,20 @@ export class BreakpointsView extends ViewPane {
}
protected layoutBody(height: number, width: number): void {
if (this.ignoreLayout) {
return;
}
super.layoutBody(height, width);
if (this.list) {
this.list.layout(height, width);
}
try {
this.ignoreLayout = true;
this.updateSize();
} finally {
this.ignoreLayout = false;
}
}
private onListContextMenu(e: IListContextMenuEvent<IEnablement>): void {

View File

@@ -6,6 +6,7 @@
import 'vs/css!./media/debug.contribution';
import 'vs/css!./media/debugHover';
import * as nls from 'vs/nls';
import { Color } from 'vs/base/common/color';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -37,14 +38,14 @@ import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { launchSchemaId } from 'vs/workbench/services/configuration/common/configuration';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { LoadedScriptsView } from 'vs/workbench/contrib/debug/browser/loadedScriptsView';
import { TOGGLE_LOG_POINT_ID, TOGGLE_CONDITIONAL_BREAKPOINT_ID, TOGGLE_BREAKPOINT_ID, RunToCursorAction } from 'vs/workbench/contrib/debug/browser/debugEditorActions';
import { ADD_LOG_POINT_ID, TOGGLE_CONDITIONAL_BREAKPOINT_ID, TOGGLE_BREAKPOINT_ID, RunToCursorAction } from 'vs/workbench/contrib/debug/browser/debugEditorActions';
import { WatchExpressionsView } from 'vs/workbench/contrib/debug/browser/watchExpressionsView';
import { VariablesView } from 'vs/workbench/contrib/debug/browser/variablesView';
import { ClearReplAction, Repl } from 'vs/workbench/contrib/debug/browser/repl';
import { DebugContentProvider } from 'vs/workbench/contrib/debug/common/debugContentProvider';
import { WelcomeView } from 'vs/workbench/contrib/debug/browser/welcomeView';
import { ThemeIcon, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { registerColor, foreground, badgeBackground, badgeForeground, listDeemphasizedForeground, contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { registerColor, foreground, badgeBackground, badgeForeground, listDeemphasizedForeground, contrastBorder, inputBorder, editorWarningForeground, errorForeground, editorInfoForeground } from 'vs/platform/theme/common/colorRegistry';
import { DebugViewPaneContainer, OpenDebugConsoleAction } from 'vs/workbench/contrib/debug/browser/debugViewlet';
import { registerEditorContribution } from 'vs/editor/browser/editorExtensions';
import { CallStackEditorContribution } from 'vs/workbench/contrib/debug/browser/callStackEditorContribution';
@@ -55,6 +56,7 @@ import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/pl
import { StartDebugQuickAccessProvider } from 'vs/workbench/contrib/debug/browser/debugQuickAccess';
import { DebugProgressContribution } from 'vs/workbench/contrib/debug/browser/debugProgress';
import { DebugTitleContribution } from 'vs/workbench/contrib/debug/browser/debugTitle';
import { Codicon } from 'vs/base/common/codicons';
class OpenDebugViewletAction extends ShowViewletAction {
public static readonly ID = VIEWLET_ID;
@@ -75,7 +77,7 @@ const viewContainer = Registry.as<IViewContainersRegistry>(ViewExtensions.ViewCo
id: VIEWLET_ID,
name: nls.localize('run', "Run"),
ctorDescriptor: new SyncDescriptor(DebugViewPaneContainer),
icon: 'codicon-debug-alt-2',
icon: Codicon.debugAlt.classNames,
alwaysUseContainerInfo: true,
order: 13 // {{SQL CARBON EDIT}}
}, ViewContainerLocation.Sidebar);
@@ -92,21 +94,21 @@ const openPanelKb: IKeybindings = {
const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry>(ViewExtensions.ViewContainersRegistry).registerViewContainer({
id: DEBUG_PANEL_ID,
name: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugPanel' }, 'Debug Console'),
icon: 'codicon-debug-console',
icon: Codicon.debugConsole.classNames,
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [DEBUG_PANEL_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]),
storageId: DEBUG_PANEL_ID,
focusCommand: {
id: OpenDebugConsoleAction.ID,
keybindings: openPanelKb
},
order: 3,
order: 2,
hideIfEmpty: true
}, ViewContainerLocation.Panel);
Registry.as<IViewsRegistry>(ViewExtensions.ViewsRegistry).registerViews([{
id: REPL_VIEW_ID,
name: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugPanel' }, 'Debug Console'),
containerIcon: 'codicon-debug-console',
containerIcon: Codicon.debugConsole.classNames,
canToggleVisibility: false,
canMoveView: true,
ctorDescriptor: new SyncDescriptor(Repl),
@@ -114,12 +116,12 @@ Registry.as<IViewsRegistry>(ViewExtensions.ViewsRegistry).registerViews([{
// Register default debug views
const viewsRegistry = Registry.as<IViewsRegistry>(ViewExtensions.ViewsRegistry);
viewsRegistry.registerViews([{ id: VARIABLES_VIEW_ID, name: nls.localize('variables', "Variables"), containerIcon: 'codicon-debug-alt-2', ctorDescriptor: new SyncDescriptor(VariablesView), order: 10, weight: 40, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusVariablesView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer);
viewsRegistry.registerViews([{ id: WATCH_VIEW_ID, name: nls.localize('watch', "Watch"), containerIcon: 'codicon-debug-alt-2', ctorDescriptor: new SyncDescriptor(WatchExpressionsView), order: 20, weight: 10, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusWatchView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer);
viewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callStack', "Call Stack"), containerIcon: 'codicon-debug-alt-2', ctorDescriptor: new SyncDescriptor(CallStackView), order: 30, weight: 30, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusCallStackView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer);
viewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), containerIcon: 'codicon-debug-alt-2', ctorDescriptor: new SyncDescriptor(BreakpointsView), order: 40, weight: 20, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' }, when: ContextKeyExpr.or(CONTEXT_BREAKPOINTS_EXIST, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer);
viewsRegistry.registerViews([{ id: WelcomeView.ID, name: WelcomeView.LABEL, containerIcon: 'codicon-debug-alt-2', ctorDescriptor: new SyncDescriptor(WelcomeView), order: 1, weight: 40, canToggleVisibility: true, when: CONTEXT_DEBUG_UX.isEqualTo('simple') }], viewContainer);
viewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), containerIcon: 'codicon-debug-alt-2', ctorDescriptor: new SyncDescriptor(LoadedScriptsView), order: 35, weight: 5, canToggleVisibility: true, canMoveView: true, collapsed: true, when: ContextKeyExpr.and(CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer);
viewsRegistry.registerViews([{ id: VARIABLES_VIEW_ID, name: nls.localize('variables', "Variables"), containerIcon: Codicon.debugAlt.classNames, ctorDescriptor: new SyncDescriptor(VariablesView), order: 10, weight: 40, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusVariablesView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer);
viewsRegistry.registerViews([{ id: WATCH_VIEW_ID, name: nls.localize('watch', "Watch"), containerIcon: Codicon.debugAlt.classNames, ctorDescriptor: new SyncDescriptor(WatchExpressionsView), order: 20, weight: 10, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusWatchView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer);
viewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callStack', "Call Stack"), containerIcon: Codicon.debugAlt.classNames, ctorDescriptor: new SyncDescriptor(CallStackView), order: 30, weight: 30, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusCallStackView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer);
viewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), containerIcon: Codicon.debugAlt.classNames, ctorDescriptor: new SyncDescriptor(BreakpointsView), order: 40, weight: 20, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' }, when: ContextKeyExpr.or(CONTEXT_BREAKPOINTS_EXIST, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer);
viewsRegistry.registerViews([{ id: WelcomeView.ID, name: WelcomeView.LABEL, containerIcon: Codicon.debugAlt.classNames, ctorDescriptor: new SyncDescriptor(WelcomeView), order: 1, weight: 40, canToggleVisibility: true, when: CONTEXT_DEBUG_UX.isEqualTo('simple') }], viewContainer);
viewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), containerIcon: Codicon.debugAlt.classNames, ctorDescriptor: new SyncDescriptor(LoadedScriptsView), order: 35, weight: 5, canToggleVisibility: true, canMoveView: true, collapsed: true, when: ContextKeyExpr.and(CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer);
registerCommands();
@@ -512,7 +514,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarNewBreakpointMenu, {
MenuRegistry.appendMenuItem(MenuId.MenubarNewBreakpointMenu, {
group: '1_breakpoints',
command: {
id: TOGGLE_LOG_POINT_ID,
id: ADD_LOG_POINT_ID,
title: nls.localize({ key: 'miLogPoint', comment: ['&& denotes a mnemonic'] }, "&&Logpoint...")
},
order: 4
@@ -599,12 +601,18 @@ const debugTokenExpressionBoolean = registerColor('debugTokenExpression.boolean'
const debugTokenExpressionNumber = registerColor('debugTokenExpression.number', { dark: '#b5cea8', light: '#098658', hc: '#89d185' }, 'Foreground color for numbers in the debug views (ie. the Variables or Watch view).');
const debugTokenExpressionError = registerColor('debugTokenExpression.error', { dark: '#f48771', light: '#e51400', hc: '#f48771' }, 'Foreground color for expression errors in the debug views (ie. the Variables or Watch view) and for error logs shown in the debug console.');
const debugViewExceptionLabelForeground = registerColor('debugView.exceptionLabelForeground', { dark: foreground, light: foreground, hc: foreground }, 'Foreground color for a label shown in the CALL STACK view when the debugger breaks on an exception.');
const debugViewExceptionLabelForeground = registerColor('debugView.exceptionLabelForeground', { dark: foreground, light: '#FFF', hc: foreground }, 'Foreground color for a label shown in the CALL STACK view when the debugger breaks on an exception.');
const debugViewExceptionLabelBackground = registerColor('debugView.exceptionLabelBackground', { dark: '#6C2022', light: '#A31515', hc: '#6C2022' }, 'Background color for a label shown in the CALL STACK view when the debugger breaks on an exception.');
const debugViewStateLabelForeground = registerColor('debugView.stateLabelForeground', { dark: foreground, light: foreground, hc: foreground }, 'Foreground color for a label in the CALL STACK view showing the current session\'s or thread\'s state.');
const debugViewStateLabelBackground = registerColor('debugView.stateLabelBackground', { dark: '#88888844', light: '#88888844', hc: '#88888844' }, 'Background color for a label in the CALL STACK view showing the current session\'s or thread\'s state.');
const debugViewValueChangedHighlight = registerColor('debugView.valueChangedHighlight', { dark: '#569CD6', light: '#569CD6', hc: '#569CD6' }, 'Color used to highlight value changes in the debug views (ie. in the Variables view).');
const debugConsoleInfoForeground = registerColor('debugConsole.infoForeground', { dark: editorInfoForeground, light: editorInfoForeground, hc: foreground }, 'Foreground color for info messages in debug REPL console.');
const debugConsoleWarningForeground = registerColor('debugConsole.warningForeground', { dark: editorWarningForeground, light: editorWarningForeground, hc: '#008000' }, 'Foreground color for warning messages in debug REPL console.');
const debugConsoleErrorForeground = registerColor('debugConsole.errorForeground', { dark: errorForeground, light: errorForeground, hc: errorForeground }, 'Foreground color for error messages in debug REPL console.');
const debugConsoleSourceForeground = registerColor('debugConsole.sourceForeground', { dark: foreground, light: foreground, hc: foreground }, 'Foreground color for source filenames in debug REPL console.');
const debugConsoleInputIconForeground = registerColor('debugConsoleInputIcon.foreground', { dark: foreground, light: foreground, hc: foreground }, 'Foreground color for debug console input marker icon.');
registerThemingParticipant((theme, collector) => {
// All these colours provide a default value so they will never be undefined, hence the `!`
const badgeBackgroundColor = theme.getColor(badgeBackground)!;
@@ -714,4 +722,53 @@ registerThemingParticipant((theme, collector) => {
color: ${tokenNumberColor};
}
`);
const debugConsoleInputBorderColor = theme.getColor(inputBorder) || Color.fromHex('#80808060');
const debugConsoleInfoForegroundColor = theme.getColor(debugConsoleInfoForeground)!;
const debugConsoleWarningForegroundColor = theme.getColor(debugConsoleWarningForeground)!;
const debugConsoleErrorForegroundColor = theme.getColor(debugConsoleErrorForeground)!;
const debugConsoleSourceForegroundColor = theme.getColor(debugConsoleSourceForeground)!;
const debugConsoleInputIconForegroundColor = theme.getColor(debugConsoleInputIconForeground)!;
collector.addRule(`
.repl .repl-input-wrapper {
border-top: 1px solid ${debugConsoleInputBorderColor};
}
.monaco-workbench .repl .repl-tree .output .expression .value.info {
color: ${debugConsoleInfoForegroundColor};
}
.monaco-workbench .repl .repl-tree .output .expression .value.warn {
color: ${debugConsoleWarningForegroundColor};
}
.monaco-workbench .repl .repl-tree .output .expression .value.error {
color: ${debugConsoleErrorForegroundColor};
}
.monaco-workbench .repl .repl-tree .output .expression .source {
color: ${debugConsoleSourceForegroundColor};
}
.monaco-workbench .repl .repl-tree .monaco-tl-contents .arrow {
color: ${debugConsoleInputIconForegroundColor};
}
`);
if (!theme.defines(debugConsoleInputIconForeground)) {
collector.addRule(`
.monaco-workbench.vs .repl .repl-tree .monaco-tl-contents .arrow {
opacity: 0.25;
}
.monaco-workbench.vs-dark .repl .repl-tree .monaco-tl-contents .arrow {
opacity: 0.4;
}
.monaco-workbench.hc-black .repl .repl-tree .monaco-tl-contents .arrow {
opacity: 1;
}
`);
}
});

View File

@@ -20,7 +20,6 @@ import { IContextViewService } from 'vs/platform/contextview/browser/contextView
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { ADD_CONFIGURATION_ID } from 'vs/workbench/contrib/debug/browser/debugCommands';
import { StartAction } from 'vs/workbench/contrib/debug/browser/debugActions';
const $ = dom.$;
@@ -32,7 +31,7 @@ export class StartDebugActionViewItem implements IActionViewItem {
private container!: HTMLElement;
private start!: HTMLElement;
private selectBox: SelectBox;
private options: { label: string, handler?: (() => boolean) }[] = [];
private options: { label: string, handler: (() => Promise<boolean>) }[] = [];
private toDispose: IDisposable[];
private selected = 0;
private providers: { label: string, pick: () => Promise<{ launch: ILaunch, config: IConfig } | undefined> }[] = [];
@@ -101,9 +100,9 @@ export class StartDebugActionViewItem implements IActionViewItem {
event.stopPropagation();
}
}));
this.toDispose.push(this.selectBox.onDidSelect(e => {
this.toDispose.push(this.selectBox.onDidSelect(async e => {
const target = this.options[e.index];
const shouldBeSelected = target.handler ? target.handler() : false;
const shouldBeSelected = target.handler ? await target.handler() : false;
if (shouldBeSelected) {
this.selected = e.index;
} else {
@@ -126,7 +125,6 @@ export class StartDebugActionViewItem implements IActionViewItem {
selectBoxContainer.style.borderLeft = colors.selectBorder ? `1px solid ${colors.selectBorder}` : '';
const selectBackgroundColor = colors.selectBackground ? `${colors.selectBackground}` : '';
this.container.style.backgroundColor = selectBackgroundColor;
this.start.style.backgroundColor = selectBackgroundColor;
}));
this.debugService.getConfigurationManager().getDynamicProviders().then(providers => {
this.providers = providers;
@@ -173,7 +171,7 @@ export class StartDebugActionViewItem implements IActionViewItem {
if (lastGroup !== presentation?.group) {
lastGroup = presentation?.group;
if (this.options.length) {
this.options.push({ label: StartDebugActionViewItem.SEPARATOR, handler: undefined });
this.options.push({ label: StartDebugActionViewItem.SEPARATOR, handler: () => Promise.resolve(false) });
disabledIdxs.push(this.options.length - 1);
}
}
@@ -183,8 +181,7 @@ export class StartDebugActionViewItem implements IActionViewItem {
const label = inWorkspace ? `${name} (${launch.name})` : name;
this.options.push({
label, handler: () => {
StartAction.GET_CONFIG_AND_LAUNCH = undefined;
label, handler: async () => {
manager.selectConfiguration(launch, name);
return true;
}
@@ -192,31 +189,39 @@ export class StartDebugActionViewItem implements IActionViewItem {
});
if (this.options.length === 0) {
this.options.push({ label: nls.localize('noConfigurations', "No Configurations"), handler: () => false });
this.options.push({ label: nls.localize('noConfigurations', "No Configurations"), handler: async () => false });
} else {
this.options.push({ label: StartDebugActionViewItem.SEPARATOR, handler: undefined });
this.options.push({ label: StartDebugActionViewItem.SEPARATOR, handler: () => Promise.resolve(false) });
disabledIdxs.push(this.options.length - 1);
}
this.providers.forEach(p => {
if (p.label === manager.selectedConfiguration.name) {
this.selected = this.options.length;
}
this.options.push({
label: `${p.label}...`, handler: () => {
StartAction.GET_CONFIG_AND_LAUNCH = p.pick;
return true;
label: `${p.label}...`, handler: async () => {
const picked = await p.pick();
if (picked) {
manager.selectConfiguration(picked.launch, p.label, picked.config);
return true;
}
return false;
}
});
});
if (this.providers.length > 0) {
this.options.push({ label: StartDebugActionViewItem.SEPARATOR, handler: undefined });
this.options.push({ label: StartDebugActionViewItem.SEPARATOR, handler: () => Promise.resolve(false) });
disabledIdxs.push(this.options.length - 1);
}
manager.getLaunches().filter(l => !l.hidden).forEach(l => {
const label = inWorkspace ? nls.localize("addConfigTo", "Add Config ({0})...", l.name) : nls.localize('addConfiguration', "Add Configuration...");
this.options.push({
label, handler: () => {
this.commandService.executeCommand(ADD_CONFIGURATION_ID, l.uri.toString());
label, handler: async () => {
await this.commandService.executeCommand(ADD_CONFIGURATION_ID, l.uri.toString());
return false;
}
});

View File

@@ -7,8 +7,8 @@ import * as nls from 'vs/nls';
import { Action } from 'vs/base/common/actions';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IDebugService, State, IEnablement, IBreakpoint, IDebugSession, ILaunch, IConfig } from 'vs/workbench/contrib/debug/common/debug';
import { Variable, Breakpoint, FunctionBreakpoint } from 'vs/workbench/contrib/debug/common/debugModel';
import { IDebugService, State, IEnablement, IBreakpoint, IDebugSession, ILaunch } from 'vs/workbench/contrib/debug/common/debug';
import { Variable, Breakpoint, FunctionBreakpoint, Expression } from 'vs/workbench/contrib/debug/common/debugModel';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
@@ -81,8 +81,8 @@ export class ConfigureAction extends AbstractDebugAction {
this.class = configurationManager.selectedConfiguration.name ? 'debug-action codicon codicon-gear' : 'debug-action codicon codicon-gear notification';
}
async run(event?: any): Promise<any> {
if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) {
async run(): Promise<any> {
if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY || this.contextService.getWorkspace().folders.length === 0) {
this.notificationService.info(nls.localize('noFolderDebugConfig', "Please first open a folder in order to do advanced debug configuration."));
return;
}
@@ -92,12 +92,12 @@ export class ConfigureAction extends AbstractDebugAction {
if (configurationManager.selectedConfiguration.name) {
launch = configurationManager.selectedConfiguration.launch;
} else {
const launches = configurationManager.getLaunches().filter(l => !!l.workspace);
const launches = configurationManager.getLaunches().filter(l => !l.hidden);
if (launches.length === 1) {
launch = launches[0];
} else {
const picks = launches.map(l => ({ label: l.name, launch: l }));
const picked = await this.quickInputService.pick<{ label: string, launch: ILaunch }>(picks, { activeItem: picks[0], placeHolder: nls.localize('selectWorkspaceFolder', "Select a workspace folder to create a launch.json file in") });
const picked = await this.quickInputService.pick<{ label: string, launch: ILaunch }>(picks, { activeItem: picks[0], placeHolder: nls.localize('selectWorkspaceFolder', "Select a workspace folder to create a launch.json file in or add it to the workspace config file") });
if (picked) {
launch = picked.launch;
}
@@ -105,8 +105,7 @@ export class ConfigureAction extends AbstractDebugAction {
}
if (launch) {
const sideBySide = !!(event && (event.ctrlKey || event.metaKey));
return launch.openConfigFile(sideBySide, false);
return launch.openConfigFile(false);
}
}
}
@@ -114,7 +113,6 @@ export class ConfigureAction extends AbstractDebugAction {
export class StartAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.start';
static LABEL = nls.localize('startDebug', "Start Debugging");
static GET_CONFIG_AND_LAUNCH: (() => Promise<{ config: IConfig, launch: ILaunch } | undefined>) | undefined;
constructor(id: string, label: string,
@IDebugService debugService: IDebugService,
@@ -130,16 +128,8 @@ export class StartAction extends AbstractDebugAction {
}
async run(): Promise<boolean> {
if (StartAction.GET_CONFIG_AND_LAUNCH) {
const picked = await StartAction.GET_CONFIG_AND_LAUNCH();
if (picked) {
return this.debugService.startDebugging(picked.launch, picked.config, { noDebug: this.isNoDebug() });
}
return Promise.resolve(false);
} else {
let { launch, name } = this.debugService.getConfigurationManager().selectedConfiguration;
return this.debugService.startDebugging(launch, name, { noDebug: this.isNoDebug() });
}
let { launch, name, config } = this.debugService.getConfigurationManager().selectedConfiguration;
return this.debugService.startDebugging(launch, config || name, { noDebug: this.isNoDebug() });
}
protected isNoDebug(): boolean {
@@ -152,7 +142,10 @@ export class StartAction extends AbstractDebugAction {
if (debugService.state === State.Initializing) {
return false;
}
if ((sessions.length > 0) && !debugService.getConfigurationManager().selectedConfiguration.name) {
let { name, config } = debugService.getConfigurationManager().selectedConfiguration;
let nameToStart = name || config?.name;
if (sessions.some(s => s.configuration.name === nameToStart)) {
// There is already a debug session running and we do not have any launch configuration selected
return false;
}
@@ -390,12 +383,12 @@ export class CopyValueAction extends Action {
static readonly LABEL = nls.localize('copyValue', "Copy Value");
constructor(
id: string, label: string, private value: Variable | string, private context: string,
id: string, label: string, private value: Variable | Expression, private context: string,
@IDebugService private readonly debugService: IDebugService,
@IClipboardService private readonly clipboardService: IClipboardService
) {
super(id, label, 'debug-action copy-value');
this._enabled = typeof this.value === 'string' || (this.value instanceof Variable && !!this.value.evaluateName);
super(id, label);
this._enabled = (this.value instanceof Expression) || (this.value instanceof Variable && !!this.value.evaluateName);
}
async run(): Promise<any> {
@@ -406,7 +399,7 @@ export class CopyValueAction extends Action {
}
const context = session.capabilities.supportsClipboardContext ? 'clipboard' : this.context;
const toEvaluate = typeof this.value === 'string' ? this.value : this.value.evaluateName || this.value.value;
const toEvaluate = this.value instanceof Variable ? (this.value.evaluateName || this.value.value) : this.value.name;
try {
const evaluation = await session.evaluate(toEvaluate, stackFrame.frameId, context);

View File

@@ -504,7 +504,7 @@ export function registerCommands(): void {
const launch = manager.getLaunches().find(l => l.uri.toString() === launchUri) || manager.selectedConfiguration.launch;
if (launch) {
const { editor, created } = await launch.openConfigFile(false, false);
const { editor, created } = await launch.openConfigFile(false);
if (editor && !created) {
const codeEditor = <ICodeEditor>editor.getControl();
if (codeEditor) {

View File

@@ -8,6 +8,7 @@ import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { Event, Emitter } from 'vs/base/common/event';
import * as strings from 'vs/base/common/strings';
import * as objects from 'vs/base/common/objects';
import * as json from 'vs/base/common/json';
import { URI as uri } from 'vs/base/common/uri';
import * as resources from 'vs/base/common/resources';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
@@ -15,14 +16,14 @@ import { ITextModel } from 'vs/editor/common/model';
import { IEditorPane } from 'vs/workbench/common/editor';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { IFileService } from 'vs/platform/files/common/files';
import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState, IWorkspaceFoldersChangeEvent } from 'vs/platform/workspace/common/workspace';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IDebugConfigurationProvider, ICompound, IDebugConfiguration, IConfig, IGlobalConfig, IConfigurationManager, ILaunch, IDebugAdapterDescriptorFactory, IDebugAdapter, IDebugSession, IAdapterDescriptor, CONTEXT_DEBUG_CONFIGURATION_TYPE, IDebugAdapterFactory, IConfigPresentation } from 'vs/workbench/contrib/debug/common/debug';
import { Debugger } from 'vs/workbench/contrib/debug/common/debugger';
import { IEditorService, ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { IEditorService, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
import { launchSchemaId } from 'vs/workbench/services/configuration/common/configuration';
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
@@ -45,6 +46,7 @@ jsonRegistry.registerSchema(launchSchemaId, launchSchema);
const DEBUG_SELECTED_CONFIG_NAME_KEY = 'debug.selectedconfigname';
const DEBUG_SELECTED_ROOT = 'debug.selectedroot';
const DEBUG_SELECTED_CONFIG = 'debug.selectedconfig';
export class ConfigurationManager implements IConfigurationManager {
private debuggers: Debugger[];
@@ -52,6 +54,7 @@ export class ConfigurationManager implements IConfigurationManager {
private launches!: ILaunch[];
private selectedName: string | undefined;
private selectedLaunch: ILaunch | undefined;
private selectedConfig: IConfig | undefined;
private toDispose: IDisposable[];
private readonly _onDidSelectConfigurationName = new Emitter<void>();
private configProviders: IDebugConfigurationProvider[];
@@ -81,10 +84,12 @@ export class ConfigurationManager implements IConfigurationManager {
const previousSelectedRoot = this.storageService.get(DEBUG_SELECTED_ROOT, StorageScope.WORKSPACE);
const previousSelectedLaunch = this.launches.find(l => l.uri.toString() === previousSelectedRoot);
this.debugConfigurationTypeContext = CONTEXT_DEBUG_CONFIGURATION_TYPE.bindTo(contextKeyService);
const storedConfig = this.storageService.get(DEBUG_SELECTED_CONFIG, StorageScope.WORKSPACE);
const selectedConfig = typeof storedConfig === 'string' ? JSON.parse(storedConfig) : undefined;
if (previousSelectedLaunch && previousSelectedLaunch.getConfigurationNames().length) {
this.selectConfiguration(previousSelectedLaunch, this.storageService.get(DEBUG_SELECTED_CONFIG_NAME_KEY, StorageScope.WORKSPACE));
this.selectConfiguration(previousSelectedLaunch, this.storageService.get(DEBUG_SELECTED_CONFIG_NAME_KEY, StorageScope.WORKSPACE), selectedConfig);
} else if (this.launches.length > 0) {
this.selectConfiguration(undefined);
this.selectConfiguration(undefined, selectedConfig ? selectedConfig.name : undefined, selectedConfig);
}
}
@@ -257,7 +262,7 @@ export class ConfigurationManager implements IConfigurationManager {
}
return undefined;
}).filter(e => typeof e === 'string') as string[];
}).filter(type => typeof type === 'string' && !!this.getDebuggerLabel(type)) as string[];
return debugDynamicExtensionsTypes.map(type => {
return {
@@ -272,13 +277,27 @@ export class ConfigurationManager implements IConfigurationManager {
picks.push(provider.provideDebugConfigurations!(launch.workspace.uri, token.token).then(configurations => configurations.map(config => ({
label: config.name,
config,
buttons: [{
iconClass: 'codicon-gear',
tooltip: nls.localize('editLaunchConfig', "Edit Debug Configuration in launch.json")
}],
launch
}))));
}
});
const promiseOfPicks = Promise.all(picks).then(result => result.reduce((first, second) => first.concat(second), []));
const result = await this.quickInputService.pick<{ label: string, launch: ILaunch, config: IConfig }>(promiseOfPicks, { placeHolder: nls.localize('selectConfiguration', "Select Debug Configuration") });
const result = await this.quickInputService.pick<{ label: string, launch: ILaunch, config: IConfig }>(promiseOfPicks, {
placeHolder: nls.localize('selectConfiguration', "Select Launch Configuration"),
onDidTriggerItemButton: async (context) => {
await this.quickInputService.cancel();
const { launch, config } = context.item;
await launch.openConfigFile(false, config.type);
// Only Launch have a pin trigger button
await (launch as Launch).writeConfiguration(config);
this.selectConfiguration(launch, config.name);
}
});
if (!result) {
// User canceled quick input we should notify the provider to cancel computing configurations
token.cancel();
@@ -385,9 +404,9 @@ export class ConfigurationManager implements IConfigurationManager {
private initLaunches(): void {
this.launches = this.contextService.getWorkspace().folders.map(folder => this.instantiationService.createInstance(Launch, this, folder));
if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) {
this.launches.push(this.instantiationService.createInstance(WorkspaceLaunch));
this.launches.push(this.instantiationService.createInstance(WorkspaceLaunch, this));
}
this.launches.push(this.instantiationService.createInstance(UserLaunch));
this.launches.push(this.instantiationService.createInstance(UserLaunch, this));
if (this.selectedLaunch && this.launches.indexOf(this.selectedLaunch) === -1) {
this.selectConfiguration(undefined);
@@ -419,10 +438,11 @@ export class ConfigurationManager implements IConfigurationManager {
return this.launches.find(l => l.workspace && l.workspace.uri.toString() === workspaceUri.toString());
}
get selectedConfiguration(): { launch: ILaunch | undefined, name: string | undefined } {
get selectedConfiguration(): { launch: ILaunch | undefined, name: string | undefined, config: IConfig | undefined } {
return {
launch: this.selectedLaunch,
name: this.selectedName
name: this.selectedName,
config: this.selectedConfig
};
}
@@ -438,7 +458,7 @@ export class ConfigurationManager implements IConfigurationManager {
return undefined;
}
selectConfiguration(launch: ILaunch | undefined, name?: string): void {
selectConfiguration(launch: ILaunch | undefined, name?: string, config?: IConfig): void {
if (typeof launch === 'undefined') {
const rootUri = this.historyService.getLastActiveWorkspaceRoot();
launch = this.getLaunch(rootUri);
@@ -457,18 +477,19 @@ export class ConfigurationManager implements IConfigurationManager {
this.storageService.remove(DEBUG_SELECTED_ROOT, StorageScope.WORKSPACE);
}
const names = launch ? launch.getConfigurationNames() : [];
if (name && names.indexOf(name) >= 0) {
if ((name && names.indexOf(name) >= 0) || config) {
this.setSelectedLaunchName(name);
}
if (!this.selectedName || names.indexOf(this.selectedName) === -1) {
} else if (!this.selectedName || names.indexOf(this.selectedName) === -1) {
this.setSelectedLaunchName(names.length ? names[0] : undefined);
}
const configuration = this.selectedLaunch && this.selectedName ? this.selectedLaunch.getConfiguration(this.selectedName) : undefined;
if (configuration) {
this.debugConfigurationTypeContext.set(configuration.type);
this.selectedConfig = config || (this.selectedLaunch && this.selectedName ? this.selectedLaunch.getConfiguration(this.selectedName) : undefined);
if (this.selectedConfig) {
this.debugConfigurationTypeContext.set(this.selectedConfig.type);
this.storageService.store(DEBUG_SELECTED_CONFIG, JSON.stringify(this.selectedConfig), StorageScope.WORKSPACE);
} else {
this.debugConfigurationTypeContext.reset();
this.storageService.remove(DEBUG_SELECTED_CONFIG, StorageScope.WORKSPACE);
}
if (this.selectedLaunch !== previousLaunch || this.selectedName !== previousName) {
@@ -565,6 +586,9 @@ export class ConfigurationManager implements IConfigurationManager {
abstract class AbstractLaunch {
protected abstract getConfig(): IGlobalConfig | undefined;
constructor(protected configurationManager: ConfigurationManager) {
}
getCompound(name: string): ICompound | undefined {
const config = this.getConfig();
if (!config || !config.compounds) {
@@ -605,6 +629,16 @@ abstract class AbstractLaunch {
return config.configurations.find(config => config && config.name === name);
}
async getInitialConfigurationContent(folderUri?: uri, type?: string, token?: CancellationToken): Promise<string> {
let content = '';
const adapter = await this.configurationManager.guessDebugger(type);
if (adapter) {
const initialConfigs = await this.configurationManager.provideDebugConfigurations(folderUri, adapter.type, token || CancellationToken.None);
content = await adapter.getInitialConfigurationContent(initialConfigs);
}
return content;
}
get hidden(): boolean {
return false;
}
@@ -613,14 +647,14 @@ abstract class AbstractLaunch {
class Launch extends AbstractLaunch implements ILaunch {
constructor(
private configurationManager: ConfigurationManager,
configurationManager: ConfigurationManager,
public workspace: IWorkspaceFolder,
@IFileService private readonly fileService: IFileService,
@ITextFileService private readonly textFileService: ITextFileService,
@IEditorService private readonly editorService: IEditorService,
@IConfigurationService private readonly configurationService: IConfigurationService
) {
super();
super(configurationManager);
}
get uri(): uri {
@@ -635,7 +669,7 @@ class Launch extends AbstractLaunch implements ILaunch {
return this.configurationService.inspect<IGlobalConfig>('launch', { resource: this.workspace.uri }).workspaceFolderValue;
}
async openConfigFile(sideBySide: boolean, preserveFocus: boolean, type?: string, token?: CancellationToken): Promise<{ editor: IEditorPane | null, created: boolean }> {
async openConfigFile(preserveFocus: boolean, type?: string, token?: CancellationToken): Promise<{ editor: IEditorPane | null, created: boolean }> {
const resource = this.uri;
let created = false;
let content = '';
@@ -644,12 +678,7 @@ class Launch extends AbstractLaunch implements ILaunch {
content = fileContent.value.toString();
} catch {
// launch.json not found: create one by collecting launch configs from debugConfigProviders
const adapter = await this.configurationManager.guessDebugger(type);
if (adapter) {
const initialConfigs = await this.configurationManager.provideDebugConfigurations(this.workspace.uri, adapter.type, token || CancellationToken.None);
content = await adapter.getInitialConfigurationContent(initialConfigs);
}
content = await this.getInitialConfigurationContent(this.workspace.uri, type, token);
if (content) {
created = true; // pin only if config file is created #8727
try {
@@ -681,22 +710,29 @@ class Launch extends AbstractLaunch implements ILaunch {
pinned: created,
revealIfVisible: true
},
}, sideBySide ? SIDE_GROUP : ACTIVE_GROUP);
}, ACTIVE_GROUP);
return ({
editor: withUndefinedAsNull(editor),
created
});
}
async writeConfiguration(configuration: IConfig): Promise<void> {
const fullConfig = objects.deepClone(this.getConfig()!);
fullConfig.configurations.push(configuration);
await this.configurationService.updateValue('launch', fullConfig, { resource: this.workspace.uri }, ConfigurationTarget.WORKSPACE_FOLDER);
}
}
class WorkspaceLaunch extends AbstractLaunch implements ILaunch {
constructor(
configurationManager: ConfigurationManager,
@IEditorService private readonly editorService: IEditorService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService
) {
super();
super(configurationManager);
}
get workspace(): undefined {
@@ -715,12 +751,22 @@ class WorkspaceLaunch extends AbstractLaunch implements ILaunch {
return this.configurationService.inspect<IGlobalConfig>('launch').workspaceValue;
}
async openConfigFile(sideBySide: boolean, preserveFocus: boolean): Promise<{ editor: IEditorPane | null, created: boolean }> {
async openConfigFile(preserveFocus: boolean, type?: string, token?: CancellationToken): Promise<{ editor: IEditorPane | null, created: boolean }> {
let launchExistInFile = !!this.getConfig();
if (!launchExistInFile) {
// Launch property in workspace config not found: create one by collecting launch configs from debugConfigProviders
let content = await this.getInitialConfigurationContent(undefined, type, token);
if (content) {
await this.configurationService.updateValue('launch', json.parse(content), ConfigurationTarget.WORKSPACE);
} else {
return { editor: null, created: false };
}
}
const editor = await this.editorService.openEditor({
resource: this.contextService.getWorkspace().configuration!,
options: { preserveFocus }
}, sideBySide ? SIDE_GROUP : ACTIVE_GROUP);
}, ACTIVE_GROUP);
return ({
editor: withUndefinedAsNull(editor),
@@ -732,10 +778,11 @@ class WorkspaceLaunch extends AbstractLaunch implements ILaunch {
class UserLaunch extends AbstractLaunch implements ILaunch {
constructor(
configurationManager: ConfigurationManager,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IPreferencesService private readonly preferencesService: IPreferencesService
) {
super();
super(configurationManager);
}
get workspace(): undefined {
@@ -758,7 +805,7 @@ class UserLaunch extends AbstractLaunch implements ILaunch {
return this.configurationService.inspect<IGlobalConfig>('launch').userValue;
}
async openConfigFile(_: boolean, preserveFocus: boolean): Promise<{ editor: IEditorPane | null, created: boolean }> {
async openConfigFile(preserveFocus: boolean): Promise<{ editor: IEditorPane | null, created: boolean }> {
const editor = await this.preferencesService.openGlobalSettings(true, { preserveFocus });
return ({
editor: withUndefinedAsNull(editor),

View File

@@ -9,7 +9,7 @@ import { Range } from 'vs/editor/common/core/range';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { ServicesAccessor, registerEditorAction, EditorAction, IActionOptions } from 'vs/editor/browser/editorExtensions';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IDebugService, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE, State, VIEWLET_ID, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, BreakpointWidgetContext, IBreakpoint, BREAKPOINT_EDITOR_CONTRIBUTION_ID, IBreakpointEditorContribution, REPL_VIEW_ID } from 'vs/workbench/contrib/debug/common/debug';
import { IDebugService, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE, State, VIEWLET_ID, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, BreakpointWidgetContext, IBreakpoint, BREAKPOINT_EDITOR_CONTRIBUTION_ID, IBreakpointEditorContribution, REPL_VIEW_ID, CONTEXT_STEP_INTO_TARGETS_SUPPORTED } from 'vs/workbench/contrib/debug/common/debug';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
@@ -17,6 +17,9 @@ import { openBreakpointSource } from 'vs/workbench/contrib/debug/browser/breakpo
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { PanelFocusContext } from 'vs/workbench/common/panel';
import { IViewsService } from 'vs/workbench/common/views';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { Action } from 'vs/base/common/actions';
import { getDomNodePagePosition } from 'vs/base/browser/dom';
export const TOGGLE_BREAKPOINT_ID = 'editor.debug.action.toggleBreakpoint';
class ToggleBreakpointAction extends EditorAction {
@@ -78,12 +81,12 @@ class ConditionalBreakpointAction extends EditorAction {
}
}
export const TOGGLE_LOG_POINT_ID = 'editor.debug.action.toggleLogPoint';
export const ADD_LOG_POINT_ID = 'editor.debug.action.addLogPoint';
class LogPointAction extends EditorAction {
constructor() {
super({
id: TOGGLE_LOG_POINT_ID,
id: ADD_LOG_POINT_ID,
label: nls.localize('logPointEditorAction', "Debug: Add Logpoint..."),
alias: 'Debug: Add Logpoint...',
precondition: undefined
@@ -241,6 +244,48 @@ class ShowDebugHoverAction extends EditorAction {
}
}
class StepIntoTargetsAction extends EditorAction {
public static readonly ID = 'editor.debug.action.stepIntoTargets';
public static readonly LABEL = nls.localize('stepIntoTargets', "Step Into Targets...");
constructor() {
super({
id: StepIntoTargetsAction.ID,
label: StepIntoTargetsAction.LABEL,
alias: 'Debug: Step Into Targets...',
precondition: ContextKeyExpr.and(CONTEXT_STEP_INTO_TARGETS_SUPPORTED, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), EditorContextKeys.editorTextFocus),
contextMenuOpts: {
group: 'debug',
order: 1.5
}
});
}
async run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> {
const debugService = accessor.get(IDebugService);
const contextMenuService = accessor.get(IContextMenuService);
const session = debugService.getViewModel().focusedSession;
const frame = debugService.getViewModel().focusedStackFrame;
if (session && frame && editor.hasModel()) {
const targets = await session.stepInTargets(frame.frameId);
const position = editor.getPosition();
const cursorCoords = editor.getScrolledVisiblePosition(position);
const editorCoords = getDomNodePagePosition(editor.getDomNode());
const x = editorCoords.left + cursorCoords.left;
const y = editorCoords.top + cursorCoords.top + cursorCoords.height;
contextMenuService.showContextMenu({
getAnchor: () => ({ x, y }),
getActions: () => {
return targets.map(t => new Action(`stepIntoTarget:${t.id}`, t.label, undefined, true, () => session.stepIn(frame.thread.threadId, t.id)));
}
});
}
}
}
class GoToBreakpointAction extends EditorAction {
constructor(private isNext: boolean, opts: IActionOptions) {
super(opts);
@@ -307,6 +352,7 @@ registerEditorAction(ToggleBreakpointAction);
registerEditorAction(ConditionalBreakpointAction);
registerEditorAction(LogPointAction);
registerEditorAction(RunToCursorAction);
registerEditorAction(StepIntoTargetsAction);
registerEditorAction(SelectionToReplAction);
registerEditorAction(SelectionToWatchExpressionsAction);
registerEditorAction(ShowDebugHoverAction);

View File

@@ -341,7 +341,7 @@ class DebugHoverAccessibilityProvider implements IListAccessibilityProvider<IExp
}
getAriaLabel(element: IExpression): string {
return nls.localize('variableAriaLabel', "{0}, value {1}, variables, debug", element.name, element.value);
return nls.localize({ key: 'variableAriaLabel', comment: ['Do not translate placholders. Placeholders are name and value of a variable.'] }, "{0}, value {1}, variables, debug", element.name, element.value);
}
}

View File

@@ -60,7 +60,7 @@ export class StartDebugQuickAccessProvider extends PickerQuickAccessProvider<IPi
tooltip: localize('customizeLaunchConfig', "Configure Launch Configuration")
}],
trigger: () => {
config.launch.openConfigFile(false, false);
config.launch.openConfigFile(false);
return TriggerAction.CLOSE_PICKER;
},
@@ -81,13 +81,18 @@ export class StartDebugQuickAccessProvider extends PickerQuickAccessProvider<IPi
// Entries detected configurations
const dynamicProviders = await configManager.getDynamicProviders();
if (dynamicProviders.length > 0) {
picks.push({ type: 'separator', label: localize('contributed', "contributed") });
picks.push({
type: 'separator', label: localize({
key: 'contributed',
comment: ['contributed is lower case because it looks better like that in UI. Nothing preceeds it. It is a name of the grouping of debug configurations.']
}, "contributed")
});
}
dynamicProviders.forEach(provider => {
picks.push({
label: `$(folder) ${provider.label}...`,
ariaLabel: localize('providerAriaLabel', "{0} contributed configurations", provider.label),
ariaLabel: localize({ key: 'providerAriaLabel', comment: ['Placeholder stands for the provider label. For example "NodeJS".'] }, "{0} contributed configurations", provider.label),
accept: async () => {
const pick = await provider.pick();
if (pick) {

View File

@@ -46,6 +46,7 @@ import { IViewsService } from 'vs/workbench/common/views';
import { generateUuid } from 'vs/base/common/uuid';
import { DebugStorage } from 'vs/workbench/contrib/debug/common/debugStorage';
import { DebugTelemetry } from 'vs/workbench/contrib/debug/common/debugTelemetry';
import { DebugCompoundRoot } from 'vs/workbench/contrib/debug/common/debugCompoundRoot';
export class DebugService implements IDebugService {
_serviceBrand: undefined;
@@ -305,6 +306,9 @@ export class DebugService implements IDebugService {
return false;
}
}
if (compound.stopAll) {
options = { ...options, compoundRoot: new DebugCompoundRoot() };
}
const values = await Promise.all(compound.configurations.map(configData => {
const name = typeof configData === 'string' ? configData : configData.name;
@@ -405,7 +409,7 @@ export class DebugService implements IDebugService {
const cfg = await this.configurationManager.resolveDebugConfigurationWithSubstitutedVariables(launch && launch.workspace ? launch.workspace.uri : undefined, type, resolvedConfig, initCancellationToken.token);
if (!cfg) {
if (launch && type && cfg === null && !initCancellationToken.token.isCancellationRequested) { // show launch.json only for "config" being "null".
await launch.openConfigFile(false, true, type, initCancellationToken.token);
await launch.openConfigFile(true, type, initCancellationToken.token);
}
return false;
}
@@ -439,7 +443,7 @@ export class DebugService implements IDebugService {
await this.showError(nls.localize('noFolderWorkspaceDebugError', "The active file can not be debugged. Make sure it is saved and that you have a debug extension installed for that file type."));
}
if (launch && !initCancellationToken.token.isCancellationRequested) {
await launch.openConfigFile(false, true, undefined, initCancellationToken.token);
await launch.openConfigFile(true, undefined, initCancellationToken.token);
}
return false;
@@ -447,7 +451,7 @@ export class DebugService implements IDebugService {
}
if (launch && type && configByProviders === null && !initCancellationToken.token.isCancellationRequested) { // show launch.json only for "config" being "null".
await launch.openConfigFile(false, true, type, initCancellationToken.token);
await launch.openConfigFile(true, type, initCancellationToken.token);
}
return false;

View File

@@ -35,6 +35,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { localize } from 'vs/nls';
import { canceled } from 'vs/base/common/errors';
import { filterExceptionsFromTelemetry } from 'vs/workbench/contrib/debug/common/debugUtils';
export class DebugSession implements IDebugSession {
@@ -97,6 +98,11 @@ export class DebugSession implements IDebugSession {
dispose(toDispose);
}));
}
const compoundRoot = this._options.compoundRoot;
if (compoundRoot) {
toDispose.push(compoundRoot.onDidSessionStop(() => this.terminate()));
}
}
getId(): string {
@@ -279,6 +285,10 @@ export class DebugSession implements IDebugSession {
} else {
await this.raw.disconnect(restart);
}
if (!restart) {
this._options.compoundRoot?.sessionStopped();
}
}
/**
@@ -291,6 +301,10 @@ export class DebugSession implements IDebugSession {
this.cancelAllRequests();
await this.raw.disconnect(restart);
if (!restart) {
this._options.compoundRoot?.sessionStopped();
}
}
/**
@@ -366,7 +380,7 @@ export class DebugSession implements IDebugSession {
}
}
async dataBreakpointInfo(name: string, variablesReference?: number): Promise<{ dataId: string | null, description: string, canPersist?: boolean }> {
async dataBreakpointInfo(name: string, variablesReference?: number): Promise<{ dataId: string | null, description: string, canPersist?: boolean } | undefined> {
if (!this.raw) {
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'data breakpoints info'));
}
@@ -488,12 +502,12 @@ export class DebugSession implements IDebugSession {
await this.raw.next({ threadId });
}
async stepIn(threadId: number): Promise<void> {
async stepIn(threadId: number, targetId?: number): Promise<void> {
if (!this.raw) {
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'stepIn'));
}
await this.raw.stepIn({ threadId });
await this.raw.stepIn({ threadId, targetId });
}
async stepOut(threadId: number): Promise<void> {
@@ -592,7 +606,7 @@ export class DebugSession implements IDebugSession {
}
const response = await this.raw.loadedSources({});
if (response.body && response.body.sources) {
if (response && response.body && response.body.sources) {
return response.body.sources.map(src => this.getSource(src));
} else {
return [];
@@ -612,6 +626,15 @@ export class DebugSession implements IDebugSession {
}, token);
}
async stepInTargets(frameId: number): Promise<{ id: number, label: string }[]> {
if (!this.raw) {
return Promise.reject(new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'stepInTargets')));
}
const response = await this.raw.stepInTargets({ frameId });
return response.body.targets;
}
async cancel(progressId: string): Promise<DebugProtocol.CancelResponse> {
if (!this.raw) {
return Promise.reject(new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'cancel')));
@@ -735,6 +758,7 @@ export class DebugSession implements IDebugSession {
await this.raw.configurationDone();
} catch (e) {
// Disconnect the debug session on configuration done error #10596
this.notificationService.error(e);
if (this.raw) {
this.raw.disconnect();
}
@@ -847,7 +871,12 @@ export class DebugSession implements IDebugSession {
// and the user opted in telemetry
if (this.raw.customTelemetryService && this.telemetryService.isOptedIn) {
// __GDPR__TODO__ We're sending events in the name of the debug extension and we can not ensure that those are declared correctly.
this.raw.customTelemetryService.publicLog(event.body.output, event.body.data);
let data = event.body.data;
if (!this.raw.customTelemetryService.sendErrorTelemetry && event.body.data) {
data = filterExceptionsFromTelemetry(event.body.data);
}
this.raw.customTelemetryService.publicLog(event.body.output, data);
}
return;

View File

@@ -39,6 +39,7 @@
.monaco-editor .debug-hover-widget .debug-hover-tree .monaco-list-row .monaco-tl-contents {
user-select: text;
-webkit-user-select: text;
white-space: pre;
}
/* Disable tree highlight in debug hover tree. */
@@ -56,7 +57,6 @@
}
.monaco-editor .debug-hover-widget .value {
white-space: pre-wrap;
color: rgba(108, 108, 108, 0.8);
overflow: auto;
font-family: var(--monaco-monospace-font);

View File

@@ -82,7 +82,8 @@
/* Call stack */
.debug-pane .debug-call-stack-title {
.debug-pane.expanded .debug-call-stack-title,
.debug-pane.vertical .debug-call-stack-title {
display: flex;
width: 100%;
}

View File

@@ -5,19 +5,19 @@
/* Debug repl */
.repl {
.monaco-workbench .repl {
height: 100%;
box-sizing: border-box;
overflow: hidden;
}
.repl .repl-tree .monaco-tl-contents {
.monaco-workbench .repl .repl-tree .monaco-tl-contents {
user-select: text;
-webkit-user-select: text;
white-space: pre;
}
.repl .repl-tree.word-wrap .monaco-tl-contents {
.monaco-workbench .repl .repl-tree.word-wrap .monaco-tl-contents {
/* Wrap words but also do not trim whitespace #6275 */
word-wrap: break-word;
white-space: pre-wrap;
@@ -30,25 +30,20 @@
cursor: pointer;
}
.repl .repl-tree .output.expression.value-and-source {
.monaco-workbench .repl .repl-tree .output.expression.value-and-source {
display: flex;
}
.repl .repl-tree .output.expression.value-and-source .value {
.monaco-workbench .repl .repl-tree .output.expression.value-and-source .value {
flex: 1;
}
.repl .repl-tree .monaco-tl-contents .arrow {
.monaco-workbench .repl .repl-tree .monaco-tl-contents .arrow {
position:absolute;
left: 2px;
opacity: 0.25;
}
.vs-dark .repl .repl-tree .monaco-tl-contents .arrow {
opacity: 0.4;
}
.repl .repl-tree .output.expression.value-and-source .source {
.monaco-workbench .repl .repl-tree .output.expression.value-and-source .source {
margin-left: 4px;
margin-right: 8px;
cursor: pointer;
@@ -59,36 +54,21 @@
max-width: 150px;
}
.repl .repl-tree .monaco-list-row {
cursor: text;
}
.repl .repl-tree .output.expression > .value,
.repl .repl-tree .evaluation-result.expression > .value {
.monaco-workbench .repl .repl-tree .output.expression > .value,
.monaco-workbench .repl .repl-tree .evaluation-result.expression > .value {
margin-left: 0px;
}
.repl .repl-tree .output.expression > .annotation,
.repl .repl-tree .evaluation-result.expression > .annotation {
font-size: inherit;
padding-left: 6px;
}
.repl .repl-tree .output.expression .name:not(:empty) {
.monaco-workbench .repl .repl-tree .output.expression .name:not(:empty) {
margin-right: 6px;
}
.repl .repl-input-wrapper {
.monaco-workbench .repl .repl-input-wrapper {
display: flex;
align-items: center;
}
/* Only show 'stale expansion' info when the element gets expanded. */
.repl .repl-tree .evaluation-result > .annotation::before {
content: '';
}
.repl .repl-input-wrapper .repl-input-chevron {
.monaco-workbench .repl .repl-input-wrapper .repl-input-chevron {
padding: 0 6px 0 8px;
width: 16px;
height: 100%;
@@ -99,34 +79,10 @@
}
/* Output coloring and styling */
.repl .repl-tree .output.expression > .ignore {
.monaco-workbench .repl .repl-tree .output.expression > .ignore {
font-style: italic;
}
.vs .repl .repl-tree .output.expression > .annotation {
color: #007ACC;
}
.vs-dark .repl .repl-tree .output.expression > .annotation {
color: #1B80B2;
}
.hc-black .repl .repl-tree .output.expression > .annotation {
color: #0000FF;
}
.vs .repl .repl-tree .output.expression > .warn {
color: #cd9731;
}
.vs-dark .repl .repl-tree .output.expression > .warn {
color: #cd9731;
}
.hc-black .repl .repl-tree .output.expression > .warn {
color: #008000;
}
/* ANSI Codes */
.monaco-workbench .repl .repl-tree .output.expression .code-bold { font-weight: bold; }
.monaco-workbench .repl .repl-tree .output.expression .code-italic { font-style: italic; }

View File

@@ -349,6 +349,13 @@ export class RawDebugSession implements IDisposable {
return Promise.reject(new Error('restartFrame not supported'));
}
stepInTargets(args: DebugProtocol.StepInTargetsArguments): Promise<DebugProtocol.StepInTargetsResponse> {
if (this.capabilities.supportsStepInTargetsRequest) {
return this.send('stepInTargets', args);
}
return Promise.reject(new Error('stepInTargets not supported'));
}
completions(args: DebugProtocol.CompletionsArguments, token: CancellationToken): Promise<DebugProtocol.CompletionsResponse> {
if (this.capabilities.supportsCompletionsRequest) {
return this.send<DebugProtocol.CompletionsResponse>('completions', args, token);

View File

@@ -5,7 +5,6 @@
import 'vs/css!./media/repl';
import { URI as uri } from 'vs/base/common/uri';
import { Color } from 'vs/base/common/color';
import { IAction, IActionViewItem, Action } from 'vs/base/common/actions';
import * as dom from 'vs/base/browser/dom';
import * as aria from 'vs/base/browser/ui/aria/aria';
@@ -21,7 +20,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { ICodeEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser';
import { memoize } from 'vs/base/common/decorators';
import { dispose, IDisposable, Disposable } from 'vs/base/common/lifecycle';
@@ -34,7 +33,7 @@ import { createAndBindHistoryNavigationWidgetScopedContextKeyService } from 'vs/
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { getSimpleEditorOptions, getSimpleCodeEditorWidgetOptions } from 'vs/workbench/contrib/codeEditor/browser/simpleEditorOptions';
import { IDecorationOptions } from 'vs/editor/common/editorCommon';
import { transparent, editorForeground, inputBorder } from 'vs/platform/theme/common/colorRegistry';
import { transparent, editorForeground } from 'vs/platform/theme/common/colorRegistry';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { FocusSessionActionViewItem } from 'vs/workbench/contrib/debug/browser/debugActionViewItems';
import { CompletionContext, CompletionList, CompletionProviderRegistry, CompletionItem, completionKindFromString, CompletionItemKind, CompletionItemInsertTextRule } from 'vs/editor/common/modes';
@@ -60,6 +59,7 @@ import { IOpenerService } from 'vs/platform/opener/common/opener';
import { ReplGroup } from 'vs/workbench/contrib/debug/common/replModel';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { EDITOR_FONT_DEFAULTS, EditorOption } from 'vs/editor/common/config/editorOptions';
import { MOUSE_CURSOR_TEXT_CSS_CLASS_NAME } from 'vs/base/browser/ui/mouseCursor/mouseCursor';
const $ = dom.$;
@@ -87,7 +87,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget {
private replInputContainer!: HTMLElement;
private dimension!: dom.Dimension;
private replInputLineCount = 1;
private model!: ITextModel;
private model: ITextModel | undefined;
private historyNavigationEnablement!: IContextKey<boolean>;
private scopedInstantiationService!: IInstantiationService;
private replElementsChangeListener: IDisposable | undefined;
@@ -271,7 +271,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget {
if (isCodeEditor(activeEditorControl)) {
this.modelChangeListener.dispose();
this.modelChangeListener = activeEditorControl.onDidChangeModelLanguage(() => this.setMode());
if (activeEditorControl.hasModel()) {
if (this.model && activeEditorControl.hasModel()) {
this.model.setMode(activeEditorControl.getModel().getLanguageIdentifier());
}
}
@@ -397,16 +397,18 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget {
getVisibleContent(): string {
let text = '';
const lineDelimiter = this.textResourcePropertiesService.getEOL(this.model.uri);
const traverseAndAppend = (node: ITreeNode<IReplElement, FuzzyScore>) => {
node.children.forEach(child => {
text += child.element.toString().trimRight() + lineDelimiter;
if (!child.collapsed && child.children.length) {
traverseAndAppend(child);
}
});
};
traverseAndAppend(this.tree.getNode());
if (this.model) {
const lineDelimiter = this.textResourcePropertiesService.getEOL(this.model.uri);
const traverseAndAppend = (node: ITreeNode<IReplElement, FuzzyScore>) => {
node.children.forEach(child => {
text += child.element.toString().trimRight() + lineDelimiter;
if (!child.collapsed && child.children.length) {
traverseAndAppend(child);
}
});
};
traverseAndAppend(this.tree.getNode());
}
return removeAnsiEscapeCodes(text);
}
@@ -508,7 +510,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget {
super.renderBody(parent);
this.container = dom.append(parent, $('.repl'));
const treeContainer = dom.append(this.container, $('.repl-tree'));
const treeContainer = dom.append(this.container, $(`.repl-tree.${MOUSE_CURSOR_TEXT_CSS_CLASS_NAME}`));
this.createReplInput(this.container);
this.replDelegate = new ReplDelegate(this.configurationService);
@@ -812,13 +814,3 @@ export class ClearReplAction extends Action {
function getReplView(viewsService: IViewsService): Repl | undefined {
return viewsService.getActiveViewWithId(REPL_VIEW_ID) as Repl ?? undefined;
}
registerThemingParticipant((theme, collector) => {
const inputBorderColor = theme.getColor(inputBorder) || Color.fromHex('#80808060');
collector.addRule(`
.repl .repl-input-wrapper {
border-top: 1px solid ${inputBorderColor};
}
`);
});

View File

@@ -23,7 +23,6 @@ import { IReplElementSource, IDebugService, IExpression, IReplElement, IDebugCon
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { localize } from 'vs/nls';
import { Codicon } from 'vs/base/common/codicons';
const $ = dom.$;
@@ -37,7 +36,6 @@ interface IReplGroupTemplateData {
interface IReplEvaluationResultTemplateData {
value: HTMLElement;
annotation: HTMLElement;
}
interface ISimpleReplElementTemplateData {
@@ -53,7 +51,6 @@ interface IRawObjectReplTemplateData {
expression: HTMLElement;
name: HTMLElement;
value: HTMLElement;
annotation: HTMLElement;
label: HighlightedLabel;
}
@@ -116,9 +113,8 @@ export class ReplEvaluationResultsRenderer implements ITreeRenderer<ReplEvaluati
renderTemplate(container: HTMLElement): IReplEvaluationResultTemplateData {
const output = dom.append(container, $('.evaluation-result.expression'));
const value = dom.append(output, $('span.value'));
const annotation = dom.append(output, $('span'));
return { value, annotation };
return { value };
}
renderElement(element: ITreeNode<ReplEvaluationResult, FuzzyScore>, index: number, templateData: IReplEvaluationResultTemplateData): void {
@@ -128,10 +124,6 @@ export class ReplEvaluationResultsRenderer implements ITreeRenderer<ReplEvaluati
colorize: true,
linkDetector: this.linkDetector
});
if (expression.hasChildren) {
templateData.annotation.className = 'annotation ' + Codicon.info.classNames;
templateData.annotation.title = localize('stateCapture', "Object state is captured from first evaluation");
}
}
disposeTemplate(templateData: IReplEvaluationResultTemplateData): void {
@@ -240,9 +232,8 @@ export class ReplRawObjectsRenderer implements ITreeRenderer<RawObjectReplElemen
const name = dom.append(expression, $('span.name'));
const label = new HighlightedLabel(name, false);
const value = dom.append(expression, $('span.value'));
const annotation = dom.append(expression, $('span'));
return { container, expression, name, label, value, annotation };
return { container, expression, name, label, value };
}
renderElement(node: ITreeNode<RawObjectReplElement, FuzzyScore>, index: number, templateData: IRawObjectReplTemplateData): void {
@@ -260,15 +251,6 @@ export class ReplRawObjectsRenderer implements ITreeRenderer<RawObjectReplElemen
showHover: false,
linkDetector: this.linkDetector
});
// annotation if any
if (element.annotation) {
templateData.annotation.className = 'annotation ' + Codicon.info.classNames;
templateData.annotation.title = element.annotation;
} else {
templateData.annotation.className = '';
templateData.annotation.title = '';
}
}
disposeTemplate(templateData: IRawObjectReplTemplateData): void {

View File

@@ -194,8 +194,8 @@ export class VariablesView extends ViewPane {
}
if (session && session.capabilities.supportsDataBreakpoints) {
const response = await session.dataBreakpointInfo(variable.name, variable.parent.reference);
const dataid = response.dataId;
if (dataid) {
const dataid = response?.dataId;
if (response && dataid) {
actions.push(new Separator());
actions.push(new Action('debug.breakWhenValueChanges', nls.localize('breakWhenValueChanges', "Break When Value Changes"), undefined, true, () => {
return this.debugService.addDataBreakpoint(response.description, dataid, !!response.canPersist, response.accessTypes);
@@ -359,7 +359,7 @@ class VariablesAccessibilityProvider implements IListAccessibilityProvider<IExpr
return nls.localize('variableScopeAriaLabel', "Scope {0}", element.name);
}
if (element instanceof Variable) {
return nls.localize('variableAriaLabel', "{0}, value {1}", element.name, element.value);
return nls.localize({ key: 'variableAriaLabel', comment: ['Placeholders are variable name and variable value respectivly. They should not be translated.'] }, "{0}, value {1}", element.name, element.value);
}
return null;

View File

@@ -189,7 +189,7 @@ export class WatchExpressionsView extends ViewPane {
this.debugService.getViewModel().setSelectedExpression(expression);
return Promise.resolve();
}));
actions.push(this.instantiationService.createInstance(CopyValueAction, CopyValueAction.ID, CopyValueAction.LABEL, expression.value, 'watch'));
actions.push(this.instantiationService.createInstance(CopyValueAction, CopyValueAction.ID, CopyValueAction.LABEL, expression, 'watch'));
actions.push(new Separator());
actions.push(new Action('debug.removeWatchExpression', nls.localize('removeWatchExpression', "Remove Expression"), undefined, true, () => {

View File

@@ -10,12 +10,12 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextKeyService, RawContextKey, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { localize } from 'vs/nls';
import { StartAction, ConfigureAction } from 'vs/workbench/contrib/debug/browser/debugActions';
import { StartAction, ConfigureAction, SelectAndStartAction } from 'vs/workbench/contrib/debug/browser/debugActions';
import { IDebugService } from 'vs/workbench/contrib/debug/common/debug';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IViewDescriptorService, IViewsRegistry, Extensions } from 'vs/workbench/common/views';
import { IViewDescriptorService, IViewsRegistry, Extensions, ViewContentPriority } from 'vs/workbench/common/views';
import { Registry } from 'vs/platform/registry/common/platform';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { WorkbenchStateContext } from 'vs/workbench/browser/contextkeys';
@@ -119,6 +119,12 @@ viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, {
preconditions: [CONTEXT_DEBUGGER_INTERESTED_IN_ACTIVE_EDITOR]
});
viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, {
content: localize({ key: 'detectThenRunAndDebug', comment: ['Please do not translate the word "commmand", it is part of our internal syntax which must not change'] },
"[Show](command:{0}) all automatic debug configurations.", SelectAndStartAction.ID),
priority: ViewContentPriority.Lowest
});
viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, {
content: localize({ key: 'customizeRunAndDebug', comment: ['Please do not translate the word "commmand", it is part of our internal syntax which must not change'] },
"To customize Run and Debug [create a launch.json file](command:{0}).", ConfigureAction.ID),

View File

@@ -24,6 +24,7 @@ import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService'
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { CancellationToken } from 'vs/base/common/cancellation';
import { DebugConfigurationProviderTriggerKind } from 'vs/workbench/api/common/extHostTypes';
import { DebugCompoundRoot } from 'vs/workbench/contrib/debug/common/debugCompoundRoot';
export const VIEWLET_ID = 'workbench.view.debug';
@@ -56,6 +57,7 @@ export const CONTEXT_FOCUSED_SESSION_IS_ATTACH = new RawContextKey<boolean>('foc
export const CONTEXT_STEP_BACK_SUPPORTED = new RawContextKey<boolean>('stepBackSupported', false);
export const CONTEXT_RESTART_FRAME_SUPPORTED = new RawContextKey<boolean>('restartFrameSupported', false);
export const CONTEXT_JUMP_TO_CURSOR_SUPPORTED = new RawContextKey<boolean>('jumpToCursorSupported', false);
export const CONTEXT_STEP_INTO_TARGETS_SUPPORTED = new RawContextKey<boolean>('stepIntoTargetsSupported', false);
export const CONTEXT_BREAKPOINTS_EXIST = new RawContextKey<boolean>('breakpointsExist', false);
export const EDITOR_CONTRIBUTION_ID = 'editor.contrib.debug';
@@ -154,6 +156,7 @@ export interface IDebugSessionOptions {
noDebug?: boolean;
parentSession?: IDebugSession;
repl?: IDebugSessionReplMode;
compoundRoot?: DebugCompoundRoot;
}
export interface IDebugSession extends ITreeElement {
@@ -214,7 +217,7 @@ export interface IDebugSession extends ITreeElement {
sendBreakpoints(modelUri: uri, bpts: IBreakpoint[], sourceModified: boolean): Promise<void>;
sendFunctionBreakpoints(fbps: IFunctionBreakpoint[]): Promise<void>;
dataBreakpointInfo(name: string, variablesReference?: number): Promise<{ dataId: string | null, description: string, canPersist?: boolean, accessTypes?: DebugProtocol.DataBreakpointAccessType[] }>;
dataBreakpointInfo(name: string, variablesReference?: number): Promise<{ dataId: string | null, description: string, canPersist?: boolean, accessTypes?: DebugProtocol.DataBreakpointAccessType[] } | undefined>;
sendDataBreakpoints(dbps: IDataBreakpoint[]): Promise<void>;
sendExceptionBreakpoints(exbpts: IExceptionBreakpoint[]): Promise<void>;
breakpointsLocations(uri: uri, lineNumber: number): Promise<IPosition[]>;
@@ -229,7 +232,7 @@ export interface IDebugSession extends ITreeElement {
restartFrame(frameId: number, threadId: number): Promise<void>;
next(threadId: number): Promise<void>;
stepIn(threadId: number): Promise<void>;
stepIn(threadId: number, targetId?: number): Promise<void>;
stepOut(threadId: number): Promise<void>;
stepBack(threadId: number): Promise<void>;
continue(threadId: number): Promise<void>;
@@ -237,6 +240,7 @@ export interface IDebugSession extends ITreeElement {
pause(threadId: number): Promise<void>;
terminateThreads(threadIds: number[]): Promise<void>;
stepInTargets(frameId: number): Promise<{ id: number, label: string }[]>;
completions(frameId: number | undefined, text: string, position: Position, overwriteBefore: number, token: CancellationToken): Promise<DebugProtocol.CompletionsResponse>;
setVariable(variablesReference: number | undefined, name: string, value: string): Promise<DebugProtocol.SetVariableResponse>;
loadSource(resource: uri): Promise<DebugProtocol.SourceResponse>;
@@ -516,6 +520,7 @@ export interface IConfig extends IEnvConfig {
export interface ICompound {
name: string;
stopAll?: boolean;
preLaunchTask?: string | TaskIdentifier;
configurations: (string | { name: string, folder: string })[];
presentation?: IConfigPresentation;
@@ -633,10 +638,11 @@ export interface IConfigurationManager {
*/
readonly selectedConfiguration: {
launch: ILaunch | undefined;
config: IConfig | undefined;
name: string | undefined;
};
selectConfiguration(launch: ILaunch | undefined, name?: string, debugStarted?: boolean): void;
selectConfiguration(launch: ILaunch | undefined, name?: string, config?: IConfig): void;
getLaunches(): ReadonlyArray<ILaunch>;
@@ -717,7 +723,7 @@ export interface ILaunch {
/**
* Opens the launch.json file. Creates if it does not exist.
*/
openConfigFile(sideBySide: boolean, preserveFocus: boolean, type?: string, token?: CancellationToken): Promise<{ editor: IEditorPane | null, created: boolean }>;
openConfigFile(preserveFocus: boolean, type?: string, token?: CancellationToken): Promise<{ editor: IEditorPane | null, created: boolean }>;
}
// Debug service interfaces

View File

@@ -0,0 +1,20 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter } from 'vs/base/common/event';
export class DebugCompoundRoot {
private stopped = false;
private stopEmitter = new Emitter<void>();
onDidSessionStop = this.stopEmitter.event;
sessionStopped(): void {
if (!this.stopped) { // avoid sending extranous terminate events
this.stopped = true;
this.stopEmitter.fire();
}
}
}

View File

@@ -215,6 +215,11 @@ export const launchSchema: IJSONSchema = {
},
description: nls.localize('app.launch.json.compounds.configurations', "Names of configurations that will be started as part of this compound.")
},
stopAll: {
type: 'boolean',
default: false,
description: nls.localize('app.launch.json.compound.stopAll', "Controls whether manually terminating one session will stop all of the compound sessions.")
},
preLaunchTask: {
type: 'string',
default: '',

View File

@@ -23,6 +23,22 @@ export function formatPII(value: string, excludePII: boolean, args: { [key: stri
});
}
/**
* Filters exceptions (keys marked with "!") from the given object. Used to
* ensure exception data is not sent on web remotes, see #97628.
*/
export function filterExceptionsFromTelemetry<T extends { [key: string]: unknown }>(data: T): Partial<T> {
const output: Partial<T> = {};
for (const key of Object.keys(data) as (keyof T & string)[]) {
if (!key.startsWith('!')) {
output[key] = data[key];
}
}
return output;
}
export function isSessionAttach(session: IDebugSession): boolean {
return session.configuration.request === 'attach' && !getExtensionHostDebugSession(session);
}

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { Event, Emitter } from 'vs/base/common/event';
import { CONTEXT_EXPRESSION_SELECTED, IViewModel, IStackFrame, IDebugSession, IThread, IExpression, IFunctionBreakpoint, CONTEXT_BREAKPOINT_SELECTED, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_JUMP_TO_CURSOR_SUPPORTED } from 'vs/workbench/contrib/debug/common/debug';
import { CONTEXT_EXPRESSION_SELECTED, IViewModel, IStackFrame, IDebugSession, IThread, IExpression, IFunctionBreakpoint, CONTEXT_BREAKPOINT_SELECTED, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, CONTEXT_STEP_INTO_TARGETS_SUPPORTED } from 'vs/workbench/contrib/debug/common/debug';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { isSessionAttach } from 'vs/workbench/contrib/debug/common/debugUtils';
@@ -27,6 +27,7 @@ export class ViewModel implements IViewModel {
private stepBackSupportedContextKey: IContextKey<boolean>;
private focusedSessionIsAttach: IContextKey<boolean>;
private restartFrameSupportedContextKey: IContextKey<boolean>;
private stepIntoTargetsSupported: IContextKey<boolean>;
private jumpToCursorSupported: IContextKey<boolean>;
constructor(contextKeyService: IContextKeyService) {
@@ -37,6 +38,7 @@ export class ViewModel implements IViewModel {
this.stepBackSupportedContextKey = CONTEXT_STEP_BACK_SUPPORTED.bindTo(contextKeyService);
this.focusedSessionIsAttach = CONTEXT_FOCUSED_SESSION_IS_ATTACH.bindTo(contextKeyService);
this.restartFrameSupportedContextKey = CONTEXT_RESTART_FRAME_SUPPORTED.bindTo(contextKeyService);
this.stepIntoTargetsSupported = CONTEXT_STEP_INTO_TARGETS_SUPPORTED.bindTo(contextKeyService);
this.jumpToCursorSupported = CONTEXT_JUMP_TO_CURSOR_SUPPORTED.bindTo(contextKeyService);
}
@@ -67,6 +69,7 @@ export class ViewModel implements IViewModel {
this.loadedScriptsSupportedContextKey.set(session ? !!session.capabilities.supportsLoadedSourcesRequest : false);
this.stepBackSupportedContextKey.set(session ? !!session.capabilities.supportsStepBack : false);
this.restartFrameSupportedContextKey.set(session ? !!session.capabilities.supportsRestartFrame : false);
this.stepIntoTargetsSupported.set(session ? !!session.capabilities.supportsStepInTargetsRequest : false);
this.jumpToCursorSupported.set(session ? !!session.capabilities.supportsGotoTargetsRequest : false);
const attach = !!session && isSessionAttach(session);
this.focusedSessionIsAttach.set(attach);

View File

@@ -5,7 +5,7 @@
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IExtensionHostDebugService } from 'vs/platform/debug/common/extensionHostDebug';
import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService';
import { ExtensionHostDebugChannelClient, ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/extensionHostDebugIpc';
export class ExtensionHostDebugService extends ExtensionHostDebugChannelClient {

View File

@@ -10,10 +10,17 @@ import { getPathFromAmdModule } from 'vs/base/common/amd';
import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { cleanRemoteAuthority } from 'vs/platform/telemetry/common/telemetryUtils';
export class NodeDebugHelperService implements IDebugHelperService {
_serviceBrand: undefined;
constructor(
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
) { }
createTelemetryService(configurationService: IConfigurationService, args: string[]): TelemetryService | undefined {
const client = new TelemetryClient(
@@ -33,7 +40,10 @@ export class NodeDebugHelperService implements IDebugHelperService {
const channel = client.getChannel('telemetryAppender');
const appender = new TelemetryAppenderClient(channel);
return new TelemetryService({ appender, sendErrorTelemetry: true }, configurationService);
return new TelemetryService({
appender,
sendErrorTelemetry: cleanRemoteAuthority(this.environmentService.configuration.remoteAuthority) !== 'other'
}, configurationService);
}
}

View File

@@ -164,7 +164,7 @@ export function prepareCommand(args: DebugProtocol.RunInTerminalRequestArguments
case ShellType.bash:
quote = (s: string) => {
s = s.replace(/(["'\\])/g, '\\$1');
s = s.replace(/(["'\\\$])/g, '\\$1');
return (s.indexOf(' ') >= 0 || s.indexOf(';') >= 0 || s.length === 0) ? `"${s}"` : s;
};

View File

@@ -0,0 +1,74 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { MockDebugAdapter, createMockDebugModel } from 'vs/workbench/contrib/debug/test/common/mockDebug';
import { DebugModel } from 'vs/workbench/contrib/debug/common/debugModel';
import { DebugSession } from 'vs/workbench/contrib/debug/browser/debugSession';
import { generateUuid } from 'vs/base/common/uuid';
import { NullOpenerService } from 'vs/platform/opener/common/opener';
import { RawDebugSession } from 'vs/workbench/contrib/debug/browser/rawDebugSession';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { stub, SinonStub } from 'sinon';
import { timeout } from 'vs/base/common/async';
suite('Debug - DebugSession telemetry', () => {
let model: DebugModel;
let session: DebugSession;
let adapter: MockDebugAdapter;
let telemetry: { isOptedIn: boolean; sendErrorTelemetry: boolean; publicLog: SinonStub };
setup(() => {
telemetry = { isOptedIn: true, sendErrorTelemetry: true, publicLog: stub() };
adapter = new MockDebugAdapter();
model = createMockDebugModel();
const telemetryService = telemetry as Partial<ITelemetryService> as ITelemetryService;
session = new DebugSession(generateUuid(), undefined!, undefined!, model, undefined, undefined!, telemetryService, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, NullOpenerService, undefined!, undefined!);
session.initializeForTest(new RawDebugSession(adapter, undefined!, undefined!, telemetryService, undefined!, undefined!, undefined!));
});
test('does not send telemetry when opted out', async () => {
telemetry.isOptedIn = false;
adapter.sendEventBody('output', {
category: 'telemetry',
output: 'someEvent',
data: { foo: 'bar', '!err': 'oh no!' }
});
await timeout(0);
assert.strictEqual(telemetry.publicLog.callCount, 0);
});
test('logs telemetry and exceptions when enabled', async () => {
adapter.sendEventBody('output', {
category: 'telemetry',
output: 'someEvent',
data: { foo: 'bar', '!err': 'oh no!' }
});
await timeout(0);
assert.deepStrictEqual(telemetry.publicLog.args[0], [
'someEvent',
{ foo: 'bar', '!err': 'oh no!' }
]);
});
test('filters exceptions when error reporting disabled', async () => {
telemetry.sendErrorTelemetry = false;
adapter.sendEventBody('output', {
category: 'telemetry',
output: 'someEvent',
data: { foo: 'bar', '!err': 'oh no!' }
});
await timeout(0);
assert.deepStrictEqual(telemetry.publicLog.args[0], [
'someEvent',
{ foo: 'bar' }
]);
});
});

View File

@@ -136,6 +136,10 @@ export class MockDebugService implements IDebugService {
export class MockSession implements IDebugSession {
stepInTargets(frameId: number): Promise<{ id: number; label: string; }[]> {
throw new Error('Method not implemented.');
}
cancel(_progressId: string): Promise<DebugProtocol.CancelResponse> {
throw new Error('Method not implemented.');
}
@@ -144,7 +148,7 @@ export class MockSession implements IDebugSession {
throw new Error('Method not implemented.');
}
dataBreakpointInfo(name: string, variablesReference?: number | undefined): Promise<{ dataId: string | null; description: string; canPersist?: boolean | undefined; }> {
dataBreakpointInfo(name: string, variablesReference?: number | undefined): Promise<{ dataId: string | null; description: string; canPersist?: boolean | undefined; } | undefined> {
throw new Error('Method not implemented.');
}
@@ -304,7 +308,7 @@ export class MockSession implements IDebugSession {
next(threadId: number): Promise<void> {
throw new Error('Method not implemented.');
}
stepIn(threadId: number): Promise<void> {
stepIn(threadId: number, targetId?: number): Promise<void> {
throw new Error('Method not implemented.');
}
stepOut(threadId: number): Promise<void> {

View File

@@ -15,7 +15,7 @@ import { IWorkbenchExtensionEnablementService } from 'vs/workbench/services/exte
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
import { Emitter } from 'vs/base/common/event';
import { TestExtensionEnablementService } from 'vs/workbench/services/extensionManagement/test/browser/extensionEnablementService.test';
import { URLService } from 'vs/platform/url/node/urlService';
import { NativeURLService } from 'vs/platform/url/common/urlService';
import { IURLService } from 'vs/platform/url/common/url';
import { ITelemetryService, lastSessionDateStorageKey } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
@@ -89,7 +89,7 @@ suite('Experiment Service', () => {
instantiationService.stub(IExtensionManagementService, 'onDidUninstallExtension', didUninstallEvent.event);
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
instantiationService.stub(ITelemetryService, NullTelemetryService);
instantiationService.stub(IURLService, URLService);
instantiationService.stub(IURLService, NativeURLService);
instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]);
testConfigurationService = new TestConfigurationService();
instantiationService.stub(IConfigurationService, testConfigurationService);

View File

@@ -7,7 +7,6 @@ import { IExtensionTipsService, IExtensionManagementService, ILocalExtension, IC
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { ExtensionRecommendations, ExtensionRecommendation } from 'vs/workbench/contrib/extensions/browser/extensionRecommendations';
import { localize } from 'vs/nls';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { ExtensionRecommendationReason } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
@@ -75,7 +74,7 @@ export class ConfigBasedRecommendations extends ExtensionRecommendations {
return;
}
const local = await this.extensionManagementService.getInstalled(ExtensionType.User);
const local = await this.extensionManagementService.getInstalled();
const { uninstalled } = this.groupByInstalled(distinct(this.importantTips.map(({ extensionId }) => extensionId)), local);
if (uninstalled.length === 0) {
return;

View File

@@ -9,7 +9,6 @@ import { ExtensionRecommendations, ExtensionRecommendation } from 'vs/workbench/
import { timeout } from 'vs/base/common/async';
import { localize } from 'vs/nls';
import { IStringDictionary } from 'vs/base/common/collections';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { basename } from 'vs/base/common/path';
@@ -61,7 +60,7 @@ export class ExeBasedRecommendations extends ExtensionRecommendations {
importantExeBasedRecommendations[tip.extensionId.toLowerCase()] = tip;
});
const local = await this.extensionManagementService.getInstalled(ExtensionType.User);
const local = await this.extensionManagementService.getInstalled();
const { installed, uninstalled } = this.groupByInstalled(Object.keys(importantExeBasedRecommendations), local);
/* Log installed and uninstalled exe based recommendations */

View File

@@ -610,7 +610,7 @@ export class ExtensionEditor extends BaseEditor {
const webview = this.contentDisposables.add(this.webviewService.createWebviewOverlay('extensionEditor', {
enableFindWidget: true,
}, {}));
}, {}, undefined));
webview.claim(this);
webview.layoutWebviewOverElement(template.content);

View File

@@ -45,11 +45,10 @@ import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { CONTEXT_SYNC_ENABLEMENT } from 'vs/platform/userDataSync/common/userDataSync';
import { IQuickAccessRegistry, Extensions } from 'vs/platform/quickinput/common/quickAccess';
import { InstallExtensionQuickAccessProvider, ManageExtensionsQuickAccessProvider } from 'vs/workbench/contrib/extensions/browser/extensionsQuickAccess';
import { ExtensionRecommendationsService } from 'vs/workbench/contrib/extensions/browser/extensionRecommendationsService';
import { CONTEXT_SYNC_ENABLEMENT } from 'vs/workbench/services/userDataSync/common/userDataSync';
// Singletons
registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService);
@@ -458,15 +457,11 @@ registerAction2(class extends Action2 {
}
async run(accessor: ServicesAccessor, id: string) {
const configurationService = accessor.get(IConfigurationService);
const ignoredExtensions = [...configurationService.getValue<string[]>('sync.ignoredExtensions')];
const index = ignoredExtensions.findIndex(ignoredExtension => areSameExtensions({ id: ignoredExtension }, { id }));
if (index !== -1) {
ignoredExtensions.splice(index, 1);
} else {
ignoredExtensions.push(id);
const extensionsWorkbenchService = accessor.get(IExtensionsWorkbenchService);
const extension = extensionsWorkbenchService.local.find(e => areSameExtensions({ id }, e.identifier));
if (extension) {
return extensionsWorkbenchService.toggleExtensionIgnoredToSync(extension);
}
return configurationService.updateValue('sync.ignoredExtensions', ignoredExtensions.length ? ignoredExtensions : undefined, ConfigurationTarget.USER);
}
});

View File

@@ -236,7 +236,7 @@ export class InstallAction extends ExtensionAction {
const extension = await this.install(this.extension);
alert(localize('installExtensionComplete', "Installing extension {0} is completed. Please reload Azure Data Studio to enable it.", this.extension.displayName));
alert(localize('installExtensionComplete', "Installing extension {0} is completed.", this.extension.displayName));
// {{SQL CARBON EDIT}} Add extension object check since ADS third party extensions will be directed to a download page
// and the extension object will be undefined.
@@ -827,7 +827,7 @@ export class MenuItemExtensionAction extends ExtensionAction {
constructor(
private readonly action: IAction,
@IConfigurationService private readonly configurationService: IConfigurationService
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
) {
super(action.id, action.label);
}
@@ -837,7 +837,7 @@ export class MenuItemExtensionAction extends ExtensionAction {
return;
}
if (this.action.id === TOGGLE_IGNORE_EXTENSION_ACTION_ID) {
this.checked = !this.configurationService.getValue<string[]>('sync.ignoredExtensions').some(id => areSameExtensions({ id }, this.extension!.identifier));
this.checked = !this.extensionsWorkbenchService.isExtensionIgnoredToSync(this.extension);
}
}
@@ -1380,7 +1380,7 @@ export class ReloadAction extends ExtensionAction {
this.enabled = true;
this.label = localize('reloadRequired', "Reload Required");
this.tooltip = localize('postEnableTooltip', "Please reload Azure Data Studio to enable this extension."); // {{SQL CARBON EDIT}} - replace Visual Studio Code with Azure Data Studio
alert(localize('installExtensionComplete', "Installing extension {0} is completed. Please reload Azure Data Studio to enable it.", this.extension.displayName)); // {{SQL CARBON EDIT}} - replace Visual Studio Code with Azure Data Studio
alert(localize('installExtensionCompletedAndReloadRequired', "Installing extension {0} is completed. Please reload Azure Data Studio to enable it.", this.extension.displayName)); // {{SQL CARBON EDIT}} - replace Visual Studio Code with Azure Data Studio
return;
}
}
@@ -2681,7 +2681,8 @@ export class SyncIgnoredIconAction extends ExtensionAction {
private static readonly DISABLE_CLASS = `${SyncIgnoredIconAction.ENABLE_CLASS} hide`;
constructor(
@IConfigurationService private readonly configurationService: IConfigurationService
@IConfigurationService private readonly configurationService: IConfigurationService,
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
) {
super('extensions.syncignore', '', SyncIgnoredIconAction.DISABLE_CLASS, false);
this._register(Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectedKeys.includes('sync.ignoredExtensions'))(() => this.update()));
@@ -2691,11 +2692,8 @@ export class SyncIgnoredIconAction extends ExtensionAction {
update(): void {
this.class = SyncIgnoredIconAction.DISABLE_CLASS;
if (this.extension) {
const ignoredExtensions = this.configurationService.getValue<string[]>('sync.ignoredExtensions') || [];
if (ignoredExtensions.some(id => areSameExtensions({ id }, this.extension!.identifier))) {
this.class = SyncIgnoredIconAction.ENABLE_CLASS;
}
if (this.extension && this.extensionsWorkbenchService.isExtensionIgnoredToSync(this.extension)) {
this.class = SyncIgnoredIconAction.ENABLE_CLASS;
}
}

View File

@@ -456,8 +456,8 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE
}
},
onDragOver: (e: DragEvent) => {
if (e.dataTransfer) {
e.dataTransfer.dropEffect = this.isSupportedDragElement(e) ? 'copy' : 'none';
if (this.isSupportedDragElement(e)) {
e.dataTransfer!.dropEffect = 'copy';
}
},
onDrop: async (e: DragEvent) => {
@@ -482,7 +482,7 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE
}
}
}
},
}
}));
super.create(append(this.root, $('.extensions')));

View File

@@ -20,7 +20,7 @@ import {
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, areSameExtensions, getMaliciousExtensionsSet, groupByExtension, ExtensionIdentifierWithVersion } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { URI } from 'vs/base/common/uri';
import { IExtension, ExtensionState, IExtensionsWorkbenchService, AutoUpdateConfigurationKey, AutoCheckUpdatesConfigurationKey } from 'vs/workbench/contrib/extensions/common/extensions';
@@ -38,6 +38,7 @@ import { IExtensionManifest, ExtensionType, IExtension as IPlatformExtension, is
import { IModeService } from 'vs/editor/common/services/modeService';
import { IProductService } from 'vs/platform/product/common/productService';
import { asDomUri } from 'vs/base/browser/dom';
import { getIgnoredExtensions } from 'vs/platform/userDataSync/common/extensionsMerge';
import { isEngineValid } from 'vs/platform/extensions/common/extensionValidator'; // {{SQL CARBON EDIT}}
import { IOpenerService } from 'vs/platform/opener/common/opener'; // {{SQL CARBON EDIT}}
@@ -98,8 +99,8 @@ class Extension implements IExtension {
return this.gallery.publisherDisplayName || this.gallery.publisher;
}
if (this.local!.metadata && this.local!.metadata.publisherDisplayName) {
return this.local!.metadata.publisherDisplayName;
if (this.local?.publisherDisplayName) {
return this.local.publisherDisplayName;
}
return this.local!.manifest.publisher;
@@ -386,7 +387,7 @@ class Extensions extends Disposable {
}
// Sync the local extension with gallery extension if local extension doesnot has metadata
if (extension.local) {
const local = extension.local.metadata ? extension.local : await this.server.extensionManagementService.updateMetadata(extension.local, { id: compatible.identifier.uuid, publisherDisplayName: compatible.publisherDisplayName, publisherId: compatible.publisherId });
const local = extension.local.identifier.uuid ? extension.local : await this.server.extensionManagementService.updateMetadata(extension.local, { id: compatible.identifier.uuid, publisherDisplayName: compatible.publisherDisplayName, publisherId: compatible.publisherId });
extension.local = local;
extension.gallery = compatible;
this._onChange.fire({ extension });
@@ -923,6 +924,39 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
}, () => this.extensionService.reinstallFromGallery(toReinstall).then(() => this.local.filter(local => areSameExtensions(local.identifier, extension.identifier))[0]));
}
isExtensionIgnoredToSync(extension: IExtension): boolean {
const localExtensions = (this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer
? this.local.filter(i => i.server === this.extensionManagementServerService.localExtensionManagementServer)
: this.local)
.filter(l => !!l.local)
.map(l => l.local!);
const ignoredExtensions = getIgnoredExtensions(localExtensions, this.configurationService);
return ignoredExtensions.includes(extension.identifier.id.toLowerCase());
}
toggleExtensionIgnoredToSync(extension: IExtension): Promise<void> {
const isIgnored = this.isExtensionIgnoredToSync(extension);
const isDefaultIgnored = extension.local?.isMachineScoped;
const id = extension.identifier.id.toLowerCase();
// first remove the extension completely from ignored extensions
let currentValue = [...this.configurationService.getValue<string[]>('sync.ignoredExtensions')].map(id => id.toLowerCase());
currentValue = currentValue.filter(v => v !== id && v !== `-${id}`);
// If ignored, then add only if it is ignored by default
if (isIgnored && isDefaultIgnored) {
currentValue.push(`-${id}`);
}
// If asked not to sync, then add only if it is not ignored by default
if (!isIgnored && !isDefaultIgnored) {
currentValue.push(id);
}
return this.configurationService.updateValue('sync.ignoredExtensions', currentValue.length ? currentValue : undefined, ConfigurationTarget.USER);
}
private installWithProgress<T>(installTask: () => Promise<T>, extensionName?: string): Promise<T> {
const title = extensionName ? nls.localize('installing named extension', "Installing '{0}' extension....", extensionName) : nls.localize('installing extension', 'Installing extension....');
return this.progressService.withProgress({

View File

@@ -12,7 +12,6 @@ import { ExtensionRecommendationSource, ExtensionRecommendationReason } from 'vs
import { IExtensionsViewPaneContainer, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions';
import { CancellationToken } from 'vs/base/common/cancellation';
import { localize } from 'vs/nls';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { StorageScope, IStorageService } from 'vs/platform/storage/common/storage';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IProductService } from 'vs/platform/product/common/productService';
@@ -181,7 +180,7 @@ export class FileBasedRecommendations extends ExtensionRecommendations {
return;
}
const installed = await this.extensionManagementService.getInstalled(ExtensionType.User);
const installed = await this.extensionManagementService.getInstalled();
if (await this.promptRecommendedExtensionForFileType(recommendationsToPrompt, installed)) {
return;
}

View File

@@ -91,7 +91,7 @@
margin-left: 10px;
}
.vs .extension-editor > .header > .details > .title > .preview {
.monaco-workbench.vs .extension-editor > .header > .details > .title > .preview {
color: white;
}
@@ -408,8 +408,8 @@
vertical-align: middle;
}
.vs-dark .extension-editor > .body > .content table .colorBox,
.hc-black .extension-editor > .body > .content table .colorBox {
.monaco-workbench.vs-dark .extension-editor > .body > .content table .colorBox,
.monaco-workbench.hc-black .extension-editor > .body > .content table .colorBox {
border-color: rgb(238, 238, 238);
}

View File

@@ -112,16 +112,16 @@
max-width: 100px;
}
.vs .extensions-viewlet > .extensions .monaco-list-row.disabled > .bookmark,
.vs-dark .extensions-viewlet > .extensions .monaco-list-row.disabled > .bookmark,
.vs .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension-list-item > .icon-container > .icon,
.vs-dark .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension-list-item > .icon-container > .icon,
.vs .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension-list-item > .details > .header-container,
.vs-dark .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension-list-item > .details > .header-container,
.vs .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension-list-item > .details > .description,
.vs-dark .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension-list-item > .details > .description,
.vs .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension-list-item > .details > .footer > .author,
.vs-dark .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension-list-item > .details > .footer > .author {
.monaco-workbench.vs .extensions-viewlet > .extensions .monaco-list-row.disabled > .bookmark,
.monaco-workbench.vs-dark .extensions-viewlet > .extensions .monaco-list-row.disabled > .bookmark,
.monaco-workbench.vs .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension-list-item > .icon-container > .icon,
.monaco-workbench.vs-dark .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension-list-item > .icon-container > .icon,
.monaco-workbench.vs .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension-list-item > .details > .header-container,
.monaco-workbench.vs-dark .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension-list-item > .details > .header-container,
.monaco-workbench.vs .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension-list-item > .details > .description,
.monaco-workbench.vs-dark .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension-list-item > .details > .description,
.monaco-workbench.vs .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension-list-item > .details > .footer > .author,
.monaco-workbench.vs-dark .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension-list-item > .details > .footer > .author {
opacity: 0.5;
}

View File

@@ -30,7 +30,7 @@ export class RemoteExtensionsInstaller extends Disposable implements IWorkbenchC
disposable = MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
command: {
id: 'workbench.extensions.installLocalExtensions',
category: localize('remote', "Remote"),
category: localize({ key: 'remote', comment: ['Remote as in remote machine'] }, "Remote"),
title: installLocalExtensionsInRemoteAction.label
}
});

View File

@@ -17,7 +17,6 @@ import { EXTENSIONS_CONFIG } from 'vs/workbench/contrib/extensions/common/extens
import { ILogService } from 'vs/platform/log/common/log';
import { CancellationToken } from 'vs/base/common/cancellation';
import { localize } from 'vs/nls';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { InstallWorkspaceRecommendedExtensionsAction, ShowRecommendedExtensionsAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { StorageScope, IStorageService } from 'vs/platform/storage/common/storage';
@@ -105,7 +104,7 @@ export class WorkspaceRecommendations extends ExtensionRecommendations {
return;
}
let installed = await this.extensionManagementService.getInstalled(ExtensionType.User);
let installed = await this.extensionManagementService.getInstalled();
installed = installed.filter(l => this.extensionEnablementService.getEnablementState(l) !== EnablementState.DisabledByExtensionKind); // Filter extensions disabled by kind
const recommendations = allowedRecommendations.filter(({ extensionId }) => installed.every(local => !areSameExtensions({ id: extensionId }, local.identifier)));

View File

@@ -89,6 +89,10 @@ export interface IExtensionsWorkbenchService {
setEnablement(extensions: IExtension | IExtension[], enablementState: EnablementState): Promise<void>;
open(extension: IExtension, options?: { sideByside?: boolean, preserveFocus?: boolean, pinned?: boolean }): Promise<any>;
checkForUpdates(): Promise<void>;
// Sync APIs
isExtensionIgnoredToSync(extension: IExtension): boolean;
toggleExtensionIgnoredToSync(extension: IExtension): Promise<void>;
}
export const ConfigurationKey = 'extensions';

View File

@@ -12,7 +12,7 @@ import { onUnexpectedError } from 'vs/base/common/errors';
import { StatusbarAlignment, IStatusbarService, IStatusbarEntryAccessor, IStatusbarEntry } from 'vs/workbench/services/statusbar/common/statusbar';
import { IExtensionHostProfileService, ProfileSessionState } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { randomPort } from 'vs/base/node/ports';
import product from 'vs/platform/product/common/product';

View File

@@ -9,7 +9,7 @@ import { IFileService } from 'vs/platform/files/common/files';
import { URI } from 'vs/base/common/uri';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
import { Schemas } from 'vs/base/common/network';
export class OpenExtensionsFolderAction extends Action {

View File

@@ -57,8 +57,8 @@
color: currentColor;
}
.vs .runtime-extensions-editor .extension > .icon-container > .icon,
.vs-dark .runtime-extensions-editor .extension > .icon-container > .icon {
.monaco-workbench.vs .runtime-extensions-editor .extension > .icon-container > .icon,
.monaco-workbench.vs-dark .runtime-extensions-editor .extension > .icon-container > .icon {
opacity: 0.5;
}

View File

@@ -24,7 +24,7 @@ import { RunOnceScheduler } from 'vs/base/common/async';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
import { writeFile } from 'vs/base/node/pfs';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { memoize } from 'vs/base/common/decorators';

View File

@@ -41,7 +41,7 @@ import { ITextModel } from 'vs/editor/common/model';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { INotificationService, Severity, IPromptChoice, IPromptOptions } from 'vs/platform/notification/common/notification';
import { URLService } from 'vs/platform/url/node/urlService';
import { NativeURLService } from 'vs/platform/url/common/urlService';
import { IExperimentService } from 'vs/workbench/contrib/experiments/common/experimentService';
import { TestExperimentService } from 'vs/workbench/contrib/experiments/test/electron-browser/experimentService.test';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
@@ -206,7 +206,7 @@ suite.skip('ExtensionRecommendationsService Test', () => { // {{SQL CARBON EDIT}
instantiationService.stub(IExtensionManagementService, 'onDidUninstallExtension', didUninstallEvent.event);
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
instantiationService.stub(ITelemetryService, NullTelemetryService);
instantiationService.stub(IURLService, URLService);
instantiationService.stub(IURLService, NativeURLService);
instantiationService.stub(IWorkspaceTagsService, new NoOpWorkspaceTagsService());
instantiationService.stub(IStorageService, new TestStorageService());
instantiationService.stub(ILogService, new NullLogService());

View File

@@ -11,11 +11,10 @@ import * as ExtensionsActions from 'vs/workbench/contrib/extensions/browser/exte
import { ExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/browser/extensionsWorkbenchService';
import {
IExtensionManagementService, IExtensionGalleryService, ILocalExtension, IGalleryExtension,
DidInstallExtensionEvent, DidUninstallExtensionEvent, InstallExtensionEvent, IExtensionIdentifier, InstallOperation, IExtensionTipsService
DidInstallExtensionEvent, DidUninstallExtensionEvent, InstallExtensionEvent, IExtensionIdentifier, InstallOperation, IExtensionTipsService, IGalleryMetadata
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, IExtensionRecommendationsService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
import { TestExtensionEnablementService } from 'vs/workbench/services/extensionManagement/test/browser/extensionEnablementService.test';
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
import { IURLService } from 'vs/platform/url/common/url';
@@ -30,7 +29,7 @@ import { TestContextService } from 'vs/workbench/test/common/workbenchTestServic
import { TestSharedProcessService } from 'vs/workbench/test/electron-browser/workbenchTestServices';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILogService, NullLogService } from 'vs/platform/log/common/log';
import { URLService } from 'vs/platform/url/node/urlService';
import { NativeURLService } from 'vs/platform/url/common/urlService';
import { URI } from 'vs/base/common/uri';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
@@ -82,11 +81,21 @@ async function setupTest() {
instantiationService.stub(IExtensionGalleryService, ExtensionGalleryService);
instantiationService.stub(ISharedProcessService, TestSharedProcessService);
instantiationService.stub(IExtensionManagementService, ExtensionManagementService);
instantiationService.stub(IExtensionManagementService, 'onInstallExtension', installEvent.event);
instantiationService.stub(IExtensionManagementService, 'onDidInstallExtension', didInstallEvent.event);
instantiationService.stub(IExtensionManagementService, 'onUninstallExtension', uninstallEvent.event);
instantiationService.stub(IExtensionManagementService, 'onDidUninstallExtension', didUninstallEvent.event);
instantiationService.stub(IExtensionManagementService, <Partial<IExtensionManagementService>>{
onInstallExtension: installEvent.event,
onDidInstallExtension: didInstallEvent.event,
onUninstallExtension: uninstallEvent.event,
onDidUninstallExtension: didUninstallEvent.event,
async getInstalled() { return []; },
async getExtensionsReport() { return []; },
async updateMetadata(local: ILocalExtension, metadata: IGalleryMetadata) {
local.identifier.uuid = metadata.id;
local.publisherDisplayName = metadata.publisherDisplayName;
local.publisherId = metadata.publisherId;
return local;
}
});
instantiationService.stub(IRemoteAgentService, RemoteAgentService);
instantiationService.stub(IExtensionManagementServerService, new class extends ExtensionManagementServerService {
@@ -105,10 +114,8 @@ async function setupTest() {
instantiationService.stub(IExperimentService, instantiationService.createInstance(TestExperimentService));
instantiationService.stub(IExtensionTipsService, instantiationService.createInstance(ExtensionTipsService));
instantiationService.stub(IExtensionRecommendationsService, {});
instantiationService.stub(IURLService, URLService);
instantiationService.stub(IURLService, NativeURLService);
instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', []);
instantiationService.stubPromise(IExtensionManagementService, 'getExtensionsReport', []);
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage());
instantiationService.stub(IExtensionService, <Partial<IExtensionService>>{ getExtensions: () => Promise.resolve([]), onDidChangeExtensions: new Emitter<void>().event, canAddExtension: (extension: IExtensionDescription) => false, canRemoveExtension: (extension: IExtensionDescription) => false });
(<TestExtensionEnablementService>instantiationService.get(IWorkbenchExtensionEnablementService)).reset();
@@ -117,7 +124,7 @@ async function setupTest() {
}
suite('ExtensionsActions Test', () => {
suite('ExtensionsActions', () => {
setup(setupTest);
teardown(() => disposables.dispose());
@@ -2491,8 +2498,7 @@ function aLocalExtension(name: string = 'someext', manifest: any = {}, propertie
properties = assign({
type: ExtensionType.User,
location: URI.file(`pub.${name}`),
identifier: { id: getGalleryExtensionId(manifest.publisher, manifest.name), uuid: undefined },
metadata: { id: getGalleryExtensionId(manifest.publisher, manifest.name), publisherId: manifest.publisher, publisherDisplayName: 'somename' }
identifier: { id: getGalleryExtensionId(manifest.publisher, manifest.name) }
}, properties);
return <ILocalExtension>Object.create({ manifest, ...properties });
}
@@ -2563,7 +2569,13 @@ function createExtensionManagementService(installed: ILocalExtension[] = []): IE
onUninstallExtension: Event.None,
onDidUninstallExtension: Event.None,
getInstalled: () => Promise.resolve<ILocalExtension[]>(installed),
installFromGallery: (extension: IGalleryExtension) => Promise.reject(new Error('not supported'))
installFromGallery: (extension: IGalleryExtension) => Promise.reject(new Error('not supported')),
updateMetadata: async (local: ILocalExtension, metadata: IGalleryMetadata) => {
local.identifier.uuid = metadata.id;
local.publisherDisplayName = metadata.publisherDisplayName;
local.publisherId = metadata.publisherId;
return local;
}
};
}

View File

@@ -30,7 +30,7 @@ import { TestMenuService } from 'vs/workbench/test/browser/workbenchTestServices
import { TestSharedProcessService } from 'vs/workbench/test/electron-browser/workbenchTestServices';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILogService, NullLogService } from 'vs/platform/log/common/log';
import { URLService } from 'vs/platform/url/node/urlService';
import { NativeURLService } from 'vs/platform/url/common/urlService';
import { URI } from 'vs/base/common/uri';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { SinonStub } from 'sinon';
@@ -142,7 +142,7 @@ suite('ExtensionsListView Tests', () => {
return reasons;
}
});
instantiationService.stub(IURLService, URLService);
instantiationService.stub(IURLService, NativeURLService);
});
setup(async () => {

View File

@@ -12,11 +12,10 @@ import { IExtensionsWorkbenchService, ExtensionState, AutoCheckUpdatesConfigurat
import { ExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/browser/extensionsWorkbenchService';
import {
IExtensionManagementService, IExtensionGalleryService, ILocalExtension, IGalleryExtension,
DidInstallExtensionEvent, DidUninstallExtensionEvent, InstallExtensionEvent, IGalleryExtensionAssets, IExtensionIdentifier, InstallOperation, IExtensionTipsService
DidInstallExtensionEvent, DidUninstallExtensionEvent, InstallExtensionEvent, IGalleryExtensionAssets, IExtensionIdentifier, InstallOperation, IExtensionTipsService, IGalleryMetadata
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionRecommendationsService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
import { TestExtensionEnablementService } from 'vs/workbench/services/extensionManagement/test/browser/extensionEnablementService.test';
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
import { IURLService } from 'vs/platform/url/common/url';
@@ -32,7 +31,7 @@ import { ILogService, NullLogService } from 'vs/platform/log/common/log';
import { IProgressService } from 'vs/platform/progress/common/progress';
import { ProgressService } from 'vs/workbench/services/progress/browser/progressService';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { URLService } from 'vs/platform/url/node/urlService';
import { NativeURLService } from 'vs/platform/url/common/urlService';
import { URI } from 'vs/base/common/uri';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
@@ -72,7 +71,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
instantiationService.stub(IProductService, {});
instantiationService.stub(IExtensionGalleryService, ExtensionGalleryService);
instantiationService.stub(IURLService, URLService);
instantiationService.stub(IURLService, NativeURLService);
instantiationService.stub(ISharedProcessService, TestSharedProcessService);
instantiationService.stub(IWorkspaceContextService, new TestContextService());
@@ -85,11 +84,20 @@ suite('ExtensionsWorkbenchServiceTest', () => {
instantiationService.stub(IRemoteAgentService, RemoteAgentService);
instantiationService.stub(IExtensionManagementService, ExtensionManagementService);
instantiationService.stub(IExtensionManagementService, 'onInstallExtension', installEvent.event);
instantiationService.stub(IExtensionManagementService, 'onDidInstallExtension', didInstallEvent.event);
instantiationService.stub(IExtensionManagementService, 'onUninstallExtension', uninstallEvent.event);
instantiationService.stub(IExtensionManagementService, 'onDidUninstallExtension', didUninstallEvent.event);
instantiationService.stub(IExtensionManagementService, <Partial<IExtensionManagementService>>{
onInstallExtension: installEvent.event,
onDidInstallExtension: didInstallEvent.event,
onUninstallExtension: uninstallEvent.event,
onDidUninstallExtension: didUninstallEvent.event,
async getInstalled() { return []; },
async getExtensionsReport() { return []; },
async updateMetadata(local: ILocalExtension, metadata: IGalleryMetadata) {
local.identifier.uuid = metadata.id;
local.publisherDisplayName = metadata.publisherDisplayName;
local.publisherId = metadata.publisherId;
return local;
}
});
instantiationService.stub(IExtensionManagementServerService, <IExtensionManagementServerService>{
localExtensionManagementServer: {
@@ -109,7 +117,6 @@ suite('ExtensionsWorkbenchServiceTest', () => {
setup(async () => {
instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', []);
instantiationService.stubPromise(IExtensionManagementService, 'getExtensionsReport', []);
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage());
instantiationService.stubPromise(INotificationService, 'prompt', 0);
await (<TestExtensionEnablementService>instantiationService.get(IWorkbenchExtensionEnablementService)).reset();
@@ -985,8 +992,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
properties = assign({
type: ExtensionType.User,
location: URI.file(`pub.${name}`),
identifier: { id: getGalleryExtensionId(manifest.publisher, manifest.name), uuid: undefined },
metadata: { id: getGalleryExtensionId(manifest.publisher, manifest.name), publisherId: manifest.publisher, publisherDisplayName: 'somename' }
identifier: { id: getGalleryExtensionId(manifest.publisher, manifest.name) }
}, properties);
return <ILocalExtension>Object.create({ manifest, ...properties });
}

View File

@@ -115,7 +115,8 @@
}
/* Theming */
.vs .monaco-workbench .feedback-form .feedback-alias, .vs .monaco-workbench .feedback-form .feedback-description {
.monaco-workbench.vs .feedback-form .feedback-alias,
.monaco-workbench.vs .feedback-form .feedback-description {
font-family: inherit;
border: 1px solid transparent;
}
@@ -167,16 +168,17 @@
background-color: #E51400;
}
.vs-dark .monaco-workbench .feedback-form h3 {
.monaco-workbench.vs-dark .feedback-form h3 {
font-weight: normal;
font-size: 1.2em;
}
.vs-dark .monaco-workbench .feedback-form .sentiment:hover {
.monaco-workbench.vs-dark .feedback-form .sentiment:hover {
background-color: rgba(30,30,30,0.8);
}
.vs-dark .monaco-workbench .feedback-form .feedback-alias, .vs-dark .monaco-workbench .feedback-form .feedback-description {
.monaco-workbench.vs-dark .feedback-form .feedback-alias,
.monaco-workbench.vs-dark .feedback-form .feedback-description {
font-family: inherit;
}
@@ -193,28 +195,29 @@
}
/* High Contrast Theming */
.hc-black .monaco-workbench .feedback-form {
.monaco-workbench.hc-black .feedback-form {
outline: 2px solid #6fc3df;
outline-offset: -2px;
}
.hc-black .monaco-workbench .feedback-form .feedback-alias, .hc-black .monaco-workbench .feedback-form .feedback-description {
.monaco-workbench.hc-black .feedback-form .feedback-alias,
.monaco-workbench.hc-black .feedback-form .feedback-description {
font-family: inherit;
}
.hc-black .monaco-workbench .feedback-form .content .contactus {
.monaco-workbench.hc-black .feedback-form .content .contactus {
padding: 10px;
float: right;
}
.hc-black .monaco-workbench .feedback-form .form-buttons .send,
.hc-black .monaco-workbench .feedback-form .form-buttons .send.in-progress,
.hc-black .monaco-workbench .feedback-form .form-buttons .send.success {
.monaco-workbench.hc-black .feedback-form .form-buttons .send,
.monaco-workbench.hc-black .feedback-form .form-buttons .send.in-progress,
.monaco-workbench.hc-black .feedback-form .form-buttons .send.success {
background-color: #0C141F;
color: #D4D4D4;
border: 1px solid #6FC3DF;
}
.hc-black .monaco-workbench .feedback-form .form-buttons .send:hover {
.monaco-workbench.hc-black .feedback-form .form-buttons .send:hover {
background-color: #0C141F;
}

View File

@@ -12,7 +12,7 @@ import { Action } from 'vs/base/common/actions';
import { VIEWLET_ID, TEXT_FILE_EDITOR_ID, IExplorerService } from 'vs/workbench/contrib/files/common/files';
import { ITextFileService, TextFileOperationError, TextFileOperationResult } from 'vs/workbench/services/textfile/common/textfiles';
import { BaseTextEditor, IEditorConfiguration } from 'vs/workbench/browser/parts/editor/textEditor';
import { EditorOptions, TextEditorOptions, IEditorCloseEvent, Verbosity } from 'vs/workbench/common/editor';
import { EditorOptions, TextEditorOptions, IEditorCloseEvent } from 'vs/workbench/common/editor';
import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel';
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
@@ -245,11 +245,6 @@ export class TextFileEditor extends BaseTextEditor {
}
}
protected getAriaLabel(): string {
const title = this.input?.getTitle(Verbosity.SHORT) || nls.localize('fileEditorAriaLabel', "editor");
return this.input?.isReadonly() ? nls.localize('readonlyEditor', "{0} readonly", title) : title;
}
clearInput(): void {
// Update/clear editor view state in settings

View File

@@ -350,18 +350,23 @@ export const acceptLocalChangesCommand = async (accessor: ServicesAccessor, reso
const reference = await resolverService.createModelReference(resource);
const model = reference.object as IResolvedTextFileEditorModel;
clearPendingResolveSaveConflictMessages(); // hide any previously shown message about how to use these actions
try {
// Trigger save
await model.save({ ignoreModifiedSince: true, reason: SaveReason.EXPLICIT });
// hide any previously shown message about how to use these actions
clearPendingResolveSaveConflictMessages();
// Reopen file input
await editorService.openEditor({ resource: model.resource }, group);
// Trigger save
await model.save({ ignoreModifiedSince: true, reason: SaveReason.EXPLICIT });
// Clean up
group.closeEditor(editor);
editor.dispose();
reference.dispose();
// Reopen file input
await editorService.openEditor({ resource: model.resource }, group);
// Clean up
group.closeEditor(editor);
editor.dispose();
} finally {
reference.dispose();
}
};
export const revertLocalChangesCommand = async (accessor: ServicesAccessor, resource: URI) => {
@@ -379,16 +384,21 @@ export const revertLocalChangesCommand = async (accessor: ServicesAccessor, reso
const reference = await resolverService.createModelReference(resource);
const model = reference.object as ITextFileEditorModel;
clearPendingResolveSaveConflictMessages(); // hide any previously shown message about how to use these actions
try {
// Revert on model
await model.revert();
// hide any previously shown message about how to use these actions
clearPendingResolveSaveConflictMessages();
// Reopen file input
await editorService.openEditor({ resource: model.resource }, group);
// Revert on model
await model.revert();
// Clean up
group.closeEditor(editor);
editor.dispose();
reference.dispose();
// Reopen file input
await editorService.openEditor({ resource: model.resource }, group);
// Clean up
group.closeEditor(editor);
editor.dispose();
} finally {
reference.dispose();
}
};

View File

@@ -109,6 +109,7 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor
id: OpenEditorsView.ID,
name: OpenEditorsView.NAME,
ctorDescriptor: new SyncDescriptor(OpenEditorsView),
containerIcon: 'codicon-files',
order: 0,
when: OpenEditorsVisibleContext,
canToggleVisibility: true,

View File

@@ -145,9 +145,9 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
weight: KeybindingWeight.WorkbenchContrib + explorerCommandsWeightBonus,
when: ContextKeyExpr.and(FilesExplorerFocusCondition, ExplorerResourceCut),
primary: KeyCode.Escape,
handler: (accessor: ServicesAccessor) => {
handler: async (accessor: ServicesAccessor) => {
const explorerService = accessor.get(IExplorerService);
explorerService.setToCopy([], true);
await explorerService.setToCopy([], true);
}
});

View File

@@ -48,7 +48,7 @@ import { sequence, timeout } from 'vs/base/common/async';
import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
import { once } from 'vs/base/common/functional';
import { IEditorOptions } from 'vs/platform/editor/common/editor';
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorGroup, OpenEditorContext } from 'vs/workbench/services/editor/common/editorGroupsService';
import { Codicon } from 'vs/base/common/codicons';
import { IViewsService } from 'vs/workbench/common/views';
import { openEditorWith, getAllAvailableEditors } from 'vs/workbench/contrib/files/common/openWith';
@@ -597,7 +597,7 @@ export class ToggleEditorTypeCommand extends Action {
return;
}
await firstNonActiveOverride[0].open(input, options, group, firstNonActiveOverride[1].id)?.override;
await firstNonActiveOverride[0].open(input, options, group, OpenEditorContext.NEW_EDITOR, firstNonActiveOverride[1].id)?.override;
}
}
@@ -1081,20 +1081,20 @@ export const deleteFileHandler = async (accessor: ServicesAccessor) => {
};
let pasteShouldMove = false;
export const copyFileHandler = (accessor: ServicesAccessor) => {
export const copyFileHandler = async (accessor: ServicesAccessor) => {
const explorerService = accessor.get(IExplorerService);
const stats = explorerService.getContext(true);
if (stats.length > 0) {
explorerService.setToCopy(stats, false);
await explorerService.setToCopy(stats, false);
pasteShouldMove = false;
}
};
export const cutFileHandler = (accessor: ServicesAccessor) => {
export const cutFileHandler = async (accessor: ServicesAccessor) => {
const explorerService = accessor.get(IExplorerService);
const stats = explorerService.getContext(true);
if (stats.length > 0) {
explorerService.setToCopy(stats, true);
await explorerService.setToCopy(stats, true);
pasteShouldMove = true;
}
};
@@ -1161,7 +1161,7 @@ export const pasteFileHandler = async (accessor: ServicesAccessor) => {
const configurationService = accessor.get(IConfigurationService);
const context = explorerService.getContext(true);
const toPaste = resources.distinctParents(clipboardService.readResources(), r => r);
const toPaste = resources.distinctParents(await clipboardService.readResources(), r => r);
const element = context.length ? context[0] : explorerService.roots[0];
// Check if target is ancestor of pasted folder
@@ -1199,7 +1199,7 @@ export const pasteFileHandler = async (accessor: ServicesAccessor) => {
if (pasteShouldMove) {
// Cut is done. Make sure to clear cut state.
explorerService.setToCopy([], false);
await explorerService.setToCopy([], false);
pasteShouldMove = false;
}
if (stats.length >= 1) {

View File

@@ -369,9 +369,15 @@ configurationRegistry.registerConfiguration({
'default': 9
},
'explorer.autoReveal': {
'type': 'boolean',
'description': nls.localize('autoReveal', "Controls whether the explorer should automatically reveal and select files when opening them."),
'default': true
'type': ['boolean', 'string'],
'enum': [true, false, 'focusNoScroll'],
'default': true,
'enumDescriptions': [
nls.localize('autoReveal.on', 'Files will be revealed and selected.'),
nls.localize('autoReveal.off', 'Files will not be revealed and selected.'),
nls.localize('autoReveal.focusNoScroll', 'Files will not be scrolled into view, but will still be focused.'),
],
'description': nls.localize('autoReveal', "Controls whether the explorer should automatically reveal and select files when opening them.")
},
'explorer.enableDragAndDrop': {
'type': 'boolean',

View File

@@ -95,6 +95,6 @@
}
/* High Contrast Theming */
.hc-black .monaco-workbench .explorer-viewlet .explorer-item {
.monaco-workbench.hc-black .explorer-viewlet .explorer-item {
line-height: 20px;
}

View File

@@ -43,7 +43,6 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
import { IAsyncDataTreeViewState } from 'vs/base/browser/ui/tree/asyncDataTree';
import { FuzzyScore } from 'vs/base/common/filters';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { isEqualOrParent } from 'vs/base/common/resources';
import { values } from 'vs/base/common/map';
import { first } from 'vs/base/common/arrays';
import { withNullAsUndefined } from 'vs/base/common/types';
@@ -56,6 +55,7 @@ import { Color } from 'vs/base/common/color';
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { IViewDescriptorService } from 'vs/workbench/common/views';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity';
interface IExplorerViewColors extends IColorMapping {
listDropBackground?: ColorValue | undefined;
@@ -146,7 +146,7 @@ export class ExplorerView extends ViewPane {
// Refresh is needed on the initial explorer open
private shouldRefresh = true;
private dragHandler!: DelayedDragHandler;
private autoReveal = false;
private autoReveal: boolean | 'focusNoScroll' = false;
private actions: IAction[] | undefined;
private decorationsProvider: ExplorerDecorationsProvider | undefined;
@@ -171,6 +171,7 @@ export class ExplorerView extends ViewPane {
@IStorageService private readonly storageService: IStorageService,
@IClipboardService private clipboardService: IClipboardService,
@IFileService private readonly fileService: IFileService,
@IUriIdentityService private readonly uriIdentityService: IUriIdentityService,
@IOpenerService openerService: IOpenerService,
) {
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
@@ -471,7 +472,7 @@ export class ExplorerView extends ViewPane {
}
}
private onContextMenu(e: ITreeContextMenuEvent<ExplorerItem>): void {
private async onContextMenu(e: ITreeContextMenuEvent<ExplorerItem>): Promise<void> {
const disposables = new DisposableStore();
let stat = e.element;
let anchor = e.anchor;
@@ -490,7 +491,7 @@ export class ExplorerView extends ViewPane {
}
// update dynamic contexts
this.fileCopiedContextKey.set(this.clipboardService.hasResources());
this.fileCopiedContextKey.set(await this.clipboardService.hasResources());
this.setContextKeys(stat);
const selection = this.tree.getSelection();
@@ -652,8 +653,7 @@ export class ExplorerView extends ViewPane {
}
// Expand all stats in the parent chain.
const ignoreCase = !this.fileService.hasCapability(resource, FileSystemProviderCapabilities.PathCaseSensitive);
let item: ExplorerItem | undefined = this.explorerService.roots.filter(i => isEqualOrParent(resource, i.resource, ignoreCase))
let item: ExplorerItem | undefined = this.explorerService.roots.filter(i => this.uriIdentityService.extUri.isEqualOrParent(resource, i.resource))
// Take the root that is the closest to the stat #72299
.sort((first, second) => second.resource.path.length - first.resource.path.length)[0];
@@ -663,7 +663,7 @@ export class ExplorerView extends ViewPane {
} catch (e) {
return this.selectResource(resource, reveal, retry + 1);
}
item = first(values(item.children), i => isEqualOrParent(resource, i.resource, ignoreCase));
item = first(values(item.children), i => this.uriIdentityService.extUri.isEqualOrParent(resource, i.resource));
}
if (item) {
@@ -674,11 +674,9 @@ export class ExplorerView extends ViewPane {
}
try {
if (reveal) {
// Don't scroll to the item if it's already visible
if (this.tree.getRelativeTop(item) === null) {
this.tree.reveal(item, 0.5);
}
if (reveal === true && this.tree.getRelativeTop(item) === null) {
// Don't scroll to the item if it's already visible, or if set not to.
this.tree.reveal(item, 0.5);
}
this.tree.setFocus([item]);

View File

@@ -7,7 +7,7 @@ import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
import * as DOM from 'vs/base/browser/dom';
import * as glob from 'vs/base/common/glob';
import { IListVirtualDelegate, ListDragOverEffect } from 'vs/base/browser/ui/list/list';
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
import { IProgressService, ProgressLocation, IProgressStep, IProgress } from 'vs/platform/progress/common/progress';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { IFileService, FileKind, FileOperationError, FileOperationResult, FileSystemProviderCapabilities } from 'vs/platform/files/common/files';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
@@ -19,7 +19,7 @@ import { ITreeNode, ITreeFilter, TreeVisibility, TreeFilterResult, IAsyncDataSou
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { IFilesConfiguration, IExplorerService } from 'vs/workbench/contrib/files/common/files';
import { IFilesConfiguration, IExplorerService, VIEW_ID } from 'vs/workbench/contrib/files/common/files';
import { dirname, joinPath, isEqualOrParent, basename, distinctParents } from 'vs/base/common/resources';
import { InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox';
import { localize } from 'vs/nls';
@@ -29,7 +29,7 @@ import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { equals, deepClone } from 'vs/base/common/objects';
import * as path from 'vs/base/common/path';
import { ExplorerItem, NewExplorerItem } from 'vs/workbench/contrib/files/common/explorerModel';
import { compareFileExtensions, compareFileNames } from 'vs/base/common/comparers';
import { compareFileExtensionsNumeric, compareFileNamesNumeric } from 'vs/base/common/comparers';
import { fillResourceDataTransfers, CodeDataTransfers, extractResources, containsDragType } from 'vs/workbench/browser/dnd';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IDragAndDropData, DataTransfers } from 'vs/base/browser/dnd';
@@ -50,12 +50,13 @@ import { Emitter, Event, EventMultiplexer } from 'vs/base/common/event';
import { ITreeCompressionDelegate } from 'vs/base/browser/ui/tree/asyncDataTree';
import { ICompressibleTreeRenderer } from 'vs/base/browser/ui/tree/objectTree';
import { ICompressedTreeNode } from 'vs/base/browser/ui/tree/compressedObjectTreeModel';
import { VSBuffer } from 'vs/base/common/buffer';
import { VSBuffer, newWriteableBufferStream } from 'vs/base/common/buffer';
import { ILabelService } from 'vs/platform/label/common/label';
import { isNumber } from 'vs/base/common/types';
import { domEvent } from 'vs/base/browser/event';
import { IEditableData } from 'vs/workbench/common/views';
import { IEditorInput } from 'vs/workbench/common/editor';
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';
export class ExplorerDelegate implements IListVirtualDelegate<ExplorerItem> {
@@ -616,7 +617,7 @@ export class FilesFilter implements ITreeFilter<ExplorerItem, FuzzyScore> {
}
}
// // Explorer Sorter
// Explorer Sorter
export class FileSorter implements ITreeSorter<ExplorerItem> {
constructor(
@@ -624,7 +625,7 @@ export class FileSorter implements ITreeSorter<ExplorerItem> {
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService
) { }
public compare(statA: ExplorerItem, statB: ExplorerItem): number {
compare(statA: ExplorerItem, statB: ExplorerItem): number {
// Do not sort roots
if (statA.isRoot) {
if (statB.isRoot) {
@@ -654,7 +655,7 @@ export class FileSorter implements ITreeSorter<ExplorerItem> {
}
if (statA.isDirectory && statB.isDirectory) {
return compareFileNames(statA.name, statB.name);
return compareFileNamesNumeric(statA.name, statB.name);
}
break;
@@ -688,17 +689,17 @@ export class FileSorter implements ITreeSorter<ExplorerItem> {
// Sort Files
switch (sortOrder) {
case 'type':
return compareFileExtensions(statA.name, statB.name);
return compareFileExtensionsNumeric(statA.name, statB.name);
case 'modified':
if (statA.mtime !== statB.mtime) {
return (statA.mtime && statB.mtime && statA.mtime < statB.mtime) ? 1 : -1;
}
return compareFileNames(statA.name, statB.name);
return compareFileNamesNumeric(statA.name, statB.name);
default: /* 'default', 'mixed', 'filesFirst' */
return compareFileNames(statA.name, statB.name);
return compareFileNamesNumeric(statA.name, statB.name);
}
}
}
@@ -712,6 +713,27 @@ const getFileOverwriteConfirm = (name: string) => {
};
};
interface IWebkitDataTransfer {
items: IWebkitDataTransferItem[];
}
interface IWebkitDataTransferItem {
webkitGetAsEntry(): IWebkitDataTransferItemEntry;
}
interface IWebkitDataTransferItemEntry {
name: string | undefined;
isFile: boolean;
isDirectory: boolean;
file(resolve: (file: File) => void, reject: () => void): void;
createReader(): IWebkitDataTransferItemEntryReader;
}
interface IWebkitDataTransferItemEntryReader {
readEntries(resolve: (file: IWebkitDataTransferItemEntry[]) => void, reject: () => void): void
}
export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
private static readonly CONFIRM_DND_SETTING_KEY = 'explorer.confirmDragAndDrop';
@@ -732,7 +754,8 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
@IInstantiationService private instantiationService: IInstantiationService,
@IWorkingCopyFileService private workingCopyFileService: IWorkingCopyFileService,
@IHostService private hostService: IHostService,
@IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService
@IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService,
@IProgressService private readonly progressService: IProgressService
) {
this.toDispose = [];
@@ -756,7 +779,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
const iconLabelName = getIconLabelNameFromHTMLElement(originalEvent.target);
if (iconLabelName && iconLabelName.index < iconLabelName.count - 1) {
const result = this._onDragOver(data, compressedTarget, targetIndex, originalEvent);
const result = this.handleDragOver(data, compressedTarget, targetIndex, originalEvent);
if (result) {
if (iconLabelName.element !== this.compressedDragOverElement) {
@@ -780,10 +803,10 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
}
this.compressedDropTargetDisposable.dispose();
return this._onDragOver(data, target, targetIndex, originalEvent);
return this.handleDragOver(data, target, targetIndex, originalEvent);
}
private _onDragOver(data: IDragAndDropData, target: ExplorerItem | undefined, targetIndex: number | undefined, originalEvent: DragEvent): boolean | ITreeDragOverReaction {
private handleDragOver(data: IDragAndDropData, target: ExplorerItem | undefined, targetIndex: number | undefined, originalEvent: DragEvent): boolean | ITreeDragOverReaction {
const isCopy = originalEvent && ((originalEvent.ctrlKey && !isMacintosh) || (originalEvent.altKey && isMacintosh));
const fromDesktop = data instanceof DesktopDragAndDropData;
const effect = (fromDesktop || isCopy) ? ListDragOverEffect.Copy : ListDragOverEffect.Move;
@@ -939,32 +962,163 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
}
private async handleWebExternalDrop(data: DesktopDragAndDropData, target: ExplorerItem, originalEvent: DragEvent): Promise<void> {
data.files.forEach(file => {
const items = (originalEvent.dataTransfer as unknown as IWebkitDataTransfer).items;
// Somehow the items thing is being modified at random, maybe as a security
// measure since this is a DND operation. As such, we copy the items into
// an array we own as early as possible before using it.
const entries: IWebkitDataTransferItemEntry[] = [];
for (const item of items) {
entries.push(item.webkitGetAsEntry());
}
const results: { isFile: boolean, resource: URI }[] = [];
const cts = new CancellationTokenSource();
// Start upload and report progress globally
const uploadPromise = this.progressService.withProgress({
location: ProgressLocation.Window,
delay: 800,
cancellable: true,
title: localize('uploadingFiles', "Uploading")
}, async progress => {
for (let entry of entries) {
const result = await this.doUploadWebFileEntry(entry, target.resource, target, progress, cts.token);
if (result) {
results.push(result);
}
}
}, () => cts.dispose(true));
// Also indicate progress in the files view
this.progressService.withProgress({ location: VIEW_ID, delay: 800 }, () => uploadPromise);
// Wait until upload is done
await uploadPromise;
// Open uploaded file in editor only if we upload just one
if (!cts.token.isCancellationRequested && results.length === 1 && results[0].isFile) {
await this.editorService.openEditor({ resource: results[0].resource, options: { pinned: true } });
}
}
private async doUploadWebFileEntry(entry: IWebkitDataTransferItemEntry, parentResource: URI, target: ExplorerItem | undefined, progress: IProgress<IProgressStep>, token: CancellationToken): Promise<{ isFile: boolean, resource: URI } | undefined> {
if (token.isCancellationRequested || !entry.name || (!entry.isFile && !entry.isDirectory)) {
return undefined;
}
const resource = joinPath(parentResource, entry.name);
// Confirm overwrite as needed
if (target && target.getChild(entry.name)) {
const { confirmed } = await this.dialogService.confirm(getFileOverwriteConfirm(resource.path));
if (!confirmed) {
return undefined;
}
}
if (token.isCancellationRequested) {
return undefined;
}
// Report progress
progress.report({ message: entry.name });
// Handle file upload
if (entry.isFile) {
const file = await new Promise<File>((resolve, reject) => entry.file(resolve, reject));
if (token.isCancellationRequested) {
return undefined;
}
// Chrome/Edge/Firefox support stream method
if (typeof file.stream === 'function') {
await this.doUploadWebFileEntryBuffered(resource, file);
}
// Fallback to unbuffered upload for other browsers
else {
await this.doUploadWebFileEntryUnbuffered(resource, file);
}
return { isFile: true, resource };
}
// Handle folder upload
else {
// Create target folder
await this.fileService.createFolder(resource);
if (token.isCancellationRequested) {
return undefined;
}
// Recursive upload files in this directory
const folderTarget = target && target.getChild(entry.name) || undefined;
const dirReader = entry.createReader();
const childEntries = await new Promise<IWebkitDataTransferItemEntry[]>((resolve, reject) => {
dirReader.readEntries(resolve, reject);
});
for (let childEntry of childEntries) {
await this.doUploadWebFileEntry(childEntry, resource, folderTarget, progress, token);
}
return { isFile: false, resource };
}
}
private async doUploadWebFileEntryBuffered(resource: URI, file: File): Promise<void> {
const writeableStream = newWriteableBufferStream();
// Read the file in chunks using File.stream() web APIs
(async () => {
try {
const reader: ReadableStreamDefaultReader<Uint8Array> = file.stream().getReader();
let res = await reader.read();
while (!res.done) {
writeableStream.write(VSBuffer.wrap(res.value));
res = await reader.read();
}
writeableStream.end(res.value instanceof Uint8Array ? VSBuffer.wrap(res.value) : undefined);
} catch (error) {
writeableStream.end(error);
}
})();
await this.fileService.writeFile(resource, writeableStream);
}
private doUploadWebFileEntryUnbuffered(resource: URI, file: File): Promise<void> {
return new Promise<void>((resolve, reject) => {
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = async (event) => {
const name = file.name;
if (typeof name === 'string' && event.target?.result instanceof ArrayBuffer) {
if (target.getChild(name)) {
const { confirmed } = await this.dialogService.confirm(getFileOverwriteConfirm(name));
if (!confirmed) {
return;
}
reader.onload = async event => {
try {
if (event.target?.result instanceof ArrayBuffer) {
await this.fileService.writeFile(resource, VSBuffer.wrap(new Uint8Array(event.target.result)));
} else {
throw new Error('Could not read from dropped file.');
}
const resource = joinPath(target.resource, name);
await this.fileService.writeFile(resource, VSBuffer.wrap(new Uint8Array(event.target.result)));
if (data.files.length === 1) {
await this.editorService.openEditor({ resource, options: { pinned: true } });
}
resolve();
} catch (error) {
reject(error);
}
};
// Start reading the file to trigger `onload`
reader.readAsArrayBuffer(file);
});
}
private async handleExternalDrop(data: DesktopDragAndDropData, target: ExplorerItem, originalEvent: DragEvent): Promise<void> {
const droppedResources = extractResources(originalEvent, true);
// Check for dropped external files to be folders
const droppedResources = extractResources(originalEvent, true);
const result = await this.fileService.resolveAll(droppedResources.map(droppedResource => ({ resource: droppedResource.resource })));
// Pass focus to window
@@ -973,7 +1127,6 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
// Handle folders by adding to workspace if we are in workspace context
const folders = result.filter(r => r.success && r.stat && r.stat.isDirectory).map(result => ({ uri: result.stat!.resource }));
if (folders.length > 0) {
const buttons = [
folders.length > 1 ? localize('copyFolders', "&&Copy Folders") : localize('copyFolder', "&&Copy Folder"),
localize('cancel', "Cancel")

View File

@@ -81,7 +81,7 @@
overflow: hidden;
}
.hc-black .monaco-workbench .open-editors .open-editor,
.hc-black .monaco-workbench .open-editors .editor-group {
.monaco-workbench.hc-black .open-editors .open-editor,
.monaco-workbench.hc-black .open-editors .editor-group {
line-height: 20px;
}

View File

@@ -5,7 +5,8 @@
import { localize } from 'vs/nls';
import { URI } from 'vs/base/common/uri';
import { EncodingMode, IFileEditorInput, Verbosity, TextResourceEditorInput, GroupIdentifier, IMoveResult, isTextEditorPane } from 'vs/workbench/common/editor';
import { EncodingMode, IFileEditorInput, Verbosity, GroupIdentifier, IMoveResult, isTextEditorPane } from 'vs/workbench/common/editor';
import { AbstractTextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput';
import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel';
import { FileOperationError, FileOperationResult, IFileService } from 'vs/platform/files/common/files';
import { ITextFileService, TextFileEditorModelState, TextFileLoadReason, TextFileOperationError, TextFileOperationResult, ITextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles';
@@ -30,7 +31,7 @@ const enum ForceOpenAs {
/**
* A file editor input is the input type for the file editor of file system resources.
*/
export class FileEditorInput extends TextResourceEditorInput implements IFileEditorInput {
export class FileEditorInput extends AbstractTextResourceEditorInput implements IFileEditorInput {
private preferredEncoding: string | undefined;
private preferredMode: string | undefined;

View File

@@ -126,10 +126,10 @@ export class ExplorerService implements IExplorerService {
await this.view.setEditable(stat, isEditing);
}
setToCopy(items: ExplorerItem[], cut: boolean): void {
async setToCopy(items: ExplorerItem[], cut: boolean): Promise<void> {
const previouslyCutItems = this.cutItems;
this.cutItems = cut ? items : undefined;
this.clipboardService.writeResources(items.map(s => s.resource));
await this.clipboardService.writeResources(items.map(s => s.resource));
this.view?.itemsCopied(items, cut, previouslyCutItems);
}
@@ -150,10 +150,11 @@ export class ExplorerService implements IExplorerService {
return !!this.editable && (this.editable.stat === stat || !stat);
}
async select(resource: URI, reveal?: boolean): Promise<void> {
async select(resource: URI, reveal?: boolean | string): Promise<void> {
if (!this.view) {
return;
}
const fileStat = this.findClosest(resource);
if (fileStat) {
await this.view.selectResource(fileStat.resource, reveal);
@@ -197,7 +198,7 @@ export class ExplorerService implements IExplorerService {
if (reveal && resource && autoReveal) {
// We did a top level refresh, reveal the active file #67118
this.select(resource, true);
this.select(resource, autoReveal);
}
}
}

View File

@@ -51,14 +51,14 @@ export interface IExplorerService {
isEditable(stat: ExplorerItem | undefined): boolean;
findClosest(resource: URI): ExplorerItem | null;
refresh(): Promise<void>;
setToCopy(stats: ExplorerItem[], cut: boolean): void;
setToCopy(stats: ExplorerItem[], cut: boolean): Promise<void>;
isCut(stat: ExplorerItem): boolean;
/**
* Selects and reveal the file element provided by the given resource if its found in the explorer.
* Will try to resolve the path in case the explorer is not yet expanded to the file yet.
*/
select(resource: URI, reveal?: boolean): Promise<void>;
select(resource: URI, reveal?: boolean | string): Promise<void>;
registerView(contextAndRefreshProvider: IExplorerView): void;
}
@@ -66,7 +66,7 @@ export interface IExplorerService {
export interface IExplorerView {
getContext(respectMultiSelection: boolean): ExplorerItem[];
refresh(recursive: boolean, item?: ExplorerItem): Promise<void>;
selectResource(resource: URI | undefined, reveal?: boolean): Promise<void>;
selectResource(resource: URI | undefined, reveal?: boolean | string): Promise<void>;
setTreeInput(): Promise<void>;
itemsCopied(tats: ExplorerItem[], cut: boolean, previousCut: ExplorerItem[] | undefined): void;
setEditable(stat: ExplorerItem, isEditing: boolean): Promise<void>;
@@ -121,7 +121,7 @@ export interface IFilesConfiguration extends PlatformIFilesConfiguration, IWorkb
openEditors: {
visible: number;
};
autoReveal: boolean;
autoReveal: boolean | 'focusNoScroll';
enableDragAndDrop: boolean;
confirmDelete: boolean;
sortOrder: SortOrder;

View File

@@ -13,7 +13,7 @@ import { IEditorInput, IEditorPane } from 'vs/workbench/common/editor';
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
import { DEFAULT_EDITOR_ID } from 'vs/workbench/contrib/files/common/files';
import { CustomEditorAssociation, CustomEditorsAssociations, customEditorsAssociationsSettingId } from 'vs/workbench/services/editor/common/editorAssociationsSetting';
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorGroup, OpenEditorContext } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService, IOpenEditorOverrideEntry, IOpenEditorOverrideHandler } from 'vs/workbench/services/editor/common/editorService';
const builtinProviderDisplayName = nls.localize('builtinProviderDisplayName', "Built-in");
@@ -45,7 +45,7 @@ export async function openEditorWith(
const overrideToUse = typeof id === 'string' && allEditorOverrides.find(([_, entry]) => entry.id === id);
if (overrideToUse) {
return overrideToUse[0].open(input, options, group, id)?.override;
return overrideToUse[0].open(input, options, group, OpenEditorContext.NEW_EDITOR, id)?.override;
}
// Prompt
@@ -108,7 +108,7 @@ export async function openEditorWith(
picker.show();
});
return pickedItem?.handler.open(input!, options, group, pickedItem.id)?.override;
return pickedItem?.handler.open(input!, options, group, OpenEditorContext.NEW_EDITOR, pickedItem.id)?.override;
}
export const defaultEditorOverrideEntry = Object.freeze({

View File

@@ -9,7 +9,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
import { isWindows, isMacintosh } from 'vs/base/common/platform';
import { Schemas } from 'vs/base/common/network';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes';
@@ -17,7 +17,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation
import { getMultiSelectedResources } from 'vs/workbench/contrib/files/browser/files';
import { IListService } from 'vs/platform/list/browser/listService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { revealResourcesInOS } from 'vs/workbench/contrib/files/electron-browser/fileCommands';
import { revealResourcesInOS } from 'vs/workbench/contrib/files/electron-sandbox/fileCommands';
import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { ResourceContextKey } from 'vs/workbench/common/resources';
import { appendToCommandPalette, appendEditorTitleContextMenuItem } from 'vs/workbench/contrib/files/browser/fileActions.contribution';

View File

@@ -9,7 +9,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
import { sequence } from 'vs/base/common/async';
import { Schemas } from 'vs/base/common/network';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
// Commands

View File

@@ -3,17 +3,13 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as os from 'os';
import * as fs from 'fs';
import * as nls from 'vs/nls';
import { join } from 'vs/base/common/path';
import { Registry } from 'vs/platform/registry/common/platform';
import { EditorInput } from 'vs/workbench/common/editor';
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { IEditorRegistry, EditorDescriptor, Extensions as EditorExtensions } from 'vs/workbench/browser/editor';
import { NativeTextFileEditor } from 'vs/workbench/contrib/files/electron-browser/textFileEditor';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { NativeTextFileEditor } from 'vs/workbench/contrib/files/electron-sandbox/textFileEditor';
// Register file editor
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
@@ -26,8 +22,3 @@ Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
new SyncDescriptor<EditorInput>(FileEditorInput)
]
);
// Register mkdtemp command
CommandsRegistry.registerCommand('mkdtemp', function () {
return fs.promises.mkdtemp(join(os.tmpdir(), 'vscodetmp-'));
});

View File

@@ -7,8 +7,7 @@ import * as nls from 'vs/nls';
import { TextFileEditor } from 'vs/workbench/contrib/files/browser/editors/textFileEditor';
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
import { EditorOptions } from 'vs/workbench/common/editor';
import { FileOperationError, FileOperationResult, IFileService } from 'vs/platform/files/common/files';
import { MIN_MAX_MEMORY_SIZE_MB, FALLBACK_MAX_MEMORY_SIZE_MB } from 'vs/platform/files/node/files';
import { FileOperationError, FileOperationResult, IFileService, MIN_MAX_MEMORY_SIZE_MB, FALLBACK_MAX_MEMORY_SIZE_MB } from 'vs/platform/files/common/files';
import { createErrorWithActions } from 'vs/base/common/errorsWithActions';
import { Action } from 'vs/base/common/actions';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@@ -23,7 +22,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
import { IExplorerService } from 'vs/workbench/contrib/files/common/files';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
/**

View File

@@ -47,4 +47,8 @@ class RegisterIssueContribution implements IWorkbenchContribution {
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(RegisterIssueContribution, LifecyclePhase.Starting);
CommandsRegistry.registerCommand('_issues.getSystemStatus', (accessor) => {
return nls.localize('statusUnsupported', "The --status argument is not yet supported in browsers.");
});
registerSingleton(IWebIssueService, WebIssueService, true);

View File

@@ -13,7 +13,8 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/electron-browser/issue';
import { WorkbenchIssueService } from 'vs/workbench/contrib/issue/electron-browser/issueService';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IIssueService, IssueReporterData } from 'vs/platform/issue/node/issue';
import { IssueReporterData } from 'vs/platform/issue/common/issue';
import { IIssueService } from 'vs/platform/issue/electron-sandbox/issue';
import { OpenIssueReporterArgs, OpenIssueReporterActionId } from 'vs/workbench/contrib/issue/common/commands';
const helpCategory = { value: nls.localize('help', "Help"), original: 'Help' };

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IssueReporterData } from 'vs/platform/issue/node/issue';
import { IssueReporterData } from 'vs/platform/issue/common/issue';
export const IWorkbenchIssueService = createDecorator<IWorkbenchIssueService>('workbenchIssueService');

View File

@@ -5,7 +5,7 @@
import { Action } from 'vs/base/common/actions';
import * as nls from 'vs/nls';
import { IssueType } from 'vs/platform/issue/node/issue';
import { IssueType } from 'vs/platform/issue/common/issue';
import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/electron-browser/issue';
export class OpenProcessExplorer extends Action {

View File

@@ -3,13 +3,14 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IssueReporterStyles, IIssueService, IssueReporterData, ProcessExplorerData, IssueReporterExtensionData } from 'vs/platform/issue/node/issue';
import { IssueReporterStyles, IssueReporterData, ProcessExplorerData, IssueReporterExtensionData } from 'vs/platform/issue/common/issue';
import { IIssueService } from 'vs/platform/issue/electron-sandbox/issue';
import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService';
import { textLinkForeground, inputBackground, inputBorder, inputForeground, buttonBackground, buttonHoverBackground, buttonForeground, inputValidationErrorBorder, foreground, inputActiveOptionBorder, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, editorBackground, editorForeground, listHoverBackground, listHoverForeground, listHighlightForeground, textLinkActiveForeground, inputValidationErrorBackground, inputValidationErrorForeground } from 'vs/platform/theme/common/colorRegistry';
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IWorkbenchExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { webFrame } from 'electron';
import { webFrame } from 'vs/base/parts/sandbox/electron-sandbox/globals';
import { assign } from 'vs/base/common/objects';
import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/electron-browser/issue';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';

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