Merge from vscode 70dc55955d586ebd427658b43cdb344f2047f9c2 (#6789)

This commit is contained in:
Anthony Dresser
2019-08-16 21:47:46 -07:00
committed by GitHub
parent fb26126bcb
commit 41d8663b09
79 changed files with 1815 additions and 572 deletions

View File

@@ -8,7 +8,7 @@ import * as resources from 'vs/base/common/resources';
import * as dom from 'vs/base/browser/dom';
import { IAction, Action } from 'vs/base/common/actions';
import { IDebugService, IBreakpoint, CONTEXT_BREAKPOINTS_FOCUSED, EDITOR_CONTRIBUTION_ID, State, DEBUG_SCHEME, IFunctionBreakpoint, IExceptionBreakpoint, IEnablement, IDebugEditorContribution } from 'vs/workbench/contrib/debug/common/debug';
import { ExceptionBreakpoint, FunctionBreakpoint, Breakpoint } from 'vs/workbench/contrib/debug/common/debugModel';
import { ExceptionBreakpoint, FunctionBreakpoint, Breakpoint, DataBreakpoint } from 'vs/workbench/contrib/debug/common/debugModel';
import { AddFunctionBreakpointAction, ToggleBreakpointsActivatedAction, RemoveAllBreakpointsAction, RemoveBreakpointAction, EnableAllBreakpointsAction, DisableAllBreakpointsAction, ReapplyBreakpointsAction } from 'vs/workbench/contrib/debug/browser/debugActions';
import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -74,6 +74,7 @@ export class BreakpointsView extends ViewletPanel {
this.instantiationService.createInstance(BreakpointsRenderer),
new ExceptionBreakpointsRenderer(this.debugService),
this.instantiationService.createInstance(FunctionBreakpointsRenderer),
this.instantiationService.createInstance(DataBreakpointsRenderer),
new FunctionBreakpointInputRenderer(this.debugService, this.contextViewService, this.themeService)
], {
identityProvider: { getId: (element: IEnablement) => element.getId() },
@@ -91,7 +92,7 @@ export class BreakpointsView extends ViewletPanel {
this._register(this.list.onContextMenu(this.onListContextMenu, this));
this._register(this.list.onDidOpen(e => {
this._register(this.list.onDidOpen(async e => {
let isSingleClick = false;
let isDoubleClick = false;
let isMiddleClick = false;
@@ -110,9 +111,11 @@ export class BreakpointsView extends ViewletPanel {
if (isMiddleClick) {
if (element instanceof Breakpoint) {
this.debugService.removeBreakpoints(element.getId());
await this.debugService.removeBreakpoints(element.getId());
} else if (element instanceof FunctionBreakpoint) {
this.debugService.removeFunctionBreakpoints(element.getId());
await this.debugService.removeFunctionBreakpoints(element.getId());
} else if (element instanceof DataBreakpoint) {
await this.debugService.removeDataBreakpoints(element.getId());
}
return;
}
@@ -222,14 +225,14 @@ export class BreakpointsView extends ViewletPanel {
private get elements(): IEnablement[] {
const model = this.debugService.getModel();
const elements = (<ReadonlyArray<IEnablement>>model.getExceptionBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getBreakpoints());
const elements = (<ReadonlyArray<IEnablement>>model.getExceptionBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getDataBreakpoints()).concat(model.getBreakpoints());
return elements;
}
private getExpandedBodySize(): number {
const model = this.debugService.getModel();
const length = model.getBreakpoints().length + model.getExceptionBreakpoints().length + model.getFunctionBreakpoints().length;
const length = model.getBreakpoints().length + model.getExceptionBreakpoints().length + model.getFunctionBreakpoints().length + model.getDataBreakpoints().length;
return Math.min(BreakpointsView.MAX_VISIBLE_FILES, length) * 22;
}
}
@@ -259,6 +262,9 @@ class BreakpointsDelegate implements IListVirtualDelegate<IEnablement> {
if (element instanceof ExceptionBreakpoint) {
return ExceptionBreakpointsRenderer.ID;
}
if (element instanceof DataBreakpoint) {
return DataBreakpointsRenderer.ID;
}
return '';
}
@@ -454,6 +460,61 @@ class FunctionBreakpointsRenderer implements IListRenderer<FunctionBreakpoint, I
}
}
class DataBreakpointsRenderer implements IListRenderer<DataBreakpoint, IBaseBreakpointWithIconTemplateData> {
constructor(
@IDebugService private readonly debugService: IDebugService
) {
// noop
}
static readonly ID = 'databreakpoints';
get templateId() {
return DataBreakpointsRenderer.ID;
}
renderTemplate(container: HTMLElement): IBaseBreakpointWithIconTemplateData {
const data: IBreakpointTemplateData = Object.create(null);
data.breakpoint = dom.append(container, $('.breakpoint'));
data.icon = $('.icon');
data.checkbox = createCheckbox();
data.toDispose = [];
data.toDispose.push(dom.addStandardDisposableListener(data.checkbox, 'change', (e) => {
this.debugService.enableOrDisableBreakpoints(!data.context.enabled, data.context);
}));
dom.append(data.breakpoint, data.icon);
dom.append(data.breakpoint, data.checkbox);
data.name = dom.append(data.breakpoint, $('span.name'));
return data;
}
renderElement(dataBreakpoint: DataBreakpoint, index: number, data: IBaseBreakpointWithIconTemplateData): void {
data.context = dataBreakpoint;
data.name.textContent = dataBreakpoint.label;
const { className, message } = getBreakpointMessageAndClassName(this.debugService, dataBreakpoint);
data.icon.className = className + ' icon';
data.icon.title = message ? message : '';
data.checkbox.checked = dataBreakpoint.enabled;
data.breakpoint.title = dataBreakpoint.label;
// Mark function breakpoints as disabled if deactivated or if debug type does not support them #9099
const session = this.debugService.getViewModel().focusedSession;
dom.toggleClass(data.breakpoint, 'disabled', (session && !session.capabilities.supportsDataBreakpoints) || !this.debugService.getModel().areBreakpointsActivated());
if (session && !session.capabilities.supportsDataBreakpoints) {
data.breakpoint.title = nls.localize('dataBreakpointsNotSupported', "Data breakpoints are not supported by this debug type");
}
}
disposeTemplate(templateData: IBaseBreakpointWithIconTemplateData): void {
dispose(templateData.toDispose);
}
}
class FunctionBreakpointInputRenderer implements IListRenderer<IFunctionBreakpoint, IInputTemplateData> {
constructor(
@@ -572,7 +633,7 @@ export function openBreakpointSource(breakpoint: IBreakpoint, sideBySide: boolea
}, sideBySide ? SIDE_GROUP : ACTIVE_GROUP);
}
export function getBreakpointMessageAndClassName(debugService: IDebugService, breakpoint: IBreakpoint | FunctionBreakpoint): { message?: string, className: string } {
export function getBreakpointMessageAndClassName(debugService: IDebugService, breakpoint: IBreakpoint | FunctionBreakpoint | DataBreakpoint): { message?: string, className: string } {
const state = debugService.state;
const debugActive = state === State.Running || state === State.Stopped;
@@ -584,7 +645,7 @@ export function getBreakpointMessageAndClassName(debugService: IDebugService, br
}
const appendMessage = (text: string): string => {
return !(breakpoint instanceof FunctionBreakpoint) && breakpoint.message ? text.concat(', ' + breakpoint.message) : text;
return !(breakpoint instanceof FunctionBreakpoint) && !(breakpoint instanceof DataBreakpoint) && breakpoint.message ? text.concat(', ' + breakpoint.message) : text;
};
if (debugActive && !breakpoint.verified) {
return {
@@ -607,6 +668,19 @@ export function getBreakpointMessageAndClassName(debugService: IDebugService, br
};
}
if (breakpoint instanceof DataBreakpoint) {
if (session && !session.capabilities.supportsDataBreakpoints) {
return {
className: 'debug-data-breakpoint-unverified',
message: nls.localize('dataBreakpointUnsupported', "Data breakpoints not supported by this debug type"),
};
}
return {
className: 'debug-data-breakpoint',
};
}
if (breakpoint.logMessage || breakpoint.condition || breakpoint.hitCondition) {
const messages: string[] = [];
if (breakpoint.logMessage) {

View File

@@ -9,7 +9,7 @@ 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';
import { Variable, Breakpoint } from 'vs/workbench/contrib/debug/common/debugModel';
import { Variable, Breakpoint, FunctionBreakpoint } from 'vs/workbench/contrib/debug/common/debugModel';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { INotificationService } from 'vs/platform/notification/common/notification';
@@ -191,7 +191,7 @@ export class RemoveBreakpointAction extends AbstractDebugAction {
public run(breakpoint: IBreakpoint): Promise<any> {
return breakpoint instanceof Breakpoint ? this.debugService.removeBreakpoints(breakpoint.getId())
: this.debugService.removeFunctionBreakpoints(breakpoint.getId());
: breakpoint instanceof FunctionBreakpoint ? this.debugService.removeFunctionBreakpoints(breakpoint.getId()) : this.debugService.removeDataBreakpoints(breakpoint.getId());
}
}
@@ -205,7 +205,7 @@ export class RemoveAllBreakpointsAction extends AbstractDebugAction {
}
public run(): Promise<any> {
return Promise.all([this.debugService.removeBreakpoints(), this.debugService.removeFunctionBreakpoints()]);
return Promise.all([this.debugService.removeBreakpoints(), this.debugService.removeFunctionBreakpoints(), this.debugService.removeDataBreakpoints()]);
}
protected isEnabled(state: State): boolean {

View File

@@ -10,7 +10,7 @@ import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/co
import { IListService } from 'vs/platform/list/browser/listService';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IDebugService, IEnablement, CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_VARIABLES_FOCUSED, EDITOR_CONTRIBUTION_ID, IDebugEditorContribution, CONTEXT_IN_DEBUG_MODE, CONTEXT_EXPRESSION_SELECTED, CONTEXT_BREAKPOINT_SELECTED, IConfig, IStackFrame, IThread, IDebugSession, CONTEXT_DEBUG_STATE, REPL_ID, IDebugConfiguration, CONTEXT_JUMP_TO_CURSOR_SUPPORTED } from 'vs/workbench/contrib/debug/common/debug';
import { Expression, Variable, Breakpoint, FunctionBreakpoint, Thread } from 'vs/workbench/contrib/debug/common/debugModel';
import { Expression, Variable, Breakpoint, FunctionBreakpoint, Thread, DataBreakpoint } from 'vs/workbench/contrib/debug/common/debugModel';
import { IExtensionsViewlet, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { ICodeEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser';
@@ -410,6 +410,8 @@ export function registerCommands(): void {
debugService.removeBreakpoints(element.getId());
} else if (element instanceof FunctionBreakpoint) {
debugService.removeFunctionBreakpoints(element.getId());
} else if (element instanceof DataBreakpoint) {
debugService.removeDataBreakpoints(element.getId());
}
}
}

View File

@@ -18,7 +18,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { FileChangesEvent, FileChangeType, IFileService } from 'vs/platform/files/common/files';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { DebugModel, ExceptionBreakpoint, FunctionBreakpoint, Breakpoint, Expression } from 'vs/workbench/contrib/debug/common/debugModel';
import { DebugModel, ExceptionBreakpoint, FunctionBreakpoint, Breakpoint, Expression, DataBreakpoint } from 'vs/workbench/contrib/debug/common/debugModel';
import { ViewModel } from 'vs/workbench/contrib/debug/common/debugViewModel';
import * as debugactions from 'vs/workbench/contrib/debug/browser/debugActions';
import { ConfigurationManager } from 'vs/workbench/contrib/debug/browser/debugConfigurationManager';
@@ -52,6 +52,7 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation';
const DEBUG_BREAKPOINTS_KEY = 'debug.breakpoint';
const DEBUG_BREAKPOINTS_ACTIVATED_KEY = 'debug.breakpointactivated';
const DEBUG_FUNCTION_BREAKPOINTS_KEY = 'debug.functionbreakpoint';
const DEBUG_DATA_BREAKPOINTS_KEY = 'debug.databreakpoint';
const DEBUG_EXCEPTION_BREAKPOINTS_KEY = 'debug.exceptionbreakpoint';
const DEBUG_WATCH_EXPRESSIONS_KEY = 'debug.watchexpressions';
@@ -129,7 +130,7 @@ export class DebugService implements IDebugService {
this.inDebugMode = CONTEXT_IN_DEBUG_MODE.bindTo(contextKeyService);
this.model = new DebugModel(this.loadBreakpoints(), this.storageService.getBoolean(DEBUG_BREAKPOINTS_ACTIVATED_KEY, StorageScope.WORKSPACE, true), this.loadFunctionBreakpoints(),
this.loadExceptionBreakpoints(), this.loadWatchExpressions(), this.textFileService);
this.loadExceptionBreakpoints(), this.loadDataBreakpoints(), this.loadWatchExpressions(), this.textFileService);
this.toDispose.push(this.model);
this.viewModel = new ViewModel(contextKeyService);
@@ -851,6 +852,8 @@ export class DebugService implements IDebugService {
await this.sendBreakpoints(breakpoint.uri);
} else if (breakpoint instanceof FunctionBreakpoint) {
await this.sendFunctionBreakpoints();
} else if (breakpoint instanceof DataBreakpoint) {
await this.sendDataBreakpoints();
} else {
await this.sendExceptionBreakpoints();
}
@@ -920,6 +923,19 @@ export class DebugService implements IDebugService {
this.storeBreakpoints();
}
async addDataBreakpoint(label: string, dataId: string, canPersist: boolean): Promise<void> {
this.model.addDataBreakpoint(label, dataId, canPersist);
await this.sendDataBreakpoints();
this.storeBreakpoints();
}
async removeDataBreakpoints(id?: string): Promise<void> {
this.model.removeDataBreakpoints(id);
await this.sendDataBreakpoints();
this.storeBreakpoints();
}
sendAllBreakpoints(session?: IDebugSession): Promise<any> {
return Promise.all(distinct(this.model.getBreakpoints(), bp => bp.uri.toString()).map(bp => this.sendBreakpoints(bp.uri, false, session)))
.then(() => this.sendFunctionBreakpoints(session))
@@ -943,6 +959,14 @@ export class DebugService implements IDebugService {
});
}
private sendDataBreakpoints(session?: IDebugSession): Promise<void> {
const breakpointsToSend = this.model.getDataBreakpoints().filter(fbp => fbp.enabled && this.model.areBreakpointsActivated());
return this.sendToOneOrAllSessions(session, s => {
return s.capabilities.supportsDataBreakpoints ? s.sendDataBreakpoints(breakpointsToSend) : Promise.resolve(undefined);
});
}
private sendExceptionBreakpoints(session?: IDebugSession): Promise<void> {
const enabledExceptionBps = this.model.getExceptionBreakpoints().filter(exb => exb.enabled);
@@ -1006,6 +1030,17 @@ export class DebugService implements IDebugService {
return result || [];
}
private loadDataBreakpoints(): DataBreakpoint[] {
let result: DataBreakpoint[] | undefined;
try {
result = JSON.parse(this.storageService.get(DEBUG_DATA_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((dbp: any) => {
return new DataBreakpoint(dbp.label, dbp.dataId, true, dbp.enabled, dbp.hitCondition, dbp.condition, dbp.logMessage);
});
} catch (e) { }
return result || [];
}
private loadWatchExpressions(): Expression[] {
let result: Expression[] | undefined;
try {
@@ -1041,6 +1076,13 @@ export class DebugService implements IDebugService {
this.storageService.remove(DEBUG_FUNCTION_BREAKPOINTS_KEY, StorageScope.WORKSPACE);
}
const dataBreakpoints = this.model.getDataBreakpoints().filter(dbp => dbp.canPersist);
if (dataBreakpoints.length) {
this.storageService.store(DEBUG_DATA_BREAKPOINTS_KEY, JSON.stringify(dataBreakpoints), StorageScope.WORKSPACE);
} else {
this.storageService.remove(DEBUG_DATA_BREAKPOINTS_KEY, StorageScope.WORKSPACE);
}
const exceptionBreakpoints = this.model.getExceptionBreakpoints();
if (exceptionBreakpoints.length) {
this.storageService.store(DEBUG_EXCEPTION_BREAKPOINTS_KEY, JSON.stringify(exceptionBreakpoints), StorageScope.WORKSPACE);

View File

@@ -12,7 +12,7 @@ import { Event, Emitter } from 'vs/base/common/event';
import { CompletionItem, completionKindFromString } from 'vs/editor/common/modes';
import { Position } 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 } 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 } 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';
@@ -327,6 +327,34 @@ export class DebugSession implements IDebugSession {
return Promise.reject(new Error('no debug adapter'));
}
dataBreakpointInfo(name: string, variablesReference?: number): Promise<{ dataId: string | null, description: string, canPersist?: boolean }> {
if (this.raw) {
if (this.raw.readyForBreakpoints) {
return this.raw.dataBreakpointInfo({ name, variablesReference }).then(response => response.body);
}
return Promise.reject(new Error(nls.localize('sessionNotReadyForBreakpoints', "Session is not ready for breakpoints")));
}
return Promise.reject(new Error('no debug adapter'));
}
sendDataBreakpoints(dataBreakpoints: IDataBreakpoint[]): Promise<void> {
if (this.raw) {
if (this.raw.readyForBreakpoints) {
return this.raw.setDataBreakpoints({ breakpoints: dataBreakpoints }).then(response => {
if (response && response.body) {
const data = new Map<string, DebugProtocol.Breakpoint>();
for (let i = 0; i < dataBreakpoints.length; i++) {
data.set(dataBreakpoints[i].getId(), response.body.breakpoints[i]);
}
this.model.setBreakpointSessionData(this.getId(), data);
}
});
}
return Promise.resolve(undefined);
}
return Promise.reject(new Error('no debug adapter'));
}
customRequest(request: string, args: any): Promise<DebugProtocol.Response> {
if (this.raw) {
return this.raw.custom(request, args);

View File

@@ -357,6 +357,20 @@ export class RawDebugSession {
return Promise.reject(new Error('setFunctionBreakpoints not supported'));
}
dataBreakpointInfo(args: DebugProtocol.DataBreakpointInfoArguments): Promise<DebugProtocol.DataBreakpointInfoResponse> {
if (this.capabilities.supportsDataBreakpoints) {
return this.send<DebugProtocol.DataBreakpointInfoResponse>('dataBreakpointInfo', args);
}
return Promise.reject(new Error('dataBreakpointInfo not supported'));
}
setDataBreakpoints(args: DebugProtocol.SetDataBreakpointsArguments): Promise<DebugProtocol.SetDataBreakpointsResponse> {
if (this.capabilities.supportsDataBreakpoints) {
return this.send<DebugProtocol.SetDataBreakpointsResponse>('setDataBreakpoints', args);
}
return Promise.reject(new Error('setDataBreakpoints not supported'));
}
setExceptionBreakpoints(args: DebugProtocol.SetExceptionBreakpointsArguments): Promise<DebugProtocol.SetExceptionBreakpointsResponse> {
return this.send<DebugProtocol.SetExceptionBreakpointsResponse>('setExceptionBreakpoints', args);
}

View File

@@ -123,7 +123,7 @@ export class VariablesView extends ViewletPanel {
this.tree.updateChildren();
}));
this._register(this.tree.onMouseDblClick(e => this.onMouseDblClick(e)));
this._register(this.tree.onContextMenu(e => this.onContextMenu(e)));
this._register(this.tree.onContextMenu(async e => await this.onContextMenu(e)));
this._register(this.onDidChangeBodyVisibility(visible => {
if (visible && this.needsRefresh) {
@@ -152,7 +152,7 @@ export class VariablesView extends ViewletPanel {
}
}
private onContextMenu(e: ITreeContextMenuEvent<IExpression | IScope>): void {
private async onContextMenu(e: ITreeContextMenuEvent<IExpression | IScope>): Promise<void> {
const variable = e.element;
if (variable instanceof Variable && !!variable.value) {
const actions: IAction[] = [];
@@ -174,6 +174,16 @@ export class VariablesView extends ViewletPanel {
return Promise.resolve(undefined);
}));
}
if (session && session.capabilities.supportsDataBreakpoints) {
const response = await session.dataBreakpointInfo(variable.name, variable.parent.reference);
const dataid = response.dataId;
if (dataid) {
actions.push(new Separator());
actions.push(new Action('debug.addDataBreakpoint', nls.localize('setDataBreakpoint', "Set Data Breakpoint"), undefined, true, () => {
return this.debugService.addDataBreakpoint(response.description, dataid, !!response.canPersist);
}));
}
}
this.contextMenuService.showContextMenu({
getAnchor: () => e.anchor,

View File

@@ -103,6 +103,7 @@ export interface IReplElementSource {
export interface IExpressionContainer extends ITreeElement {
readonly hasChildren: boolean;
getChildren(): Promise<IExpression[]>;
readonly reference?: number;
}
export interface IExpression extends IReplElement, IExpressionContainer {
@@ -201,6 +202,8 @@ export interface IDebugSession extends ITreeElement {
sendBreakpoints(modelUri: uri, bpts: IBreakpoint[], sourceModified: boolean): Promise<void>;
sendFunctionBreakpoints(fbps: IFunctionBreakpoint[]): Promise<void>;
dataBreakpointInfo(name: string, variablesReference?: number): Promise<{ dataId: string | null, description: string, canPersist?: boolean }>;
sendDataBreakpoints(dbps: IDataBreakpoint[]): Promise<void>;
sendExceptionBreakpoints(exbpts: IExceptionBreakpoint[]): Promise<void>;
stackTrace(threadId: number, startFrame: number, levels: number): Promise<DebugProtocol.StackTraceResponse>;
@@ -357,6 +360,12 @@ export interface IExceptionBreakpoint extends IEnablement {
readonly label: string;
}
export interface IDataBreakpoint extends IBaseBreakpoint {
readonly label: string;
readonly dataId: string;
readonly canPersist: boolean;
}
export interface IExceptionInfo {
readonly id?: string;
readonly description?: string;
@@ -404,6 +413,7 @@ export interface IDebugModel extends ITreeElement {
getBreakpoints(filter?: { uri?: uri, lineNumber?: number, column?: number, enabledOnly?: boolean }): ReadonlyArray<IBreakpoint>;
areBreakpointsActivated(): boolean;
getFunctionBreakpoints(): ReadonlyArray<IFunctionBreakpoint>;
getDataBreakpoints(): ReadonlyArray<IDataBreakpoint>;
getExceptionBreakpoints(): ReadonlyArray<IExceptionBreakpoint>;
getWatchExpressions(): ReadonlyArray<IExpression & IEvaluate>;
@@ -416,9 +426,9 @@ export interface IDebugModel extends ITreeElement {
* An event describing a change to the set of [breakpoints](#debug.Breakpoint).
*/
export interface IBreakpointsChangeEvent {
added?: Array<IBreakpoint | IFunctionBreakpoint>;
removed?: Array<IBreakpoint | IFunctionBreakpoint>;
changed?: Array<IBreakpoint | IFunctionBreakpoint>;
added?: Array<IBreakpoint | IFunctionBreakpoint | IDataBreakpoint>;
removed?: Array<IBreakpoint | IFunctionBreakpoint | IDataBreakpoint>;
changed?: Array<IBreakpoint | IFunctionBreakpoint | IDataBreakpoint>;
sessionOnly?: boolean;
}
@@ -754,6 +764,17 @@ export interface IDebugService {
*/
removeFunctionBreakpoints(id?: string): Promise<void>;
/**
* Adds a new data breakpoint.
*/
addDataBreakpoint(label: string, dataId: string, canPersist: boolean): Promise<void>;
/**
* Removes all data breakpoints. If id is passed only removes the data breakpoint with the passed id.
* Notifies debug adapter of breakpoint changes.
*/
removeDataBreakpoints(id?: string): Promise<void>;
/**
* Sends all breakpoints to the passed session.
* If session is not passed, sends all breakpoints to each session.

View File

@@ -16,7 +16,7 @@ import { distinct, lastIndex } from 'vs/base/common/arrays';
import { Range, IRange } from 'vs/editor/common/core/range';
import {
ITreeElement, IExpression, IExpressionContainer, IDebugSession, IStackFrame, IExceptionBreakpoint, IBreakpoint, IFunctionBreakpoint, IDebugModel, IReplElementSource,
IThread, IRawModelUpdate, IScope, IRawStoppedDetails, IEnablement, IBreakpointData, IExceptionInfo, IReplElement, IBreakpointsChangeEvent, IBreakpointUpdateData, IBaseBreakpoint, State
IThread, IRawModelUpdate, IScope, IRawStoppedDetails, IEnablement, IBreakpointData, IExceptionInfo, IReplElement, IBreakpointsChangeEvent, IBreakpointUpdateData, IBaseBreakpoint, State, IDataBreakpoint
} from 'vs/workbench/contrib/debug/common/debug';
import { Source, UNKNOWN_SOURCE_LABEL } from 'vs/workbench/contrib/debug/common/debugSource';
import { commonSuffixLength } from 'vs/base/common/strings';
@@ -735,6 +735,34 @@ export class FunctionBreakpoint extends BaseBreakpoint implements IFunctionBreak
}
}
export class DataBreakpoint extends BaseBreakpoint implements IDataBreakpoint {
constructor(
public label: string,
public dataId: string,
public canPersist: boolean,
enabled: boolean,
hitCondition: string | undefined,
condition: string | undefined,
logMessage: string | undefined,
id = generateUuid()
) {
super(enabled, hitCondition, condition, logMessage, id);
}
toJSON(): any {
const result = super.toJSON();
result.label = this.label;
result.dataid = this.dataId;
return result;
}
toString(): string {
return this.label;
}
}
export class ExceptionBreakpoint extends Enablement implements IExceptionBreakpoint {
constructor(public filter: string, public label: string, enabled: boolean) {
@@ -778,6 +806,7 @@ export class DebugModel implements IDebugModel {
private breakpointsActivated: boolean,
private functionBreakpoints: FunctionBreakpoint[],
private exceptionBreakpoints: ExceptionBreakpoint[],
private dataBreakopints: DataBreakpoint[],
private watchExpressions: Expression[],
private textFileService: ITextFileService
) {
@@ -918,6 +947,10 @@ export class DebugModel implements IDebugModel {
return this.functionBreakpoints;
}
getDataBreakpoints(): IDataBreakpoint[] {
return this.dataBreakopints;
}
getExceptionBreakpoints(): IExceptionBreakpoint[] {
return this.exceptionBreakpoints;
}
@@ -991,6 +1024,12 @@ export class DebugModel implements IDebugModel {
fbp.setSessionData(sessionId, fbpData);
}
});
this.dataBreakopints.forEach(dbp => {
const dbpData = data.get(dbp.getId());
if (dbpData) {
dbp.setSessionData(sessionId, dbpData);
}
});
this._onDidChangeBreakpoints.fire({
sessionOnly: true
@@ -1001,6 +1040,7 @@ export class DebugModel implements IDebugModel {
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
@@ -1038,7 +1078,7 @@ export class DebugModel implements IDebugModel {
}
enableOrDisableAllBreakpoints(enable: boolean): void {
const changed: Array<IBreakpoint | IFunctionBreakpoint> = [];
const changed: Array<IBreakpoint | IFunctionBreakpoint | IDataBreakpoint> = [];
this.breakpoints.forEach(bp => {
if (bp.enabled !== enable) {
@@ -1052,6 +1092,12 @@ export class DebugModel implements IDebugModel {
}
fbp.enabled = enable;
});
this.dataBreakopints.forEach(dbp => {
if (dbp.enabled !== enable) {
changed.push(dbp);
}
dbp.enabled = enable;
});
this._onDidChangeBreakpoints.fire({ changed: changed });
}
@@ -1073,7 +1119,6 @@ export class DebugModel implements IDebugModel {
}
removeFunctionBreakpoints(id?: string): void {
let removed: FunctionBreakpoint[];
if (id) {
removed = this.functionBreakpoints.filter(fbp => fbp.getId() === id);
@@ -1082,7 +1127,25 @@ export class DebugModel implements IDebugModel {
removed = this.functionBreakpoints;
this.functionBreakpoints = [];
}
this._onDidChangeBreakpoints.fire({ removed: removed });
this._onDidChangeBreakpoints.fire({ removed });
}
addDataBreakpoint(label: string, dataId: string, canPersist: boolean): void {
const newDataBreakpoint = new DataBreakpoint(label, dataId, canPersist, true, undefined, undefined, undefined);
this.dataBreakopints.push(newDataBreakpoint);
this._onDidChangeBreakpoints.fire({ added: [newDataBreakpoint] });
}
removeDataBreakpoints(id?: string): void {
let removed: DataBreakpoint[];
if (id) {
removed = this.dataBreakopints.filter(fbp => fbp.getId() === id);
this.dataBreakopints = this.dataBreakopints.filter(fbp => fbp.getId() !== id);
} else {
removed = this.dataBreakopints;
this.dataBreakopints = [];
}
this._onDidChangeBreakpoints.fire({ removed });
}
getWatchExpressions(): Expression[] {

View File

@@ -23,7 +23,7 @@ suite('Debug - Model', () => {
let rawSession: MockRawSession;
setup(() => {
model = new DebugModel([], true, [], [], [], <any>{ isDirty: (e: any) => false });
model = new DebugModel([], true, [], [], [], [], <any>{ isDirty: (e: any) => false });
rawSession = new MockRawSession();
});

View File

@@ -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 } 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 } 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 } 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';
@@ -79,6 +79,13 @@ export class MockDebugService implements IDebugService {
throw new Error('not implemented');
}
addDataBreakpoint(label: string, dataId: string, canPersist: boolean): Promise<void> {
throw new Error('Method not implemented.');
}
removeDataBreakpoints(id?: string | undefined): Promise<void> {
throw new Error('Method not implemented.');
}
public addReplExpression(name: string): Promise<void> {
throw new Error('not implemented');
}
@@ -125,6 +132,13 @@ export class MockDebugService implements IDebugService {
}
export class MockSession implements IDebugSession {
dataBreakpointInfo(name: string, variablesReference?: number | undefined): Promise<{ dataId: string | null; description: string; canPersist?: boolean | undefined; }> {
throw new Error('Method not implemented.');
}
sendDataBreakpoints(dbps: IDataBreakpoint[]): Promise<void> {
throw new Error('Method not implemented.');
}
subId: string | undefined;

View File

@@ -47,7 +47,7 @@ import { timeout } from 'vs/base/common/async';
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry'; // {{SQL CARBON EDIT}}
import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys'; // {{SQL CARBON EDIT}}
import { IWorkspaceStatsService } from 'vs/workbench/contrib/stats/common/workspaceStats';
import { Platform, setImmediate } from 'vs/base/common/platform';
import { setImmediate, isWeb } from 'vs/base/common/platform';
import { platform, env as processEnv } from 'vs/base/common/process';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
@@ -996,7 +996,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
* If user has any of the tools listed in this.productService.exeBasedExtensionTips, fetch corresponding recommendations
*/
private async fetchExecutableRecommendations(important: boolean): Promise<void> {
if (Platform.Web) {
if (isWeb) {
return;
}

View File

@@ -144,7 +144,7 @@ class Extension implements IExtension {
private get localIconUrl(): string | null {
if (this.local && this.local.manifest.icon) {
return asDomUri(resources.joinPath(this.local.location, this.local.manifest.icon)).toString();
return asDomUri(resources.joinPath(this.local.location, this.local.manifest.icon)).toString(true);
}
return null;
}

View File

@@ -236,7 +236,6 @@ class ResolveSaveConflictAction extends Action {
@IEditorService private readonly editorService: IEditorService,
@INotificationService private readonly notificationService: INotificationService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IStorageService private readonly storageService: IStorageService,
@IEnvironmentService private readonly environmentService: IEnvironmentService
) {
super('workbench.files.action.resolveConflict', nls.localize('compareChanges', "Compare"));
@@ -250,21 +249,15 @@ class ResolveSaveConflictAction extends Action {
await TextFileContentProvider.open(resource, CONFLICT_RESOLUTION_SCHEME, editorLabel, this.editorService, { pinned: true });
if (this.storageService.getBoolean(LEARN_MORE_DIRTY_WRITE_IGNORE_KEY, StorageScope.GLOBAL)) {
return; // return if this message is ignored
}
// Show additional help how to resolve the save conflict
const primaryActions: IAction[] = [
this.instantiationService.createInstance(ResolveConflictLearnMoreAction)
];
const secondaryActions: IAction[] = [
this.instantiationService.createInstance(DoNotShowResolveConflictLearnMoreAction)
];
const actions: INotificationActions = { primary: primaryActions, secondary: secondaryActions };
const handle = this.notificationService.notify({ severity: Severity.Info, message: conflictEditorHelp, actions });
Event.once(handle.onDidClose)(() => { dispose(primaryActions); dispose(secondaryActions); });
const actions: INotificationActions = { primary: [this.instantiationService.createInstance(ResolveConflictLearnMoreAction)] };
const handle = this.notificationService.notify({
severity: Severity.Info,
message: conflictEditorHelp,
actions,
neverShowAgain: { id: LEARN_MORE_DIRTY_WRITE_IGNORE_KEY, isSecondary: true }
});
Event.once(handle.onDidClose)(() => dispose(actions.primary!));
pendingResolveSaveConflictMessages.push(handle);
}

View File

@@ -218,56 +218,46 @@ export class FilesRenderer implements ITreeRenderer<ExplorerItem, FuzzyScore, IF
const lastDot = value.lastIndexOf('.');
inputBox.value = value;
inputBox.focus();
inputBox.select({ start: 0, end: lastDot > 0 && !stat.isDirectory ? lastDot : value.length });
let isFinishableDisposeEvent = false;
setTimeout(() => {
// Check if disposed
if (!inputBox.inputElement) {
return;
}
inputBox.focus();
inputBox.select({ start: 0, end: lastDot > 0 && !stat.isDirectory ? lastDot : value.length });
isFinishableDisposeEvent = true;
}, 0);
const done = once(async (success: boolean) => {
const done = once(async (success: boolean, blur: boolean) => {
label.element.style.display = 'none';
const value = inputBox.value;
dispose(toDispose);
label.element.remove();
// Timeout: once done rendering only then re-render #70902
setTimeout(() => editableData.onFinish(value, success), 0);
container.removeChild(label.element);
editableData.onFinish(value, success);
});
const blurDisposable = DOM.addDisposableListener(inputBox.inputElement, DOM.EventType.BLUR, () => {
done(inputBox.isInputValid());
});
// It can happen that the tree re-renders this node. When that happens,
// we're gonna get a blur event first and only after an element disposable.
// Because of that, we should setTimeout the blur handler to differentiate
// between the blur happening because of a unrender or because of a user action.
let ignoreBlur = false;
const toDispose = [
inputBox,
DOM.addStandardDisposableListener(inputBox.inputElement, DOM.EventType.KEY_DOWN, (e: IKeyboardEvent) => {
if (e.equals(KeyCode.Enter)) {
if (inputBox.validate()) {
done(true);
done(true, false);
}
} else if (e.equals(KeyCode.Escape)) {
done(false);
done(false, false);
}
}),
blurDisposable,
DOM.addDisposableListener(inputBox.inputElement, DOM.EventType.BLUR, () => {
setTimeout(() => {
if (!ignoreBlur) {
done(inputBox.isInputValid(), true);
}
}, 0);
}),
label,
styler
];
return toDisposable(() => {
if (isFinishableDisposeEvent) {
done(false);
}
else {
dispose(toDispose);
label.element.remove();
}
});
return toDisposable(() => ignoreBlur = true);
}
disposeElement?(element: ITreeNode<ExplorerItem, FuzzyScore>, index: number, templateData: IFileTemplateData): void {

View File

@@ -68,8 +68,7 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo
}
private onDidInstallExtension(e: DidInstallExtensionEvent): void {
const donotAskUpdateKey = 'langugage.update.donotask';
if (!this.storageService.getBoolean(donotAskUpdateKey, StorageScope.GLOBAL) && e.local && e.operation === InstallOperation.Install && e.local.manifest.contributes && e.local.manifest.contributes.localizations && e.local.manifest.contributes.localizations.length) {
if (e.local && e.operation === InstallOperation.Install && e.local.manifest.contributes && e.local.manifest.contributes.localizations && e.local.manifest.contributes.localizations.length) {
const locale = e.local.manifest.contributes.localizations[0].languageId;
if (platform.language !== locale) {
const updateAndRestart = platform.locale !== locale;
@@ -83,12 +82,11 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo
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));
}
}, {
label: localize('neverAgain', "Don't Show Again"),
isSecondary: true,
run: () => this.storageService.store(donotAskUpdateKey, true, StorageScope.GLOBAL)
}],
{ sticky: true }
{
sticky: true,
neverShowAgain: { id: 'langugage.update.donotask', isSecondary: true }
}
);
}
}
@@ -302,4 +300,4 @@ ExtensionsRegistry.registerExtensionPoint({
}
}
}
});
});

View File

@@ -168,13 +168,14 @@ class InsertSnippetAction extends EditorAction {
return quickInputService.pick(picks, { matchOnDetail: true }).then(pick => resolve(pick && pick.snippet), reject);
}
}).then(async snippet => {
if (!snippet) {
return;
}
let clipboardText: string | undefined;
if (snippet.needsClipboard) {
clipboardText = await clipboardService.readText();
}
if (snippet) {
SnippetController2.get(editor).insert(snippet.codeSnippet, { clipboardText });
}
SnippetController2.get(editor).insert(snippet.codeSnippet, { clipboardText });
});
}
}

View File

@@ -8,9 +8,8 @@ import { IFileService, IResolveFileResult, IFileStat } from 'vs/platform/files/c
import { IWorkspaceContextService, WorkbenchState, IWorkspace } from 'vs/platform/workspace/common/workspace';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IWindowService, IWindowConfiguration } from 'vs/platform/windows/common/windows';
import { INotificationService, IPromptChoice } from 'vs/platform/notification/common/notification';
import { INotificationService, NeverShowAgainScope, INeverShowAgainOptions } from 'vs/platform/notification/common/notification';
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { ITextFileService, ITextFileContent } from 'vs/workbench/services/textfile/common/textfiles';
import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
@@ -22,8 +21,6 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IWorkspaceStatsService, Tags } from 'vs/workbench/contrib/stats/common/workspaceStats';
import { getHashedRemotesFromConfig } from 'vs/workbench/contrib/stats/electron-browser/workspaceStats';
const DISABLE_WORKSPACE_PROMPT_KEY = 'workspaces.dontPromptToOpen';
const ModulesToLookFor = [
// Packages that suggest a node server
'express',
@@ -103,7 +100,6 @@ export class WorkspaceStatsService implements IWorkspaceStatsService {
@IWindowService private readonly windowService: IWindowService,
@INotificationService private readonly notificationService: INotificationService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@IStorageService private readonly storageService: IStorageService,
@ITextFileService private readonly textFileService: ITextFileService
) { }
@@ -449,15 +445,7 @@ export class WorkspaceStatsService implements IWorkspaceStatsService {
}
private doHandleWorkspaceFiles(folder: URI, workspaces: string[]): void {
if (this.storageService.getBoolean(DISABLE_WORKSPACE_PROMPT_KEY, StorageScope.WORKSPACE)) {
return; // prompt disabled by user
}
const doNotShowAgain: IPromptChoice = {
label: localize('never again', "Don't Show Again"),
isSecondary: true,
run: () => this.storageService.store(DISABLE_WORKSPACE_PROMPT_KEY, true, StorageScope.WORKSPACE)
};
const neverShowAgain: INeverShowAgainOptions = { id: 'workspaces.dontPromptToOpen', scope: NeverShowAgainScope.WORKSPACE, isSecondary: true };
// Prompt to open one workspace
if (workspaces.length === 1) {
@@ -466,7 +454,7 @@ export class WorkspaceStatsService implements IWorkspaceStatsService {
this.notificationService.prompt(Severity.Info, localize('workspaceFound', "This folder contains a workspace file '{0}'. Do you want to open it? [Learn more]({1}) about workspace files.", workspaceFile, 'https://go.microsoft.com/fwlink/?linkid=2025315'), [{
label: localize('openWorkspace', "Open Workspace"),
run: () => this.windowService.openWindow([{ workspaceUri: joinPath(folder, workspaceFile) }])
}, doNotShowAgain]);
}], { neverShowAgain });
}
// Prompt to select a workspace from many
@@ -482,7 +470,7 @@ export class WorkspaceStatsService implements IWorkspaceStatsService {
}
});
}
}, doNotShowAgain]);
}], { neverShowAgain });
}
}

View File

@@ -11,7 +11,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
import { ITerminalConfiguration, ITerminalFont, IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, TERMINAL_CONFIG_SECTION, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, MINIMUM_LETTER_SPACING, LinuxDistro, IShellLaunchConfig } from 'vs/workbench/contrib/terminal/common/terminal';
import Severity from 'vs/base/common/severity';
import { Terminal as XTermTerminal } from 'xterm';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { INotificationService, NeverShowAgainScope } from 'vs/platform/notification/common/notification';
import { IBrowserTerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminal';
import { Emitter, Event } from 'vs/base/common/event';
import { basename } from 'vs/base/common/path';
@@ -254,7 +254,6 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
return r;
}
private readonly NO_RECOMMENDATIONS_KEY = 'terminalConfigHelper/launchRecommendationsIgnore';
private recommendationsShown = false;
public async showRecommendations(shellLaunchConfig: IShellLaunchConfig): Promise<void> {
@@ -264,10 +263,6 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
this.recommendationsShown = true;
if (platform.isWindows && shellLaunchConfig.executable && basename(shellLaunchConfig.executable).toLowerCase() === 'wsl.exe') {
if (this._storageService.getBoolean(this.NO_RECOMMENDATIONS_KEY, StorageScope.WORKSPACE, false)) {
return;
}
if (! await this.isExtensionInstalled('ms-vscode-remote.remote-wsl')) {
this._notificationService.prompt(
Severity.Info,
@@ -276,16 +271,10 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
"Check out the 'Visual Studio Code Remote - WSL' extension for a great development experience in WSL. Click [here]({0}) to learn more.",
'https://go.microsoft.com/fwlink/?linkid=2097212'
),
[
{
label: nls.localize('doNotShowAgain', "Don't Show Again"),
run: () => {
this._storageService.store(this.NO_RECOMMENDATIONS_KEY, true, StorageScope.WORKSPACE);
}
}
],
[],
{
sticky: true
sticky: true,
neverShowAgain: { id: 'terminalConfigHelper/launchRecommendationsIgnore', scope: NeverShowAgainScope.WORKSPACE }
}
);
}

View File

@@ -144,18 +144,20 @@ export function getCwd(
try {
customCwd = configurationResolverService.resolve(lastActiveWorkspace, customCwd);
} catch (e) {
// There was an issue resolving a variable, just use the unresolved customCwd which
// which will fail, and log the error in the console.
// There was an issue resolving a variable, log the error in the console and
// fallback to the default.
if (logService) {
logService.error('Could not resolve terminal.integrated.cwd', e);
}
return customCwd;
customCwd = undefined;
}
}
if (path.isAbsolute(customCwd)) {
cwd = customCwd;
} else if (root) {
cwd = path.join(root.fsPath, customCwd);
if (customCwd) {
if (path.isAbsolute(customCwd)) {
cwd = customCwd;
} else if (root) {
cwd = path.join(root.fsPath, customCwd);
}
}
}
@@ -208,33 +210,33 @@ export function getDefaultShell(
if (!maybeExecutable) {
maybeExecutable = getShellSetting(fetchSetting, isWorkspaceShellAllowed, 'shell', platformOverride);
}
maybeExecutable = maybeExecutable || defaultShell;
let executable: string = maybeExecutable || defaultShell;
// Change Sysnative to System32 if the OS is Windows but NOT WoW64. It's
// safe to assume that this was used by accident as Sysnative does not
// exist and will break the terminal in non-WoW64 environments.
if ((platformOverride === platform.Platform.Windows) && !isWoW64 && windir) {
const sysnativePath = path.join(windir, 'Sysnative').replace(/\//g, '\\').toLowerCase();
if (maybeExecutable && maybeExecutable.toLowerCase().indexOf(sysnativePath) === 0) {
maybeExecutable = path.join(windir, 'System32', maybeExecutable.substr(sysnativePath.length + 1));
if (executable && executable.toLowerCase().indexOf(sysnativePath) === 0) {
executable = path.join(windir, 'System32', executable.substr(sysnativePath.length + 1));
}
}
// Convert / to \ on Windows for convenience
if (maybeExecutable && platformOverride === platform.Platform.Windows) {
maybeExecutable = maybeExecutable.replace(/\//g, '\\');
if (executable && platformOverride === platform.Platform.Windows) {
executable = executable.replace(/\//g, '\\');
}
if (configurationResolverService) {
try {
maybeExecutable = configurationResolverService.resolve(lastActiveWorkspace, maybeExecutable);
executable = configurationResolverService.resolve(lastActiveWorkspace, executable);
} catch (e) {
logService.error(`Could not resolve shell`, e);
maybeExecutable = maybeExecutable;
executable = executable;
}
}
return maybeExecutable;
return executable;
}
export function getDefaultShellArgs(

View File

@@ -19,7 +19,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
import { IUpdateService, State as UpdateState, StateType, IUpdate } from 'vs/platform/update/common/update';
import * as semver from 'semver-umd';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { INotificationService, INotificationHandle, Severity } from 'vs/platform/notification/common/notification';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { ReleaseNotesManager } from './releaseNotesEditor';
@@ -165,32 +165,8 @@ export class ProductContribution implements IWorkbenchContribution {
}
}
class NeverShowAgain {
private readonly key: string;
readonly action = new Action(`neverShowAgain:${this.key}`, nls.localize('neveragain', "Don't Show Again"), undefined, true, (notification: INotificationHandle) => {
// Hide notification
notification.close();
this.storageService.store(this.key, true, StorageScope.GLOBAL);
return Promise.resolve(true);
});
constructor(key: string, @IStorageService private readonly storageService: IStorageService) {
this.key = `neverShowAgain:${key}`;
}
shouldShow(): boolean {
return !this.storageService.getBoolean(this.key, StorageScope.GLOBAL, false);
}
}
export class Win3264BitContribution implements IWorkbenchContribution {
private static readonly KEY = 'update/win32-64bits';
private static readonly URL = 'https://code.visualstudio.com/updates/v1_15#_windows-64-bit';
private static readonly INSIDER_URL = 'https://github.com/Microsoft/vscode-docs/blob/vnext/release-notes/v1_15.md#windows-64-bit';
@@ -203,28 +179,18 @@ export class Win3264BitContribution implements IWorkbenchContribution {
return;
}
const neverShowAgain = new NeverShowAgain(Win3264BitContribution.KEY, storageService);
if (!neverShowAgain.shouldShow()) {
return;
}
const url = product.quality === 'insider'
? Win3264BitContribution.INSIDER_URL
: Win3264BitContribution.URL;
const handle = notificationService.prompt(
notificationService.prompt(
severity.Info,
nls.localize('64bitisavailable', "{0} for 64-bit Windows is now available! Click [here]({1}) to learn more.", product.nameShort, url),
[{
label: nls.localize('neveragain', "Don't Show Again"),
isSecondary: true,
run: () => {
neverShowAgain.action.run(handle);
neverShowAgain.action.dispose();
}
}],
{ sticky: true }
[],
{
sticky: true,
neverShowAgain: { id: 'neverShowAgain:update/win32-64bits', isSecondary: true }
}
);
}
}
@@ -401,23 +367,13 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu
}
// windows fast updates (target === system)
const neverShowAgain = new NeverShowAgain('update/win32-fast-updates', this.storageService);
if (!neverShowAgain.shouldShow()) {
return;
}
const handle = this.notificationService.prompt(
this.notificationService.prompt(
severity.Info,
nls.localize('updateInstalling', "{0} {1} is being installed in the background; we'll let you know when it's done.", product.nameLong, update.productVersion),
[{
label: nls.localize('neveragain', "Don't Show Again"),
isSecondary: true,
run: () => {
neverShowAgain.action.run(handle);
neverShowAgain.action.dispose();
}
}]
[],
{
neverShowAgain: { id: 'neverShowAgain:update/win32-fast-updates', isSecondary: true }
}
);
}

View File

@@ -39,11 +39,11 @@ class WebviewIconsManager {
this._icons.forEach((value, key) => {
const webviewSelector = `.show-file-icons .webview-${key}-name-file-icon::before`;
if (URI.isUri(value)) {
cssRules.push(`${webviewSelector} { content: ""; background-image: url(${dom.asDomUri(value).toString()}); }`);
cssRules.push(`${webviewSelector} { content: ""; background-image: ${dom.asCSSUrl(value)}; }`);
}
else {
cssRules.push(`.vs ${webviewSelector} { content: ""; background-image: url(${dom.asDomUri(value.light).toString()}); }`);
cssRules.push(`.vs-dark ${webviewSelector} { content: ""; background-image: url(${dom.asDomUri(value.dark).toString()}); }`);
cssRules.push(`.vs ${webviewSelector} { content: ""; background-image: ${dom.asCSSUrl(value.light)}; }`);
cssRules.push(`.vs-dark ${webviewSelector} { content: ""; background-image: ${dom.asCSSUrl(value.dark)}; }`);
}
});
this._styleElement.innerHTML = cssRules.join('\n');