Merge from vscode 817eb6b0c720a4ecbc13c020afbbebfed667aa09 (#7356)
@@ -359,7 +359,7 @@ export class LanguageConfigurationFileHandler {
|
||||
const schemaId = 'vscode://schemas/language-configuration';
|
||||
const schema: IJSONSchema = {
|
||||
allowComments: true,
|
||||
allowsTrailingCommas: true,
|
||||
allowTrailingCommas: true,
|
||||
default: {
|
||||
comments: {
|
||||
blockComment: ['/*', '*/'],
|
||||
|
||||
@@ -94,13 +94,13 @@ export function attachSuggestEnabledInputBoxStyler(widget: IThemable, themeServi
|
||||
|
||||
export class SuggestEnabledInput extends Widget implements IThemable {
|
||||
|
||||
private _onShouldFocusResults = new Emitter<void>();
|
||||
private readonly _onShouldFocusResults = new Emitter<void>();
|
||||
readonly onShouldFocusResults: Event<void> = this._onShouldFocusResults.event;
|
||||
|
||||
private _onEnter = new Emitter<void>();
|
||||
private readonly _onEnter = new Emitter<void>();
|
||||
readonly onEnter: Event<void> = this._onEnter.event;
|
||||
|
||||
private _onInputDidChange = new Emitter<string | undefined>();
|
||||
private readonly _onInputDidChange = new Emitter<string | undefined>();
|
||||
readonly onInputDidChange: Event<string | undefined> = this._onInputDidChange.event;
|
||||
|
||||
private readonly inputWidget: CodeEditorWidget;
|
||||
|
||||
@@ -57,7 +57,7 @@ export class CommentNode extends Disposable {
|
||||
protected toolbar: ToolBar | undefined;
|
||||
private _commentFormActions: CommentFormActions | null = null;
|
||||
|
||||
private _onDidDelete = new Emitter<CommentNode>();
|
||||
private readonly _onDidDelete = new Emitter<CommentNode>();
|
||||
|
||||
public get domNode(): HTMLElement {
|
||||
return this._domNode;
|
||||
|
||||
@@ -65,8 +65,8 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
private _commentForm: HTMLElement;
|
||||
private _reviewThreadReplyButton: HTMLElement;
|
||||
private _resizeObserver: any;
|
||||
private _onDidClose = new Emitter<ReviewZoneWidget | undefined>();
|
||||
private _onDidCreateThread = new Emitter<ReviewZoneWidget>();
|
||||
private readonly _onDidClose = new Emitter<ReviewZoneWidget | undefined>();
|
||||
private readonly _onDidCreateThread = new Emitter<ReviewZoneWidget>();
|
||||
private _isExpanded?: boolean;
|
||||
private _collapseAction: Action;
|
||||
private _commentGlyph?: CommentGlyphWidget;
|
||||
|
||||
@@ -10,7 +10,7 @@ import { coalesce, findFirstInSorted } from 'vs/base/common/arrays';
|
||||
import { CancelablePromise, createCancelablePromise, Delayer } from 'vs/base/common/async';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import 'vs/css!./media/review';
|
||||
import { IMarginData } from 'vs/editor/browser/controller/mouseTarget';
|
||||
import { IActiveCodeEditor, ICodeEditor, IEditorMouseEvent, isCodeEditor, isDiffEditor, IViewZone, MouseTargetType } from 'vs/editor/browser/editorBrowser';
|
||||
@@ -103,7 +103,6 @@ class CommentingRangeDecorator {
|
||||
|
||||
private decorationOptions: ModelDecorationOptions;
|
||||
private commentingRangeDecorations: CommentingRangeDecoration[] = [];
|
||||
private disposables: IDisposable[] = [];
|
||||
|
||||
constructor() {
|
||||
const decorationOptions: IModelDecorationOptions = {
|
||||
@@ -146,14 +145,13 @@ class CommentingRangeDecorator {
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.disposables = dispose(this.disposables);
|
||||
this.commentingRangeDecorations = [];
|
||||
}
|
||||
}
|
||||
|
||||
export class ReviewController implements IEditorContribution {
|
||||
private globalToDispose: IDisposable[];
|
||||
private localToDispose: IDisposable[];
|
||||
private readonly globalToDispose = new DisposableStore();
|
||||
private readonly localToDispose = new DisposableStore();
|
||||
private editor: ICodeEditor;
|
||||
private _commentWidgets: ReviewZoneWidget[];
|
||||
private _commentInfos: ICommentInfo[];
|
||||
@@ -175,8 +173,6 @@ export class ReviewController implements IEditorContribution {
|
||||
@IContextMenuService readonly contextMenuService: IContextMenuService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService
|
||||
) {
|
||||
this.globalToDispose = [];
|
||||
this.localToDispose = [];
|
||||
this._commentInfos = [];
|
||||
this._commentWidgets = [];
|
||||
this._pendingCommentCache = {};
|
||||
@@ -190,20 +186,20 @@ export class ReviewController implements IEditorContribution {
|
||||
|
||||
this._commentingRangeDecorator = new CommentingRangeDecorator();
|
||||
|
||||
this.globalToDispose.push(this.commentService.onDidDeleteDataProvider(ownerId => {
|
||||
this.globalToDispose.add(this.commentService.onDidDeleteDataProvider(ownerId => {
|
||||
delete this._pendingCommentCache[ownerId];
|
||||
this.beginCompute();
|
||||
}));
|
||||
this.globalToDispose.push(this.commentService.onDidSetDataProvider(_ => this.beginCompute()));
|
||||
this.globalToDispose.add(this.commentService.onDidSetDataProvider(_ => this.beginCompute()));
|
||||
|
||||
this.globalToDispose.push(this.commentService.onDidSetResourceCommentInfos(e => {
|
||||
this.globalToDispose.add(this.commentService.onDidSetResourceCommentInfos(e => {
|
||||
const editorURI = this.editor && this.editor.hasModel() && this.editor.getModel().uri;
|
||||
if (editorURI && editorURI.toString() === e.resource.toString()) {
|
||||
this.setComments(e.commentInfos.filter(commentInfo => commentInfo !== null));
|
||||
}
|
||||
}));
|
||||
|
||||
this.globalToDispose.push(this.editor.onDidChangeModel(e => this.onModelChanged(e)));
|
||||
this.globalToDispose.add(this.editor.onDidChangeModel(e => this.onModelChanged(e)));
|
||||
this.codeEditorService.registerDecorationType(COMMENTEDITOR_DECORATION_KEY, {});
|
||||
this.beginCompute();
|
||||
}
|
||||
@@ -326,8 +322,8 @@ export class ReviewController implements IEditorContribution {
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.globalToDispose = dispose(this.globalToDispose);
|
||||
this.localToDispose = dispose(this.localToDispose);
|
||||
this.globalToDispose.dispose();
|
||||
this.localToDispose.dispose();
|
||||
|
||||
this._commentWidgets.forEach(widget => widget.dispose());
|
||||
|
||||
@@ -335,15 +331,15 @@ export class ReviewController implements IEditorContribution {
|
||||
}
|
||||
|
||||
public onModelChanged(e: IModelChangedEvent): void {
|
||||
this.localToDispose = dispose(this.localToDispose);
|
||||
this.localToDispose.clear();
|
||||
|
||||
this.removeCommentWidgetsAndStoreCache();
|
||||
|
||||
this.localToDispose.push(this.editor.onMouseDown(e => this.onEditorMouseDown(e)));
|
||||
this.localToDispose.push(this.editor.onMouseUp(e => this.onEditorMouseUp(e)));
|
||||
this.localToDispose.add(this.editor.onMouseDown(e => this.onEditorMouseDown(e)));
|
||||
this.localToDispose.add(this.editor.onMouseUp(e => this.onEditorMouseUp(e)));
|
||||
|
||||
this._computeCommentingRangeScheduler = new Delayer<ICommentInfo[]>(200);
|
||||
this.localToDispose.push({
|
||||
this.localToDispose.add({
|
||||
dispose: () => {
|
||||
if (this._computeCommentingRangeScheduler) {
|
||||
this._computeCommentingRangeScheduler.cancel();
|
||||
@@ -351,10 +347,10 @@ export class ReviewController implements IEditorContribution {
|
||||
this._computeCommentingRangeScheduler = null;
|
||||
}
|
||||
});
|
||||
this.localToDispose.push(this.editor.onDidChangeModelContent(async () => {
|
||||
this.localToDispose.add(this.editor.onDidChangeModelContent(async () => {
|
||||
this.beginComputeCommentingRanges();
|
||||
}));
|
||||
this.localToDispose.push(this.commentService.onDidUpdateCommentThreads(async e => {
|
||||
this.localToDispose.add(this.commentService.onDidUpdateCommentThreads(async e => {
|
||||
const editorURI = this.editor && this.editor.hasModel() && this.editor.getModel().uri;
|
||||
if (!editorURI) {
|
||||
return;
|
||||
|
||||
@@ -144,16 +144,16 @@
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.monaco-editor .review-widget .head .review-actions > .monaco-action-bar .icon.expand-review-action {
|
||||
.monaco-editor .review-widget .head .review-actions > .monaco-action-bar .codicon.expand-review-action {
|
||||
background-image: url("./close-light.svg");
|
||||
background-size: 16px;
|
||||
}
|
||||
|
||||
.monaco-editor.vs-dark .review-widget .head .review-actions > .monaco-action-bar .icon.expand-review-action {
|
||||
.monaco-editor.vs-dark .review-widget .head .review-actions > .monaco-action-bar .codicon.expand-review-action {
|
||||
background-image: url("./close-dark.svg");
|
||||
}
|
||||
|
||||
.monaco-editor.hc-black .review-widget .head .review-actions > .monaco-action-bar .icon.expand-review-action {
|
||||
.monaco-editor.hc-black .review-widget .head .review-actions > .monaco-action-bar .codicon.expand-review-action {
|
||||
background-image: url("./close-hc.svg");
|
||||
}
|
||||
|
||||
@@ -417,7 +417,7 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.monaco-editor .review-widget .head .review-actions .action-label.icon.close-review-action {
|
||||
.monaco-editor .review-widget .head .review-actions .action-label.codicon.close-review-action {
|
||||
background: url("./close.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import { ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/c
|
||||
import { getMultiSelectedResources } from 'vs/workbench/contrib/files/browser/files';
|
||||
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { firstOrDefault } from 'vs/base/common/arrays';
|
||||
|
||||
const viewCategory = nls.localize('viewCategory', "View");
|
||||
|
||||
@@ -32,7 +33,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
handler: async (accessor: ServicesAccessor, resource: URI | object) => {
|
||||
const editorService = accessor.get(IEditorService);
|
||||
const resources = getMultiSelectedResources(resource, accessor.get(IListService), editorService);
|
||||
const targetResource = resources[0];
|
||||
const targetResource = firstOrDefault(resources);
|
||||
if (!targetResource) {
|
||||
return undefined; // {{SQL CARBON EDIT}} strict-null-check
|
||||
}
|
||||
@@ -89,14 +90,6 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
}
|
||||
});
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, {
|
||||
order: 40,
|
||||
command: {
|
||||
id: REOPEN_WITH_COMMAND_ID,
|
||||
title: REOPEN_WITH_TITLE,
|
||||
}
|
||||
});
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
|
||||
command: {
|
||||
id: REOPEN_WITH_COMMAND_ID,
|
||||
|
||||
@@ -135,7 +135,7 @@ export interface IExpressionTemplateData {
|
||||
name: HTMLSpanElement;
|
||||
value: HTMLSpanElement;
|
||||
inputBoxContainer: HTMLElement;
|
||||
enableInputBox(expression: IExpression, options: IInputBoxOptions): void;
|
||||
enableInputBox(options: IInputBoxOptions): void;
|
||||
toDispose: IDisposable[];
|
||||
label: HighlightedLabel;
|
||||
}
|
||||
@@ -159,15 +159,12 @@ export abstract class AbstractExpressionsRenderer implements ITreeRenderer<IExpr
|
||||
const inputBoxContainer = dom.append(expression, $('.inputBoxContainer'));
|
||||
const toDispose: IDisposable[] = [];
|
||||
|
||||
const enableInputBox = (expression: IExpression, options: IInputBoxOptions) => {
|
||||
const enableInputBox = (options: IInputBoxOptions) => {
|
||||
name.style.display = 'none';
|
||||
value.style.display = 'none';
|
||||
inputBoxContainer.style.display = 'initial';
|
||||
|
||||
const inputBox = new InputBox(inputBoxContainer, this.contextViewService, {
|
||||
placeholder: options.placeholder,
|
||||
ariaLabel: options.ariaLabel
|
||||
});
|
||||
const inputBox = new InputBox(inputBoxContainer, this.contextViewService, options);
|
||||
const styler = attachInputBoxStyler(inputBox, this.themeService);
|
||||
|
||||
inputBox.value = replaceWhitespace(options.initialValue);
|
||||
@@ -217,10 +214,10 @@ export abstract class AbstractExpressionsRenderer implements ITreeRenderer<IExpr
|
||||
|
||||
renderElement(node: ITreeNode<IExpression, FuzzyScore>, index: number, data: IExpressionTemplateData): void {
|
||||
const { element } = node;
|
||||
if (element === this.debugService.getViewModel().getSelectedExpression()) {
|
||||
if (element === this.debugService.getViewModel().getSelectedExpression() || (element instanceof Variable && element.errorMessage)) {
|
||||
const options = this.getInputBoxOptions(element);
|
||||
if (options) {
|
||||
data.enableInputBox(element, options);
|
||||
data.enableInputBox(options);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as nls from 'vs/nls';
|
||||
import * as env from 'vs/base/common/platform';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { URI as uri } from 'vs/base/common/uri';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import severity from 'vs/base/common/severity';
|
||||
import { IAction, Action } from 'vs/base/common/actions';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
@@ -166,11 +166,13 @@ class BreakpointEditorContribution implements IBreakpointEditorContribution {
|
||||
|
||||
const anchor = { x: e.event.posx, y: e.event.posy };
|
||||
const breakpoints = this.debugService.getModel().getBreakpoints({ lineNumber, uri });
|
||||
const actions = this.getContextMenuActions(breakpoints, uri, lineNumber);
|
||||
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => anchor,
|
||||
getActions: () => this.getContextMenuActions(breakpoints, uri, lineNumber),
|
||||
getActionsContext: () => breakpoints.length ? breakpoints[0] : undefined
|
||||
getActions: () => actions,
|
||||
getActionsContext: () => breakpoints.length ? breakpoints[0] : undefined,
|
||||
onHide: () => dispose(actions)
|
||||
});
|
||||
} else {
|
||||
const breakpoints = this.debugService.getModel().getBreakpoints({ uri, lineNumber });
|
||||
@@ -243,7 +245,7 @@ class BreakpointEditorContribution implements IBreakpointEditorContribution {
|
||||
this.toDispose.push(this.editor.onDidChangeModelDecorations(() => this.onModelDecorationsChanged()));
|
||||
}
|
||||
|
||||
private getContextMenuActions(breakpoints: ReadonlyArray<IBreakpoint>, uri: uri, lineNumber: number, column?: number): Array<IAction | ContextSubMenu> {
|
||||
private getContextMenuActions(breakpoints: ReadonlyArray<IBreakpoint>, uri: URI, lineNumber: number, column?: number): Array<IAction | ContextSubMenu> {
|
||||
const actions: Array<IAction | ContextSubMenu> = [];
|
||||
if (breakpoints.length === 1) {
|
||||
const breakpointType = breakpoints[0].logMessage ? nls.localize('logPoint', "Logpoint") : nls.localize('breakpoint', "Breakpoint");
|
||||
@@ -371,7 +373,8 @@ class BreakpointEditorContribution implements IBreakpointEditorContribution {
|
||||
let inlineWidget: InlineBreakpointWidget | undefined = undefined;
|
||||
const breakpoint = breakpoints[index];
|
||||
if (breakpoint.column) {
|
||||
inlineWidget = new InlineBreakpointWidget(activeCodeEditor, decorationId, desiredBreakpointDecorations[index].options.glyphMarginClassName, breakpoint, this.debugService, this.contextMenuService, () => this.getContextMenuActions([breakpoint], activeCodeEditor.getModel().uri, breakpoint.lineNumber, breakpoint.column));
|
||||
const contextMenuActions = () => this.getContextMenuActions([breakpoint], activeCodeEditor.getModel().uri, breakpoint.lineNumber, breakpoint.column);
|
||||
inlineWidget = new InlineBreakpointWidget(activeCodeEditor, decorationId, desiredBreakpointDecorations[index].options.glyphMarginClassName, breakpoint, this.debugService, this.contextMenuService, contextMenuActions);
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -394,8 +397,12 @@ class BreakpointEditorContribution implements IBreakpointEditorContribution {
|
||||
});
|
||||
this.candidateDecorations = candidateDecorationIds.map((decorationId, index) => {
|
||||
const candidate = desiredCandidateDecorations[index];
|
||||
const cssClass = candidate.breakpoint ? undefined : 'debug-breakpoint-disabled';
|
||||
const inlineWidget = new InlineBreakpointWidget(activeCodeEditor, decorationId, cssClass, candidate.breakpoint, this.debugService, this.contextMenuService, () => this.getContextMenuActions([], activeCodeEditor.getModel().uri, candidate.range.startLineNumber, candidate.range.startColumn));
|
||||
// Candidate decoration has a breakpoint attached when a breakpoint is already at that location and we did not yet set a decoration there
|
||||
// In practice this happens for the first breakpoint that was set on a line
|
||||
// We could have also rendered this first decoration as part of desiredBreakpointDecorations however at that moment we have no location information
|
||||
const cssClass = candidate.breakpoint ? getBreakpointMessageAndClassName(this.debugService, candidate.breakpoint).className : 'debug-breakpoint-disabled';
|
||||
const contextMenuActions = () => this.getContextMenuActions(candidate.breakpoint ? [candidate.breakpoint] : [], activeCodeEditor.getModel().uri, candidate.range.startLineNumber, candidate.range.startColumn);
|
||||
const inlineWidget = new InlineBreakpointWidget(activeCodeEditor, decorationId, cssClass, candidate.breakpoint, this.debugService, this.contextMenuService, contextMenuActions);
|
||||
|
||||
return {
|
||||
decorationId,
|
||||
@@ -524,14 +531,15 @@ class InlineBreakpointWidget implements IContentWidget, IDisposable {
|
||||
await this.debugService.addBreakpoints(this.editor.getModel().uri, [{ lineNumber: this.range!.startLineNumber, column: this.range!.startColumn }], 'debugEditorInlineWidget');
|
||||
}
|
||||
}));
|
||||
this.toDispose.push(dom.addDisposableListener(this.domNode, dom.EventType.CONTEXT_MENU, async e => {
|
||||
this.toDispose.push(dom.addDisposableListener(this.domNode, dom.EventType.CONTEXT_MENU, e => {
|
||||
const event = new StandardMouseEvent(e);
|
||||
const anchor = { x: event.posx, y: event.posy };
|
||||
|
||||
const actions = this.getContextMenuActions();
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => anchor,
|
||||
getActions: () => this.getContextMenuActions(),
|
||||
getActionsContext: () => this.breakpoint
|
||||
getActions: () => actions,
|
||||
getActionsContext: () => this.breakpoint,
|
||||
onHide: () => dispose(actions)
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -152,6 +152,7 @@ export class BreakpointWidget extends ZoneWidget implements IPrivateBreakpointWi
|
||||
|
||||
const value = this.getInputValue(this.breakpoint);
|
||||
this.input.getModel().setValue(value);
|
||||
this.input.focus();
|
||||
});
|
||||
|
||||
this.createBreakpointInput(dom.append(container, $('.inputContainer')));
|
||||
|
||||
@@ -196,7 +196,8 @@ export class BreakpointsView extends ViewletPanel {
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => e.anchor,
|
||||
getActions: () => actions,
|
||||
getActionsContext: () => element
|
||||
getActionsContext: () => element,
|
||||
onHide: () => dispose(actions)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -654,9 +655,8 @@ export function getBreakpointMessageAndClassName(debugService: IDebugService, br
|
||||
};
|
||||
}
|
||||
|
||||
const session = debugService.getViewModel().focusedSession;
|
||||
if (breakpoint instanceof FunctionBreakpoint) {
|
||||
if (session && !session.capabilities.supportsFunctionBreakpoints) {
|
||||
if (!breakpoint.supported) {
|
||||
return {
|
||||
className: 'debug-function-breakpoint-unverified',
|
||||
message: nls.localize('functionBreakpointUnsupported', "Function breakpoints not supported by this debug type"),
|
||||
@@ -670,7 +670,7 @@ export function getBreakpointMessageAndClassName(debugService: IDebugService, br
|
||||
}
|
||||
|
||||
if (breakpoint instanceof DataBreakpoint) {
|
||||
if (session && !session.capabilities.supportsDataBreakpoints) {
|
||||
if (!breakpoint.supported) {
|
||||
return {
|
||||
className: 'debug-data-breakpoint-unverified',
|
||||
message: nls.localize('dataBreakpointUnsupported', "Data breakpoints not supported by this debug type"),
|
||||
@@ -685,30 +685,17 @@ export function getBreakpointMessageAndClassName(debugService: IDebugService, br
|
||||
|
||||
if (breakpoint.logMessage || breakpoint.condition || breakpoint.hitCondition) {
|
||||
const messages: string[] = [];
|
||||
if (breakpoint.logMessage) {
|
||||
if (session && !session.capabilities.supportsLogPoints) {
|
||||
return {
|
||||
className: 'debug-breakpoint-unsupported',
|
||||
message: nls.localize('logBreakpointUnsupported', "Logpoints not supported by this debug type"),
|
||||
};
|
||||
}
|
||||
|
||||
if (!breakpoint.supported) {
|
||||
return {
|
||||
className: 'debug-breakpoint-unsupported',
|
||||
message: nls.localize('breakpointUnsupported', "Breakpoints of this type are not supported by the debugger"),
|
||||
};
|
||||
}
|
||||
|
||||
if (breakpoint.logMessage) {
|
||||
messages.push(nls.localize('logMessage', "Log Message: {0}", breakpoint.logMessage));
|
||||
}
|
||||
|
||||
if (session && breakpoint.condition && !session.capabilities.supportsConditionalBreakpoints) {
|
||||
return {
|
||||
className: 'debug-breakpoint-unsupported',
|
||||
message: nls.localize('conditionalBreakpointUnsupported', "Conditional breakpoints not supported by this debug type"),
|
||||
};
|
||||
}
|
||||
if (session && breakpoint.hitCondition && !session.capabilities.supportsHitConditionalBreakpoints) {
|
||||
return {
|
||||
className: 'debug-breakpoint-unsupported',
|
||||
message: nls.localize('hitBreakpointUnsupported', "Hit conditional breakpoints not supported by this debug type"),
|
||||
};
|
||||
}
|
||||
|
||||
if (breakpoint.condition) {
|
||||
messages.push(nls.localize('expression', "Expression: {0}", breakpoint.condition));
|
||||
}
|
||||
|
||||
@@ -312,7 +312,7 @@ export class CallStackView extends ViewletPanel {
|
||||
}
|
||||
|
||||
const actions: IAction[] = [];
|
||||
const actionsDisposable = createAndFillInContextMenuActions(this.contributedContextMenu, { arg: this.getContextForContributedActions(element), shouldForwardArgs: true }, actions, this.contextMenuService);
|
||||
const actionsDisposable = createAndFillInContextMenuActions(this.contributedContextMenu, { arg: this.getContextForContributedActions(element), shouldForwardArgs: false }, actions, this.contextMenuService);
|
||||
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => e.anchor,
|
||||
|
||||
@@ -128,11 +128,11 @@ Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).regi
|
||||
|
||||
const debugCategory = nls.localize('debugCategory', "Debug");
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(StartAction, StartAction.ID, StartAction.LABEL, { primary: KeyCode.F5 }, CONTEXT_IN_DEBUG_MODE.toNegated()), 'Debug: Start Debugging', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(StartAction, StartAction.ID, StartAction.LABEL, { primary: KeyCode.F5 }), 'Debug: Start Debugging', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ConfigureAction, ConfigureAction.ID, ConfigureAction.LABEL), 'Debug: Open launch.json', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(AddFunctionBreakpointAction, AddFunctionBreakpointAction.ID, AddFunctionBreakpointAction.LABEL), 'Debug: Add Function Breakpoint', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ReapplyBreakpointsAction, ReapplyBreakpointsAction.ID, ReapplyBreakpointsAction.LABEL), 'Debug: Reapply All Breakpoints', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(RunAction, RunAction.ID, RunAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.F5, mac: { primary: KeyMod.WinCtrl | KeyCode.F5 } }, CONTEXT_IN_DEBUG_MODE.toNegated()), 'Debug: Start Without Debugging', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(RunAction, RunAction.ID, RunAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.F5, mac: { primary: KeyMod.WinCtrl | KeyCode.F5 } }), 'Debug: Start Without Debugging', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(RemoveAllBreakpointsAction, RemoveAllBreakpointsAction.ID, RemoveAllBreakpointsAction.LABEL), 'Debug: Remove All Breakpoints', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(EnableAllBreakpointsAction, EnableAllBreakpointsAction.ID, EnableAllBreakpointsAction.LABEL), 'Debug: Enable All Breakpoints', debugCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(DisableAllBreakpointsAction, DisableAllBreakpointsAction.ID, DisableAllBreakpointsAction.LABEL), 'Debug: Disable All Breakpoints', debugCategory);
|
||||
@@ -556,13 +556,13 @@ if (isMacintosh) {
|
||||
});
|
||||
};
|
||||
|
||||
registerTouchBarEntry(StartAction.ID, StartAction.LABEL, 0, CONTEXT_IN_DEBUG_MODE.toNegated(), URI.parse(registerAndGetAmdImageURL('vs/workbench/contrib/debug/browser/media/continue-tb.png')));
|
||||
registerTouchBarEntry(RunAction.ID, RunAction.LABEL, 1, CONTEXT_IN_DEBUG_MODE.toNegated(), URI.parse(registerAndGetAmdImageURL('vs/workbench/contrib/debug/browser/media/continue-without-debugging-tb.png')));
|
||||
registerTouchBarEntry(CONTINUE_ID, CONTINUE_LABEL, 0, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), URI.parse(registerAndGetAmdImageURL('vs/workbench/contrib/debug/browser/media/continue-tb.png')));
|
||||
registerTouchBarEntry(PAUSE_ID, PAUSE_LABEL, 1, ContextKeyExpr.and(CONTEXT_IN_DEBUG_MODE, ContextKeyExpr.notEquals('debugState', 'stopped')), URI.parse(registerAndGetAmdImageURL('vs/workbench/contrib/debug/browser/media/pause-tb.png')));
|
||||
registerTouchBarEntry(STEP_OVER_ID, STEP_OVER_LABEL, 2, CONTEXT_IN_DEBUG_MODE, URI.parse(registerAndGetAmdImageURL('vs/workbench/contrib/debug/browser/media/stepover-tb.png')));
|
||||
registerTouchBarEntry(STEP_INTO_ID, STEP_INTO_LABEL, 3, CONTEXT_IN_DEBUG_MODE, URI.parse(registerAndGetAmdImageURL('vs/workbench/contrib/debug/browser/media/stepinto-tb.png')));
|
||||
registerTouchBarEntry(STEP_OUT_ID, STEP_OUT_LABEL, 4, CONTEXT_IN_DEBUG_MODE, URI.parse(registerAndGetAmdImageURL('vs/workbench/contrib/debug/browser/media/stepout-tb.png')));
|
||||
registerTouchBarEntry(RESTART_SESSION_ID, RESTART_LABEL, 5, CONTEXT_IN_DEBUG_MODE, URI.parse(registerAndGetAmdImageURL('vs/workbench/contrib/debug/browser/media/restart-tb.png')));
|
||||
registerTouchBarEntry(STOP_ID, STOP_LABEL, 6, CONTEXT_IN_DEBUG_MODE, URI.parse(registerAndGetAmdImageURL('vs/workbench/contrib/debug/browser/media/stop-tb.png')));
|
||||
registerTouchBarEntry(StartAction.ID, StartAction.LABEL, 0, CONTEXT_IN_DEBUG_MODE.toNegated(), URI.parse(require.toUrl('vs/workbench/contrib/debug/browser/media/continue-tb.png')));
|
||||
registerTouchBarEntry(RunAction.ID, RunAction.LABEL, 1, CONTEXT_IN_DEBUG_MODE.toNegated(), URI.parse(require.toUrl('vs/workbench/contrib/debug/browser/media/continue-without-debugging-tb.png')));
|
||||
registerTouchBarEntry(CONTINUE_ID, CONTINUE_LABEL, 0, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), URI.parse(require.toUrl('vs/workbench/contrib/debug/browser/media/continue-tb.png')));
|
||||
registerTouchBarEntry(PAUSE_ID, PAUSE_LABEL, 1, ContextKeyExpr.and(CONTEXT_IN_DEBUG_MODE, ContextKeyExpr.notEquals('debugState', 'stopped')), URI.parse(require.toUrl('vs/workbench/contrib/debug/browser/media/pause-tb.png')));
|
||||
registerTouchBarEntry(STEP_OVER_ID, STEP_OVER_LABEL, 2, CONTEXT_IN_DEBUG_MODE, URI.parse(require.toUrl('vs/workbench/contrib/debug/browser/media/stepover-tb.png')));
|
||||
registerTouchBarEntry(STEP_INTO_ID, STEP_INTO_LABEL, 3, CONTEXT_IN_DEBUG_MODE, URI.parse(require.toUrl('vs/workbench/contrib/debug/browser/media/stepinto-tb.png')));
|
||||
registerTouchBarEntry(STEP_OUT_ID, STEP_OUT_LABEL, 4, CONTEXT_IN_DEBUG_MODE, URI.parse(require.toUrl('vs/workbench/contrib/debug/browser/media/stepout-tb.png')));
|
||||
registerTouchBarEntry(RESTART_SESSION_ID, RESTART_LABEL, 5, CONTEXT_IN_DEBUG_MODE, URI.parse(require.toUrl('vs/workbench/contrib/debug/browser/media/restart-tb.png')));
|
||||
registerTouchBarEntry(STOP_ID, STOP_LABEL, 6, CONTEXT_IN_DEBUG_MODE, URI.parse(require.toUrl('vs/workbench/contrib/debug/browser/media/stop-tb.png')));
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ export class FocusSessionActionViewItem extends SelectActionViewItem {
|
||||
this._register(attachSelectBoxStyler(this.selectBox, themeService));
|
||||
|
||||
this._register(this.debugService.getViewModel().onDidFocusSession(() => {
|
||||
const session = this.debugService.getViewModel().focusedSession;
|
||||
const session = this.getSelectedSession();
|
||||
if (session) {
|
||||
const index = this.getSessions().indexOf(session);
|
||||
this.select(index);
|
||||
@@ -222,11 +222,11 @@ export class FocusSessionActionViewItem extends SelectActionViewItem {
|
||||
}
|
||||
|
||||
protected getActionContext(_: string, index: number): any {
|
||||
return this.debugService.getModel().getSessions()[index];
|
||||
return this.getSessions()[index];
|
||||
}
|
||||
|
||||
private update() {
|
||||
const session = this.debugService.getViewModel().focusedSession;
|
||||
const session = this.getSelectedSession();
|
||||
const sessions = this.getSessions();
|
||||
const names = sessions.map(s => {
|
||||
const label = s.getLabel();
|
||||
@@ -240,10 +240,23 @@ export class FocusSessionActionViewItem extends SelectActionViewItem {
|
||||
this.setOptions(names.map(data => <ISelectOptionItem>{ text: data }), session ? sessions.indexOf(session) : undefined);
|
||||
}
|
||||
|
||||
private getSelectedSession(): IDebugSession | undefined {
|
||||
const session = this.debugService.getViewModel().focusedSession;
|
||||
return session ? this.mapFocusedSessionToSelected(session) : undefined;
|
||||
}
|
||||
|
||||
protected getSessions(): ReadonlyArray<IDebugSession> {
|
||||
const showSubSessions = this.configurationService.getValue<IDebugConfiguration>('debug').showSubSessionsInToolBar;
|
||||
const sessions = this.debugService.getModel().getSessions();
|
||||
|
||||
return showSubSessions ? sessions : sessions.filter(s => !s.parentSession);
|
||||
}
|
||||
|
||||
protected mapFocusedSessionToSelected(focusedSession: IDebugSession): IDebugSession {
|
||||
const showSubSessions = this.configurationService.getValue<IDebugConfiguration>('debug').showSubSessionsInToolBar;
|
||||
while (focusedSession.parentSession && !showSubSessions) {
|
||||
focusedSession = focusedSession.parentSession;
|
||||
}
|
||||
return focusedSession;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import * as lifecycle from 'vs/base/common/lifecycle';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { IDebugService, State, IEnablement, IBreakpoint, IDebugSession } from 'vs/workbench/contrib/debug/common/debug';
|
||||
@@ -16,16 +15,16 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
|
||||
import { IHistoryService } from 'vs/workbench/services/history/common/history';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
import { startDebugging } from 'vs/workbench/contrib/debug/common/debugUtils';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
|
||||
export abstract class AbstractDebugAction extends Action {
|
||||
|
||||
protected toDispose: lifecycle.IDisposable[];
|
||||
protected toDispose: IDisposable[];
|
||||
|
||||
constructor(
|
||||
id: string, label: string, cssClass: string,
|
||||
@IDebugService protected debugService: IDebugService,
|
||||
@IKeybindingService protected keybindingService: IKeybindingService,
|
||||
public weight?: number
|
||||
) {
|
||||
super(id, label, cssClass, false);
|
||||
this.toDispose = [];
|
||||
@@ -35,11 +34,11 @@ export abstract class AbstractDebugAction extends Action {
|
||||
this.updateEnablement();
|
||||
}
|
||||
|
||||
public run(e?: any): Promise<any> {
|
||||
run(_: any): Promise<any> {
|
||||
throw new Error('implement me');
|
||||
}
|
||||
|
||||
public get tooltip(): string {
|
||||
get tooltip(): string {
|
||||
const keybinding = this.keybindingService.lookupKeybinding(this.id);
|
||||
const keybindingLabel = keybinding && keybinding.getLabel();
|
||||
|
||||
@@ -54,13 +53,13 @@ export abstract class AbstractDebugAction extends Action {
|
||||
this.enabled = this.isEnabled(state);
|
||||
}
|
||||
|
||||
protected isEnabled(state: State): boolean {
|
||||
protected isEnabled(_: State): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
dispose(): void {
|
||||
super.dispose();
|
||||
this.toDispose = lifecycle.dispose(this.toDispose);
|
||||
this.toDispose = dispose(this.toDispose);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +78,7 @@ export class ConfigureAction extends AbstractDebugAction {
|
||||
this.updateClass();
|
||||
}
|
||||
|
||||
public get tooltip(): string {
|
||||
get tooltip(): string {
|
||||
if (this.debugService.getConfigurationManager().selectedConfiguration.name) {
|
||||
return ConfigureAction.LABEL;
|
||||
}
|
||||
@@ -93,7 +92,7 @@ export class ConfigureAction extends AbstractDebugAction {
|
||||
this.class = configurationCount > 0 ? 'debug-action configure' : 'debug-action configure notification';
|
||||
}
|
||||
|
||||
public run(event?: any): Promise<any> {
|
||||
run(event?: any): Promise<any> {
|
||||
if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) {
|
||||
this.notificationService.info(nls.localize('noFolderDebugConfig', "Please first open a folder in order to do advanced debug configuration."));
|
||||
return Promise.resolve();
|
||||
@@ -127,7 +126,7 @@ export class StartAction extends AbstractDebugAction {
|
||||
this.toDispose.push(this.contextService.onDidChangeWorkbenchState(() => this.updateEnablement()));
|
||||
}
|
||||
|
||||
public run(): Promise<boolean> {
|
||||
run(): Promise<boolean> {
|
||||
return startDebugging(this.debugService, this.historyService, this.isNoDebug());
|
||||
}
|
||||
|
||||
@@ -135,7 +134,7 @@ export class StartAction extends AbstractDebugAction {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static isEnabled(debugService: IDebugService) {
|
||||
static isEnabled(debugService: IDebugService) {
|
||||
const sessions = debugService.getModel().getSessions();
|
||||
|
||||
if (debugService.state === State.Initializing) {
|
||||
@@ -176,7 +175,7 @@ export class SelectAndStartAction extends AbstractDebugAction {
|
||||
super(id, label, '', debugService, keybindingService);
|
||||
}
|
||||
|
||||
public run(): Promise<any> {
|
||||
run(): Promise<any> {
|
||||
return this.quickOpenService.show('debug ');
|
||||
}
|
||||
}
|
||||
@@ -189,7 +188,7 @@ export class RemoveBreakpointAction extends Action {
|
||||
super(id, label, 'debug-action remove');
|
||||
}
|
||||
|
||||
public run(breakpoint: IBreakpoint): Promise<any> {
|
||||
run(breakpoint: IBreakpoint): Promise<any> {
|
||||
return breakpoint instanceof Breakpoint ? this.debugService.removeBreakpoints(breakpoint.getId())
|
||||
: breakpoint instanceof FunctionBreakpoint ? this.debugService.removeFunctionBreakpoints(breakpoint.getId()) : this.debugService.removeDataBreakpoints(breakpoint.getId());
|
||||
}
|
||||
@@ -204,13 +203,13 @@ export class RemoveAllBreakpointsAction extends AbstractDebugAction {
|
||||
this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement()));
|
||||
}
|
||||
|
||||
public run(): Promise<any> {
|
||||
run(): Promise<any> {
|
||||
return Promise.all([this.debugService.removeBreakpoints(), this.debugService.removeFunctionBreakpoints(), this.debugService.removeDataBreakpoints()]);
|
||||
}
|
||||
|
||||
protected isEnabled(state: State): boolean {
|
||||
protected isEnabled(_: State): boolean {
|
||||
const model = this.debugService.getModel();
|
||||
return super.isEnabled(state) && (model.getBreakpoints().length > 0 || model.getFunctionBreakpoints().length > 0 || model.getDataBreakpoints().length > 0);
|
||||
return (model.getBreakpoints().length > 0 || model.getFunctionBreakpoints().length > 0 || model.getDataBreakpoints().length > 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,13 +222,13 @@ export class EnableAllBreakpointsAction extends AbstractDebugAction {
|
||||
this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement()));
|
||||
}
|
||||
|
||||
public run(): Promise<any> {
|
||||
run(): Promise<any> {
|
||||
return this.debugService.enableOrDisableBreakpoints(true);
|
||||
}
|
||||
|
||||
protected isEnabled(state: State): boolean {
|
||||
protected isEnabled(_: State): boolean {
|
||||
const model = this.debugService.getModel();
|
||||
return super.isEnabled(state) && (<ReadonlyArray<IEnablement>>model.getBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getExceptionBreakpoints()).some(bp => !bp.enabled);
|
||||
return (<ReadonlyArray<IEnablement>>model.getBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getExceptionBreakpoints()).some(bp => !bp.enabled);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,13 +241,13 @@ export class DisableAllBreakpointsAction extends AbstractDebugAction {
|
||||
this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement()));
|
||||
}
|
||||
|
||||
public run(): Promise<any> {
|
||||
run(): Promise<any> {
|
||||
return this.debugService.enableOrDisableBreakpoints(false);
|
||||
}
|
||||
|
||||
protected isEnabled(state: State): boolean {
|
||||
protected isEnabled(_: State): boolean {
|
||||
const model = this.debugService.getModel();
|
||||
return super.isEnabled(state) && (<ReadonlyArray<IEnablement>>model.getBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getExceptionBreakpoints()).some(bp => bp.enabled);
|
||||
return (<ReadonlyArray<IEnablement>>model.getBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getExceptionBreakpoints()).some(bp => bp.enabled);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,11 +266,11 @@ export class ToggleBreakpointsActivatedAction extends AbstractDebugAction {
|
||||
}));
|
||||
}
|
||||
|
||||
public run(): Promise<any> {
|
||||
run(): Promise<any> {
|
||||
return this.debugService.setBreakpointsActivated(!this.debugService.getModel().areBreakpointsActivated());
|
||||
}
|
||||
|
||||
protected isEnabled(state: State): boolean {
|
||||
protected isEnabled(_: State): boolean {
|
||||
return !!(this.debugService.getModel().getFunctionBreakpoints().length || this.debugService.getModel().getBreakpoints().length || this.debugService.getModel().getDataBreakpoints().length);
|
||||
}
|
||||
}
|
||||
@@ -285,13 +284,13 @@ export class ReapplyBreakpointsAction extends AbstractDebugAction {
|
||||
this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement()));
|
||||
}
|
||||
|
||||
public run(): Promise<any> {
|
||||
run(): Promise<any> {
|
||||
return this.debugService.setBreakpointsActivated(true);
|
||||
}
|
||||
|
||||
protected isEnabled(state: State): boolean {
|
||||
const model = this.debugService.getModel();
|
||||
return super.isEnabled(state) && (state === State.Running || state === State.Stopped) &&
|
||||
return (state === State.Running || state === State.Stopped) &&
|
||||
((model.getFunctionBreakpoints().length + model.getBreakpoints().length + model.getExceptionBreakpoints().length + model.getDataBreakpoints().length) > 0);
|
||||
}
|
||||
}
|
||||
@@ -305,12 +304,12 @@ export class AddFunctionBreakpointAction extends AbstractDebugAction {
|
||||
this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement()));
|
||||
}
|
||||
|
||||
public run(): Promise<any> {
|
||||
run(): Promise<any> {
|
||||
this.debugService.addFunctionBreakpoint();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
protected isEnabled(state: State): boolean {
|
||||
protected isEnabled(_: State): boolean {
|
||||
return !this.debugService.getViewModel().getSelectedFunctionBreakpoint()
|
||||
&& this.debugService.getModel().getFunctionBreakpoints().every(fbp => !!fbp.name);
|
||||
}
|
||||
@@ -326,14 +325,14 @@ export class AddWatchExpressionAction extends AbstractDebugAction {
|
||||
this.toDispose.push(this.debugService.getViewModel().onDidSelectExpression(() => this.updateEnablement()));
|
||||
}
|
||||
|
||||
public run(): Promise<any> {
|
||||
run(): Promise<any> {
|
||||
this.debugService.addWatchExpression();
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
protected isEnabled(state: State): boolean {
|
||||
protected isEnabled(_: State): boolean {
|
||||
const focusedExpression = this.debugService.getViewModel().getSelectedExpression();
|
||||
return super.isEnabled(state) && this.debugService.getModel().getWatchExpressions().every(we => !!we.name && we !== focusedExpression);
|
||||
return this.debugService.getModel().getWatchExpressions().every(we => !!we.name && we !== focusedExpression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,13 +345,13 @@ export class RemoveAllWatchExpressionsAction extends AbstractDebugAction {
|
||||
this.toDispose.push(this.debugService.getModel().onDidChangeWatchExpressions(() => this.updateEnablement()));
|
||||
}
|
||||
|
||||
public run(): Promise<any> {
|
||||
run(): Promise<any> {
|
||||
this.debugService.removeWatchExpressions();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
protected isEnabled(state: State): boolean {
|
||||
return super.isEnabled(state) && this.debugService.getModel().getWatchExpressions().length > 0;
|
||||
protected isEnabled(_: State): boolean {
|
||||
return this.debugService.getModel().getWatchExpressions().length > 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,10 +364,10 @@ export class FocusSessionAction extends AbstractDebugAction {
|
||||
@IKeybindingService keybindingService: IKeybindingService,
|
||||
@IEditorService private readonly editorService: IEditorService
|
||||
) {
|
||||
super(id, label, '', debugService, keybindingService, 100);
|
||||
super(id, label, '', debugService, keybindingService);
|
||||
}
|
||||
|
||||
public run(session: IDebugSession): Promise<any> {
|
||||
run(session: IDebugSession): Promise<any> {
|
||||
this.debugService.focusStackFrame(undefined, undefined, session, true);
|
||||
const stackFrame = this.debugService.getViewModel().focusedStackFrame;
|
||||
if (stackFrame) {
|
||||
@@ -392,17 +391,19 @@ export class CopyValueAction extends Action {
|
||||
this._enabled = typeof this.value === 'string' || (this.value instanceof Variable && !!this.value.evaluateName);
|
||||
}
|
||||
|
||||
public run(): Promise<any> {
|
||||
async run(): Promise<any> {
|
||||
const stackFrame = this.debugService.getViewModel().focusedStackFrame;
|
||||
const session = this.debugService.getViewModel().focusedSession;
|
||||
|
||||
if (this.value instanceof Variable && stackFrame && session && this.value.evaluateName) {
|
||||
return session.evaluate(this.value.evaluateName, stackFrame.frameId, this.context).then(result => {
|
||||
return this.clipboardService.writeText(result.body.result);
|
||||
}, err => this.clipboardService.writeText(this.value.value));
|
||||
try {
|
||||
const evaluation = await session.evaluate(this.value.evaluateName, stackFrame.frameId, this.context);
|
||||
this.clipboardService.writeText(evaluation.body.result);
|
||||
} catch (e) {
|
||||
this.clipboardService.writeText(this.value.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return this.clipboardService.writeText(this.value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ export class ConfigurationManager implements IConfigurationManager {
|
||||
private selectedName: string | undefined;
|
||||
private selectedLaunch: ILaunch | undefined;
|
||||
private toDispose: IDisposable[];
|
||||
private _onDidSelectConfigurationName = new Emitter<void>();
|
||||
private readonly _onDidSelectConfigurationName = new Emitter<void>();
|
||||
private configProviders: IDebugConfigurationProvider[];
|
||||
private adapterDescriptorFactories: IDebugAdapterDescriptorFactory[];
|
||||
private debugAdapterFactories = new Map<string, IDebugAdapterFactory>();
|
||||
|
||||
@@ -137,7 +137,7 @@ export class DebugHoverWidget implements IContentWidget {
|
||||
return this.domNode;
|
||||
}
|
||||
|
||||
showAt(range: Range, focus: boolean): Promise<void> {
|
||||
async showAt(range: Range, focus: boolean): Promise<void> {
|
||||
const pos = range.getStartPosition();
|
||||
|
||||
const session = this.debugService.getViewModel().focusedSession;
|
||||
@@ -153,63 +153,64 @@ export class DebugHoverWidget implements IContentWidget {
|
||||
return Promise.resolve(this.hide());
|
||||
}
|
||||
|
||||
let promise: Promise<IExpression | undefined>;
|
||||
let expression;
|
||||
if (session.capabilities.supportsEvaluateForHovers) {
|
||||
const result = new Expression(matchingExpression);
|
||||
promise = result.evaluate(session, this.debugService.getViewModel().focusedStackFrame, 'hover').then(() => result);
|
||||
expression = new Expression(matchingExpression);
|
||||
await expression.evaluate(session, this.debugService.getViewModel().focusedStackFrame, 'hover');
|
||||
} else {
|
||||
promise = this.findExpressionInStackFrame(coalesce(matchingExpression.split('.').map(word => word.trim())));
|
||||
expression = await this.findExpressionInStackFrame(coalesce(matchingExpression.split('.').map(word => word.trim())));
|
||||
}
|
||||
|
||||
return promise.then(expression => {
|
||||
if (!expression || (expression instanceof Expression && !expression.available)) {
|
||||
this.hide();
|
||||
return undefined;
|
||||
}
|
||||
if (!expression || (expression instanceof Expression && !expression.available)) {
|
||||
this.hide();
|
||||
return undefined;
|
||||
}
|
||||
|
||||
this.highlightDecorations = this.editor.deltaDecorations(this.highlightDecorations, [{
|
||||
range: new Range(pos.lineNumber, start, pos.lineNumber, start + matchingExpression.length),
|
||||
options: DebugHoverWidget._HOVER_HIGHLIGHT_DECORATION_OPTIONS
|
||||
}]);
|
||||
this.highlightDecorations = this.editor.deltaDecorations(this.highlightDecorations, [{
|
||||
range: new Range(pos.lineNumber, start, pos.lineNumber, start + matchingExpression.length),
|
||||
options: DebugHoverWidget._HOVER_HIGHLIGHT_DECORATION_OPTIONS
|
||||
}]);
|
||||
|
||||
return this.doShow(pos, expression, focus);
|
||||
});
|
||||
return this.doShow(pos, expression, focus);
|
||||
}
|
||||
|
||||
private static _HOVER_HIGHLIGHT_DECORATION_OPTIONS = ModelDecorationOptions.register({
|
||||
className: 'hoverHighlight'
|
||||
});
|
||||
|
||||
private doFindExpression(container: IExpressionContainer, namesToFind: string[]): Promise<IExpression | null> {
|
||||
private async doFindExpression(container: IExpressionContainer, namesToFind: string[]): Promise<IExpression | null> {
|
||||
if (!container) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
return container.getChildren().then(children => {
|
||||
// look for our variable in the list. First find the parents of the hovered variable if there are any.
|
||||
const filtered = children.filter(v => namesToFind[0] === v.name);
|
||||
if (filtered.length !== 1) {
|
||||
return null;
|
||||
}
|
||||
const children = await container.getChildren();
|
||||
// look for our variable in the list. First find the parents of the hovered variable if there are any.
|
||||
const filtered = children.filter(v => namesToFind[0] === v.name);
|
||||
if (filtered.length !== 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (namesToFind.length === 1) {
|
||||
return filtered[0];
|
||||
} else {
|
||||
return this.doFindExpression(filtered[0], namesToFind.slice(1));
|
||||
}
|
||||
});
|
||||
if (namesToFind.length === 1) {
|
||||
return filtered[0];
|
||||
} else {
|
||||
return this.doFindExpression(filtered[0], namesToFind.slice(1));
|
||||
}
|
||||
}
|
||||
|
||||
private findExpressionInStackFrame(namesToFind: string[]): Promise<IExpression | undefined> {
|
||||
return this.debugService.getViewModel().focusedStackFrame!.getScopes()
|
||||
.then(scopes => scopes.filter(s => !s.expensive))
|
||||
.then(scopes => Promise.all(scopes.map(scope => this.doFindExpression(scope, namesToFind))))
|
||||
.then(coalesce)
|
||||
// only show if all expressions found have the same value
|
||||
.then(expressions => (expressions.length > 0 && expressions.every(e => e.value === expressions[0].value)) ? expressions[0] : undefined);
|
||||
private async findExpressionInStackFrame(namesToFind: string[]): Promise<IExpression | undefined> {
|
||||
const focusedStackFrame = this.debugService.getViewModel().focusedStackFrame;
|
||||
if (!focusedStackFrame) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const scopes = await focusedStackFrame.getScopes();
|
||||
const nonExpensive = scopes.filter(s => !s.expensive);
|
||||
const expressions = coalesce(await Promise.all(nonExpensive.map(scope => this.doFindExpression(scope, namesToFind))));
|
||||
// only show if all expressions found have the same value
|
||||
return expressions.length > 0 && expressions.every(e => e.value === expressions[0].value) ? expressions[0] : undefined;
|
||||
}
|
||||
|
||||
private doShow(position: Position, expression: IExpression, focus: boolean, forceValueHover = false): Promise<void> {
|
||||
private async doShow(position: Position, expression: IExpression, focus: boolean, forceValueHover = false): Promise<void> {
|
||||
if (!this.domNode) {
|
||||
this.create();
|
||||
}
|
||||
@@ -239,20 +240,19 @@ export class DebugHoverWidget implements IContentWidget {
|
||||
this.valueContainer.hidden = true;
|
||||
this.complexValueContainer.hidden = false;
|
||||
|
||||
return this.tree.setInput(expression).then(() => {
|
||||
this.complexValueTitle.textContent = replaceWhitespace(expression.value);
|
||||
this.complexValueTitle.title = expression.value;
|
||||
this.layoutTreeAndContainer();
|
||||
this.editor.layoutContentWidget(this);
|
||||
this.scrollbar.scanDomNode();
|
||||
this.tree.scrollTop = 0;
|
||||
this.tree.scrollLeft = 0;
|
||||
await this.tree.setInput(expression);
|
||||
this.complexValueTitle.textContent = replaceWhitespace(expression.value);
|
||||
this.complexValueTitle.title = expression.value;
|
||||
this.layoutTreeAndContainer();
|
||||
this.editor.layoutContentWidget(this);
|
||||
this.scrollbar.scanDomNode();
|
||||
this.tree.scrollTop = 0;
|
||||
this.tree.scrollLeft = 0;
|
||||
|
||||
if (focus) {
|
||||
this.editor.render();
|
||||
this.tree.domFocus();
|
||||
}
|
||||
});
|
||||
if (focus) {
|
||||
this.editor.render();
|
||||
this.tree.domFocus();
|
||||
}
|
||||
}
|
||||
|
||||
private layoutTreeAndContainer(): void {
|
||||
|
||||
@@ -21,19 +21,19 @@ class AddConfigEntry extends QuickOpenEntry {
|
||||
super(highlights);
|
||||
}
|
||||
|
||||
public getLabel(): string {
|
||||
getLabel(): string {
|
||||
return this.label;
|
||||
}
|
||||
|
||||
public getDescription(): string {
|
||||
getDescription(): string {
|
||||
return this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? this.launch.name : '';
|
||||
}
|
||||
|
||||
public getAriaLabel(): string {
|
||||
getAriaLabel(): string {
|
||||
return nls.localize('entryAriaLabel', "{0}, debug", this.getLabel());
|
||||
}
|
||||
|
||||
public run(mode: Mode): boolean {
|
||||
run(mode: Mode): boolean {
|
||||
if (mode === Mode.PREVIEW) {
|
||||
return false;
|
||||
}
|
||||
@@ -49,19 +49,19 @@ class StartDebugEntry extends QuickOpenEntry {
|
||||
super(highlights);
|
||||
}
|
||||
|
||||
public getLabel(): string {
|
||||
getLabel(): string {
|
||||
return this.configurationName;
|
||||
}
|
||||
|
||||
public getDescription(): string {
|
||||
getDescription(): string {
|
||||
return this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? this.launch.name : '';
|
||||
}
|
||||
|
||||
public getAriaLabel(): string {
|
||||
getAriaLabel(): string {
|
||||
return nls.localize('entryAriaLabel', "{0}, debug", this.getLabel());
|
||||
}
|
||||
|
||||
public run(mode: Mode): boolean {
|
||||
run(mode: Mode): boolean {
|
||||
if (mode === Mode.PREVIEW || !StartAction.isEnabled(this.debugService)) {
|
||||
return false;
|
||||
}
|
||||
@@ -75,7 +75,7 @@ class StartDebugEntry extends QuickOpenEntry {
|
||||
|
||||
export class DebugQuickOpenHandler extends QuickOpenHandler {
|
||||
|
||||
public static readonly ID = 'workbench.picker.launch';
|
||||
static readonly ID = 'workbench.picker.launch';
|
||||
|
||||
private autoFocusIndex: number | undefined;
|
||||
|
||||
@@ -88,11 +88,11 @@ export class DebugQuickOpenHandler extends QuickOpenHandler {
|
||||
super();
|
||||
}
|
||||
|
||||
public getAriaLabel(): string {
|
||||
getAriaLabel(): string {
|
||||
return nls.localize('debugAriaLabel', "Type a name of a launch configuration to run.");
|
||||
}
|
||||
|
||||
public getResults(input: string, token: CancellationToken): Promise<QuickOpenModel> {
|
||||
getResults(input: string, token: CancellationToken): Promise<QuickOpenModel> {
|
||||
const configurations: QuickOpenEntry[] = [];
|
||||
|
||||
const configManager = this.debugService.getConfigurationManager();
|
||||
@@ -122,14 +122,14 @@ export class DebugQuickOpenHandler extends QuickOpenHandler {
|
||||
return Promise.resolve(new QuickOpenModel(configurations));
|
||||
}
|
||||
|
||||
public getAutoFocus(input: string): IAutoFocus {
|
||||
getAutoFocus(input: string): IAutoFocus {
|
||||
return {
|
||||
autoFocusFirstEntry: !!input,
|
||||
autoFocusIndex: this.autoFocusIndex
|
||||
};
|
||||
}
|
||||
|
||||
public getEmptyLabel(searchString: string): string {
|
||||
getEmptyLabel(searchString: string): string {
|
||||
if (searchString.length > 0) {
|
||||
return nls.localize('noConfigurationsMatching', "No debug configurations matching");
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ import { IAction } from 'vs/base/common/actions';
|
||||
import { deepClone, equals } from 'vs/base/common/objects';
|
||||
import { DebugSession } from 'vs/workbench/contrib/debug/browser/debugSession';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IDebugService, State, IDebugSession, CONTEXT_DEBUG_TYPE, CONTEXT_DEBUG_STATE, CONTEXT_IN_DEBUG_MODE, IThread, IDebugConfiguration, VIEWLET_ID, REPL_ID, IConfig, ILaunch, IViewModel, IConfigurationManager, IDebugModel, IEnablement, IBreakpoint, IBreakpointData, ICompound, IGlobalConfig, IStackFrame, AdapterEndEvent, getStateLabel } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IDebugService, State, IDebugSession, CONTEXT_DEBUG_TYPE, CONTEXT_DEBUG_STATE, CONTEXT_IN_DEBUG_MODE, IThread, IDebugConfiguration, VIEWLET_ID, REPL_ID, IConfig, ILaunch, IViewModel, IConfigurationManager, IDebugModel, IEnablement, IBreakpoint, IBreakpointData, ICompound, IGlobalConfig, IStackFrame, AdapterEndEvent, getStateLabel, IDebugSessionOptions } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { isExtensionHostDebugging } from 'vs/workbench/contrib/debug/common/debugUtils';
|
||||
import { isErrorWithActions, createErrorWithActions } from 'vs/base/common/errorsWithActions';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
@@ -167,9 +167,7 @@ export class DebugService implements IDebugService {
|
||||
this.toDispose.push(this.viewModel.onDidFocusStackFrame(() => {
|
||||
this.onStateChange();
|
||||
}));
|
||||
this.toDispose.push(this.viewModel.onDidFocusSession(session => {
|
||||
const id = session ? session.getId() : undefined;
|
||||
this.model.setBreakpointsSessionId(id);
|
||||
this.toDispose.push(this.viewModel.onDidFocusSession(() => {
|
||||
this.onStateChange();
|
||||
}));
|
||||
}
|
||||
@@ -255,7 +253,7 @@ export class DebugService implements IDebugService {
|
||||
* main entry point
|
||||
* properly manages compounds, checks for errors and handles the initializing state.
|
||||
*/
|
||||
startDebugging(launch: ILaunch | undefined, configOrName?: IConfig | string, noDebug = false, parentSession?: IDebugSession): Promise<boolean> {
|
||||
startDebugging(launch: ILaunch | undefined, configOrName?: IConfig | string, options?: IDebugSessionOptions): Promise<boolean> {
|
||||
|
||||
this.startInitializingState();
|
||||
// make sure to save all files and that the configuration is up to date
|
||||
@@ -318,7 +316,7 @@ export class DebugService implements IDebugService {
|
||||
}
|
||||
}
|
||||
|
||||
return this.createSession(launchForName, launchForName!.getConfiguration(name), noDebug, parentSession);
|
||||
return this.createSession(launchForName, launchForName!.getConfiguration(name), options);
|
||||
})).then(values => values.every(success => !!success)); // Compound launch is a success only if each configuration launched successfully
|
||||
}
|
||||
|
||||
@@ -328,7 +326,7 @@ export class DebugService implements IDebugService {
|
||||
return Promise.reject(new Error(message));
|
||||
}
|
||||
|
||||
return this.createSession(launch, config, noDebug, parentSession);
|
||||
return this.createSession(launch, config, options);
|
||||
});
|
||||
}));
|
||||
}).then(success => {
|
||||
@@ -344,7 +342,7 @@ export class DebugService implements IDebugService {
|
||||
/**
|
||||
* gets the debugger for the type, resolves configurations by providers, substitutes variables and runs prelaunch tasks
|
||||
*/
|
||||
private createSession(launch: ILaunch | undefined, config: IConfig | undefined, noDebug: boolean, parentSession?: IDebugSession): Promise<boolean> {
|
||||
private createSession(launch: ILaunch | undefined, config: IConfig | undefined, options?: IDebugSessionOptions): Promise<boolean> {
|
||||
// We keep the debug type in a separate variable 'type' so that a no-folder config has no attributes.
|
||||
// Storing the type in the config would break extensions that assume that the no-folder case is indicated by an empty config.
|
||||
let type: string | undefined;
|
||||
@@ -356,7 +354,7 @@ export class DebugService implements IDebugService {
|
||||
}
|
||||
const unresolvedConfig = deepClone(config);
|
||||
|
||||
if (noDebug) {
|
||||
if (options && options.noDebug) {
|
||||
config!.noDebug = true;
|
||||
}
|
||||
|
||||
@@ -390,7 +388,7 @@ export class DebugService implements IDebugService {
|
||||
const workspace = launch ? launch.workspace : undefined;
|
||||
return this.runTaskAndCheckErrors(workspace, resolvedConfig.preLaunchTask).then(result => {
|
||||
if (result === TaskRunResult.Success) {
|
||||
return this.doCreateSession(workspace, { resolved: resolvedConfig, unresolved: unresolvedConfig }, parentSession);
|
||||
return this.doCreateSession(workspace, { resolved: resolvedConfig, unresolved: unresolvedConfig }, options);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
@@ -419,9 +417,9 @@ export class DebugService implements IDebugService {
|
||||
/**
|
||||
* instantiates the new session, initializes the session, registers session listeners and reports telemetry
|
||||
*/
|
||||
private doCreateSession(root: IWorkspaceFolder | undefined, configuration: { resolved: IConfig, unresolved: IConfig | undefined }, parentSession?: IDebugSession): Promise<boolean> {
|
||||
private doCreateSession(root: IWorkspaceFolder | undefined, configuration: { resolved: IConfig, unresolved: IConfig | undefined }, options?: IDebugSessionOptions): Promise<boolean> {
|
||||
|
||||
const session = this.instantiationService.createInstance(DebugSession, configuration, root, this.model, parentSession);
|
||||
const session = this.instantiationService.createInstance(DebugSession, configuration, root, this.model, options);
|
||||
this.model.addSession(session);
|
||||
// register listeners as the very first thing!
|
||||
this.registerSessionListeners(session);
|
||||
|
||||
@@ -12,7 +12,7 @@ import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { CompletionItem, completionKindFromString } from 'vs/editor/common/modes';
|
||||
import { Position, IPosition } from 'vs/editor/common/core/position';
|
||||
import * as aria from 'vs/base/browser/ui/aria/aria';
|
||||
import { IDebugSession, IConfig, IThread, IRawModelUpdate, IDebugService, IRawStoppedDetails, State, LoadedSourceEvent, IFunctionBreakpoint, IExceptionBreakpoint, IBreakpoint, IExceptionInfo, AdapterEndEvent, IDebugger, VIEWLET_ID, IDebugConfiguration, IReplElement, IStackFrame, IExpression, IReplElementSource, IDataBreakpoint } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IDebugSession, IConfig, IThread, IRawModelUpdate, IDebugService, IRawStoppedDetails, State, LoadedSourceEvent, IFunctionBreakpoint, IExceptionBreakpoint, IBreakpoint, IExceptionInfo, AdapterEndEvent, IDebugger, VIEWLET_ID, IDebugConfiguration, IReplElement, IStackFrame, IExpression, IReplElementSource, IDataBreakpoint, IDebugSessionOptions } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import { Thread, ExpressionContainer, DebugModel } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
@@ -43,6 +43,7 @@ export class DebugSession implements IDebugSession {
|
||||
private _subId: string | undefined;
|
||||
private raw: RawDebugSession | undefined;
|
||||
private initialized = false;
|
||||
private _options: IDebugSessionOptions;
|
||||
|
||||
private sources = new Map<string, Source>();
|
||||
private threads = new Map<number, Thread>();
|
||||
@@ -66,7 +67,7 @@ export class DebugSession implements IDebugSession {
|
||||
private _configuration: { resolved: IConfig, unresolved: IConfig | undefined },
|
||||
public root: IWorkspaceFolder,
|
||||
private model: DebugModel,
|
||||
private _parentSession: IDebugSession | undefined,
|
||||
options: IDebugSessionOptions | undefined,
|
||||
@IDebugService private readonly debugService: IDebugService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@@ -79,7 +80,12 @@ export class DebugSession implements IDebugSession {
|
||||
@IOpenerService private readonly openerService: IOpenerService
|
||||
) {
|
||||
this.id = generateUuid();
|
||||
this.repl = new ReplModel(this);
|
||||
this._options = options || {};
|
||||
if (this.hasSeparateRepl()) {
|
||||
this.repl = new ReplModel();
|
||||
} else {
|
||||
this.repl = (this.parentSession as DebugSession).repl;
|
||||
}
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
@@ -103,7 +109,7 @@ export class DebugSession implements IDebugSession {
|
||||
}
|
||||
|
||||
get parentSession(): IDebugSession | undefined {
|
||||
return this._parentSession;
|
||||
return this._options.parentSession;
|
||||
}
|
||||
|
||||
setConfiguration(configuration: { resolved: IConfig, unresolved: IConfig | undefined }) {
|
||||
@@ -307,7 +313,7 @@ export class DebugSession implements IDebugSession {
|
||||
data.set(breakpointsToSend[i].getId(), response.body.breakpoints[i]);
|
||||
}
|
||||
|
||||
this.model.setBreakpointSessionData(this.getId(), data);
|
||||
this.model.setBreakpointSessionData(this.getId(), this.capabilities, data);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -321,7 +327,7 @@ export class DebugSession implements IDebugSession {
|
||||
for (let i = 0; i < fbpts.length; i++) {
|
||||
data.set(fbpts[i].getId(), response.body.breakpoints[i]);
|
||||
}
|
||||
this.model.setBreakpointSessionData(this.getId(), data);
|
||||
this.model.setBreakpointSessionData(this.getId(), this.capabilities, data);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -361,7 +367,7 @@ export class DebugSession implements IDebugSession {
|
||||
for (let i = 0; i < dataBreakpoints.length; i++) {
|
||||
data.set(dataBreakpoints[i].getId(), response.body.breakpoints[i]);
|
||||
}
|
||||
this.model.setBreakpointSessionData(this.getId(), data);
|
||||
this.model.setBreakpointSessionData(this.getId(), this.capabilities, data);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -838,7 +844,7 @@ export class DebugSession implements IDebugSession {
|
||||
}], false);
|
||||
if (bps.length === 1) {
|
||||
const data = new Map<string, DebugProtocol.Breakpoint>([[bps[0].getId(), event.body.breakpoint]]);
|
||||
this.model.setBreakpointSessionData(this.getId(), data);
|
||||
this.model.setBreakpointSessionData(this.getId(), this.capabilities, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -857,11 +863,11 @@ export class DebugSession implements IDebugSession {
|
||||
event.body.breakpoint.column = undefined;
|
||||
}
|
||||
const data = new Map<string, DebugProtocol.Breakpoint>([[breakpoint.getId(), event.body.breakpoint]]);
|
||||
this.model.setBreakpointSessionData(this.getId(), data);
|
||||
this.model.setBreakpointSessionData(this.getId(), this.capabilities, data);
|
||||
}
|
||||
if (functionBreakpoint) {
|
||||
const data = new Map<string, DebugProtocol.Breakpoint>([[functionBreakpoint.getId(), event.body.breakpoint]]);
|
||||
this.model.setBreakpointSessionData(this.getId(), data);
|
||||
this.model.setBreakpointSessionData(this.getId(), this.capabilities, data);
|
||||
}
|
||||
}
|
||||
}));
|
||||
@@ -879,6 +885,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
this.rawListeners.push(this.raw.onDidExitAdapter(event => {
|
||||
this.initialized = true;
|
||||
this.model.setBreakpointSessionData(this.getId(), this.capabilities, undefined);
|
||||
this._onDidEndAdapter.fire(event);
|
||||
}));
|
||||
}
|
||||
@@ -954,13 +961,17 @@ export class DebugSession implements IDebugSession {
|
||||
return this.repl.getReplElements();
|
||||
}
|
||||
|
||||
hasSeparateRepl(): boolean {
|
||||
return !this.parentSession || this._options.repl !== 'mergeWithParent';
|
||||
}
|
||||
|
||||
removeReplExpressions(): void {
|
||||
this.repl.removeReplExpressions();
|
||||
this._onDidChangeREPLElements.fire();
|
||||
}
|
||||
|
||||
async addReplExpression(stackFrame: IStackFrame | undefined, name: string): Promise<void> {
|
||||
const expressionEvaluated = this.repl.addReplExpression(stackFrame, name);
|
||||
const expressionEvaluated = this.repl.addReplExpression(this, stackFrame, name);
|
||||
this._onDidChangeREPLElements.fire();
|
||||
await expressionEvaluated;
|
||||
this._onDidChangeREPLElements.fire();
|
||||
@@ -974,7 +985,7 @@ export class DebugSession implements IDebugSession {
|
||||
}
|
||||
|
||||
logToRepl(sev: severity, args: any[], frame?: { uri: URI, line: number, column: number }) {
|
||||
this.repl.logToRepl(sev, args, frame);
|
||||
this.repl.logToRepl(this, sev, args, frame);
|
||||
this._onDidChangeREPLElements.fire();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 4L12 8L8 12L4 8L8 4Z" fill="#848484"/>
|
||||
<path d="M8 3L13 8L8 13L3 8L8 3Z" fill="#848484"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 154 B After Width: | Height: | Size: 154 B |
@@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 4.84323L11.1365 7.97969L8 11.1161L4.86355 7.97969L8 4.84323Z" stroke="#848484" stroke-width="1.25"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.02039 7.97961L8 3L12.9796 7.97961L8 12.9592L3.02039 7.97961ZM8 10.7696L10.79 7.97961L8 5.18956L5.20996 7.97961L8 10.7696Z" fill="#848484"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 216 B After Width: | Height: | Size: 295 B |
@@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 4L12 8L8 12L4 8L8 4Z" fill="#E51400"/>
|
||||
<path d="M8 3L13 8L8 13L3 8L8 3Z" fill="#E51400"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 154 B After Width: | Height: | Size: 154 B |
@@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.3259 10.2223C11.7654 9.56448 12 8.79112 12 8C12.0001 7.47467 11.8968 6.95447 11.6958 6.4691C11.4948 5.98374 11.2002 5.54273 10.8287 5.17126C10.4573 4.7998 10.0163 4.50517 9.5309 4.3042C9.04553 4.10323 8.52533 3.99986 8 4C7.20888 4 6.43552 4.2346 5.77772 4.67412C5.11992 5.11365 4.60723 5.73836 4.30448 6.46927C4.00173 7.20017 3.92252 8.00444 4.07686 8.78036C4.2312 9.55628 4.61216 10.269 5.17157 10.8284C5.73098 11.3878 6.44372 11.7688 7.21964 11.9231C7.99556 12.0775 8.79983 11.9983 9.53073 11.6955C10.2616 11.3928 10.8864 10.8801 11.3259 10.2223ZM8.4 9.6H7.6V10.4H8.4V9.6ZM7.6 8.8V5.6H8.4V8.8H7.6Z" fill="#E51400"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.3259 10.2223C11.7654 9.56448 12 8.79112 12 8C12.0001 7.47467 11.8968 6.95447 11.6958 6.4691C11.4948 5.98374 11.2002 5.54273 10.8287 5.17126C10.4573 4.7998 10.0163 4.50517 9.5309 4.3042C9.04553 4.10323 8.52533 3.99986 8 4C7.20888 4 6.43552 4.2346 5.77772 4.67412C5.11992 5.11365 4.60723 5.73836 4.30448 6.46927C4.00173 7.20017 3.92252 8.00444 4.07686 8.78036C4.2312 9.55628 4.61216 10.269 5.17157 10.8284C5.73098 11.3878 6.44372 11.7688 7.21964 11.9231C7.99556 12.0775 8.79983 11.9983 9.53073 11.6955C10.2616 11.3928 10.8864 10.8801 11.3259 10.2223ZM8.65 10H7.4V11H8.65V10ZM7.4 9V5H8.65V9H7.4Z" fill="#E51400"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 774 B After Width: | Height: | Size: 767 B |
@@ -356,7 +356,7 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
|
||||
|
||||
getActions(): IAction[] {
|
||||
const result: IAction[] = [];
|
||||
if (this.debugService.getModel().getSessions(true).filter(s => !sessionsToIgnore.has(s)).length > 1) {
|
||||
if (this.debugService.getModel().getSessions(true).filter(s => s.hasSeparateRepl() && !sessionsToIgnore.has(s)).length > 1) {
|
||||
result.push(this.selectReplAction);
|
||||
}
|
||||
result.push(this.clearReplAction);
|
||||
@@ -504,7 +504,8 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => e.anchor,
|
||||
getActions: () => actions,
|
||||
getActionsContext: () => e.element
|
||||
getActionsContext: () => e.element,
|
||||
onHide: () => dispose(actions)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -968,12 +969,15 @@ registerEditorAction(FilterReplAction);
|
||||
|
||||
class SelectReplActionViewItem extends FocusSessionActionViewItem {
|
||||
|
||||
protected getActionContext(_: string, index: number): any {
|
||||
return this.debugService.getModel().getSessions(true)[index];
|
||||
protected getSessions(): ReadonlyArray<IDebugSession> {
|
||||
return this.debugService.getModel().getSessions(true).filter(s => s.hasSeparateRepl() && !sessionsToIgnore.has(s));
|
||||
}
|
||||
|
||||
protected getSessions(): ReadonlyArray<IDebugSession> {
|
||||
return this.debugService.getModel().getSessions(true).filter(s => !sessionsToIgnore.has(s));
|
||||
protected mapFocusedSessionToSelected(focusedSession: IDebugSession): IDebugSession {
|
||||
while (focusedSession.parentSession && !focusedSession.hasSeparateRepl()) {
|
||||
focusedSession = focusedSession.parentSession;
|
||||
}
|
||||
return focusedSession;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import { FuzzyScore, createMatches } from 'vs/base/common/filters';
|
||||
import { HighlightedLabel, IHighlight } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { dispose } from 'vs/base/common/lifecycle';
|
||||
|
||||
const $ = dom.$;
|
||||
let forgetScopes = true;
|
||||
@@ -188,7 +189,8 @@ export class VariablesView extends ViewletPanel {
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => e.anchor,
|
||||
getActions: () => actions,
|
||||
getActionsContext: () => variable
|
||||
getActionsContext: () => variable,
|
||||
onHide: () => dispose(actions)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import { FuzzyScore } from 'vs/base/common/filters';
|
||||
import { IHighlight } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';
|
||||
import { variableSetEmitter, VariablesRenderer } from 'vs/workbench/contrib/debug/browser/variablesView';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { dispose } from 'vs/base/common/lifecycle';
|
||||
|
||||
const MAX_VALUE_RENDER_LENGTH_IN_VIEWLET = 1024;
|
||||
|
||||
@@ -175,7 +176,8 @@ export class WatchExpressionsView extends ViewletPanel {
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => anchor,
|
||||
getActions: () => actions,
|
||||
getActionsContext: () => element
|
||||
getActionsContext: () => element,
|
||||
onHide: () => dispose(actions)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,6 +147,14 @@ export interface LoadedSourceEvent {
|
||||
source: Source;
|
||||
}
|
||||
|
||||
export type IDebugSessionReplMode = 'separate' | 'mergeWithParent';
|
||||
|
||||
export interface IDebugSessionOptions {
|
||||
noDebug?: boolean;
|
||||
parentSession?: IDebugSession;
|
||||
repl?: IDebugSessionReplMode;
|
||||
}
|
||||
|
||||
export interface IDebugSession extends ITreeElement {
|
||||
|
||||
readonly configuration: IConfig;
|
||||
@@ -173,7 +181,7 @@ export interface IDebugSession extends ITreeElement {
|
||||
clearThreads(removeThreads: boolean, reference?: number): void;
|
||||
|
||||
getReplElements(): IReplElement[];
|
||||
|
||||
hasSeparateRepl(): boolean;
|
||||
removeReplExpressions(): void;
|
||||
addReplExpression(stackFrame: IStackFrame | undefined, name: string): Promise<void>;
|
||||
appendToRepl(data: string | IExpression, severity: severity, source?: IReplElementSource): void;
|
||||
@@ -311,7 +319,7 @@ export interface IStackFrame extends ITreeElement {
|
||||
forgetScopes(): void;
|
||||
restart(): Promise<any>;
|
||||
toString(): string;
|
||||
openInEditor(editorService: IEditorService, preserveFocus?: boolean, sideBySide?: boolean): Promise<ITextEditor | null>;
|
||||
openInEditor(editorService: IEditorService, preserveFocus?: boolean, sideBySide?: boolean): Promise<ITextEditor | undefined>;
|
||||
equals(other: IStackFrame): boolean;
|
||||
}
|
||||
|
||||
@@ -342,6 +350,7 @@ export interface IBaseBreakpoint extends IEnablement {
|
||||
readonly hitCondition?: string;
|
||||
readonly logMessage?: string;
|
||||
readonly verified: boolean;
|
||||
readonly supported: boolean;
|
||||
getIdFromAdapter(sessionId: string): number | undefined;
|
||||
}
|
||||
|
||||
@@ -815,7 +824,7 @@ export interface IDebugService {
|
||||
* Returns true if the start debugging was successfull. For compound launches, all configurations have to start successfuly for it to return success.
|
||||
* On errors the startDebugging will throw an error, however some error and cancelations are handled and in that case will simply return false.
|
||||
*/
|
||||
startDebugging(launch: ILaunch | undefined, configOrName?: IConfig | string, noDebug?: boolean, parentSession?: IDebugSession): Promise<boolean>;
|
||||
startDebugging(launch: ILaunch | undefined, configOrName?: IConfig | string, options?: IDebugSessionOptions): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Restarts a session or creates a new one if there is no active session.
|
||||
|
||||
@@ -23,6 +23,7 @@ import { posix } from 'vs/base/common/path';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { ITextEditor } from 'vs/workbench/common/editor';
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
|
||||
export class ExpressionContainer implements IExpressionContainer {
|
||||
|
||||
@@ -337,8 +338,8 @@ export class StackFrame implements IStackFrame {
|
||||
return sourceToString === UNKNOWN_SOURCE_LABEL ? this.name : `${this.name} (${sourceToString})`;
|
||||
}
|
||||
|
||||
openInEditor(editorService: IEditorService, preserveFocus?: boolean, sideBySide?: boolean, pinned?: boolean): Promise<ITextEditor | null> {
|
||||
return !this.source.available ? Promise.resolve(null) :
|
||||
openInEditor(editorService: IEditorService, preserveFocus?: boolean, sideBySide?: boolean, pinned?: boolean): Promise<ITextEditor | undefined> {
|
||||
return !this.source.available ? Promise.resolve(undefined) :
|
||||
this.source.openInEditor(editorService, this.range, preserveFocus, sideBySide, pinned);
|
||||
}
|
||||
|
||||
@@ -498,10 +499,28 @@ export class Enablement implements IEnablement {
|
||||
}
|
||||
}
|
||||
|
||||
export class BaseBreakpoint extends Enablement implements IBaseBreakpoint {
|
||||
interface IBreakpointSessionData extends DebugProtocol.Breakpoint {
|
||||
supportsConditionalBreakpoints: boolean;
|
||||
supportsHitConditionalBreakpoints: boolean;
|
||||
supportsLogPoints: boolean;
|
||||
supportsFunctionBreakpoints: boolean;
|
||||
supportsDataBreakpoints: boolean;
|
||||
}
|
||||
|
||||
private sessionData = new Map<string, DebugProtocol.Breakpoint>();
|
||||
private sessionId: string | undefined;
|
||||
function toBreakpointSessionData(data: DebugProtocol.Breakpoint, capabilities: DebugProtocol.Capabilities): IBreakpointSessionData {
|
||||
return mixin({
|
||||
supportsConditionalBreakpoints: !!capabilities.supportsConditionalBreakpoints,
|
||||
supportsHitConditionalBreakpoints: !!capabilities.supportsHitConditionalBreakpoints,
|
||||
supportsLogPoints: !!capabilities.supportsLogPoints,
|
||||
supportsFunctionBreakpoints: !!capabilities.supportsFunctionBreakpoints,
|
||||
supportsDataBreakpoints: !!capabilities.supportsDataBreakpoints
|
||||
}, data);
|
||||
}
|
||||
|
||||
export abstract class BaseBreakpoint extends Enablement implements IBaseBreakpoint {
|
||||
|
||||
private sessionData = new Map<string, IBreakpointSessionData>();
|
||||
protected data: IBreakpointSessionData | undefined;
|
||||
|
||||
constructor(
|
||||
enabled: boolean,
|
||||
@@ -516,32 +535,38 @@ export class BaseBreakpoint extends Enablement implements IBaseBreakpoint {
|
||||
}
|
||||
}
|
||||
|
||||
protected getSessionData(): DebugProtocol.Breakpoint | undefined {
|
||||
return this.sessionId ? this.sessionData.get(this.sessionId) : undefined;
|
||||
}
|
||||
setSessionData(sessionId: string, data: IBreakpointSessionData | undefined): void {
|
||||
if (!data) {
|
||||
this.sessionData.delete(sessionId);
|
||||
} else {
|
||||
this.sessionData.set(sessionId, data);
|
||||
}
|
||||
|
||||
setSessionData(sessionId: string, data: DebugProtocol.Breakpoint): void {
|
||||
this.sessionData.set(sessionId, data);
|
||||
}
|
||||
|
||||
setSessionId(sessionId: string | undefined): void {
|
||||
this.sessionId = sessionId;
|
||||
const allData = Array.from(this.sessionData.values());
|
||||
const verifiedData = distinct(allData.filter(d => d.verified), d => `${d.line}:${d.column}`);
|
||||
if (verifiedData.length) {
|
||||
// In case multiple session verified the breakpoint and they provide different data show the intial data that the user set (corner case)
|
||||
this.data = verifiedData.length === 1 ? verifiedData[0] : undefined;
|
||||
} else {
|
||||
// No session verified the breakpoint
|
||||
this.data = allData.length ? allData[0] : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
get message(): string | undefined {
|
||||
const data = this.getSessionData();
|
||||
if (!data) {
|
||||
if (!this.data) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return data.message;
|
||||
return this.data.message;
|
||||
}
|
||||
|
||||
get verified(): boolean {
|
||||
const data = this.getSessionData();
|
||||
return data ? data.verified : true;
|
||||
return this.data ? this.data.verified : true;
|
||||
}
|
||||
|
||||
abstract get supported(): boolean;
|
||||
|
||||
getIdFromAdapter(sessionId: string): number | undefined {
|
||||
const data = this.sessionData.get(sessionId);
|
||||
return data ? data.id : undefined;
|
||||
@@ -576,23 +601,20 @@ export class Breakpoint extends BaseBreakpoint implements IBreakpoint {
|
||||
}
|
||||
|
||||
get lineNumber(): number {
|
||||
const data = this.getSessionData();
|
||||
return this.verified && data && typeof data.line === 'number' ? data.line : this._lineNumber;
|
||||
return this.verified && this.data && typeof this.data.line === 'number' ? this.data.line : this._lineNumber;
|
||||
}
|
||||
|
||||
get verified(): boolean {
|
||||
const data = this.getSessionData();
|
||||
if (data) {
|
||||
return data.verified && !this.textFileService.isDirty(this.uri);
|
||||
if (this.data) {
|
||||
return this.data.verified && !this.textFileService.isDirty(this.uri);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
get column(): number | undefined {
|
||||
const data = this.getSessionData();
|
||||
// Only respect the column if the user explictly set the column to have an inline breakpoint
|
||||
return data && typeof data.column === 'number' && typeof this._column === 'number' ? data.column : this._column;
|
||||
return this.verified && this.data && typeof this.data.column === 'number' && typeof this._column === 'number' ? this.data.column : this._column;
|
||||
}
|
||||
|
||||
get message(): string | undefined {
|
||||
@@ -604,18 +626,15 @@ export class Breakpoint extends BaseBreakpoint implements IBreakpoint {
|
||||
}
|
||||
|
||||
get adapterData(): any {
|
||||
const data = this.getSessionData();
|
||||
return data && data.source && data.source.adapterData ? data.source.adapterData : this._adapterData;
|
||||
return this.data && this.data.source && this.data.source.adapterData ? this.data.source.adapterData : this._adapterData;
|
||||
}
|
||||
|
||||
get endLineNumber(): number | undefined {
|
||||
const data = this.getSessionData();
|
||||
return data ? data.endLine : undefined;
|
||||
return this.verified && this.data ? this.data.endLine : undefined;
|
||||
}
|
||||
|
||||
get endColumn(): number | undefined {
|
||||
const data = this.getSessionData();
|
||||
return data ? data.endColumn : undefined;
|
||||
return this.verified && this.data ? this.data.endColumn : undefined;
|
||||
}
|
||||
|
||||
get sessionAgnosticData(): { lineNumber: number, column: number | undefined } {
|
||||
@@ -625,7 +644,25 @@ export class Breakpoint extends BaseBreakpoint implements IBreakpoint {
|
||||
};
|
||||
}
|
||||
|
||||
setSessionData(sessionId: string, data: DebugProtocol.Breakpoint): void {
|
||||
get supported(): boolean {
|
||||
if (!this.data) {
|
||||
return true;
|
||||
}
|
||||
if (this.logMessage && !this.data.supportsLogPoints) {
|
||||
return false;
|
||||
}
|
||||
if (this.condition && !this.data.supportsConditionalBreakpoints) {
|
||||
return false;
|
||||
}
|
||||
if (this.hitCondition && !this.data.supportsHitConditionalBreakpoints) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
setSessionData(sessionId: string, data: IBreakpointSessionData | undefined): void {
|
||||
super.setSessionData(sessionId, data);
|
||||
if (!this._adapterData) {
|
||||
this._adapterData = this.adapterData;
|
||||
@@ -685,6 +722,14 @@ export class FunctionBreakpoint extends BaseBreakpoint implements IFunctionBreak
|
||||
return result;
|
||||
}
|
||||
|
||||
get supported(): boolean {
|
||||
if (!this.data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return this.data.supportsFunctionBreakpoints;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return this.name;
|
||||
}
|
||||
@@ -713,6 +758,14 @@ export class DataBreakpoint extends BaseBreakpoint implements IDataBreakpoint {
|
||||
return result;
|
||||
}
|
||||
|
||||
get supported(): boolean {
|
||||
if (!this.data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return this.data.supportsDataBreakpoints;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return this.label;
|
||||
}
|
||||
@@ -751,7 +804,6 @@ export class DebugModel implements IDebugModel {
|
||||
private sessions: IDebugSession[];
|
||||
private toDispose: lifecycle.IDisposable[];
|
||||
private schedulers = new Map<string, RunOnceScheduler>();
|
||||
private breakpointsSessionId: string | undefined;
|
||||
private breakpointsActivated = true;
|
||||
private readonly _onDidChangeBreakpoints: Emitter<IBreakpointsChangeEvent | undefined>;
|
||||
private readonly _onDidChangeCallStack: Emitter<void>;
|
||||
@@ -945,7 +997,6 @@ export class DebugModel implements IDebugModel {
|
||||
|
||||
addBreakpoints(uri: uri, rawData: IBreakpointData[], fireEvent = true): IBreakpoint[] {
|
||||
const newBreakpoints = rawData.map(rawBp => new Breakpoint(uri, rawBp.lineNumber, rawBp.column, rawBp.enabled === false ? false : true, rawBp.condition, rawBp.hitCondition, rawBp.logMessage, undefined, this.textFileService, rawBp.id));
|
||||
newBreakpoints.forEach(bp => bp.setSessionId(this.breakpointsSessionId));
|
||||
this.breakpoints = this.breakpoints.concat(newBreakpoints);
|
||||
this.breakpointsActivated = true;
|
||||
this.sortAndDeDup();
|
||||
@@ -975,23 +1026,35 @@ export class DebugModel implements IDebugModel {
|
||||
this._onDidChangeBreakpoints.fire({ changed: updated });
|
||||
}
|
||||
|
||||
setBreakpointSessionData(sessionId: string, data: Map<string, DebugProtocol.Breakpoint>): void {
|
||||
setBreakpointSessionData(sessionId: string, capabilites: DebugProtocol.Capabilities, data: Map<string, DebugProtocol.Breakpoint> | undefined): void {
|
||||
this.breakpoints.forEach(bp => {
|
||||
const bpData = data.get(bp.getId());
|
||||
if (bpData) {
|
||||
bp.setSessionData(sessionId, bpData);
|
||||
if (!data) {
|
||||
bp.setSessionData(sessionId, undefined);
|
||||
} else {
|
||||
const bpData = data.get(bp.getId());
|
||||
if (bpData) {
|
||||
bp.setSessionData(sessionId, toBreakpointSessionData(bpData, capabilites));
|
||||
}
|
||||
}
|
||||
});
|
||||
this.functionBreakpoints.forEach(fbp => {
|
||||
const fbpData = data.get(fbp.getId());
|
||||
if (fbpData) {
|
||||
fbp.setSessionData(sessionId, fbpData);
|
||||
if (!data) {
|
||||
fbp.setSessionData(sessionId, undefined);
|
||||
} else {
|
||||
const fbpData = data.get(fbp.getId());
|
||||
if (fbpData) {
|
||||
fbp.setSessionData(sessionId, toBreakpointSessionData(fbpData, capabilites));
|
||||
}
|
||||
}
|
||||
});
|
||||
this.dataBreakopints.forEach(dbp => {
|
||||
const dbpData = data.get(dbp.getId());
|
||||
if (dbpData) {
|
||||
dbp.setSessionData(sessionId, dbpData);
|
||||
if (!data) {
|
||||
dbp.setSessionData(sessionId, undefined);
|
||||
} else {
|
||||
const dbpData = data.get(dbp.getId());
|
||||
if (dbpData) {
|
||||
dbp.setSessionData(sessionId, toBreakpointSessionData(dbpData, capabilites));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1000,17 +1063,6 @@ export class DebugModel implements IDebugModel {
|
||||
});
|
||||
}
|
||||
|
||||
setBreakpointsSessionId(sessionId: string | undefined): void {
|
||||
this.breakpointsSessionId = sessionId;
|
||||
this.breakpoints.forEach(bp => bp.setSessionId(sessionId));
|
||||
this.functionBreakpoints.forEach(fbp => fbp.setSessionId(sessionId));
|
||||
this.dataBreakopints.forEach(dbp => dbp.setSessionId(sessionId));
|
||||
|
||||
this._onDidChangeBreakpoints.fire({
|
||||
sessionOnly: true
|
||||
});
|
||||
}
|
||||
|
||||
private sortAndDeDup(): void {
|
||||
this.breakpoints = this.breakpoints.sort((first, second) => {
|
||||
if (first.uri.toString() !== second.uri.toString()) {
|
||||
|
||||
@@ -137,7 +137,7 @@ export const launchSchema: IJSONSchema = {
|
||||
id: launchSchemaId,
|
||||
type: 'object',
|
||||
title: nls.localize('app.launch.json.title', "Launch"),
|
||||
allowsTrailingCommas: true,
|
||||
allowTrailingCommas: true,
|
||||
allowComments: true,
|
||||
required: [],
|
||||
default: { version: '0.2.0', configurations: [], compounds: [] },
|
||||
|
||||
@@ -13,7 +13,6 @@ import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { isUri } from 'vs/workbench/contrib/debug/common/debugUtils';
|
||||
import { ITextEditor } from 'vs/workbench/common/editor';
|
||||
import { withUndefinedAsNull } from 'vs/base/common/types';
|
||||
|
||||
export const UNKNOWN_SOURCE_LABEL = nls.localize('unknownSource', "Unknown Source");
|
||||
|
||||
@@ -32,9 +31,9 @@ export const UNKNOWN_SOURCE_LABEL = nls.localize('unknownSource', "Unknown Sourc
|
||||
|
||||
export class Source {
|
||||
|
||||
public readonly uri: uri;
|
||||
public available: boolean;
|
||||
public raw: DebugProtocol.Source;
|
||||
readonly uri: uri;
|
||||
available: boolean;
|
||||
raw: DebugProtocol.Source;
|
||||
|
||||
constructor(raw_: DebugProtocol.Source | undefined, sessionId: string) {
|
||||
let path: string;
|
||||
@@ -94,8 +93,8 @@ export class Source {
|
||||
return this.uri.scheme === DEBUG_SCHEME;
|
||||
}
|
||||
|
||||
openInEditor(editorService: IEditorService, selection: IRange, preserveFocus?: boolean, sideBySide?: boolean, pinned?: boolean): Promise<ITextEditor | null> {
|
||||
return !this.available ? Promise.resolve(null) : editorService.openEditor({
|
||||
openInEditor(editorService: IEditorService, selection: IRange, preserveFocus?: boolean, sideBySide?: boolean, pinned?: boolean): Promise<ITextEditor | undefined> {
|
||||
return !this.available ? Promise.resolve(undefined) : editorService.openEditor({
|
||||
resource: this.uri,
|
||||
description: this.origin,
|
||||
options: {
|
||||
@@ -105,7 +104,7 @@ export class Source {
|
||||
revealInCenterIfOutsideViewport: true,
|
||||
pinned: pinned || (!preserveFocus && !this.inMemory)
|
||||
}
|
||||
}, sideBySide ? SIDE_GROUP : ACTIVE_GROUP).then(withUndefinedAsNull);
|
||||
}, sideBySide ? SIDE_GROUP : ACTIVE_GROUP);
|
||||
}
|
||||
|
||||
static getEncodedDebugData(modelUri: uri): { name: string, path: string, sessionId?: string, sourceReference?: number } {
|
||||
|
||||
@@ -27,7 +27,7 @@ export function startDebugging(debugService: IDebugService, historyService: IHis
|
||||
configurationManager.selectConfiguration(launch);
|
||||
}
|
||||
|
||||
return debugService.startDebugging(launch, undefined, noDebug);
|
||||
return debugService.startDebugging(launch, undefined, { noDebug });
|
||||
}
|
||||
|
||||
export function formatPII(value: string, excludePII: boolean, args: { [key: string]: string }): string {
|
||||
|
||||
@@ -108,16 +108,14 @@ export class ReplEvaluationResult extends ExpressionContainer implements IReplEl
|
||||
export class ReplModel {
|
||||
private replElements: IReplElement[] = [];
|
||||
|
||||
constructor(private session: IDebugSession) { }
|
||||
|
||||
getReplElements(): IReplElement[] {
|
||||
return this.replElements;
|
||||
}
|
||||
|
||||
async addReplExpression(stackFrame: IStackFrame | undefined, name: string): Promise<void> {
|
||||
async addReplExpression(session: IDebugSession, stackFrame: IStackFrame | undefined, name: string): Promise<void> {
|
||||
this.addReplElement(new ReplEvaluationInput(name));
|
||||
const result = new ReplEvaluationResult();
|
||||
await result.evaluateExpression(name, this.session, stackFrame, 'repl');
|
||||
await result.evaluateExpression(name, session, stackFrame, 'repl');
|
||||
this.addReplElement(result);
|
||||
}
|
||||
|
||||
@@ -153,14 +151,14 @@ export class ReplModel {
|
||||
}
|
||||
}
|
||||
|
||||
logToRepl(sev: severity, args: any[], frame?: { uri: URI, line: number, column: number }) {
|
||||
logToRepl(session: IDebugSession, sev: severity, args: any[], frame?: { uri: URI, line: number, column: number }) {
|
||||
|
||||
let source: IReplElementSource | undefined;
|
||||
if (frame) {
|
||||
source = {
|
||||
column: frame.column,
|
||||
lineNumber: frame.line,
|
||||
source: this.session.getSource({
|
||||
source: session.getSource({
|
||||
name: basenameOrAuthority(frame.uri),
|
||||
path: frame.uri.fsPath
|
||||
})
|
||||
|
||||
@@ -10,6 +10,7 @@ import { ExtensionHostDebugChannelClient, ExtensionHostDebugBroadcastChannel } f
|
||||
import { IWindowsService } from 'vs/platform/windows/common/windows';
|
||||
import { IProcessEnvironment } from 'vs/base/common/platform';
|
||||
import { ParsedArgs } from 'vs/platform/environment/common/environment';
|
||||
import { WindowsService } from 'vs/platform/windows/electron-browser/windowsService';
|
||||
|
||||
export class ExtensionHostDebugService extends ExtensionHostDebugChannelClient {
|
||||
|
||||
@@ -22,7 +23,7 @@ export class ExtensionHostDebugService extends ExtensionHostDebugChannelClient {
|
||||
|
||||
openExtensionDevelopmentHostWindow(args: ParsedArgs, env: IProcessEnvironment): Promise<void> {
|
||||
// TODO@Isidor use debug IPC channel
|
||||
return this.windowsService.openExtensionDevelopmentHostWindow(args, env);
|
||||
return (this.windowsService as WindowsService).openExtensionDevelopmentHostWindow(args, env);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,10 +14,6 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
export class NodeDebugHelperService implements IDebugHelperService {
|
||||
_serviceBrand: undefined;
|
||||
|
||||
constructor(
|
||||
) {
|
||||
}
|
||||
|
||||
createTelemetryService(configurationService: IConfigurationService, args: string[]): TelemetryService | undefined {
|
||||
|
||||
const client = new TelemetryClient(
|
||||
@@ -41,4 +37,4 @@ export class NodeDebugHelperService implements IDebugHelperService {
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(IDebugHelperService, NodeDebugHelperService);
|
||||
registerSingleton(IDebugHelperService, NodeDebugHelperService);
|
||||
|
||||
@@ -12,11 +12,11 @@ import { MockRawSession } from 'vs/workbench/contrib/debug/test/common/mockDebug
|
||||
import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
|
||||
import { DebugSession } from 'vs/workbench/contrib/debug/browser/debugSession';
|
||||
import { SimpleReplElement, RawObjectReplElement, ReplEvaluationInput, ReplModel } from 'vs/workbench/contrib/debug/common/replModel';
|
||||
import { IBreakpointUpdateData } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IBreakpointUpdateData, IDebugSessionOptions } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { NullOpenerService } from 'vs/platform/opener/common/opener';
|
||||
|
||||
function createMockSession(model: DebugModel, name = 'mockSession', parentSession?: DebugSession | undefined): DebugSession {
|
||||
return new DebugSession({ resolved: { name, type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, parentSession, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, NullOpenerService);
|
||||
function createMockSession(model: DebugModel, name = 'mockSession', options?: IDebugSessionOptions): DebugSession {
|
||||
return new DebugSession({ resolved: { name, type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, options, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, NullOpenerService);
|
||||
}
|
||||
|
||||
suite('Debug - Model', () => {
|
||||
@@ -110,6 +110,44 @@ suite('Debug - Model', () => {
|
||||
assert.equal(model.getFunctionBreakpoints().length, 0);
|
||||
});
|
||||
|
||||
test('breakpoints multiple sessions', () => {
|
||||
const modelUri = uri.file('/myfolder/myfile.js');
|
||||
const breakpoints = model.addBreakpoints(modelUri, [{ lineNumber: 5, enabled: true, condition: 'x > 5' }, { lineNumber: 10, enabled: false }]);
|
||||
const session = createMockSession(model);
|
||||
const data = new Map<string, DebugProtocol.Breakpoint>();
|
||||
|
||||
assert.equal(breakpoints[0].lineNumber, 5);
|
||||
assert.equal(breakpoints[1].lineNumber, 10);
|
||||
|
||||
data.set(breakpoints[0].getId(), { verified: false, line: 10 });
|
||||
data.set(breakpoints[1].getId(), { verified: true, line: 50 });
|
||||
model.setBreakpointSessionData(session.getId(), {}, data);
|
||||
assert.equal(breakpoints[0].lineNumber, 5);
|
||||
assert.equal(breakpoints[1].lineNumber, 50);
|
||||
|
||||
const session2 = createMockSession(model);
|
||||
const data2 = new Map<string, DebugProtocol.Breakpoint>();
|
||||
data2.set(breakpoints[0].getId(), { verified: true, line: 100 });
|
||||
data2.set(breakpoints[1].getId(), { verified: true, line: 500 });
|
||||
model.setBreakpointSessionData(session2.getId(), {}, data2);
|
||||
|
||||
// Breakpoint is verified only once, show that line
|
||||
assert.equal(breakpoints[0].lineNumber, 100);
|
||||
// Breakpoint is verified two times, show the original line
|
||||
assert.equal(breakpoints[1].lineNumber, 10);
|
||||
|
||||
model.setBreakpointSessionData(session.getId(), {}, undefined);
|
||||
// No more double session verification
|
||||
assert.equal(breakpoints[0].lineNumber, 100);
|
||||
assert.equal(breakpoints[1].lineNumber, 500);
|
||||
|
||||
assert.equal(breakpoints[0].supported, false);
|
||||
const data3 = new Map<string, DebugProtocol.Breakpoint>();
|
||||
data3.set(breakpoints[0].getId(), { verified: true, line: 500 });
|
||||
model.setBreakpointSessionData(session2.getId(), { supportsConditionalBreakpoints: true }, data2);
|
||||
assert.equal(breakpoints[0].supported, true);
|
||||
});
|
||||
|
||||
// Threads
|
||||
|
||||
test('threads simple', () => {
|
||||
@@ -341,10 +379,10 @@ suite('Debug - Model', () => {
|
||||
session['raw'] = <any>rawSession;
|
||||
const thread = new Thread(session, 'mockthread', 1);
|
||||
const stackFrame = new StackFrame(thread, 1, <any>undefined, 'app.js', 'normal', { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 10 }, 1);
|
||||
const replModel = new ReplModel(session);
|
||||
replModel.addReplExpression(stackFrame, 'myVariable').then();
|
||||
replModel.addReplExpression(stackFrame, 'myVariable').then();
|
||||
replModel.addReplExpression(stackFrame, 'myVariable').then();
|
||||
const replModel = new ReplModel();
|
||||
replModel.addReplExpression(session, stackFrame, 'myVariable').then();
|
||||
replModel.addReplExpression(session, stackFrame, 'myVariable').then();
|
||||
replModel.addReplExpression(session, stackFrame, 'myVariable').then();
|
||||
|
||||
assert.equal(replModel.getReplElements().length, 3);
|
||||
replModel.getReplElements().forEach(re => {
|
||||
@@ -405,13 +443,13 @@ suite('Debug - Model', () => {
|
||||
model.addSession(session);
|
||||
const secondSession = createMockSession(model, 'mockSession2');
|
||||
model.addSession(secondSession);
|
||||
const firstChild = createMockSession(model, 'firstChild', session);
|
||||
const firstChild = createMockSession(model, 'firstChild', { parentSession: session });
|
||||
model.addSession(firstChild);
|
||||
const secondChild = createMockSession(model, 'secondChild', session);
|
||||
const secondChild = createMockSession(model, 'secondChild', { parentSession: session });
|
||||
model.addSession(secondChild);
|
||||
const thirdSession = createMockSession(model, 'mockSession3');
|
||||
model.addSession(thirdSession);
|
||||
const anotherChild = createMockSession(model, 'secondChild', secondSession);
|
||||
const anotherChild = createMockSession(model, 'secondChild', { parentSession: secondSession });
|
||||
model.addSession(anotherChild);
|
||||
|
||||
const sessions = model.getSessions();
|
||||
@@ -426,8 +464,7 @@ suite('Debug - Model', () => {
|
||||
// Repl output
|
||||
|
||||
test('repl output', () => {
|
||||
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, NullOpenerService);
|
||||
const repl = new ReplModel(session);
|
||||
const repl = new ReplModel();
|
||||
repl.appendToRepl('first line\n', severity.Error);
|
||||
repl.appendToRepl('second line ', severity.Error);
|
||||
repl.appendToRepl('third line ', severity.Error);
|
||||
@@ -466,4 +503,41 @@ suite('Debug - Model', () => {
|
||||
assert.equal(elements[1], '23\n45\n');
|
||||
assert.equal(elements[2], '6');
|
||||
});
|
||||
|
||||
test('repl merging', () => {
|
||||
// 'mergeWithParent' should be ignored when there is no parent.
|
||||
const parent = createMockSession(model, 'parent', { repl: 'mergeWithParent' });
|
||||
const child1 = createMockSession(model, 'child1', { parentSession: parent, repl: 'separate' });
|
||||
const child2 = createMockSession(model, 'child2', { parentSession: parent, repl: 'mergeWithParent' });
|
||||
const grandChild = createMockSession(model, 'grandChild', { parentSession: child2, repl: 'mergeWithParent' });
|
||||
const child3 = createMockSession(model, 'child3', { parentSession: parent });
|
||||
|
||||
parent.appendToRepl('1\n', severity.Info);
|
||||
assert.equal(parent.getReplElements().length, 1);
|
||||
assert.equal(child1.getReplElements().length, 0);
|
||||
assert.equal(child2.getReplElements().length, 1);
|
||||
assert.equal(grandChild.getReplElements().length, 1);
|
||||
assert.equal(child3.getReplElements().length, 0);
|
||||
|
||||
grandChild.appendToRepl('1\n', severity.Info);
|
||||
assert.equal(parent.getReplElements().length, 2);
|
||||
assert.equal(child1.getReplElements().length, 0);
|
||||
assert.equal(child2.getReplElements().length, 2);
|
||||
assert.equal(grandChild.getReplElements().length, 2);
|
||||
assert.equal(child3.getReplElements().length, 0);
|
||||
|
||||
child3.appendToRepl('1\n', severity.Info);
|
||||
assert.equal(parent.getReplElements().length, 2);
|
||||
assert.equal(child1.getReplElements().length, 0);
|
||||
assert.equal(child2.getReplElements().length, 2);
|
||||
assert.equal(grandChild.getReplElements().length, 2);
|
||||
assert.equal(child3.getReplElements().length, 1);
|
||||
|
||||
child1.appendToRepl('1\n', severity.Info);
|
||||
assert.equal(parent.getReplElements().length, 2);
|
||||
assert.equal(child1.getReplElements().length, 1);
|
||||
assert.equal(child2.getReplElements().length, 2);
|
||||
assert.equal(grandChild.getReplElements().length, 2);
|
||||
assert.equal(child3.getReplElements().length, 1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@ import { URI as uri } from 'vs/base/common/uri';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { Position, IPosition } from 'vs/editor/common/core/position';
|
||||
import { ILaunch, IDebugService, State, IDebugSession, IConfigurationManager, IStackFrame, IBreakpointData, IBreakpointUpdateData, IConfig, IDebugModel, IViewModel, IBreakpoint, LoadedSourceEvent, IThread, IRawModelUpdate, IFunctionBreakpoint, IExceptionBreakpoint, IDebugger, IExceptionInfo, AdapterEndEvent, IReplElement, IExpression, IReplElementSource, IDataBreakpoint } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { ILaunch, IDebugService, State, IDebugSession, IConfigurationManager, IStackFrame, IBreakpointData, IBreakpointUpdateData, IConfig, IDebugModel, IViewModel, IBreakpoint, LoadedSourceEvent, IThread, IRawModelUpdate, IFunctionBreakpoint, IExceptionBreakpoint, IDebugger, IExceptionInfo, AdapterEndEvent, IReplElement, IExpression, IReplElementSource, IDataBreakpoint, IDebugSessionOptions } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
|
||||
import { CompletionItem } from 'vs/editor/common/modes';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
@@ -102,7 +102,7 @@ export class MockDebugService implements IDebugService {
|
||||
|
||||
public removeWatchExpressions(id?: string): void { }
|
||||
|
||||
public startDebugging(launch: ILaunch, configOrName?: IConfig | string, noDebug?: boolean): Promise<boolean> {
|
||||
public startDebugging(launch: ILaunch, configOrName?: IConfig | string, options?: IDebugSessionOptions): Promise<boolean> {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
@@ -159,6 +159,10 @@ export class MockSession implements IDebugSession {
|
||||
return [];
|
||||
}
|
||||
|
||||
hasSeparateRepl(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
removeReplExpressions(): void { }
|
||||
get onDidChangeReplElements(): Event<void> {
|
||||
throw new Error('not implemented');
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
import 'vs/css!./media/extensionEditor';
|
||||
import { localize } from 'vs/nls';
|
||||
import * as marked from 'vs/base/common/marked/marked';
|
||||
import { createCancelablePromise } from 'vs/base/common/async';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { OS } from 'vs/base/common/platform';
|
||||
@@ -56,6 +55,11 @@ import { renderDashboardContributions } from 'sql/workbench/parts/extensions/bro
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { platform } from 'vs/base/common/process';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { renderMarkdownDocument } from 'vs/workbench/common/markdownDocumentRenderer';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { TokenizationRegistry } from 'vs/editor/common/modes';
|
||||
import { generateTokensCSSForColorMap } from 'vs/editor/common/modes/supports/tokenization';
|
||||
|
||||
function removeEmbeddedSVGs(documentContent: string): string {
|
||||
const newDocument = new DOMParser().parseFromString(documentContent, 'text/html');
|
||||
@@ -187,7 +191,8 @@ export class ExtensionEditor extends BaseEditor {
|
||||
@IStorageService storageService: IStorageService,
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService,
|
||||
@IWebviewService private readonly webviewService: IWebviewService
|
||||
@IWebviewService private readonly webviewService: IWebviewService,
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
) {
|
||||
super(ExtensionEditor.ID, telemetryService, themeService, storageService);
|
||||
this.extensionReadme = null;
|
||||
@@ -580,44 +585,68 @@ export class ExtensionEditor extends BaseEditor {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
private openMarkdown(cacheResult: CacheResult<string>, noContentCopy: string, template: IExtensionEditorTemplate): Promise<IActiveElement> {
|
||||
return this.loadContents(() => cacheResult, template)
|
||||
.then(marked.parse)
|
||||
.then(content => this.renderBody(content))
|
||||
.then(removeEmbeddedSVGs)
|
||||
.then(body => {
|
||||
const webviewElement = this.webviewService.createWebview('extensionEditor',
|
||||
{
|
||||
enableFindWidget: true,
|
||||
},
|
||||
{});
|
||||
webviewElement.mountTo(template.content);
|
||||
this.contentDisposables.add(webviewElement.onDidFocus(() => this.fireOnDidFocus()));
|
||||
const removeLayoutParticipant = arrays.insert(this.layoutParticipants, webviewElement);
|
||||
this.contentDisposables.add(toDisposable(removeLayoutParticipant));
|
||||
webviewElement.html = body;
|
||||
private async openMarkdown(cacheResult: CacheResult<string>, noContentCopy: string, template: IExtensionEditorTemplate): Promise<IActiveElement> {
|
||||
try {
|
||||
const body = await this.renderMarkdown(cacheResult, template);
|
||||
|
||||
this.contentDisposables.add(webviewElement.onDidClickLink(link => {
|
||||
if (!link) {
|
||||
return;
|
||||
}
|
||||
// Whitelist supported schemes for links
|
||||
if (['http', 'https', 'mailto'].indexOf(link.scheme) >= 0 || (link.scheme === 'command' && link.path === ShowCurrentReleaseNotesActionId)) {
|
||||
this.openerService.open(link);
|
||||
}
|
||||
}, null, this.contentDisposables));
|
||||
this.contentDisposables.add(webviewElement);
|
||||
return webviewElement;
|
||||
})
|
||||
.then(undefined, () => {
|
||||
const p = append(template.content, $('p.nocontent'));
|
||||
p.textContent = noContentCopy;
|
||||
return p;
|
||||
const webviewElement = this.contentDisposables.add(this.webviewService.createWebviewEditorOverlay('extensionEditor', {
|
||||
enableFindWidget: true,
|
||||
}, {}));
|
||||
|
||||
webviewElement.claim(this);
|
||||
webviewElement.layoutWebviewOverElement(template.content);
|
||||
webviewElement.html = body;
|
||||
|
||||
this.contentDisposables.add(webviewElement.onDidFocus(() => this.fireOnDidFocus()));
|
||||
const removeLayoutParticipant = arrays.insert(this.layoutParticipants, {
|
||||
layout: () => {
|
||||
webviewElement.layout();
|
||||
webviewElement.layoutWebviewOverElement(template.content);
|
||||
}
|
||||
});
|
||||
this.contentDisposables.add(toDisposable(removeLayoutParticipant));
|
||||
|
||||
let isDisposed = false;
|
||||
this.contentDisposables.add(toDisposable(() => { isDisposed = true; }));
|
||||
|
||||
this.contentDisposables.add(this.themeService.onThemeChange(async () => {
|
||||
// Render again since syntax highlighting of code blocks may have changed
|
||||
const body = await this.renderMarkdown(cacheResult, template);
|
||||
if (!isDisposed) { // Make sure we weren't disposed of in the meantime
|
||||
webviewElement.html = body;
|
||||
}
|
||||
}));
|
||||
|
||||
this.contentDisposables.add(webviewElement.onDidClickLink(link => {
|
||||
if (!link) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Whitelist supported schemes for links
|
||||
if ([Schemas.http, Schemas.https, Schemas.mailto].indexOf(link.scheme) >= 0 || (link.scheme === 'command' && link.path === ShowCurrentReleaseNotesActionId)) {
|
||||
this.openerService.open(link);
|
||||
}
|
||||
}, null, this.contentDisposables));
|
||||
|
||||
return webviewElement;
|
||||
} catch (e) {
|
||||
const p = append(template.content, $('p.nocontent'));
|
||||
p.textContent = noContentCopy;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
private async renderMarkdown(cacheResult: CacheResult<string>, template: IExtensionEditorTemplate) {
|
||||
const contents = await this.loadContents(() => cacheResult, template);
|
||||
const content = await renderMarkdownDocument(contents, this.extensionService, this.modeService);
|
||||
const documentContent = await this.renderBody(content);
|
||||
return removeEmbeddedSVGs(documentContent);
|
||||
}
|
||||
|
||||
private async renderBody(body: string): Promise<string> {
|
||||
const nonce = generateUuid();
|
||||
const colorMap = TokenizationRegistry.getColorMap();
|
||||
const css = colorMap ? generateTokensCSSForColorMap(colorMap) : '';
|
||||
return `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
@@ -695,14 +724,9 @@ export class ExtensionEditor extends BaseEditor {
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
|
||||
font-size: 14px;
|
||||
line-height: 19px;
|
||||
}
|
||||
|
||||
.mac code {
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
font-family: var(--vscode-editor-font-family);
|
||||
font-weight: var(--vscode-editor-font-weight);
|
||||
font-size: var(--vscode-editor-font-size);
|
||||
}
|
||||
|
||||
code > div {
|
||||
@@ -711,6 +735,10 @@ export class ExtensionEditor extends BaseEditor {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.monaco-tokenized-source {
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
#scroll-to-top {
|
||||
position: fixed;
|
||||
width: 40px;
|
||||
@@ -795,6 +823,7 @@ export class ExtensionEditor extends BaseEditor {
|
||||
border-color: rgba(255, 255, 255, 0.18);
|
||||
}
|
||||
|
||||
${css}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -26,7 +26,7 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { Query } from 'vs/workbench/contrib/extensions/common/extensionQuery';
|
||||
import { IFileService, IFileContent } from 'vs/platform/files/common/files';
|
||||
import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
|
||||
@@ -1178,7 +1178,7 @@ export class ReloadAction extends ExtensionAction {
|
||||
|
||||
constructor(
|
||||
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@IHostService private readonly hostService: IHostService,
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService,
|
||||
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService
|
||||
@@ -1230,7 +1230,7 @@ export class ReloadAction extends ExtensionAction {
|
||||
if (this.extension.local) {
|
||||
const isEnabled = this.extensionEnablementService.isEnabled(this.extension.local);
|
||||
|
||||
// Extension is runningÎ
|
||||
// Extension is running
|
||||
if (runningExtension) {
|
||||
if (isEnabled) {
|
||||
if (!this.extensionService.canAddExtension(toExtensionDescription(this.extension.local))) {
|
||||
@@ -1241,11 +1241,6 @@ export class ReloadAction extends ExtensionAction {
|
||||
// {{SQL CARBON EDIT}} - replace Visual Studio Code with Azure Data Studio
|
||||
this.tooltip = localize('postUpdateTooltip', "Please reload Azure Data Studio to enable the updated extension.");
|
||||
}
|
||||
} else {
|
||||
this.enabled = true;
|
||||
this.label = localize('reloadRequired', "Reload Required");
|
||||
// {{SQL CARBON EDIT}} - replace Visual Studio Code with Azure Data Studio
|
||||
this.tooltip = localize('postEnableTooltip', "Please reload Azure Data Studio to enable this extension.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1285,7 +1280,7 @@ export class ReloadAction extends ExtensionAction {
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
return Promise.resolve(this.windowService.reloadWindow());
|
||||
return Promise.resolve(this.hostService.reload());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1634,6 +1629,29 @@ export class ShowRecommendedExtensionsAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
export class ShowSyncedExtensionsAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.extensions.action.listSyncedExtensions';
|
||||
static LABEL = localize('showSyncedExtensions', "Show My Accoount Extensions");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IViewletService private readonly viewletService: IViewletService
|
||||
) {
|
||||
super(id, label, undefined, true);
|
||||
}
|
||||
|
||||
run(): Promise<void> {
|
||||
return this.viewletService.openViewlet(VIEWLET_ID, true)
|
||||
.then(viewlet => viewlet as IExtensionsViewlet)
|
||||
.then(viewlet => {
|
||||
viewlet.search('@myaccount ');
|
||||
viewlet.focus();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class InstallWorkspaceRecommendedExtensionsAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.extensions.action.installWorkspaceRecommendedExtensions';
|
||||
@@ -2622,11 +2640,10 @@ export class SystemDisabledWarningAction extends ExtensionAction {
|
||||
|
||||
constructor(
|
||||
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@ILabelService private readonly labelService: ILabelService,
|
||||
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService,
|
||||
) {
|
||||
super('extensions.install', '', `${SystemDisabledWarningAction.CLASS} hide`, false);
|
||||
this._register(this.labelService.onDidChangeFormatters(() => this.update(), this));
|
||||
@@ -2662,32 +2679,24 @@ export class SystemDisabledWarningAction extends ExtensionAction {
|
||||
return;
|
||||
}
|
||||
const runningExtension = this._runningExtensions.filter(e => areSameExtensions({ id: e.identifier.value, uuid: e.uuid }, this.extension.identifier))[0];
|
||||
const runningExtensionServer = runningExtension ? this.extensionManagementServerService.getExtensionManagementServer(runningExtension.extensionLocation) : null;
|
||||
const localExtension = this.extensionsWorkbenchService.local.filter(e => areSameExtensions(e.identifier, this.extension.identifier))[0];
|
||||
const localExtensionServer = localExtension ? localExtension.server : null;
|
||||
if (this.extension.server === this.extensionManagementServerService.localExtensionManagementServer && !isUIExtension(this.extension.local.manifest, this.productService, this.configurationService)) {
|
||||
if (runningExtensionServer === this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
if (!runningExtension && this.extension.enablementState === EnablementState.DisabledByExtensionKind) {
|
||||
this.class = `${SystemDisabledWarningAction.WARNING_CLASS}`;
|
||||
const server = this.extensionManagementServerService.localExtensionManagementServer === this.extension.server ? this.extensionManagementServerService.remoteExtensionManagementServer : this.extensionManagementServerService.localExtensionManagementServer;
|
||||
this.tooltip = localize('Install in other server to enable', "Install the extension on '{0}' to enable.", server.label);
|
||||
return;
|
||||
}
|
||||
if (this.extensionEnablementService.isEnabled(this.extension.local)) {
|
||||
const runningExtensionServer = runningExtension ? this.extensionManagementServerService.getExtensionManagementServer(runningExtension.extensionLocation) : null;
|
||||
if (this.extension.server === this.extensionManagementServerService.localExtensionManagementServer && runningExtensionServer === this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
this.class = `${SystemDisabledWarningAction.INFO_CLASS}`;
|
||||
this.tooltip = localize('disabled locally', "Extension is enabled on '{0}' and disabled locally.", this.extensionManagementServerService.remoteExtensionManagementServer.label);
|
||||
return;
|
||||
}
|
||||
if (localExtensionServer !== this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
this.class = `${SystemDisabledWarningAction.WARNING_CLASS}`;
|
||||
this.tooltip = localize('Install in remote server', "Install the extension on '{0}' to enable.", this.extensionManagementServerService.remoteExtensionManagementServer.label);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.extension.server === this.extensionManagementServerService.remoteExtensionManagementServer && isUIExtension(this.extension.local.manifest, this.productService, this.configurationService)) {
|
||||
if (runningExtensionServer === this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
if (this.extension.server === this.extensionManagementServerService.remoteExtensionManagementServer && runningExtensionServer === this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
this.class = `${SystemDisabledWarningAction.INFO_CLASS}`;
|
||||
this.tooltip = localize('disabled remotely', "Extension is enabled locally and disabled on '{0}'.", this.extensionManagementServerService.remoteExtensionManagementServer.label);
|
||||
return;
|
||||
}
|
||||
if (localExtensionServer !== this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
this.class = `${SystemDisabledWarningAction.WARNING_CLASS}`;
|
||||
this.tooltip = localize('Install in local server', "Install the extension locally to enable.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2810,10 +2819,9 @@ export class InstallVSIXAction extends Action {
|
||||
label = InstallVSIXAction.LABEL,
|
||||
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@IHostService private readonly hostService: IHostService,
|
||||
@IFileDialogService private readonly fileDialogService: IFileDialogService,
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
// {{SQL CARBON EDIT}}
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IStorageService private storageService: IStorageService
|
||||
@@ -2825,17 +2833,17 @@ export class InstallVSIXAction extends Action {
|
||||
// {{SQL CARBON EDIT}} - Replace run body
|
||||
let extensionPolicy = this.configurationService.getValue<string>(ExtensionsPolicyKey);
|
||||
if (extensionPolicy === ExtensionsPolicy.allowAll) {
|
||||
return Promise.resolve(this.windowService.showOpenDialog({
|
||||
return Promise.resolve(this.fileDialogService.showOpenDialog({
|
||||
title: localize('installFromVSIX', "Install from VSIX"),
|
||||
filters: [{ name: 'VSIX Extensions', extensions: ['vsix'] }],
|
||||
properties: ['openFile'],
|
||||
buttonLabel: mnemonicButtonLabel(localize({ key: 'installButton', comment: ['&& denotes a mnemonic'] }, "&&Install"))
|
||||
canSelectFiles: true,
|
||||
openLabel: mnemonicButtonLabel(localize({ key: 'installButton', comment: ['&& denotes a mnemonic'] }, "&&Install"))
|
||||
}).then(result => {
|
||||
if (!result) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.all(result.map(vsix => {
|
||||
if (!this.storageService.getBoolean(vsix, StorageScope.GLOBAL)) {
|
||||
if (!this.storageService.getBoolean(vsix.fsPath, StorageScope.GLOBAL)) {
|
||||
this.notificationService.prompt(
|
||||
Severity.Warning,
|
||||
localize('thirdPartyExtension.vsix', 'This is a third party extension and might involve security risks. Are you sure you want to install this extension?'),
|
||||
@@ -2843,13 +2851,13 @@ export class InstallVSIXAction extends Action {
|
||||
{
|
||||
label: localize('thirdPartExt.yes', 'Yes'),
|
||||
run: () => {
|
||||
this.extensionsWorkbenchService.install(URI.file(vsix)).then(extension => {
|
||||
this.extensionsWorkbenchService.install(vsix).then(extension => {
|
||||
const requireReload = !(extension.local && this.extensionService.canAddExtension(toExtensionDescription(extension.local)));
|
||||
const message = requireReload ? localize('InstallVSIXAction.successReload', "Please reload Azure Data Studio to complete installing the extension {0}.", extension.identifier.id)
|
||||
: localize('InstallVSIXAction.success', "Completed installing the extension {0}.", extension.identifier.id);
|
||||
const actions = requireReload ? [{
|
||||
label: localize('InstallVSIXAction.reloadNow', "Reload Now"),
|
||||
run: () => this.windowService.reloadWindow()
|
||||
run: () => this.hostService.reload()
|
||||
}] : [];
|
||||
this.notificationService.prompt(
|
||||
Severity.Info,
|
||||
@@ -2868,7 +2876,7 @@ export class InstallVSIXAction extends Action {
|
||||
label: localize('thirdPartyExt.dontShowAgain', 'Don\'t Show Again'),
|
||||
isSecondary: true,
|
||||
run: () => {
|
||||
this.storageService.store(vsix, true, StorageScope.GLOBAL);
|
||||
this.storageService.store(vsix.fsPath, true, StorageScope.GLOBAL);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
@@ -2876,13 +2884,13 @@ export class InstallVSIXAction extends Action {
|
||||
{ sticky: true }
|
||||
);
|
||||
} else {
|
||||
this.extensionsWorkbenchService.install(URI.file(vsix)).then(extension => {
|
||||
this.extensionsWorkbenchService.install(vsix).then(extension => {
|
||||
const requireReload = !(extension.local && this.extensionService.canAddExtension(toExtensionDescription(extension.local)));
|
||||
const message = requireReload ? localize('InstallVSIXAction.successReload', "Please reload Azure Data Studio to complete installing the extension {0}.", extension.identifier.id)
|
||||
: localize('InstallVSIXAction.success', "Completed installing the extension {0}.", extension.identifier.id);
|
||||
const actions = requireReload ? [{
|
||||
label: localize('InstallVSIXAction.reloadNow', "Reload Now"),
|
||||
run: () => this.windowService.reloadWindow()
|
||||
run: () => this.hostService.reload()
|
||||
}] : [];
|
||||
this.notificationService.prompt(
|
||||
Severity.Info,
|
||||
@@ -2912,7 +2920,7 @@ export class ReinstallAction extends Action {
|
||||
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@IHostService private readonly hostService: IHostService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IExtensionService private readonly extensionService: IExtensionService
|
||||
) {
|
||||
@@ -2956,7 +2964,7 @@ export class ReinstallAction extends Action {
|
||||
: localize('ReinstallAction.success', "Reinstalling the extension {0} is completed.", extension.identifier.id);
|
||||
const actions = requireReload ? [{
|
||||
label: localize('InstallVSIXAction.reloadNow', "Reload Now"),
|
||||
run: () => this.windowService.reloadWindow()
|
||||
run: () => this.hostService.reload()
|
||||
}] : [];
|
||||
this.notificationService.prompt(
|
||||
Severity.Info,
|
||||
@@ -2980,7 +2988,7 @@ export class InstallSpecificVersionOfExtensionAction extends Action {
|
||||
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@IHostService private readonly hostService: IHostService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService,
|
||||
@@ -3042,7 +3050,7 @@ export class InstallSpecificVersionOfExtensionAction extends Action {
|
||||
: localize('InstallAnotherVersionExtensionAction.success', "Installing the extension {0} is completed.", extension.identifier.id);
|
||||
const actions = requireReload ? [{
|
||||
label: localize('InstallAnotherVersionExtensionAction.reloadNow', "Reload Now"),
|
||||
run: () => this.windowService.reloadWindow()
|
||||
run: () => this.hostService.reload()
|
||||
}] : [];
|
||||
this.notificationService.prompt(
|
||||
Severity.Info,
|
||||
@@ -3069,7 +3077,7 @@ export class InstallLocalExtensionsInRemoteAction extends Action {
|
||||
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@IHostService private readonly hostService: IHostService,
|
||||
@IProgressService private readonly progressService: IProgressService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService
|
||||
) {
|
||||
@@ -3182,7 +3190,7 @@ export class InstallLocalExtensionsInRemoteAction extends Action {
|
||||
message: localize('finished installing', "Successfully installed extensions in {0}. Please reload the window to enable them.", this.extensionManagementServerService.remoteExtensionManagementServer!.label),
|
||||
actions: {
|
||||
primary: [new Action('realod', localize('reload', "Reload Window"), '', true,
|
||||
() => this.windowService.reloadWindow())]
|
||||
() => this.hostService.reload())]
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import { values } from 'vs/base/common/map';
|
||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
|
||||
@@ -23,7 +23,7 @@ export class ExtensionDependencyChecker extends Disposable implements IWorkbench
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IWindowService private readonly windowService: IWindowService
|
||||
@IHostService private readonly hostService: IHostService
|
||||
) {
|
||||
super();
|
||||
CommandsRegistry.registerCommand('workbench.extensions.installMissingDepenencies', () => this.installMissingDependencies());
|
||||
@@ -69,7 +69,7 @@ export class ExtensionDependencyChecker extends Disposable implements IWorkbench
|
||||
message: localize('finished installing missing deps', "Finished installing missing dependencies. Please reload the window now."),
|
||||
actions: {
|
||||
primary: [new Action('realod', localize('reload', "Reload Window"), '', true,
|
||||
() => this.windowService.reloadWindow())]
|
||||
() => this.hostService.reload())]
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -22,12 +22,12 @@ import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID, AutoUpdate
|
||||
import {
|
||||
ShowEnabledExtensionsAction, ShowInstalledExtensionsAction, ShowRecommendedExtensionsAction, ShowPopularExtensionsAction, ShowDisabledExtensionsAction,
|
||||
ShowOutdatedExtensionsAction, ClearExtensionsInputAction, ChangeSortAction, UpdateAllAction, CheckForUpdatesAction, DisableAllAction, EnableAllAction,
|
||||
EnableAutoUpdateAction, DisableAutoUpdateAction, ShowBuiltInExtensionsAction, InstallVSIXAction
|
||||
EnableAutoUpdateAction, DisableAutoUpdateAction, ShowBuiltInExtensionsAction, InstallVSIXAction, ShowSyncedExtensionsAction
|
||||
} from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionEnablementService, IExtensionManagementServerService, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
|
||||
import { ExtensionsListView, EnabledExtensionsView, DisabledExtensionsView, RecommendedExtensionsView, WorkspaceRecommendedExtensionsView, BuiltInExtensionsView, BuiltInThemesExtensionsView, BuiltInBasicsExtensionsView, ServerExtensionsView, DefaultRecommendedExtensionsView } from 'vs/workbench/contrib/extensions/browser/extensionsViews';
|
||||
import { ExtensionsListView, EnabledExtensionsView, DisabledExtensionsView, RecommendedExtensionsView, WorkspaceRecommendedExtensionsView, BuiltInExtensionsView, BuiltInThemesExtensionsView, BuiltInBasicsExtensionsView, ServerExtensionsView, DefaultRecommendedExtensionsView, SyncedExtensionsView } from 'vs/workbench/contrib/extensions/browser/extensionsViews';
|
||||
import { OpenGlobalSettingsAction } from 'vs/workbench/contrib/preferences/browser/preferencesActions';
|
||||
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
@@ -43,7 +43,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
|
||||
import { getMaliciousExtensionsSet } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { IAddedViewDescriptorRef } from 'vs/workbench/browser/parts/views/views';
|
||||
import { ViewletPanel } from 'vs/workbench/browser/parts/views/panelViewlet';
|
||||
@@ -58,6 +58,7 @@ import { ViewContainerViewlet } from 'vs/workbench/browser/parts/views/viewsView
|
||||
import { RemoteNameContext } from 'vs/workbench/browser/contextkeys';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { MementoObject } from 'vs/workbench/common/memento';
|
||||
import { SyncStatus, CONTEXT_SYNC_STATE } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
|
||||
const NonEmptyWorkspaceContext = new RawContextKey<boolean>('nonEmptyWorkspace', false);
|
||||
const DefaultViewsContext = new RawContextKey<boolean>('defaultExtensionViews', true);
|
||||
@@ -70,6 +71,7 @@ const HasInstalledExtensionsContext = new RawContextKey<boolean>('hasInstalledEx
|
||||
const SearchBuiltInExtensionsContext = new RawContextKey<boolean>('searchBuiltInExtensions', false);
|
||||
const RecommendedExtensionsContext = new RawContextKey<boolean>('recommendedExtensions', false);
|
||||
const DefaultRecommendedExtensionsContext = new RawContextKey<boolean>('defaultRecommendedExtensions', false);
|
||||
const SyncedExtensionsContext = new RawContextKey<boolean>('syncedExtensions', false);
|
||||
const viewIdNameMappings: { [id: string]: string } = {
|
||||
'extensions.listView': localize('marketPlace', "Marketplace"),
|
||||
'extensions.enabledExtensionList': localize('enabledExtensions', "Enabled"),
|
||||
@@ -84,6 +86,7 @@ const viewIdNameMappings: { [id: string]: string } = {
|
||||
'extensions.builtInExtensionsList': localize('builtInExtensions', "Features"),
|
||||
'extensions.builtInThemesExtensionsList': localize('builtInThemesExtensions', "Themes"),
|
||||
'extensions.builtInBasicsExtensionsList': localize('builtInBasicsExtensions', "Programming Languages"),
|
||||
'extensions.syncedExtensionsList': localize('syncedExtensions', "My Account"),
|
||||
};
|
||||
|
||||
export class ExtensionsViewletViewsContribution implements IWorkbenchContribution {
|
||||
@@ -110,6 +113,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
|
||||
viewDescriptors.push(this.createDefaultRecommendedExtensionsListViewDescriptor());
|
||||
viewDescriptors.push(this.createOtherRecommendedExtensionsListViewDescriptor());
|
||||
viewDescriptors.push(this.createWorkspaceRecommendedExtensionsListViewDescriptor());
|
||||
viewDescriptors.push(this.createSyncedExtensionsViewDescriptor());
|
||||
|
||||
if (this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
viewDescriptors.push(...this.createExtensionsViewDescriptorsForServer(this.extensionManagementServerService.localExtensionManagementServer));
|
||||
@@ -314,6 +318,17 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
|
||||
weight: 100
|
||||
};
|
||||
}
|
||||
|
||||
private createSyncedExtensionsViewDescriptor(): IViewDescriptor {
|
||||
const id = 'extensions.syncedExtensionsList';
|
||||
return {
|
||||
id,
|
||||
name: viewIdNameMappings[id],
|
||||
ctorDescriptor: { ctor: SyncedExtensionsView },
|
||||
when: ContextKeyExpr.and(CONTEXT_SYNC_STATE.notEqualsTo(SyncStatus.Uninitialized), ContextKeyExpr.has('config.userConfiguration.enableSync'), ContextKeyExpr.has('syncedExtensions')),
|
||||
weight: 100
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensionsViewlet {
|
||||
@@ -330,6 +345,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
|
||||
private hasInstalledExtensionsContextKey: IContextKey<boolean>;
|
||||
private searchBuiltInExtensionsContextKey: IContextKey<boolean>;
|
||||
private recommendedExtensionsContextKey: IContextKey<boolean>;
|
||||
private syncedExtensionsContextKey: IContextKey<boolean>;
|
||||
private defaultRecommendedExtensionsContextKey: IContextKey<boolean>;
|
||||
|
||||
private searchDelayer: Delayer<void>;
|
||||
@@ -371,6 +387,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
|
||||
this.recommendedExtensionsContextKey = RecommendedExtensionsContext.bindTo(contextKeyService);
|
||||
this.defaultRecommendedExtensionsContextKey = DefaultRecommendedExtensionsContext.bindTo(contextKeyService);
|
||||
this.defaultRecommendedExtensionsContextKey.set(!this.configurationService.getValue<boolean>(ShowRecommendationsOnlyOnDemandKey));
|
||||
this.syncedExtensionsContextKey = SyncedExtensionsContext.bindTo(contextKeyService);
|
||||
this._register(this.viewletService.onDidViewletOpen(this.onViewletOpen, this));
|
||||
this.searchViewletState = this.getMemento(StorageScope.WORKSPACE);
|
||||
|
||||
@@ -469,8 +486,8 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
|
||||
this.instantiationService.createInstance(ShowDisabledExtensionsAction, ShowDisabledExtensionsAction.ID, ShowDisabledExtensionsAction.LABEL),
|
||||
this.instantiationService.createInstance(ShowBuiltInExtensionsAction, ShowBuiltInExtensionsAction.ID, ShowBuiltInExtensionsAction.LABEL),
|
||||
this.instantiationService.createInstance(ShowRecommendedExtensionsAction, ShowRecommendedExtensionsAction.ID, ShowRecommendedExtensionsAction.LABEL),
|
||||
// {{SQL CARBON EDIT}}
|
||||
// this.instantiationService.createInstance(ShowPopularExtensionsAction, ShowPopularExtensionsAction.ID, ShowPopularExtensionsAction.LABEL),
|
||||
// this.instantiationService.createInstance(ShowPopularExtensionsAction, ShowPopularExtensionsAction.ID, ShowPopularExtensionsAction.LABEL), // {{SQL CARBON EDIT}}
|
||||
this.instantiationService.createInstance(ShowSyncedExtensionsAction, ShowSyncedExtensionsAction.ID, ShowSyncedExtensionsAction.LABEL),
|
||||
new Separator(),
|
||||
// {{SQL CARBON EDIT}}
|
||||
//this.instantiationService.createInstance(ChangeSortAction, 'extensions.sort.install', localize('sort by installs', "Sort By: Install Count"), this.onSearchChange, 'installs'),
|
||||
@@ -519,6 +536,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
|
||||
|
||||
private doSearch(): Promise<void> {
|
||||
const value = this.normalizedQuery();
|
||||
const isSyncedExtensionsQuery = ExtensionsListView.isSyncedExtensionsQuery(value);
|
||||
const isRecommendedExtensionsQuery = ExtensionsListView.isRecommendedExtensionsQuery(value);
|
||||
this.searchInstalledExtensionsContextKey.set(ExtensionsListView.isInstalledExtensionsQuery(value));
|
||||
this.searchOutdatedExtensionsContextKey.set(ExtensionsListView.isOutdatedExtensionsQuery(value));
|
||||
@@ -526,7 +544,8 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
|
||||
this.searchDisabledExtensionsContextKey.set(ExtensionsListView.isDisabledExtensionsQuery(value));
|
||||
this.searchBuiltInExtensionsContextKey.set(ExtensionsListView.isBuiltInExtensionsQuery(value));
|
||||
this.recommendedExtensionsContextKey.set(isRecommendedExtensionsQuery);
|
||||
this.searchMarketplaceExtensionsContextKey.set(!!value && !ExtensionsListView.isLocalExtensionsQuery(value) && !isRecommendedExtensionsQuery);
|
||||
this.syncedExtensionsContextKey.set(isSyncedExtensionsQuery);
|
||||
this.searchMarketplaceExtensionsContextKey.set(!!value && !ExtensionsListView.isLocalExtensionsQuery(value) && !isRecommendedExtensionsQuery && !isSyncedExtensionsQuery);
|
||||
this.nonEmptyWorkspaceContextKey.set(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY);
|
||||
this.defaultViewsContextKey.set(!value);
|
||||
|
||||
@@ -647,7 +666,7 @@ export class MaliciousExtensionChecker implements IWorkbenchContribution {
|
||||
|
||||
constructor(
|
||||
@IExtensionManagementService private readonly extensionsManagementService: IExtensionManagementService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@IHostService private readonly hostService: IHostService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService
|
||||
@@ -678,7 +697,7 @@ export class MaliciousExtensionChecker implements IWorkbenchContribution {
|
||||
localize('malicious warning', "We have uninstalled '{0}' which was reported to be problematic.", e.identifier.id),
|
||||
[{
|
||||
label: localize('reloadNow', "Reload Now"),
|
||||
run: () => this.windowService.reloadWindow()
|
||||
run: () => this.hostService.reload()
|
||||
}],
|
||||
{ sticky: true }
|
||||
);
|
||||
|
||||
@@ -47,6 +47,7 @@ import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { SeverityIcon } from 'vs/platform/severityIcon/common/severityIcon';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IUserDataSyncService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
|
||||
|
||||
class ExtensionsViewState extends Disposable implements IExtensionsViewState {
|
||||
@@ -104,6 +105,7 @@ export class ExtensionsListView extends ViewletPanel {
|
||||
@IExtensionManagementServerService protected readonly extensionManagementServerService: IExtensionManagementServerService,
|
||||
@IProductService protected readonly productService: IProductService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IUserDataSyncService private readonly userDataSyncService: IUserDataSyncService,
|
||||
) {
|
||||
super({ ...(options as IViewletPanelOptions), ariaHeaderLabel: options.title, showActionsAlways: true }, keybindingService, contextMenuService, configurationService, contextKeyService);
|
||||
this.server = options.server;
|
||||
@@ -456,8 +458,10 @@ export class ExtensionsListView extends ViewletPanel {
|
||||
} else if (ExtensionsListView.isRecommendedExtensionsQuery(query.value)) {
|
||||
return this.getRecommendationsModel(query, options, token);
|
||||
// {{SQL CARBON EDIT}}
|
||||
} else if (ExtensionsListView.isAllMarketplaceExtensionsQuery(query.value)) {
|
||||
} else if (ExtensionsListView.isAllMarketplaceExtensionsQuery(query.value)) { // {{SQL CARBON EDIT}} add if
|
||||
return this.getAllMarketplaceModel(query, options, token);
|
||||
} else if (ExtensionsListView.isSyncedExtensionsQuery(query.value)) {
|
||||
return this.getSyncedExtensionsModel(query, options, token);
|
||||
}
|
||||
|
||||
if (/\bcurated:([^\s]+)\b/.test(query.value)) {
|
||||
@@ -765,6 +769,23 @@ export class ExtensionsListView extends ViewletPanel {
|
||||
.then(result => this.getPagedModel(result));
|
||||
}
|
||||
|
||||
private async getSyncedExtensionsModel(query: Query, options: IQueryOptions, token: CancellationToken): Promise<IPagedModel<IExtension>> {
|
||||
const syncedExtensions = await this.userDataSyncService.getRemoteExtensions();
|
||||
if (!syncedExtensions.length) {
|
||||
return this.showEmptyModel();
|
||||
}
|
||||
const ids: string[] = [], names: string[] = [];
|
||||
for (const installed of syncedExtensions) {
|
||||
if (installed.identifier.uuid) {
|
||||
ids.push(installed.identifier.uuid);
|
||||
} else {
|
||||
names.push(installed.identifier.id);
|
||||
}
|
||||
}
|
||||
const pager = await this.extensionsWorkbenchService.queryGallery({ ids, names, pageSize: ids.length }, token);
|
||||
return this.getPagedModel(pager || []);
|
||||
}
|
||||
|
||||
// Sorts the firstPage of the pager in the same order as given array of extension ids
|
||||
private sortFirstPage(pager: IPager<IExtension>, ids: string[]) {
|
||||
ids = ids.map(x => x.toLowerCase());
|
||||
@@ -904,6 +925,10 @@ export class ExtensionsListView extends ViewletPanel {
|
||||
return /@recommended:keymaps/i.test(query);
|
||||
}
|
||||
|
||||
static isSyncedExtensionsQuery(query: string): boolean {
|
||||
return /@myaccount/i.test(query);
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
super.focus();
|
||||
if (!this.list) {
|
||||
@@ -944,10 +969,11 @@ export class ServerExtensionsView extends ExtensionsListView {
|
||||
@IExtensionsWorkbenchService extensionsWorkbenchService: IExtensionsWorkbenchService,
|
||||
@IExtensionManagementServerService extensionManagementServerService: IExtensionManagementServerService,
|
||||
@IProductService productService: IProductService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IUserDataSyncService userDataSyncService: IUserDataSyncService
|
||||
) {
|
||||
options.server = server;
|
||||
super(options, notificationService, keybindingService, contextMenuService, instantiationService, themeService, extensionService, extensionsWorkbenchService, editorService, tipsService, telemetryService, configurationService, contextService, experimentService, workbenchThemeService, extensionManagementServerService, productService, contextKeyService);
|
||||
super(options, notificationService, keybindingService, contextMenuService, instantiationService, themeService, extensionService, extensionsWorkbenchService, editorService, tipsService, telemetryService, configurationService, contextService, experimentService, workbenchThemeService, extensionManagementServerService, productService, contextKeyService, userDataSyncService);
|
||||
this._register(onDidChangeTitle(title => this.updateTitle(title)));
|
||||
}
|
||||
|
||||
@@ -1003,6 +1029,14 @@ export class BuiltInBasicsExtensionsView extends ExtensionsListView {
|
||||
}
|
||||
}
|
||||
|
||||
export class SyncedExtensionsView extends ExtensionsListView {
|
||||
|
||||
async show(query: string): Promise<IPagedModel<IExtension>> {
|
||||
query = query || '@myaccount';
|
||||
return ExtensionsListView.isSyncedExtensionsQuery(query) ? super.show(query) : this.showEmptyModel();
|
||||
}
|
||||
}
|
||||
|
||||
export class DefaultRecommendedExtensionsView extends ExtensionsListView {
|
||||
// {{SQL CARBON EDIT}}
|
||||
private readonly recommendedExtensionsQuery = '@allmarketplace';
|
||||
|
||||
@@ -11,7 +11,7 @@ export const ExtensionsConfigurationSchemaId = 'vscode://schemas/extensions';
|
||||
export const ExtensionsConfigurationSchema: IJSONSchema = {
|
||||
id: ExtensionsConfigurationSchemaId,
|
||||
allowComments: true,
|
||||
allowsTrailingCommas: true,
|
||||
allowTrailingCommas: true,
|
||||
type: 'object',
|
||||
title: localize('app.extensions.json.title', "Extensions"),
|
||||
additionalProperties: false,
|
||||
@@ -39,7 +39,7 @@ export const ExtensionsConfigurationSchema: IJSONSchema = {
|
||||
|
||||
export const ExtensionsConfigurationInitialContent: string = [
|
||||
'{',
|
||||
'\t// See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.',
|
||||
'\t// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.',
|
||||
'\t// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp',
|
||||
'',
|
||||
'\t// List of extensions which should be recommended for users of this workspace.',
|
||||
|
||||
@@ -12,7 +12,7 @@ import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { StatusbarAlignment, IStatusbarService, IStatusbarEntryAccessor, IStatusbarEntry } from 'vs/platform/statusbar/common/statusbar';
|
||||
import { IExtensionHostProfileService, ProfileSessionState } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IWindowsService } from 'vs/platform/windows/common/windows';
|
||||
import { IElectronService } from 'vs/platform/electron/node/electron';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { randomPort } from 'vs/base/node/ports';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
@@ -46,7 +46,7 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio
|
||||
@IExtensionService private readonly _extensionService: IExtensionService,
|
||||
@IEditorService private readonly _editorService: IEditorService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@IWindowsService private readonly _windowsService: IWindowsService,
|
||||
@IElectronService private readonly _electronService: IElectronService,
|
||||
@IDialogService private readonly _dialogService: IDialogService,
|
||||
@IStatusbarService private readonly _statusbarService: IStatusbarService,
|
||||
) {
|
||||
@@ -122,7 +122,7 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio
|
||||
secondaryButton: nls.localize('cancel', "Cancel")
|
||||
}).then(res => {
|
||||
if (res.confirmed) {
|
||||
this._windowsService.relaunch({ addArgs: [`--inspect-extensions=${randomPort()}`] });
|
||||
this._electronService.relaunch({ addArgs: [`--inspect-extensions=${randomPort()}`] });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { clipboard } from 'electron';
|
||||
import { EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows';
|
||||
import { IElectronService } from 'vs/platform/electron/node/electron';
|
||||
import { writeFile } from 'vs/base/node/pfs';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
@@ -307,7 +307,7 @@ export class RuntimeExtensionsEditor extends BaseEditor {
|
||||
|
||||
const activationTimes = element.status.activationTimes!;
|
||||
let syncTime = activationTimes.codeLoadingTime + activationTimes.activateCallTime;
|
||||
data.activationTime.textContent = activationTimes.startup ? `Startup Activation: ${syncTime}ms` : `Activation: ${syncTime}ms`;
|
||||
data.activationTime.textContent = activationTimes.activationReason.startup ? `Startup Activation: ${syncTime}ms` : `Activation: ${syncTime}ms`;
|
||||
|
||||
data.actionbar.clear();
|
||||
if (element.unresponsiveProfile) {
|
||||
@@ -318,43 +318,45 @@ export class RuntimeExtensionsEditor extends BaseEditor {
|
||||
}
|
||||
|
||||
let title: string;
|
||||
if (activationTimes.activationEvent === '*') {
|
||||
title = nls.localize('starActivation', "Activated on start-up");
|
||||
} else if (/^workspaceContains:/.test(activationTimes.activationEvent)) {
|
||||
let fileNameOrGlob = activationTimes.activationEvent.substr('workspaceContains:'.length);
|
||||
const activationId = activationTimes.activationReason.extensionId.value;
|
||||
const activationEvent = activationTimes.activationReason.activationEvent;
|
||||
if (activationEvent === '*') {
|
||||
title = nls.localize('starActivation', "Activated by {0} on start-up", activationId);
|
||||
} else if (/^workspaceContains:/.test(activationEvent)) {
|
||||
let fileNameOrGlob = activationEvent.substr('workspaceContains:'.length);
|
||||
if (fileNameOrGlob.indexOf('*') >= 0 || fileNameOrGlob.indexOf('?') >= 0) {
|
||||
title = nls.localize({
|
||||
key: 'workspaceContainsGlobActivation',
|
||||
comment: [
|
||||
'{0} will be a glob pattern'
|
||||
]
|
||||
}, "Activated because a file matching {0} exists in your workspace", fileNameOrGlob);
|
||||
}, "Activated by {1} because a file matching {1} exists in your workspace", fileNameOrGlob, activationId);
|
||||
} else {
|
||||
title = nls.localize({
|
||||
key: 'workspaceContainsFileActivation',
|
||||
comment: [
|
||||
'{0} will be a file name'
|
||||
]
|
||||
}, "Activated because file {0} exists in your workspace", fileNameOrGlob);
|
||||
}, "Activated by {1} because file {0} exists in your workspace", fileNameOrGlob, activationId);
|
||||
}
|
||||
} else if (/^workspaceContainsTimeout:/.test(activationTimes.activationEvent)) {
|
||||
const glob = activationTimes.activationEvent.substr('workspaceContainsTimeout:'.length);
|
||||
} else if (/^workspaceContainsTimeout:/.test(activationEvent)) {
|
||||
const glob = activationEvent.substr('workspaceContainsTimeout:'.length);
|
||||
title = nls.localize({
|
||||
key: 'workspaceContainsTimeout',
|
||||
comment: [
|
||||
'{0} will be a glob pattern'
|
||||
]
|
||||
}, "Activated because searching for {0} took too long", glob);
|
||||
} else if (/^onLanguage:/.test(activationTimes.activationEvent)) {
|
||||
let language = activationTimes.activationEvent.substr('onLanguage:'.length);
|
||||
title = nls.localize('languageActivation', "Activated because you opened a {0} file", language);
|
||||
}, "Activated by {1} because searching for {0} took too long", glob, activationId);
|
||||
} else if (/^onLanguage:/.test(activationEvent)) {
|
||||
let language = activationEvent.substr('onLanguage:'.length);
|
||||
title = nls.localize('languageActivation', "Activated by {1} because you opened a {0} file", language, activationId);
|
||||
} else {
|
||||
title = nls.localize({
|
||||
key: 'workspaceGenericActivation',
|
||||
comment: [
|
||||
'The {0} placeholder will be an activation event, like e.g. \'language:typescript\', \'debug\', etc.'
|
||||
]
|
||||
}, "Activated on {0}", activationTimes.activationEvent);
|
||||
}, "Activated by {1} on {0}", activationEvent, activationId);
|
||||
}
|
||||
data.activationTime.title = title;
|
||||
|
||||
@@ -536,7 +538,7 @@ export class DebugExtensionHostAction extends Action {
|
||||
|
||||
constructor(
|
||||
@IDebugService private readonly _debugService: IDebugService,
|
||||
@IWindowsService private readonly _windowsService: IWindowsService,
|
||||
@IElectronService private readonly _electronService: IElectronService,
|
||||
@IDialogService private readonly _dialogService: IDialogService,
|
||||
@IExtensionService private readonly _extensionService: IExtensionService,
|
||||
) {
|
||||
@@ -555,7 +557,7 @@ export class DebugExtensionHostAction extends Action {
|
||||
secondaryButton: nls.localize('cancel', "Cancel")
|
||||
});
|
||||
if (res.confirmed) {
|
||||
this._windowsService.relaunch({ addArgs: [`--inspect-extensions=${randomPort()}`] });
|
||||
this._electronService.relaunch({ addArgs: [`--inspect-extensions=${randomPort()}`] });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -609,7 +611,7 @@ export class SaveExtensionHostProfileAction extends Action {
|
||||
|
||||
constructor(
|
||||
id: string = SaveExtensionHostProfileAction.ID, label: string = SaveExtensionHostProfileAction.LABEL,
|
||||
@IWindowService private readonly _windowService: IWindowService,
|
||||
@IElectronService private readonly _electronService: IElectronService,
|
||||
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
|
||||
@IExtensionHostProfileService private readonly _extensionHostProfileService: IExtensionHostProfileService,
|
||||
) {
|
||||
@@ -624,7 +626,7 @@ export class SaveExtensionHostProfileAction extends Action {
|
||||
}
|
||||
|
||||
private async _asyncRun(): Promise<any> {
|
||||
let picked = await this._windowService.showSaveDialog({
|
||||
let picked = await this._electronService.showSaveDialog({
|
||||
title: 'Save Extension Host Profile',
|
||||
buttonLabel: 'Save',
|
||||
defaultPath: `CPU-${new Date().toISOString().replace(/[\-:]/g, '')}.cpuprofile`,
|
||||
@@ -634,13 +636,15 @@ export class SaveExtensionHostProfileAction extends Action {
|
||||
}]
|
||||
});
|
||||
|
||||
if (!picked) {
|
||||
if (!picked || !picked.filePath || picked.canceled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const profileInfo = this._extensionHostProfileService.lastProfile;
|
||||
let dataToWrite: object = profileInfo ? profileInfo.data : {};
|
||||
|
||||
let savePath = picked.filePath;
|
||||
|
||||
if (this._environmentService.isBuilt) {
|
||||
const profiler = await import('v8-inspect-profiler');
|
||||
// when running from a not-development-build we remove
|
||||
@@ -651,9 +655,9 @@ export class SaveExtensionHostProfileAction extends Action {
|
||||
let tmp = profiler.rewriteAbsolutePaths({ profile: dataToWrite as any }, 'piiRemoved');
|
||||
dataToWrite = tmp.profile;
|
||||
|
||||
picked = picked + '.txt';
|
||||
savePath = savePath + '.txt';
|
||||
}
|
||||
|
||||
return writeFile(picked, JSON.stringify(profileInfo ? profileInfo.data : {}, null, '\t'));
|
||||
return writeFile(savePath, JSON.stringify(profileInfo ? profileInfo.data : {}, null, '\t'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1465,7 +1465,7 @@ suite('ExtensionsActions Test', () => {
|
||||
assert.equal(testObject.tooltip, 'Please reload Azure Data Studio to enable this extension.'); // {{SQL CARBON EDIT}} - replace Visual Studio Code with Azure Data Studio
|
||||
});
|
||||
|
||||
test('Test ReloadAction when ui extension is disabled on remote server and installed in local server', async () => {
|
||||
test('Test ReloadAction is disabled when remote ui extension is installed in local server', async () => {
|
||||
// multi server setup
|
||||
const gallery = aGalleryExtension('a');
|
||||
const localExtensionManagementService = createExtensionManagementService([]);
|
||||
@@ -1480,7 +1480,7 @@ suite('ExtensionsActions Test', () => {
|
||||
|
||||
const onDidChangeExtensionsEmitter: Emitter<void> = new Emitter<void>();
|
||||
instantiationService.stub(IExtensionService, <Partial<IExtensionService>>{
|
||||
getExtensions: () => Promise.resolve([]),
|
||||
getExtensions: () => Promise.resolve([ExtensionsActions.toExtensionDescription(remoteExtension)]),
|
||||
onDidChangeExtensions: onDidChangeExtensionsEmitter.event,
|
||||
canAddExtension: (extension) => false
|
||||
});
|
||||
@@ -1497,8 +1497,69 @@ suite('ExtensionsActions Test', () => {
|
||||
const localExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file('pub.a') });
|
||||
onDidInstallEvent.fire({ identifier: localExtension.identifier, local: localExtension, operation: InstallOperation.Install });
|
||||
|
||||
assert.ok(testObject.enabled);
|
||||
assert.equal(testObject.tooltip, 'Please reload Azure Data Studio to enable this extension.'); // {{SQL CARBON EDIT}} - replace Visual Studio Code with Azure Data Studio
|
||||
assert.ok(!testObject.enabled);
|
||||
});
|
||||
|
||||
test('Test ReloadAction for remote ui extension is disabled when it is installed and enabled in local server', async () => {
|
||||
// multi server setup
|
||||
const gallery = aGalleryExtension('a');
|
||||
const localExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file('pub.a') });
|
||||
const localExtensionManagementService = createExtensionManagementService([localExtension]);
|
||||
const onDidInstallEvent = new Emitter<DidInstallExtensionEvent>();
|
||||
localExtensionManagementService.onDidInstallExtension = onDidInstallEvent.event;
|
||||
const remoteExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file('pub.a').with({ scheme: Schemas.vscodeRemote }) });
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, localExtensionManagementService, createExtensionManagementService([remoteExtension]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
const workbenchService: IExtensionsWorkbenchService = instantiationService.createInstance(ExtensionsWorkbenchService);
|
||||
instantiationService.set(IExtensionsWorkbenchService, workbenchService);
|
||||
|
||||
const onDidChangeExtensionsEmitter: Emitter<void> = new Emitter<void>();
|
||||
instantiationService.stub(IExtensionService, <Partial<IExtensionService>>{
|
||||
getExtensions: () => Promise.resolve([ExtensionsActions.toExtensionDescription(localExtension)]),
|
||||
onDidChangeExtensions: onDidChangeExtensionsEmitter.event,
|
||||
canAddExtension: (extension) => false
|
||||
});
|
||||
const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction);
|
||||
instantiationService.createInstance(ExtensionContainers, [testObject]);
|
||||
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
|
||||
|
||||
await workbenchService.queryGallery(CancellationToken.None);
|
||||
const extensions = await workbenchService.queryLocal(extensionManagementServerService.remoteExtensionManagementServer!);
|
||||
testObject.extension = extensions[0];
|
||||
assert.ok(testObject.extension);
|
||||
assert.ok(!testObject.enabled);
|
||||
});
|
||||
|
||||
test('Test ReloadAction for local ui extension is disabled when it is installed and enabled in remote server', async () => {
|
||||
// multi server setup
|
||||
const gallery = aGalleryExtension('a');
|
||||
const localExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file('pub.a') });
|
||||
const localExtensionManagementService = createExtensionManagementService([localExtension]);
|
||||
const onDidInstallEvent = new Emitter<DidInstallExtensionEvent>();
|
||||
localExtensionManagementService.onDidInstallExtension = onDidInstallEvent.event;
|
||||
const remoteExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file('pub.a').with({ scheme: Schemas.vscodeRemote }) });
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, localExtensionManagementService, createExtensionManagementService([remoteExtension]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
const workbenchService: IExtensionsWorkbenchService = instantiationService.createInstance(ExtensionsWorkbenchService);
|
||||
instantiationService.set(IExtensionsWorkbenchService, workbenchService);
|
||||
|
||||
const onDidChangeExtensionsEmitter: Emitter<void> = new Emitter<void>();
|
||||
instantiationService.stub(IExtensionService, <Partial<IExtensionService>>{
|
||||
getExtensions: () => Promise.resolve([ExtensionsActions.toExtensionDescription(remoteExtension)]),
|
||||
onDidChangeExtensions: onDidChangeExtensionsEmitter.event,
|
||||
canAddExtension: (extension) => false
|
||||
});
|
||||
const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction);
|
||||
instantiationService.createInstance(ExtensionContainers, [testObject]);
|
||||
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
|
||||
|
||||
await workbenchService.queryGallery(CancellationToken.None);
|
||||
const extensions = await workbenchService.queryLocal(extensionManagementServerService.localExtensionManagementServer!);
|
||||
testObject.extension = extensions[0];
|
||||
assert.ok(testObject.extension);
|
||||
assert.ok(!testObject.enabled);
|
||||
});
|
||||
|
||||
test('Test remote install action is enabled for local workspace extension', async () => {
|
||||
@@ -1854,7 +1915,7 @@ suite('ExtensionsActions Test', () => {
|
||||
assert.ok(!testObject.enabled);
|
||||
});
|
||||
|
||||
test('Test local install action is enabled for remote ui extension', async () => {
|
||||
test('Test local install action is disabled for remote ui extension', async () => {
|
||||
// multi server setup
|
||||
const remoteUIExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService(), createExtensionManagementService([remoteUIExtension]));
|
||||
@@ -1870,9 +1931,7 @@ suite('ExtensionsActions Test', () => {
|
||||
const extensions = await workbenchService.queryLocal(extensionManagementServerService.remoteExtensionManagementServer!);
|
||||
await workbenchService.queryGallery(CancellationToken.None);
|
||||
testObject.extension = extensions[0];
|
||||
assert.ok(testObject.enabled);
|
||||
assert.equal('Install Locally', testObject.label);
|
||||
assert.equal('extension-action prominent install', testObject.class);
|
||||
assert.ok(!testObject.enabled);
|
||||
});
|
||||
|
||||
test('Test local install action when installing remote ui extension', async () => {
|
||||
@@ -1896,54 +1955,10 @@ suite('ExtensionsActions Test', () => {
|
||||
const extensions = await workbenchService.queryLocal(extensionManagementServerService.remoteExtensionManagementServer!);
|
||||
await workbenchService.queryGallery(CancellationToken.None);
|
||||
testObject.extension = extensions[0];
|
||||
assert.ok(testObject.enabled);
|
||||
assert.equal('Install Locally', testObject.label);
|
||||
assert.equal('extension-action prominent install', testObject.class);
|
||||
|
||||
onInstallExtension.fire({ identifier: remoteUIExtension.identifier, gallery });
|
||||
assert.ok(testObject.enabled);
|
||||
assert.equal('Installing', testObject.label);
|
||||
assert.equal('extension-action install installing', testObject.class);
|
||||
});
|
||||
|
||||
test('Test local install action when installing remote ui extension is finished', async () => {
|
||||
// multi server setup
|
||||
const localExtensionManagementService: IExtensionManagementService = createExtensionManagementService();
|
||||
const onInstallExtension = new Emitter<InstallExtensionEvent>();
|
||||
localExtensionManagementService.onInstallExtension = onInstallExtension.event;
|
||||
const onDidInstallEvent = new Emitter<DidInstallExtensionEvent>();
|
||||
localExtensionManagementService.onDidInstallExtension = onDidInstallEvent.event;
|
||||
const remoteUIExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, localExtensionManagementService, createExtensionManagementService([remoteUIExtension]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
const workbenchService: IExtensionsWorkbenchService = instantiationService.createInstance(ExtensionsWorkbenchService);
|
||||
instantiationService.stub(IExtensionsWorkbenchService, workbenchService, 'open', undefined);
|
||||
instantiationService.set(IExtensionsWorkbenchService, workbenchService);
|
||||
|
||||
const gallery = aGalleryExtension('a', { identifier: remoteUIExtension.identifier });
|
||||
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
|
||||
const testObject: ExtensionsActions.InstallAction = instantiationService.createInstance(ExtensionsActions.LocalInstallAction);
|
||||
instantiationService.createInstance(ExtensionContainers, [testObject]);
|
||||
|
||||
const extensions = await workbenchService.queryLocal(extensionManagementServerService.remoteExtensionManagementServer!);
|
||||
await workbenchService.queryGallery(CancellationToken.None);
|
||||
testObject.extension = extensions[0];
|
||||
assert.ok(testObject.enabled);
|
||||
assert.equal('Install Locally', testObject.label);
|
||||
assert.equal('extension-action prominent install', testObject.class);
|
||||
|
||||
onInstallExtension.fire({ identifier: remoteUIExtension.identifier, gallery });
|
||||
assert.ok(testObject.enabled);
|
||||
assert.equal('Installing', testObject.label);
|
||||
assert.equal('extension-action install installing', testObject.class);
|
||||
|
||||
const installedExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file(`pub.a`) });
|
||||
onDidInstallEvent.fire({ identifier: installedExtension.identifier, local: installedExtension, operation: InstallOperation.Install });
|
||||
assert.ok(!testObject.enabled);
|
||||
});
|
||||
|
||||
test('Test local install action is enabled for disabled remote ui extension', async () => {
|
||||
test('Test local install action is disabled for disabled remote ui extension', async () => {
|
||||
// multi server setup
|
||||
const remoteUIExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService(), createExtensionManagementService([remoteUIExtension]));
|
||||
@@ -1960,9 +1975,7 @@ suite('ExtensionsActions Test', () => {
|
||||
const extensions = await workbenchService.queryLocal(extensionManagementServerService.remoteExtensionManagementServer!);
|
||||
await workbenchService.queryGallery(CancellationToken.None);
|
||||
testObject.extension = extensions[0];
|
||||
assert.ok(testObject.enabled);
|
||||
assert.equal('Install Locally', testObject.label);
|
||||
assert.equal('extension-action prominent install', testObject.class);
|
||||
assert.ok(!testObject.enabled);
|
||||
});
|
||||
|
||||
test('Test local install action is disabled when extension is not set', async () => {
|
||||
@@ -2062,7 +2075,7 @@ suite('ExtensionsActions Test', () => {
|
||||
assert.ok(!testObject.enabled);
|
||||
});
|
||||
|
||||
test('Test local install action is disabled for remoteUI extension if it is uninstalled locally', async () => {
|
||||
test('Test local install action is disabled for remote UI extension if it uninstalled locally', async () => {
|
||||
// multi server setup
|
||||
const extensionManagementService = instantiationService.get(IExtensionManagementService);
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService(), extensionManagementService);
|
||||
@@ -2080,14 +2093,13 @@ suite('ExtensionsActions Test', () => {
|
||||
const extensions = await workbenchService.queryLocal(extensionManagementServerService.remoteExtensionManagementServer!);
|
||||
await workbenchService.queryGallery(CancellationToken.None);
|
||||
testObject.extension = extensions[0];
|
||||
assert.ok(testObject.enabled);
|
||||
assert.equal('Install Locally', testObject.label);
|
||||
assert.ok(!testObject.enabled);
|
||||
|
||||
uninstallEvent.fire(remoteUIExtension.identifier);
|
||||
assert.ok(!testObject.enabled);
|
||||
});
|
||||
|
||||
test('Test local install action is enabled for remote UI extension if it has gallery', async () => {
|
||||
test('Test local install action is disabled for remote UI extension if it has gallery', async () => {
|
||||
// multi server setup
|
||||
const remoteUIExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService(), createExtensionManagementService([remoteUIExtension]));
|
||||
@@ -2103,7 +2115,7 @@ suite('ExtensionsActions Test', () => {
|
||||
const extensions = await workbenchService.queryLocal(extensionManagementServerService.remoteExtensionManagementServer!);
|
||||
testObject.extension = extensions[0];
|
||||
assert.ok(testObject.extension);
|
||||
assert.ok(testObject.enabled);
|
||||
assert.ok(!testObject.enabled);
|
||||
});
|
||||
|
||||
test('Test local install action is disabled for remote UI system extension', async () => {
|
||||
|
||||
@@ -16,16 +16,15 @@ import { EditorOptions, TextEditorOptions, IEditorCloseEvent } from 'vs/workbenc
|
||||
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';
|
||||
import { FileOperationError, FileOperationResult, FileChangesEvent, IFileService, FALLBACK_MAX_MEMORY_SIZE_MB, MIN_MAX_MEMORY_SIZE_MB } from 'vs/platform/files/common/files';
|
||||
import { FileOperationError, FileOperationResult, FileChangesEvent, IFileService } from 'vs/platform/files/common/files';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { ScrollType } from 'vs/editor/common/editorCommon';
|
||||
import { IWindowsService, IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorGroupsService, IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
@@ -56,8 +55,6 @@ export class TextFileEditor extends BaseTextEditor {
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IEditorGroupsService editorGroupService: IEditorGroupsService,
|
||||
@ITextFileService textFileService: ITextFileService,
|
||||
@IWindowsService private readonly windowsService: IWindowsService,
|
||||
@IPreferencesService private readonly preferencesService: IPreferencesService,
|
||||
@IWindowService windowService: IWindowService,
|
||||
@IExplorerService private readonly explorerService: IExplorerService
|
||||
) {
|
||||
@@ -167,63 +164,48 @@ export class TextFileEditor extends BaseTextEditor {
|
||||
// Readonly flag
|
||||
textEditor.updateOptions({ readOnly: textFileModel.isReadonly() });
|
||||
} catch (error) {
|
||||
|
||||
// In case we tried to open a file inside the text editor and the response
|
||||
// indicates that this is not a text file, reopen the file through the binary
|
||||
// editor.
|
||||
if ((<TextFileOperationError>error).textFileOperationResult === TextFileOperationResult.FILE_IS_BINARY) {
|
||||
return this.openAsBinary(input, options);
|
||||
}
|
||||
|
||||
// Similar, handle case where we were asked to open a folder in the text editor.
|
||||
if ((<FileOperationError>error).fileOperationResult === FileOperationResult.FILE_IS_DIRECTORY) {
|
||||
this.openAsFolder(input);
|
||||
|
||||
throw new Error(nls.localize('openFolderError', "File is a directory"));
|
||||
}
|
||||
|
||||
// Offer to create a file from the error if we have a file not found and the name is valid
|
||||
if ((<FileOperationError>error).fileOperationResult === FileOperationResult.FILE_NOT_FOUND && isValidBasename(basename(input.getResource()))) {
|
||||
throw createErrorWithActions(toErrorMessage(error), {
|
||||
actions: [
|
||||
new Action('workbench.files.action.createMissingFile', nls.localize('createFile', "Create File"), undefined, true, async () => {
|
||||
await this.textFileService.create(input.getResource());
|
||||
|
||||
return this.editorService.openEditor({
|
||||
resource: input.getResource(),
|
||||
options: {
|
||||
pinned: true // new file gets pinned by default
|
||||
}
|
||||
});
|
||||
})
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
if ((<FileOperationError>error).fileOperationResult === FileOperationResult.FILE_EXCEED_MEMORY_LIMIT) {
|
||||
const memoryLimit = Math.max(MIN_MAX_MEMORY_SIZE_MB, +this.configurationService.getValue<number>(undefined, 'files.maxMemoryForLargeFilesMB') || FALLBACK_MAX_MEMORY_SIZE_MB);
|
||||
|
||||
throw createErrorWithActions(toErrorMessage(error), {
|
||||
actions: [
|
||||
new Action('workbench.window.action.relaunchWithIncreasedMemoryLimit', nls.localize('relaunchWithIncreasedMemoryLimit', "Restart with {0} MB", memoryLimit), undefined, true, () => {
|
||||
return this.windowsService.relaunch({
|
||||
addArgs: [
|
||||
`--max-memory=${memoryLimit}`
|
||||
]
|
||||
});
|
||||
}),
|
||||
new Action('workbench.window.action.configureMemoryLimit', nls.localize('configureMemoryLimit', 'Configure Memory Limit'), undefined, true, () => {
|
||||
return this.preferencesService.openGlobalSettings(undefined, { query: 'files.maxMemoryForLargeFilesMB' });
|
||||
})
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
// Otherwise make sure the error bubbles up
|
||||
throw error;
|
||||
this.handleSetInputError(error, input, options);
|
||||
}
|
||||
}
|
||||
|
||||
protected handleSetInputError(error: Error, input: FileEditorInput, options: EditorOptions | undefined): void {
|
||||
|
||||
// In case we tried to open a file inside the text editor and the response
|
||||
// indicates that this is not a text file, reopen the file through the binary
|
||||
// editor.
|
||||
if ((<TextFileOperationError>error).textFileOperationResult === TextFileOperationResult.FILE_IS_BINARY) {
|
||||
return this.openAsBinary(input, options);
|
||||
}
|
||||
|
||||
// Similar, handle case where we were asked to open a folder in the text editor.
|
||||
if ((<FileOperationError>error).fileOperationResult === FileOperationResult.FILE_IS_DIRECTORY) {
|
||||
this.openAsFolder(input);
|
||||
|
||||
throw new Error(nls.localize('openFolderError', "File is a directory"));
|
||||
}
|
||||
|
||||
// Offer to create a file from the error if we have a file not found and the name is valid
|
||||
if ((<FileOperationError>error).fileOperationResult === FileOperationResult.FILE_NOT_FOUND && isValidBasename(basename(input.getResource()))) {
|
||||
throw createErrorWithActions(toErrorMessage(error), {
|
||||
actions: [
|
||||
new Action('workbench.files.action.createMissingFile', nls.localize('createFile', "Create File"), undefined, true, async () => {
|
||||
await this.textFileService.create(input.getResource());
|
||||
|
||||
return this.editorService.openEditor({
|
||||
resource: input.getResource(),
|
||||
options: {
|
||||
pinned: true // new file gets pinned by default
|
||||
}
|
||||
});
|
||||
})
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
// Otherwise make sure the error bubbles up
|
||||
throw error;
|
||||
}
|
||||
|
||||
private openAsBinary(input: FileEditorInput, options: EditorOptions | undefined): void {
|
||||
input.setForceOpenAsBinary();
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ export class NewFileAction extends Action {
|
||||
@ICommandService private commandService: ICommandService
|
||||
) {
|
||||
super('explorer.newFile', NEW_FILE_LABEL);
|
||||
this.class = 'explorer-action new-file';
|
||||
this.class = 'explorer-action codicon-new-file';
|
||||
this._register(explorerService.onDidChangeEditable(e => {
|
||||
const elementIsBeingEdited = explorerService.isEditable(e);
|
||||
this.enabled = !elementIsBeingEdited;
|
||||
@@ -114,7 +114,7 @@ export class NewFolderAction extends Action {
|
||||
@ICommandService private commandService: ICommandService
|
||||
) {
|
||||
super('explorer.newFolder', NEW_FOLDER_LABEL);
|
||||
this.class = 'explorer-action new-folder';
|
||||
this.class = 'explorer-action codicon-new-folder';
|
||||
this._register(explorerService.onDidChangeEditable(e => {
|
||||
const elementIsBeingEdited = explorerService.isEditable(e);
|
||||
this.enabled = !elementIsBeingEdited;
|
||||
@@ -603,7 +603,7 @@ export class SaveAllAction extends BaseSaveAllAction {
|
||||
public static readonly LABEL = SAVE_ALL_LABEL;
|
||||
|
||||
public get class(): string {
|
||||
return 'explorer-action save-all';
|
||||
return 'explorer-action codicon-save-all';
|
||||
}
|
||||
|
||||
protected doRun(context: any): Promise<any> {
|
||||
@@ -621,7 +621,7 @@ export class SaveAllInGroupAction extends BaseSaveAllAction {
|
||||
public static readonly LABEL = nls.localize('saveAllInGroup', "Save All in Group");
|
||||
|
||||
public get class(): string {
|
||||
return 'explorer-action save-all';
|
||||
return 'explorer-action codicon-save-all';
|
||||
}
|
||||
|
||||
protected doRun(context: any): Promise<any> {
|
||||
@@ -639,7 +639,7 @@ export class CloseGroupAction extends Action {
|
||||
public static readonly LABEL = nls.localize('closeGroup', "Close Group");
|
||||
|
||||
constructor(id: string, label: string, @ICommandService private readonly commandService: ICommandService) {
|
||||
super(id, label, 'action-close-all-files');
|
||||
super(id, label, 'codicon-close-all');
|
||||
}
|
||||
|
||||
public run(context?: any): Promise<any> {
|
||||
@@ -702,7 +702,7 @@ export class CollapseExplorerView extends Action {
|
||||
@IViewletService private readonly viewletService: IViewletService,
|
||||
@IExplorerService readonly explorerService: IExplorerService
|
||||
) {
|
||||
super(id, label, 'explorer-action collapse-explorer');
|
||||
super(id, label, 'explorer-action codicon-collapse-all');
|
||||
this._register(explorerService.onDidChangeEditable(e => {
|
||||
const elementIsBeingEdited = explorerService.isEditable(e);
|
||||
this.enabled = !elementIsBeingEdited;
|
||||
@@ -730,7 +730,7 @@ export class RefreshExplorerView extends Action {
|
||||
@IViewletService private readonly viewletService: IViewletService,
|
||||
@IExplorerService private readonly explorerService: IExplorerService
|
||||
) {
|
||||
super(id, label, 'explorer-action refresh-explorer');
|
||||
super(id, label, 'explorer-action codicon-refresh');
|
||||
this._register(explorerService.onDidChangeEditable(e => {
|
||||
const elementIsBeingEdited = explorerService.isEditable(e);
|
||||
this.enabled = !elementIsBeingEdited;
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
// {{SQL CARBON EDIT}} import EditorInput
|
||||
import { toResource, IEditorCommandsContext, SideBySideEditor, EditorInput } from 'vs/workbench/common/editor';
|
||||
import { IWindowsService, IWindowService, IURIToOpen, IOpenSettings, INewWindowOptions, isWorkspaceToOpen } from 'vs/platform/windows/common/windows';
|
||||
import { toResource, IEditorCommandsContext, SideBySideEditor, EditorInput } from 'vs/workbench/common/editor'; // {{SQL CARBON EDIT}} import EditorInput
|
||||
import { IWindowService, IURIToOpen, IOpenSettings, isWorkspaceToOpen } from 'vs/platform/windows/common/windows';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
@@ -101,9 +101,9 @@ export const openWindowCommand = (accessor: ServicesAccessor, urisToOpen: IURITo
|
||||
}
|
||||
};
|
||||
|
||||
export const newWindowCommand = (accessor: ServicesAccessor, options?: INewWindowOptions) => {
|
||||
const windowsService = accessor.get(IWindowsService);
|
||||
windowsService.openNewWindow(options);
|
||||
export const newWindowCommand = (accessor: ServicesAccessor, options?: { reuse?: boolean, remoteAuthority?: string }) => {
|
||||
const hostService = accessor.get(IHostService);
|
||||
hostService.openEmptyWindow(options);
|
||||
};
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
|
||||
@@ -18,7 +18,6 @@ import { VIEWLET_ID, SortOrderConfiguration, FILE_EDITOR_INPUT_ID, IExplorerServ
|
||||
import { FileEditorTracker } from 'vs/workbench/contrib/files/browser/editors/fileEditorTracker';
|
||||
import { SaveErrorHandler } from 'vs/workbench/contrib/files/browser/saveErrorHandler';
|
||||
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
|
||||
import { TextFileEditor } from 'vs/workbench/contrib/files/browser/editors/textFileEditor';
|
||||
import { BinaryFileEditor } from 'vs/workbench/contrib/files/browser/editors/binaryFileEditor';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
@@ -26,7 +25,6 @@ import { IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry'
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { DirtyFilesTracker } from 'vs/workbench/contrib/files/common/dirtyFilesTracker';
|
||||
import { ExplorerViewlet, ExplorerViewletViewsContribution } from 'vs/workbench/contrib/files/browser/explorerViewlet';
|
||||
import { IEditorRegistry, EditorDescriptor, Extensions as EditorExtensions } from 'vs/workbench/browser/editor';
|
||||
import { DataUriEditorInput } from 'vs/workbench/common/editor/dataUriEditorInput';
|
||||
@@ -101,17 +99,6 @@ registry.registerWorkbenchAction(
|
||||
);
|
||||
|
||||
// Register file editors
|
||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
||||
new EditorDescriptor(
|
||||
TextFileEditor,
|
||||
TextFileEditor.ID,
|
||||
nls.localize('textFileEditor', "Text File Editor")
|
||||
),
|
||||
[
|
||||
new SyncDescriptor<EditorInput>(FileEditorInput)
|
||||
]
|
||||
);
|
||||
|
||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
||||
new EditorDescriptor(
|
||||
BinaryFileEditor,
|
||||
@@ -145,8 +132,6 @@ interface ISerializedFileInput {
|
||||
// Register Editor Input Factory
|
||||
class FileEditorInputFactory implements IEditorInputFactory {
|
||||
|
||||
constructor() { }
|
||||
|
||||
serialize(editorInput: EditorInput): string {
|
||||
const fileEditorInput = <FileEditorInput>editorInput;
|
||||
const resource = fileEditorInput.getResource();
|
||||
@@ -183,9 +168,6 @@ Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).regi
|
||||
// Register Save Error Handler
|
||||
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(SaveErrorHandler, LifecyclePhase.Starting);
|
||||
|
||||
// Register Dirty Files Tracker
|
||||
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DirtyFilesTracker, LifecyclePhase.Starting);
|
||||
|
||||
// Register uri display for file uris
|
||||
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(FileUriLabelContribution, LifecyclePhase.Starting);
|
||||
|
||||
@@ -341,7 +323,8 @@ configurationRegistry.registerConfiguration({
|
||||
'files.maxMemoryForLargeFilesMB': {
|
||||
'type': 'number',
|
||||
'default': 4096,
|
||||
'markdownDescription': nls.localize('maxMemoryForLargeFilesMB', "Controls the memory available to VS Code after restart when trying to open large files. Same effect as specifying `--max-memory=NEWSIZE` on the command line.")
|
||||
'markdownDescription': nls.localize('maxMemoryForLargeFilesMB', "Controls the memory available to VS Code after restart when trying to open large files. Same effect as specifying `--max-memory=NEWSIZE` on the command line."),
|
||||
included: platform.isNative
|
||||
},
|
||||
'files.simpleDialog.enable': {
|
||||
'type': 'boolean',
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
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 { TextFileEditor } from 'vs/workbench/contrib/files/browser/editors/textFileEditor';
|
||||
import { DirtyFilesTracker } from 'vs/workbench/contrib/files/common/dirtyFilesTracker';
|
||||
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
|
||||
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
|
||||
// Register file editor
|
||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
||||
new EditorDescriptor(
|
||||
TextFileEditor,
|
||||
TextFileEditor.ID,
|
||||
nls.localize('textFileEditor', "Text File Editor")
|
||||
),
|
||||
[
|
||||
new SyncDescriptor<EditorInput>(FileEditorInput)
|
||||
]
|
||||
);
|
||||
|
||||
// Register Dirty Files Tracker
|
||||
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DirtyFilesTracker, LifecyclePhase.Starting);
|
||||
@@ -1,3 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.99998 8.70711L11.6464 12.3536L12.3535 11.6464L8.70708 8L12.3535 4.35355L11.6464 3.64645L7.99998 7.29289L4.35353 3.64645L3.64642 4.35355L7.29287 8L3.64642 11.6464L4.35353 12.3536L7.99998 8.70711Z" fill="#C5C5C5"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 368 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><circle fill="#C5C5C5" cx="8" cy="8" r="4"/></svg>
|
||||
|
Before Width: | Height: | Size: 167 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><circle fill="#FFF" cx="8" cy="8" r="4"/></svg>
|
||||
|
Before Width: | Height: | Size: 164 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><circle fill="#424242" cx="8" cy="8" r="4"/></svg>
|
||||
|
Before Width: | Height: | Size: 167 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="3 3 16 16" enable-background="new 3 3 16 16"><polygon fill="#FFF" points="12.597,11.042 15.4,13.845 13.844,15.4 11.042,12.598 8.239,15.4 6.683,13.845 9.485,11.042 6.683,8.239 8.238,6.683 11.042,9.486 13.845,6.683 15.4,8.239"/></svg>
|
||||
|
Before Width: | Height: | Size: 304 B |
@@ -1,3 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.99998 8.70711L11.6464 12.3536L12.3535 11.6465L8.70708 8.00001L12.3535 4.35356L11.6464 3.64645L7.99998 7.2929L4.35353 3.64645L3.64642 4.35356L7.29287 8.00001L3.64642 11.6465L4.35353 12.3536L7.99998 8.70711Z" fill="#424242"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 379 B |
@@ -1,3 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 3H4V0H3V3H0V4H3V7H4V4H7V3ZM13.9 4.6L10.5 1.1L10.2 1H5V2H9V6H13V13H4V8H3V13.5L3.5 14H9H13.5L14 13.5V5L13.9 4.6ZM12.9032 5L10 2V5H12.9032Z" fill="#C5C5C5"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 310 B |
@@ -1,3 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 3H4V0H3V3H0V4H3V7H4V4H7V3ZM13.9 4.6L10.5 1.1L10.2 1H5V2H9V6H13V13H4V8H3V13.5L3.5 14H9H13.5L14 13.5V5L13.9 4.6ZM12.9032 5L10 2V5H12.9032Z" fill="white"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 308 B |
@@ -1,3 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 3H4V0H3V3H0V4H3V7H4V4H7V3ZM13.9 4.6L10.5 1.1L10.2 1H5V2H9V6H13V13H4V8H3V13.5L3.5 14H9H13.5L14 13.5V5L13.9 4.6ZM12.9032 5L10 2V5H12.9032Z" fill="#424242"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 310 B |
@@ -1,3 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 3H4V0H3V3H0V4H3V7H4V4H7V3ZM5.5 7H5V6H5.3L6.1 5.1L6.5 5H14V4H8V3H14.5L15 3.5V13.5L14.5 14H1.5L1 13.5V6.5V6V5H2V6V6.5V13H14V7V6H6.7L5.9 6.9L5.5 7Z" fill="#C5C5C5"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 318 B |
@@ -1,3 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 3H4V0H3V3H0V4H3V7H4V4H7V3ZM5.5 7H5V6H5.3L6.1 5.1L6.5 5H14V4H8V3H14.5L15 3.5V13.5L14.5 14H1.5L1 13.5V6.5V6V5H2V6V6.5V13H14V7V6H6.7L5.9 6.9L5.5 7Z" fill="white"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 316 B |
@@ -1,3 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 3H4V0H3V3H0V4H3V7H4V4H7V3ZM5.5 7H5V6H5.3L6.1 5.1L6.5 5H14V4H8V3H14.5L15 3.5V13.5L14.5 14H1.5L1 13.5V6.5V6V5H2V6V6.5V13H14V7V6H6.7L5.9 6.9L5.5 7Z" fill="#424242"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 318 B |
@@ -1,4 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.62132 8.08579L7.91421 7.37868L6.5 8.79289L5.08579 7.37868L4.37868 8.08579L5.79289 9.5L4.37868 10.9142L5.08579 11.6213L6.5 10.2071L7.91421 11.6213L8.62132 10.9142L7.20711 9.5L8.62132 8.08579Z" fill="#C5C5C5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 3L6 2H13L14 3V10L13 11H11V13L10 14H3L2 13V6L3 5H5V3ZM6 5H10L11 6V10H13V3H6V5ZM10 6H3V13H10V6Z" fill="#C5C5C5"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 528 B |
@@ -1,4 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.62132 8.08579L7.91421 7.37868L6.5 8.79289L5.08579 7.37868L4.37868 8.08579L5.79289 9.5L4.37868 10.9142L5.08579 11.6213L6.5 10.2071L7.91421 11.6213L8.62132 10.9142L7.20711 9.5L8.62132 8.08579Z" fill="#424242"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 3L6 2H13L14 3V10L13 11H11V13L10 14H3L2 13V6L3 5H5V3ZM6 5H10L11 6V10H13V3H6V5ZM10 6H3V13H10V6Z" fill="#424242"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 528 B |
@@ -1,4 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9 9H4V10H9V9Z" fill="#C5C5C5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 3L6 2H13L14 3V10L13 11H11V13L10 14H3L2 13V6L3 5H5V3ZM6 5H10L11 6V10H13V3H6V5ZM10 6H3V13H10V6Z" fill="#C5C5C5"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 309 B |
@@ -1,4 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9 9H4V10H9V9Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 3L6 2H13L14 3V10L13 11H11V13L10 14H3L2 13V6L3 5H5V3ZM6 5H10L11 6V10H13V3H6V5ZM10 6H3V13H10V6Z" fill="white"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 305 B |
@@ -1,4 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9 9H4V10H9V9Z" fill="#424242"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 3L6 2H13L14 3V10L13 11H11V13L10 14H3L2 13V6L3 5H5V3ZM6 5H10L11 6V10H13V3H6V5ZM10 6H3V13H10V6Z" fill="#424242"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 309 B |
@@ -62,6 +62,8 @@
|
||||
|
||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row > .monaco-action-bar {
|
||||
visibility: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.explorer-viewlet .panel-header .count {
|
||||
@@ -84,9 +86,12 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row > .monaco-action-bar .close-editor-action {
|
||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row > .monaco-action-bar .codicon-close {
|
||||
width: 8px;
|
||||
height: 22px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row > .monaco-action-bar .action-close-all-files,
|
||||
|
||||
@@ -3,84 +3,6 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/* Close all */
|
||||
.monaco-workbench .explorer-viewlet .action-close-all-files {
|
||||
background: url("close-all-light.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .explorer-viewlet .action-close-all-files {
|
||||
background: url("close-all-dark.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench .explorer-viewlet .action-close-all-files {
|
||||
background: url("close-all-light.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
/* Save all */
|
||||
.monaco-workbench .explorer-action.save-all {
|
||||
background: url("save-all-light.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .explorer-action.save-all {
|
||||
background: url("save-all-dark.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench .explorer-action.save-all {
|
||||
background: url("save-all-hc.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
/* Add file */
|
||||
.monaco-workbench .explorer-action.new-file {
|
||||
background: url("add-file-light.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .explorer-action.new-file {
|
||||
background: url("add-file-dark.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench .explorer-action.new-file {
|
||||
background: url("add-file-hc.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
/* Add Folder */
|
||||
.monaco-workbench .explorer-action.new-folder {
|
||||
background: url("add-folder-light.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .explorer-action.new-folder {
|
||||
background: url("add-folder-dark.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench .explorer-action.new-folder {
|
||||
background: url("add-folder-hc.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
/* Refresh */
|
||||
.monaco-workbench .explorer-action.refresh-explorer {
|
||||
background: url("refresh-light.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .explorer-action.refresh-explorer {
|
||||
background: url("refresh-dark.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench .explorer-action.refresh-explorer {
|
||||
background: url("refresh-hc.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
/* Collapse all */
|
||||
.monaco-workbench .explorer-action.collapse-explorer {
|
||||
background: url("collapse-all-light.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .explorer-action.collapse-explorer {
|
||||
background: url("collapse-all-dark.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench .explorer-action.collapse-explorer {
|
||||
background: url("collapse-all-hc.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
/* Split editor vertical */
|
||||
.monaco-workbench .quick-open-sidebyside-vertical {
|
||||
background-image: url("split-editor-vertical-light.svg");
|
||||
@@ -116,28 +38,6 @@
|
||||
background: url("preview-dark.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.explorer-viewlet .explorer-open-editors .close-editor-action {
|
||||
background: url("action-close-light.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.explorer-viewlet .explorer-open-editors .focused .monaco-list-row.selected:not(.highlighted) .close-editor-action {
|
||||
background: url("action-close-focus.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row.dirty:not(:hover) > .monaco-action-bar .close-editor-action {
|
||||
background: url("action-close-dirty.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row.dirty:not(:hover) > .monaco-action-bar .close-editor-action,
|
||||
.hc-black .monaco-workbench .explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row.dirty:not(:hover) > .monaco-action-bar .close-editor-action {
|
||||
background: url("action-close-dirty-dark.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.explorer-viewlet .explorer-open-editors .monaco-list.focused .monaco-list-row.selected.dirty:not(:hover) > .monaco-action-bar .close-editor-action {
|
||||
background: url("action-close-dirty-focus.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .explorer-viewlet .explorer-open-editors .close-editor-action,
|
||||
.hc-black .monaco-workbench .explorer-viewlet .explorer-open-editors .close-editor-action {
|
||||
background: url("action-close-dark.svg") center center no-repeat;
|
||||
.explorer-viewlet .explorer-open-editors .monaco-list .monaco-list-row.dirty:not(:hover) > .monaco-action-bar .codicon-close::before {
|
||||
content: "\ea71";
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.56253 2.51578C3.46348 3.4501 2 5.55414 2 8C2 11.3137 4.68629 14 8 14C11.3137 14 14 11.3137 14 8C14 5.3252 12.2497 3.0592 9.83199 2.28483L9.52968 3.23832C11.5429 3.88455 13 5.77211 13 8C13 10.7614 10.7614 13 8 13C5.23858 13 3 10.7614 3 8C3 6.31104 3.83742 4.81768 5.11969 3.91246L5.56253 2.51578Z" fill="#C5C5C5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 3H2V2H5.5L6 2.5V6H5V3Z" fill="#C5C5C5"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 562 B |
@@ -1,4 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.56253 2.51578C3.46348 3.4501 2 5.55414 2 8C2 11.3137 4.68629 14 8 14C11.3137 14 14 11.3137 14 8C14 5.3252 12.2497 3.0592 9.83199 2.28483L9.52968 3.23832C11.5429 3.88455 13 5.77211 13 8C13 10.7614 10.7614 13 8 13C5.23858 13 3 10.7614 3 8C3 6.31104 3.83742 4.81768 5.11969 3.91246L5.56253 2.51578Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 3H2V2H5.5L6 2.5V6H5V3Z" fill="white"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 558 B |
@@ -1,4 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.56253 2.51578C3.46348 3.4501 2 5.55414 2 8C2 11.3137 4.68629 14 8 14C11.3137 14 14 11.3137 14 8C14 5.3252 12.2497 3.0592 9.83199 2.28483L9.52968 3.23832C11.5429 3.88455 13 5.77211 13 8C13 10.7614 10.7614 13 8 13C5.23858 13 3 10.7614 3 8C3 6.31104 3.83742 4.81768 5.11969 3.91246L5.56253 2.51578Z" fill="#424242"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 3H2V2H5.5L6 2.5V6H5V3Z" fill="#424242"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 562 B |
@@ -1,3 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15 3V11.5L14.5 12H12V14.5L11.5 15H1.5L1 14.5V4.5L1.5 4H3.985V1.5L4.485 1H13L13.353 1.147L14.853 2.647L15 3ZM12 6V11H14V3.206L12.793 2H4.985V4H10L10.353 4.146L11.853 5.646L12 6ZM11 14H2V5H3V8.07143H9V5H9.793L11 6.208V14ZM8 5H6V7.5H8V5Z" fill="#C5C5C5"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 406 B |
@@ -1,3 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15 3V11.5L14.5 12H12V14.5L11.5 15H1.5L1 14.5V4.5L1.5 4H3.985V1.5L4.485 1H13L13.353 1.147L14.853 2.647L15 3ZM12 6V11H14V3.206L12.793 2H4.985V4H10L10.353 4.146L11.853 5.646L12 6ZM11 14H2V5H3V8.07143H9V5H9.793L11 6.208V14ZM8 5H6V7.5H8V5Z" fill="white"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 404 B |
@@ -1,3 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15 3V11.5L14.5 12H12V14.5L11.5 15H1.5L1 14.5V4.5L1.5 4H3.985V1.5L4.485 1H13L13.353 1.147L14.853 2.647L15 3ZM12 6V11H14V3.206L12.793 2H4.985V4H10L10.353 4.146L11.853 5.646L12 6ZM11 14H2V5H3V8.07143H9V5H9.793L11 6.208V14ZM8 5H6V7.5H8V5Z" fill="#424242"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 406 B |
@@ -15,7 +15,7 @@ import { explorerRootErrorEmitter } from 'vs/workbench/contrib/files/browser/vie
|
||||
|
||||
export class ExplorerDecorationsProvider implements IDecorationsProvider {
|
||||
readonly label: string = localize('label', "Explorer");
|
||||
private _onDidChange = new Emitter<URI[]>();
|
||||
private readonly _onDidChange = new Emitter<URI[]>();
|
||||
private readonly toDispose = new DisposableStore();
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -604,7 +604,6 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async handleExternalDrop(data: DesktopDragAndDropData, target: ExplorerItem, originalEvent: DragEvent): Promise<void> {
|
||||
const droppedResources = extractResources(originalEvent, true);
|
||||
// Check for dropped external files to be folders
|
||||
|
||||
@@ -7,8 +7,6 @@ import * as nls from 'vs/nls';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { VIEWLET_ID } from 'vs/workbench/contrib/files/common/files';
|
||||
import { TextFileModelChangeEvent, ITextFileService, AutoSaveMode, ModelState } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { platform, Platform } from 'vs/base/common/platform';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -18,22 +16,18 @@ import * as arrays from 'vs/base/common/arrays';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
|
||||
export class DirtyFilesTracker extends Disposable implements IWorkbenchContribution {
|
||||
private isDocumentedEdited: boolean;
|
||||
private lastKnownDirtyCount: number | undefined;
|
||||
private readonly badgeHandle = this._register(new MutableDisposable());
|
||||
|
||||
constructor(
|
||||
@ITextFileService private readonly textFileService: ITextFileService,
|
||||
@ITextFileService protected readonly textFileService: ITextFileService,
|
||||
@ILifecycleService private readonly lifecycleService: ILifecycleService,
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IActivityService private readonly activityService: IActivityService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@IUntitledEditorService private readonly untitledEditorService: IUntitledEditorService
|
||||
@IUntitledEditorService protected readonly untitledEditorService: IUntitledEditorService
|
||||
) {
|
||||
super();
|
||||
|
||||
this.isDocumentedEdited = false;
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
@@ -54,23 +48,15 @@ export class DirtyFilesTracker extends Disposable implements IWorkbenchContribut
|
||||
return typeof this.lastKnownDirtyCount === 'number' && this.lastKnownDirtyCount > 0;
|
||||
}
|
||||
|
||||
private onUntitledDidChangeDirty(resource: URI): void {
|
||||
protected onUntitledDidChangeDirty(resource: URI): void {
|
||||
const gotDirty = this.untitledEditorService.isDirty(resource);
|
||||
|
||||
if ((!this.isDocumentedEdited && gotDirty) || (this.isDocumentedEdited && !gotDirty)) {
|
||||
this.updateDocumentEdited();
|
||||
}
|
||||
|
||||
if (gotDirty || this.hasDirtyCount) {
|
||||
this.updateActivityBadge();
|
||||
}
|
||||
}
|
||||
|
||||
private onTextFilesDirty(e: TextFileModelChangeEvent[]): void {
|
||||
if ((this.textFileService.getAutoSaveMode() !== AutoSaveMode.AFTER_SHORT_DELAY) && !this.isDocumentedEdited) {
|
||||
this.updateDocumentEdited(); // no indication needed when auto save is enabled for short delay
|
||||
}
|
||||
|
||||
protected onTextFilesDirty(e: TextFileModelChangeEvent[]): void {
|
||||
if (this.textFileService.getAutoSaveMode() !== AutoSaveMode.AFTER_SHORT_DELAY) {
|
||||
this.updateActivityBadge(); // no indication needed when auto save is enabled for short delay
|
||||
}
|
||||
@@ -98,29 +84,17 @@ export class DirtyFilesTracker extends Disposable implements IWorkbenchContribut
|
||||
}));
|
||||
}
|
||||
|
||||
private onTextFilesSaved(e: TextFileModelChangeEvent[]): void {
|
||||
if (this.isDocumentedEdited) {
|
||||
this.updateDocumentEdited();
|
||||
}
|
||||
|
||||
protected onTextFilesSaved(e: TextFileModelChangeEvent[]): void {
|
||||
if (this.hasDirtyCount) {
|
||||
this.updateActivityBadge();
|
||||
}
|
||||
}
|
||||
|
||||
private onTextFilesSaveError(e: TextFileModelChangeEvent[]): void {
|
||||
if (!this.isDocumentedEdited) {
|
||||
this.updateDocumentEdited();
|
||||
}
|
||||
|
||||
protected onTextFilesSaveError(e: TextFileModelChangeEvent[]): void {
|
||||
this.updateActivityBadge();
|
||||
}
|
||||
|
||||
private onTextFilesReverted(e: TextFileModelChangeEvent[]): void {
|
||||
if (this.isDocumentedEdited) {
|
||||
this.updateDocumentEdited();
|
||||
}
|
||||
|
||||
protected onTextFilesReverted(e: TextFileModelChangeEvent[]): void {
|
||||
if (this.hasDirtyCount) {
|
||||
this.updateActivityBadge();
|
||||
}
|
||||
@@ -136,13 +110,4 @@ export class DirtyFilesTracker extends Disposable implements IWorkbenchContribut
|
||||
this.badgeHandle.value = this.activityService.showActivity(VIEWLET_ID, new NumberBadge(dirtyCount, num => num === 1 ? nls.localize('dirtyFile', "1 unsaved file") : nls.localize('dirtyFiles', "{0} unsaved files", dirtyCount)), 'explorer-viewlet-label');
|
||||
}
|
||||
}
|
||||
|
||||
private updateDocumentEdited(): void {
|
||||
if (platform === Platform.Mac) {
|
||||
const hasDirtyFiles = this.textFileService.isDirty();
|
||||
this.isDocumentedEdited = hasDirtyFiles;
|
||||
|
||||
this.windowService.setDocumentEdited(hasDirtyFiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
import { createMemoizer } from 'vs/base/common/decorators';
|
||||
import { dirname } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { EncodingMode, ConfirmResult, EditorInput, IFileEditorInput, ITextEditorModel, Verbosity, IRevertOptions } from 'vs/workbench/common/editor';
|
||||
@@ -28,13 +28,15 @@ const enum ForceOpenAs {
|
||||
* A file editor input is the input type for the file editor of file system resources.
|
||||
*/
|
||||
export class FileEditorInput extends EditorInput implements IFileEditorInput {
|
||||
|
||||
private static readonly MEMOIZER = createMemoizer();
|
||||
|
||||
private preferredEncoding: string;
|
||||
private preferredMode: string;
|
||||
|
||||
private forceOpenAs: ForceOpenAs = ForceOpenAs.None;
|
||||
|
||||
private textModelReference: Promise<IReference<ITextEditorModel>> | null = null;
|
||||
private name: string;
|
||||
|
||||
/**
|
||||
* An editor input who's contents are retrieved from file services.
|
||||
@@ -69,6 +71,7 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput {
|
||||
this._register(this.textFileService.models.onModelSaved(e => this.onDirtyStateChange(e)));
|
||||
this._register(this.textFileService.models.onModelReverted(e => this.onDirtyStateChange(e)));
|
||||
this._register(this.textFileService.models.onModelOrphanedChanged(e => this.onModelOrphanedChanged(e)));
|
||||
this._register(this.labelService.onDidChangeFormatters(() => FileEditorInput.MEMOIZER.clear()));
|
||||
}
|
||||
|
||||
private onDirtyStateChange(e: TextFileModelChangeEvent): void {
|
||||
@@ -144,22 +147,22 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput {
|
||||
return FILE_EDITOR_INPUT_ID;
|
||||
}
|
||||
|
||||
@FileEditorInput.MEMOIZER
|
||||
getName(): string {
|
||||
if (!this.name) {
|
||||
this.name = this.labelService.getUriBasenameLabel(this.resource);
|
||||
}
|
||||
|
||||
return this.decorateLabel(this.name);
|
||||
return this.decorateLabel(this.labelService.getUriBasenameLabel(this.resource));
|
||||
}
|
||||
|
||||
@FileEditorInput.MEMOIZER
|
||||
private get shortDescription(): string {
|
||||
return this.labelService.getUriBasenameLabel(dirname(this.resource));
|
||||
}
|
||||
|
||||
@FileEditorInput.MEMOIZER
|
||||
private get mediumDescription(): string {
|
||||
return this.labelService.getUriLabel(dirname(this.resource), { relative: true });
|
||||
}
|
||||
|
||||
@FileEditorInput.MEMOIZER
|
||||
private get longDescription(): string {
|
||||
return this.labelService.getUriLabel(dirname(this.resource));
|
||||
}
|
||||
@@ -176,17 +179,17 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput {
|
||||
}
|
||||
}
|
||||
|
||||
@memoize
|
||||
@FileEditorInput.MEMOIZER
|
||||
private get shortTitle(): string {
|
||||
return this.getName();
|
||||
}
|
||||
|
||||
@memoize
|
||||
@FileEditorInput.MEMOIZER
|
||||
private get mediumTitle(): string {
|
||||
return this.labelService.getUriLabel(this.resource, { relative: true });
|
||||
}
|
||||
|
||||
@memoize
|
||||
@FileEditorInput.MEMOIZER
|
||||
private get longTitle(): string {
|
||||
return this.labelService.getUriLabel(this.resource);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ export class ExplorerModel implements IDisposable {
|
||||
|
||||
private _roots!: ExplorerItem[];
|
||||
private _listener: IDisposable;
|
||||
private _onDidChangeRoots = new Emitter<void>();
|
||||
private readonly _onDidChangeRoots = new Emitter<void>();
|
||||
|
||||
constructor(private readonly contextService: IWorkspaceContextService) {
|
||||
const setRoots = () => this._roots = this.contextService.getWorkspace().folders
|
||||
|
||||
@@ -31,11 +31,11 @@ export class ExplorerService implements IExplorerService {
|
||||
|
||||
private static readonly EXPLORER_FILE_CHANGES_REACT_DELAY = 500; // delay in ms to react to file changes to give our internal events a chance to react first
|
||||
|
||||
private _onDidChangeRoots = new Emitter<void>();
|
||||
private _onDidChangeItem = new Emitter<{ item?: ExplorerItem, recursive: boolean }>();
|
||||
private _onDidChangeEditable = new Emitter<ExplorerItem>();
|
||||
private _onDidSelectResource = new Emitter<{ resource?: URI, reveal?: boolean }>();
|
||||
private _onDidCopyItems = new Emitter<{ items: ExplorerItem[], cut: boolean, previouslyCutItems: ExplorerItem[] | undefined }>();
|
||||
private readonly _onDidChangeRoots = new Emitter<void>();
|
||||
private readonly _onDidChangeItem = new Emitter<{ item?: ExplorerItem, recursive: boolean }>();
|
||||
private readonly _onDidChangeEditable = new Emitter<ExplorerItem>();
|
||||
private readonly _onDidSelectResource = new Emitter<{ resource?: URI, reveal?: boolean }>();
|
||||
private readonly _onDidCopyItems = new Emitter<{ items: ExplorerItem[], cut: boolean, previouslyCutItems: ExplorerItem[] | undefined }>();
|
||||
private readonly disposables = new DisposableStore();
|
||||
private editable: { stat: ExplorerItem, data: IEditableData } | undefined;
|
||||
private _sortOrder: SortOrder;
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { TextFileModelChangeEvent, ITextFileService, AutoSaveMode } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { platform, Platform } from 'vs/base/common/platform';
|
||||
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IActivityService } from 'vs/workbench/services/activity/common/activity';
|
||||
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { DirtyFilesTracker } from 'vs/workbench/contrib/files/common/dirtyFilesTracker';
|
||||
import { IElectronService } from 'vs/platform/electron/node/electron';
|
||||
|
||||
export class NativeDirtyFilesTracker extends DirtyFilesTracker {
|
||||
private isDocumentedEdited: boolean;
|
||||
|
||||
constructor(
|
||||
@ITextFileService protected readonly textFileService: ITextFileService,
|
||||
@ILifecycleService lifecycleService: ILifecycleService,
|
||||
@IEditorService editorService: IEditorService,
|
||||
@IActivityService activityService: IActivityService,
|
||||
@IUntitledEditorService protected readonly untitledEditorService: IUntitledEditorService,
|
||||
@IElectronService private readonly electronService: IElectronService
|
||||
) {
|
||||
super(textFileService, lifecycleService, editorService, activityService, untitledEditorService);
|
||||
|
||||
this.isDocumentedEdited = false;
|
||||
}
|
||||
|
||||
protected onUntitledDidChangeDirty(resource: URI): void {
|
||||
const gotDirty = this.untitledEditorService.isDirty(resource);
|
||||
if ((!this.isDocumentedEdited && gotDirty) || (this.isDocumentedEdited && !gotDirty)) {
|
||||
this.updateDocumentEdited();
|
||||
}
|
||||
|
||||
super.onUntitledDidChangeDirty(resource);
|
||||
}
|
||||
|
||||
protected onTextFilesDirty(e: TextFileModelChangeEvent[]): void {
|
||||
if ((this.textFileService.getAutoSaveMode() !== AutoSaveMode.AFTER_SHORT_DELAY) && !this.isDocumentedEdited) {
|
||||
this.updateDocumentEdited(); // no indication needed when auto save is enabled for short delay
|
||||
}
|
||||
|
||||
super.onTextFilesDirty(e);
|
||||
}
|
||||
|
||||
protected onTextFilesSaved(e: TextFileModelChangeEvent[]): void {
|
||||
if (this.isDocumentedEdited) {
|
||||
this.updateDocumentEdited();
|
||||
}
|
||||
|
||||
super.onTextFilesSaved(e);
|
||||
}
|
||||
|
||||
protected onTextFilesSaveError(e: TextFileModelChangeEvent[]): void {
|
||||
if (!this.isDocumentedEdited) {
|
||||
this.updateDocumentEdited();
|
||||
}
|
||||
|
||||
super.onTextFilesSaveError(e);
|
||||
}
|
||||
|
||||
protected onTextFilesReverted(e: TextFileModelChangeEvent[]): void {
|
||||
if (this.isDocumentedEdited) {
|
||||
this.updateDocumentEdited();
|
||||
}
|
||||
|
||||
super.onTextFilesReverted(e);
|
||||
}
|
||||
|
||||
private updateDocumentEdited(): void {
|
||||
if (platform === Platform.Mac) {
|
||||
const hasDirtyFiles = this.textFileService.isDirty();
|
||||
this.isDocumentedEdited = hasDirtyFiles;
|
||||
|
||||
this.electronService.setDocumentEdited(hasDirtyFiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
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 { NativeDirtyFilesTracker } from 'vs/workbench/contrib/files/electron-browser/dirtyFilesTracker';
|
||||
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
|
||||
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
|
||||
// Register file editor
|
||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
||||
new EditorDescriptor(
|
||||
NativeTextFileEditor,
|
||||
NativeTextFileEditor.ID,
|
||||
nls.localize('textFileEditor', "Text File Editor")
|
||||
),
|
||||
[
|
||||
new SyncDescriptor<EditorInput>(FileEditorInput)
|
||||
]
|
||||
);
|
||||
|
||||
// Register Dirty Files Tracker
|
||||
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(NativeDirtyFilesTracker, LifecyclePhase.Starting);
|
||||
@@ -0,0 +1,80 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
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 { createErrorWithActions } from 'vs/base/common/errorsWithActions';
|
||||
import { toErrorMessage } from 'vs/base/common/errorMessage';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
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';
|
||||
|
||||
/**
|
||||
* An implementation of editor for file system resources.
|
||||
*/
|
||||
export class NativeTextFileEditor extends TextFileEditor {
|
||||
|
||||
constructor(
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IFileService fileService: IFileService,
|
||||
@IViewletService viewletService: IViewletService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IWorkspaceContextService contextService: IWorkspaceContextService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@ITextResourceConfigurationService configurationService: ITextResourceConfigurationService,
|
||||
@IEditorService editorService: IEditorService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IEditorGroupsService editorGroupService: IEditorGroupsService,
|
||||
@ITextFileService textFileService: ITextFileService,
|
||||
@IElectronService private readonly electronService: IElectronService,
|
||||
@IPreferencesService private readonly preferencesService: IPreferencesService,
|
||||
@IWindowService windowService: IWindowService,
|
||||
@IExplorerService explorerService: IExplorerService
|
||||
) {
|
||||
super(telemetryService, fileService, viewletService, instantiationService, contextService, storageService, configurationService, editorService, themeService, editorGroupService, textFileService, windowService, explorerService);
|
||||
}
|
||||
|
||||
protected handleSetInputError(error: Error, input: FileEditorInput, options: EditorOptions | undefined): void {
|
||||
|
||||
// Allow to restart with higher memory limit if the file is too large
|
||||
if ((<FileOperationError>error).fileOperationResult === FileOperationResult.FILE_EXCEED_MEMORY_LIMIT) {
|
||||
const memoryLimit = Math.max(MIN_MAX_MEMORY_SIZE_MB, +this.configurationService.getValue<number>(undefined, 'files.maxMemoryForLargeFilesMB') || FALLBACK_MAX_MEMORY_SIZE_MB);
|
||||
|
||||
throw createErrorWithActions(toErrorMessage(error), {
|
||||
actions: [
|
||||
new Action('workbench.window.action.relaunchWithIncreasedMemoryLimit', nls.localize('relaunchWithIncreasedMemoryLimit', "Restart with {0} MB", memoryLimit), undefined, true, () => {
|
||||
return this.electronService.relaunch({
|
||||
addArgs: [
|
||||
`--max-memory=${memoryLimit}`
|
||||
]
|
||||
});
|
||||
}),
|
||||
new Action('workbench.window.action.configureMemoryLimit', nls.localize('configureMemoryLimit', 'Configure Memory Limit'), undefined, true, () => {
|
||||
return this.preferencesService.openGlobalSettings(undefined, { query: 'files.maxMemoryForLargeFilesMB' });
|
||||
})
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
// Fallback to handling in super type
|
||||
super.handleSetInputError(error, input, options);
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IWindowsService } from 'vs/platform/windows/common/windows';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { VIEWLET_ID as EXTENSIONS_VIEWLET_ID, IExtensionsViewlet } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||
@@ -39,7 +39,7 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IJSONEditingService private readonly jsonEditingService: IJSONEditingService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@IWindowsService private readonly windowsService: IWindowsService,
|
||||
@IHostService private readonly hostService: IHostService,
|
||||
@IStorageService private readonly storageService: IStorageService,
|
||||
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
|
||||
@IExtensionGalleryService private readonly galleryService: IExtensionGalleryService,
|
||||
@@ -81,7 +81,7 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo
|
||||
label: updateAndRestart ? localize('yes', "Yes") : localize('restart now', "Restart Now"),
|
||||
run: () => {
|
||||
const updatePromise = updateAndRestart ? this.jsonEditingService.write(this.environmentService.localeResource, [{ key: 'locale', value: locale }], true) : Promise.resolve(undefined);
|
||||
updatePromise.then(() => this.windowsService.relaunch({}), e => this.notificationService.error(e));
|
||||
updatePromise.then(() => this.hostService.restart(), e => this.notificationService.error(e));
|
||||
}
|
||||
}],
|
||||
{
|
||||
@@ -171,7 +171,7 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo
|
||||
label: translations['installAndRestart'],
|
||||
run: () => {
|
||||
logUserReaction('installAndRestart');
|
||||
this.installExtension(extensionToInstall).then(() => this.windowsService.relaunch({}));
|
||||
this.installExtension(extensionToInstall).then(() => this.hostService.restart());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -233,7 +233,7 @@ function registerLocaleDefinitionSchema(languages: string[]): void {
|
||||
jsonRegistry.registerSchema(localeDefinitionFileSchemaId, {
|
||||
id: localeDefinitionFileSchemaId,
|
||||
allowComments: true,
|
||||
allowsTrailingCommas: true,
|
||||
allowTrailingCommas: true,
|
||||
description: 'Locale Definition file',
|
||||
type: 'object',
|
||||
default: {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
|
||||
import { ILocalizationsService, LanguageType } from 'vs/platform/localizations/common/localizations';
|
||||
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing';
|
||||
import { IWindowsService } from 'vs/platform/windows/common/windows';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { language } from 'vs/base/common/platform';
|
||||
import { firstIndex } from 'vs/base/common/arrays';
|
||||
@@ -26,7 +26,7 @@ export class ConfigureLocaleAction extends Action {
|
||||
@ILocalizationsService private readonly localizationService: ILocalizationsService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@IJSONEditingService private readonly jsonEditingService: IJSONEditingService,
|
||||
@IWindowsService private readonly windowsService: IWindowsService,
|
||||
@IHostService private readonly hostService: IHostService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IViewletService private readonly viewletService: IViewletService,
|
||||
@IDialogService private readonly dialogService: IDialogService
|
||||
@@ -74,7 +74,7 @@ export class ConfigureLocaleAction extends Action {
|
||||
});
|
||||
|
||||
if (restart.confirmed) {
|
||||
this.windowsService.relaunch({});
|
||||
this.hostService.restart();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
@@ -117,7 +117,7 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
|
||||
this.rangeHighlightDecorations = this._register(this.instantiationService.createInstance(RangeHighlightDecorations));
|
||||
|
||||
// actions
|
||||
this.collapseAllAction = this._register(new Action('vs.tree.collapse', localize('collapseAll', "Collapse All"), 'monaco-tree-action codicon-collapse-all', true, async () => this.collapseAll()));
|
||||
this.collapseAllAction = this._register(new Action('vs.tree.collapse', localize('collapseAll', "Collapse All"), 'monaco-tree-action collapse-all', true, async () => this.collapseAll()));
|
||||
this.filterAction = this._register(this.instantiationService.createInstance(MarkersFilterAction, { filterText: this.panelState['filter'] || '', filterHistory: this.panelState['filterHistory'] || [], useFilesExclude: !!this.panelState['useFilesExclude'] }));
|
||||
}
|
||||
|
||||
|
||||
@@ -298,7 +298,7 @@ export class MarkersFilterActionViewItem extends BaseActionViewItem {
|
||||
export class QuickFixAction extends Action {
|
||||
|
||||
public static readonly ID: string = 'workbench.actions.problems.quickfix';
|
||||
private static readonly CLASS: string = 'markers-panel-action-quickfix';
|
||||
private static readonly CLASS: string = 'markers-panel-action-quickfix codicon-lightbulb';
|
||||
private static readonly AUTO_FIX_CLASS: string = QuickFixAction.CLASS + ' autofixable';
|
||||
|
||||
private readonly _onShowQuickFixes = this._register(new Emitter<void>());
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 9C10.3304 9 9 10.3304 9 12C9 13.6696 10.3304 15 12 15C13.6696 15 15 13.6696 15 12C15 10.3304 13.6696 9 12 9ZM11.2028 12.4712L10.704 14L12 13.024L13.3054 14L12.7972 12.4712L14 11.6394H12.5361L12 10L11.4732 11.6394H10L11.2028 12.4712Z" fill="#75BEFF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.1708 8.08474C9.85081 8.35911 8.77687 9.27684 8.28696 10.5H6.40867V12.7012C6.40867 12.7823 6.4372 12.8512 6.49888 12.9127C6.56058 12.9741 6.63007 13.0028 6.71205 13.0028H8.12487C8.21364 13.3513 8.34773 13.6809 8.52059 13.9851C8.45462 13.9951 8.38715 14 8.31823 14H6.71205C6.53223 14 6.36223 13.9663 6.20306 13.8984C6.04564 13.8311 5.90753 13.7388 5.78961 13.6213C5.67168 13.5038 5.57895 13.3661 5.51141 13.2091C5.44311 13.0503 5.40927 12.8807 5.40927 12.7012V11.1009C5.40927 10.622 5.31772 10.1795 5.13553 9.77209C4.95683 9.36336 4.69832 8.99156 4.35953 8.65806C3.92468 8.22903 3.58896 7.75003 3.35361 7.22134C3.11756 6.69107 3 6.11672 3 5.49953C3 5.08664 3.05342 4.68802 3.16048 4.30397C3.26728 3.92089 3.41907 3.56286 3.61595 3.23018C3.81257 2.89377 4.04777 2.58911 4.32146 2.31641C4.59503 2.04383 4.89858 1.80953 5.23195 1.61364C5.56979 1.41764 5.93146 1.2662 6.31578 1.15983C6.70106 1.0532 7.10094 1 7.51514 1C7.92934 1 8.32923 1.0532 8.71451 1.15983C9.09883 1.2662 9.45803 1.41739 9.79183 1.61351C10.1294 1.80938 10.4351 2.0437 10.7088 2.31641C10.9825 2.5891 11.2177 2.89376 11.4143 3.23016C11.6112 3.56285 11.763 3.92088 11.8698 4.30397C11.9769 4.68802 12.0303 5.08664 12.0303 5.49953C12.0303 6.11672 11.9127 6.69107 11.6767 7.22134C11.5412 7.52562 11.3725 7.81344 11.1708 8.08474Z" fill="#75BEFF"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -1,4 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 9C10.3304 9 9 10.3304 9 12C9 13.6696 10.3304 15 12 15C13.6696 15 15 13.6696 15 12C15 10.3304 13.6696 9 12 9ZM11.2028 12.4712L10.704 14L12 13.024L13.3054 14L12.7972 12.4712L14 11.6394H12.5361L12 10L11.4732 11.6394H10L11.2028 12.4712Z" fill="#75BEFF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.1708 8.08474C9.85081 8.35911 8.77687 9.27684 8.28696 10.5H6.40867V12.7012C6.40867 12.7823 6.4372 12.8512 6.49888 12.9127C6.56058 12.9741 6.63007 13.0028 6.71205 13.0028H8.12487C8.21364 13.3513 8.34773 13.6809 8.52059 13.9851C8.45462 13.9951 8.38715 14 8.31823 14H6.71205C6.53223 14 6.36223 13.9663 6.20306 13.8984C6.04564 13.8311 5.90753 13.7388 5.78961 13.6213C5.67168 13.5038 5.57895 13.3661 5.51141 13.2091C5.44311 13.0503 5.40927 12.8807 5.40927 12.7012V11.1009C5.40927 10.622 5.31772 10.1795 5.13553 9.77209C4.95683 9.36336 4.69832 8.99156 4.35953 8.65806C3.92468 8.22903 3.58896 7.75003 3.35361 7.22134C3.11756 6.69107 3 6.11672 3 5.49953C3 5.08664 3.05342 4.68802 3.16048 4.30397C3.26728 3.92089 3.41907 3.56286 3.61595 3.23018C3.81257 2.89377 4.04777 2.58911 4.32146 2.31641C4.59503 2.04383 4.89858 1.80953 5.23195 1.61364C5.56979 1.41764 5.93146 1.2662 6.31578 1.15983C6.70106 1.0532 7.10094 1 7.51514 1C7.92934 1 8.32923 1.0532 8.71451 1.15983C9.09883 1.2662 9.45803 1.41739 9.79183 1.61351C10.1294 1.80938 10.4351 2.0437 10.7088 2.31641C10.9825 2.5891 11.2177 2.89376 11.4143 3.23016C11.6112 3.56285 11.763 3.92088 11.8698 4.30397C11.9769 4.68802 12.0303 5.08664 12.0303 5.49953C12.0303 6.11672 11.9127 6.69107 11.6767 7.22134C11.5412 7.52562 11.3725 7.81344 11.1708 8.08474Z" fill="#75BEFF"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -1,4 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 9C10.3304 9 9 10.3304 9 12C9 13.6696 10.3304 15 12 15C13.6696 15 15 13.6696 15 12C15 10.3304 13.6696 9 12 9ZM11.2028 12.4712L10.704 14L12 13.024L13.3054 14L12.7972 12.4712L14 11.6394H12.5361L12 10L11.4732 11.6394H10L11.2028 12.4712Z" fill="#007ACC"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.1708 8.08474C9.85081 8.35911 8.77687 9.27684 8.28696 10.5H6.40867V12.7012C6.40867 12.7823 6.4372 12.8512 6.49888 12.9127C6.56058 12.9741 6.63007 13.0028 6.71205 13.0028H8.12487C8.21364 13.3513 8.34773 13.6809 8.52059 13.9851C8.45462 13.9951 8.38715 14 8.31823 14H6.71205C6.53223 14 6.36223 13.9663 6.20306 13.8984C6.04564 13.8311 5.90753 13.7388 5.78961 13.6213C5.67168 13.5038 5.57895 13.3661 5.51141 13.2091C5.44311 13.0503 5.40927 12.8807 5.40927 12.7012V11.1009C5.40927 10.622 5.31772 10.1795 5.13553 9.77209C4.95683 9.36336 4.69832 8.99156 4.35953 8.65806C3.92468 8.22903 3.58896 7.75003 3.35361 7.22134C3.11756 6.69107 3 6.11672 3 5.49953C3 5.08664 3.05342 4.68802 3.16048 4.30397C3.26728 3.92089 3.41907 3.56286 3.61595 3.23018C3.81257 2.89377 4.04777 2.58911 4.32146 2.31641C4.59503 2.04383 4.89858 1.80953 5.23195 1.61364C5.56979 1.41764 5.93146 1.2662 6.31578 1.15983C6.70106 1.0532 7.10094 1 7.51514 1C7.92934 1 8.32923 1.0532 8.71451 1.15983C9.09883 1.2662 9.45803 1.41739 9.79183 1.61351C10.1294 1.80938 10.4351 2.0437 10.7088 2.31641C10.9825 2.5891 11.2177 2.89376 11.4143 3.23016C11.6112 3.56285 11.763 3.92088 11.8698 4.30397C11.9769 4.68802 12.0303 5.08664 12.0303 5.49953C12.0303 6.11672 11.9127 6.69107 11.6767 7.22134C11.5412 7.52562 11.3725 7.81344 11.1708 8.08474Z" fill="#007ACC"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -1,3 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.6708 8.65806C11.3319 8.9916 11.0716 9.36278 10.8886 9.77172C10.7105 10.1792 10.621 10.6219 10.621 11.1009V12.7012C10.621 12.8807 10.5872 13.0503 10.5189 13.2091C10.4513 13.3661 10.3586 13.5038 10.2407 13.6213C10.1228 13.7388 9.98464 13.8311 9.82723 13.8984C9.66806 13.9663 9.49806 14 9.31823 14H7.71205C7.53223 14 7.36223 13.9663 7.20306 13.8984C7.04564 13.8311 6.90753 13.7388 6.78961 13.6213C6.67168 13.5038 6.57895 13.3661 6.51141 13.2091C6.44311 13.0503 6.40927 12.8807 6.40927 12.7012V11.1009C6.40927 10.622 6.31772 10.1795 6.13553 9.77209C5.95683 9.36336 5.69832 8.99156 5.35953 8.65806C4.92468 8.22903 4.58896 7.75003 4.35361 7.22134C4.11756 6.69107 4 6.11672 4 5.49953C4 5.08664 4.05342 4.68802 4.16048 4.30397C4.26728 3.92089 4.41907 3.56286 4.61595 3.23018C4.81257 2.89377 5.04777 2.58911 5.32146 2.31641C5.59503 2.04383 5.89858 1.80953 6.23195 1.61364C6.56979 1.41764 6.93146 1.2662 7.31578 1.15983C7.70106 1.0532 8.10094 1 8.51514 1C8.92934 1 9.32923 1.0532 9.71451 1.15983C10.0988 1.2662 10.458 1.41739 10.7918 1.61351C11.1294 1.80938 11.4351 2.0437 11.7088 2.31641C11.9825 2.5891 12.2177 2.89376 12.4143 3.23016C12.6112 3.56285 12.763 3.92088 12.8698 4.30397C12.9769 4.68802 13.0303 5.08664 13.0303 5.49953C13.0303 6.11672 12.9127 6.69107 12.6767 7.22134C12.4413 7.75003 12.1056 8.22903 11.6708 8.65806ZM9.62162 10.5H7.40867V12.7012C7.40867 12.7823 7.4372 12.8512 7.49888 12.9127C7.56058 12.9741 7.63007 13.0028 7.71205 13.0028H9.31823C9.40022 13.0028 9.46971 12.9741 9.5314 12.9127C9.59309 12.8512 9.62162 12.7823 9.62162 12.7012V10.5Z" fill="#FFCC00"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -1,3 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.6708 8.65806C11.3319 8.9916 11.0716 9.36278 10.8886 9.77172C10.7105 10.1792 10.621 10.6219 10.621 11.1009V12.7012C10.621 12.8807 10.5872 13.0503 10.5189 13.2091C10.4513 13.3661 10.3586 13.5038 10.2407 13.6213C10.1228 13.7388 9.98464 13.8311 9.82723 13.8984C9.66806 13.9663 9.49806 14 9.31823 14H7.71205C7.53223 14 7.36223 13.9663 7.20306 13.8984C7.04564 13.8311 6.90753 13.7388 6.78961 13.6213C6.67168 13.5038 6.57895 13.3661 6.51141 13.2091C6.44311 13.0503 6.40927 12.8807 6.40927 12.7012V11.1009C6.40927 10.622 6.31772 10.1795 6.13553 9.77209C5.95683 9.36336 5.69832 8.99156 5.35953 8.65806C4.92468 8.22903 4.58896 7.75003 4.35361 7.22134C4.11756 6.69107 4 6.11672 4 5.49953C4 5.08664 4.05342 4.68802 4.16048 4.30397C4.26728 3.92089 4.41907 3.56286 4.61595 3.23018C4.81257 2.89377 5.04777 2.58911 5.32146 2.31641C5.59503 2.04383 5.89858 1.80953 6.23195 1.61364C6.56979 1.41764 6.93146 1.2662 7.31578 1.15983C7.70106 1.0532 8.10094 1 8.51514 1C8.92934 1 9.32923 1.0532 9.71451 1.15983C10.0988 1.2662 10.458 1.41739 10.7918 1.61351C11.1294 1.80938 11.4351 2.0437 11.7088 2.31641C11.9825 2.5891 12.2177 2.89376 12.4143 3.23016C12.6112 3.56285 12.763 3.92088 12.8698 4.30397C12.9769 4.68802 13.0303 5.08664 13.0303 5.49953C13.0303 6.11672 12.9127 6.69107 12.6767 7.22134C12.4413 7.75003 12.1056 8.22903 11.6708 8.65806ZM9.62162 10.5H7.40867V12.7012C7.40867 12.7823 7.4372 12.8512 7.49888 12.9127C7.56058 12.9741 7.63007 13.0028 7.71205 13.0028H9.31823C9.40022 13.0028 9.46971 12.9741 9.5314 12.9127C9.59309 12.8512 9.62162 12.7823 9.62162 12.7012V10.5Z" fill="#FFCC00"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -1,4 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.6708 8.65806C11.3319 8.9916 11.0716 9.36278 10.8886 9.77172C10.7105 10.1792 10.621 10.6219 10.621 11.1009V12.7012C10.621 12.8807 10.5872 13.0503 10.5189 13.2091C10.4513 13.3661 10.3586 13.5038 10.2407 13.6213C10.1228 13.7388 9.98464 13.8311 9.82723 13.8984C9.66806 13.9663 9.49806 14 9.31823 14H7.71205C7.53223 14 7.36223 13.9663 7.20306 13.8984C7.04564 13.8311 6.90753 13.7388 6.78961 13.6213C6.67168 13.5038 6.57895 13.3661 6.51141 13.2091C6.44311 13.0503 6.40927 12.8807 6.40927 12.7012V11.1009C6.40927 10.622 6.31772 10.1795 6.13553 9.77209C5.95683 9.36336 5.69832 8.99156 5.35953 8.65806C4.92468 8.22903 4.58896 7.75003 4.35361 7.22134C4.11756 6.69107 4 6.11672 4 5.49953C4 5.08664 4.05342 4.68802 4.16048 4.30397C4.26728 3.92089 4.41907 3.56286 4.61595 3.23018C4.81257 2.89377 5.04777 2.58911 5.32146 2.31641C5.59503 2.04383 5.89858 1.80953 6.23195 1.61364C6.56979 1.41764 6.93146 1.2662 7.31578 1.15983C7.70106 1.0532 8.10094 1 8.51514 1C8.92934 1 9.32923 1.0532 9.71451 1.15983C10.0988 1.2662 10.458 1.41739 10.7918 1.61351C11.1294 1.80938 11.4351 2.0437 11.7088 2.31641C11.9825 2.5891 12.2177 2.89376 12.4143 3.23016C12.6112 3.56285 12.763 3.92088 12.8698 4.30397C12.9769 4.68802 13.0303 5.08664 13.0303 5.49953C13.0303 6.11672 12.9127 6.69107 12.6767 7.22134C12.4413 7.75003 12.1056 8.22903 11.6708 8.65806ZM9.62162 10.5H7.40867V12.7012C7.40867 12.7823 7.4372 12.8512 7.49888 12.9127C7.56058 12.9741 7.63007 13.0028 7.71205 13.0028H9.31823C9.40022 13.0028 9.46971 12.9741 9.5314 12.9127C9.59309 12.8512 9.62162 12.7823 9.62162 12.7012V10.5Z" fill="#FFCC00"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.6708 8.65806C11.3319 8.9916 11.0716 9.36278 10.8886 9.77172C10.7105 10.1792 10.621 10.6219 10.621 11.1009V12.7012C10.621 12.8807 10.5872 13.0503 10.5189 13.2091C10.4513 13.3661 10.3586 13.5038 10.2407 13.6213C10.1228 13.7388 9.98464 13.8311 9.82723 13.8984C9.66806 13.9663 9.49806 14 9.31823 14H7.71205C7.53223 14 7.36223 13.9663 7.20306 13.8984C7.04564 13.8311 6.90753 13.7388 6.78961 13.6213C6.67168 13.5038 6.57895 13.3661 6.51141 13.2091C6.44311 13.0503 6.40927 12.8807 6.40927 12.7012V11.1009C6.40927 10.622 6.31772 10.1795 6.13553 9.77209C5.95683 9.36336 5.69832 8.99156 5.35953 8.65806C4.92468 8.22903 4.58896 7.75003 4.35361 7.22134C4.11756 6.69107 4 6.11672 4 5.49953C4 5.08664 4.05342 4.68802 4.16048 4.30397C4.26728 3.92089 4.41907 3.56286 4.61595 3.23018C4.81257 2.89377 5.04777 2.58911 5.32146 2.31641C5.59503 2.04383 5.89858 1.80953 6.23195 1.61364C6.56979 1.41764 6.93146 1.2662 7.31578 1.15983C7.70106 1.0532 8.10094 1 8.51514 1C8.92934 1 9.32923 1.0532 9.71451 1.15983C10.0988 1.2662 10.458 1.41739 10.7918 1.61351C11.1294 1.80938 11.4351 2.0437 11.7088 2.31641C11.9825 2.5891 12.2177 2.89376 12.4143 3.23016C12.6112 3.56285 12.763 3.92088 12.8698 4.30397C12.9769 4.68802 13.0303 5.08664 13.0303 5.49953C13.0303 6.11672 12.9127 6.69107 12.6767 7.22134C12.4413 7.75003 12.1056 8.22903 11.6708 8.65806ZM9.62162 10.5H7.40867V12.7012C7.40867 12.7823 7.4372 12.8512 7.49888 12.9127C7.56058 12.9741 7.63007 13.0028 7.71205 13.0028H9.31823C9.40022 13.0028 9.46971 12.9741 9.5314 12.9127C9.59309 12.8512 9.62162 12.7823 9.62162 12.7012V10.5Z" fill="#DDB100"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.3 KiB |
@@ -153,31 +153,6 @@
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.markers-panel .monaco-tl-contents .actions .action-label.icon.markers-panel-action-quickfix {
|
||||
background: url('lightbulb-light.svg') center no-repeat;
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.markers-panel .monaco-tl-contents .actions .action-label.icon.markers-panel-action-quickfix.autofixable {
|
||||
background: url('lightbulb-autofix-light.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .markers-panel .monaco-tl-contents .actions .action-label.icon.markers-panel-action-quickfix {
|
||||
background: url('lightbulb-dark.svg') center no-repeat;
|
||||
}
|
||||
|
||||
.hc-black .markers-panel .monaco-tl-contents .actions .action-label.icon.markers-panel-action-quickfix {
|
||||
background: url('lightbulb-hc.svg') center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .markers-panel .monaco-tl-contents .actions .action-label.icon.markers-panel-action-quickfix.autofixable {
|
||||
background: url('lightbulb-autofix-dark.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.hc-black .markers-panel .monaco-tl-contents .actions .action-label.icon.markers-panel-action-quickfix.autofixable {
|
||||
background: url('lightbulb-autofix-hc.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.markers-panel .monaco-tl-contents .actions .monaco-action-bar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ class OutlineViewState {
|
||||
private _filterOnType = true;
|
||||
private _sortBy = OutlineSortOrder.ByKind;
|
||||
|
||||
private _onDidChange = new Emitter<{ followCursor?: boolean, sortBy?: boolean, filterOnType?: boolean }>();
|
||||
private readonly _onDidChange = new Emitter<{ followCursor?: boolean, sortBy?: boolean, filterOnType?: boolean }>();
|
||||
readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
set followCursor(value: boolean) {
|
||||
@@ -385,7 +385,7 @@ export class OutlinePanel extends ViewletPanel {
|
||||
|
||||
getActions(): IAction[] {
|
||||
return [
|
||||
new Action('collapse', localize('collapse', "Collapse All"), 'explorer-action collapse-explorer', true, () => {
|
||||
new Action('collapse', localize('collapse', "Collapse All"), 'explorer-action codicon-collapse-all', true, () => {
|
||||
return new CollapseAction(this._tree, true, undefined).run();
|
||||
})
|
||||
];
|
||||
|
||||
@@ -177,10 +177,10 @@ class PerfModelContentProvider implements ITextModelContentProvider {
|
||||
if (!times) {
|
||||
continue;
|
||||
}
|
||||
if (times.startup) {
|
||||
eager.push([id, times.startup, times.codeLoadingTime, times.activateCallTime, times.activateResolvedTime, times.activationEvent]);
|
||||
if (times.activationReason.startup) {
|
||||
eager.push([id, times.activationReason.startup, times.codeLoadingTime, times.activateCallTime, times.activateResolvedTime, times.activationReason.activationEvent, times.activationReason.extensionId.value]);
|
||||
} else {
|
||||
normal.push([id, times.startup, times.codeLoadingTime, times.activateCallTime, times.activateResolvedTime, times.activationEvent]);
|
||||
normal.push([id, times.activationReason.startup, times.codeLoadingTime, times.activateCallTime, times.activateResolvedTime, times.activationReason.activationEvent, times.activationReason.extensionId.value]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ class PerfModelContentProvider implements ITextModelContentProvider {
|
||||
if (table.length > 0) {
|
||||
md.heading(2, 'Extension Activation Stats');
|
||||
md.table(
|
||||
['Extension', 'Eager', 'Load Code', 'Call Activate', 'Finish Activate', 'Event'],
|
||||
['Extension', 'Eager', 'Load Code', 'Call Activate', 'Finish Activate', 'Event', 'By'],
|
||||
table
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IWindowsService } from 'vs/platform/windows/common/windows';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { PerfviewInput } from 'vs/workbench/contrib/performance/electron-browser/perfviewEditor';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
@@ -23,7 +22,6 @@ import { IElectronService } from 'vs/platform/electron/node/electron';
|
||||
export class StartupProfiler implements IWorkbenchContribution {
|
||||
|
||||
constructor(
|
||||
@IWindowsService private readonly _windowsService: IWindowsService,
|
||||
@IDialogService private readonly _dialogService: IDialogService,
|
||||
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
|
||||
@ITextModelService private readonly _textModelResolverService: ITextModelService,
|
||||
@@ -95,13 +93,13 @@ export class StartupProfiler implements IWorkbenchContribution {
|
||||
secondaryButton: undefined
|
||||
}).then(() => {
|
||||
// now we are ready to restart
|
||||
this._windowsService.relaunch({ removeArgs });
|
||||
this._electronService.relaunch({ removeArgs });
|
||||
});
|
||||
});
|
||||
|
||||
} else {
|
||||
// simply restart
|
||||
this._windowsService.relaunch({ removeArgs });
|
||||
this._electronService.relaunch({ removeArgs });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,7 +13,7 @@ import { ILifecycleService, StartupKind } from 'vs/platform/lifecycle/common/lif
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IUpdateService } from 'vs/platform/update/common/update';
|
||||
import { IWindowsService } from 'vs/platform/windows/common/windows';
|
||||
import { IElectronService } from 'vs/platform/electron/node/electron';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import * as files from 'vs/workbench/contrib/files/common/files';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
@@ -27,7 +27,7 @@ export class StartupTimings implements IWorkbenchContribution {
|
||||
|
||||
constructor(
|
||||
@ITimerService private readonly _timerService: ITimerService,
|
||||
@IWindowsService private readonly _windowsService: IWindowsService,
|
||||
@IElectronService private readonly _electronService: IElectronService,
|
||||
@IEditorService private readonly _editorService: IEditorService,
|
||||
@IViewletService private readonly _viewletService: IViewletService,
|
||||
@IPanelService private readonly _panelService: IPanelService,
|
||||
@@ -76,10 +76,10 @@ export class StartupTimings implements IWorkbenchContribution {
|
||||
]).then(([startupMetrics]) => {
|
||||
return promisify(appendFile)(appendTo, `${startupMetrics.ellapsed}\t${product.nameShort}\t${(product.commit || '').slice(0, 10) || '0000000000'}\t${sessionId}\t${isStandardStartup ? 'standard_start' : 'NO_standard_start'}\n`);
|
||||
}).then(() => {
|
||||
this._windowsService.quit();
|
||||
this._electronService.quit();
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this._windowsService.quit();
|
||||
this._electronService.quit();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||