mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-09 09:42:34 -05:00
Merge from vscode 70dc55955d586ebd427658b43cdb344f2047f9c2 (#6789)
This commit is contained in:
@@ -5,10 +5,10 @@
|
||||
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { URI as uri } from 'vs/base/common/uri';
|
||||
import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, IDebugAdapter, IDebugAdapterDescriptorFactory, IDebugSession, IDebugAdapterFactory } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, IDebugAdapter, IDebugAdapterDescriptorFactory, IDebugSession, IDebugAdapterFactory, IDataBreakpoint } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import {
|
||||
ExtHostContext, ExtHostDebugServiceShape, MainThreadDebugServiceShape, DebugSessionUUID, MainContext,
|
||||
IExtHostContext, IBreakpointsDeltaDto, ISourceMultiBreakpointDto, ISourceBreakpointDto, IFunctionBreakpointDto, IDebugSessionDto
|
||||
IExtHostContext, IBreakpointsDeltaDto, ISourceMultiBreakpointDto, ISourceBreakpointDto, IFunctionBreakpointDto, IDebugSessionDto, IDataBreakpointDto
|
||||
} from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import severity from 'vs/base/common/severity';
|
||||
@@ -110,15 +110,16 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
|
||||
// send all breakpoints
|
||||
const bps = this.debugService.getModel().getBreakpoints();
|
||||
const fbps = this.debugService.getModel().getFunctionBreakpoints();
|
||||
const dbps = this.debugService.getModel().getDataBreakpoints();
|
||||
if (bps.length > 0 || fbps.length > 0) {
|
||||
this._proxy.$acceptBreakpointsDelta({
|
||||
added: this.convertToDto(bps).concat(this.convertToDto(fbps))
|
||||
added: this.convertToDto(bps).concat(this.convertToDto(fbps)).concat(this.convertToDto(dbps))
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public $registerBreakpoints(DTOs: Array<ISourceMultiBreakpointDto | IFunctionBreakpointDto>): Promise<void> {
|
||||
public $registerBreakpoints(DTOs: Array<ISourceMultiBreakpointDto | IFunctionBreakpointDto | IDataBreakpointDto>): Promise<void> {
|
||||
|
||||
for (let dto of DTOs) {
|
||||
if (dto.type === 'sourceMulti') {
|
||||
@@ -136,14 +137,17 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
|
||||
this.debugService.addBreakpoints(uri.revive(dto.uri), rawbps, 'extension');
|
||||
} else if (dto.type === 'function') {
|
||||
this.debugService.addFunctionBreakpoint(dto.functionName, dto.id);
|
||||
} else if (dto.type === 'data') {
|
||||
this.debugService.addDataBreakpoint(dto.label, dto.dataId, dto.canPersist);
|
||||
}
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public $unregisterBreakpoints(breakpointIds: string[], functionBreakpointIds: string[]): Promise<void> {
|
||||
public $unregisterBreakpoints(breakpointIds: string[], functionBreakpointIds: string[], dataBreakpointIds: string[]): Promise<void> {
|
||||
breakpointIds.forEach(id => this.debugService.removeBreakpoints(id));
|
||||
functionBreakpointIds.forEach(id => this.debugService.removeFunctionBreakpoints(id));
|
||||
dataBreakpointIds.forEach(id => this.debugService.removeDataBreakpoints(id));
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
@@ -294,7 +298,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private convertToDto(bps: (ReadonlyArray<IBreakpoint | IFunctionBreakpoint>)): Array<ISourceBreakpointDto | IFunctionBreakpointDto> {
|
||||
private convertToDto(bps: (ReadonlyArray<IBreakpoint | IFunctionBreakpoint | IDataBreakpoint>)): Array<ISourceBreakpointDto | IFunctionBreakpointDto | IDataBreakpointDto> {
|
||||
return bps.map(bp => {
|
||||
if ('name' in bp) {
|
||||
const fbp = <IFunctionBreakpoint>bp;
|
||||
@@ -307,6 +311,19 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
|
||||
logMessage: fbp.logMessage,
|
||||
functionName: fbp.name
|
||||
};
|
||||
} else if ('dataId' in bp) {
|
||||
const dbp = <IDataBreakpoint>bp;
|
||||
return <IDataBreakpointDto>{
|
||||
type: 'data',
|
||||
id: dbp.getId(),
|
||||
dataId: dbp.dataId,
|
||||
enabled: dbp.enabled,
|
||||
condition: dbp.condition,
|
||||
hitCondition: dbp.hitCondition,
|
||||
logMessage: dbp.logMessage,
|
||||
label: dbp.label,
|
||||
canPersist: dbp.canPersist
|
||||
};
|
||||
} else {
|
||||
const sbp = <IBreakpoint>bp;
|
||||
return <ISourceBreakpointDto>{
|
||||
|
||||
@@ -37,7 +37,7 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
|
||||
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
|
||||
import { createCSSRule, asDomUri } from 'vs/base/browser/dom';
|
||||
import { createCSSRule, asCSSUrl } from 'vs/base/browser/dom';
|
||||
|
||||
export interface IUserFriendlyViewsContainerDescriptor {
|
||||
id: string;
|
||||
@@ -210,7 +210,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
|
||||
});
|
||||
}
|
||||
|
||||
private addCustomViewContainers(extensionPoints: IExtensionPointUser<ViewContainerExtensionPointType>[], existingViewContainers: ViewContainer[]): void {
|
||||
private addCustomViewContainers(extensionPoints: readonly IExtensionPointUser<ViewContainerExtensionPointType>[], existingViewContainers: ViewContainer[]): void {
|
||||
const viewContainersRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
|
||||
let order = TEST_VIEW_CONTAINER_ORDER + viewContainersRegistry.all.filter(v => !!v.extensionId).length + 1;
|
||||
for (let { value, collector, description } of extensionPoints) {
|
||||
@@ -227,7 +227,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
|
||||
}
|
||||
}
|
||||
|
||||
private removeCustomViewContainers(extensionPoints: IExtensionPointUser<ViewContainerExtensionPointType>[]): void {
|
||||
private removeCustomViewContainers(extensionPoints: readonly IExtensionPointUser<ViewContainerExtensionPointType>[]): void {
|
||||
const viewContainersRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
|
||||
const removedExtensions: Set<string> = extensionPoints.reduce((result, e) => { result.add(ExtensionIdentifier.toKey(e.description.identifier)); return result; }, new Set<string>());
|
||||
for (const viewContainer of viewContainersRegistry.all) {
|
||||
@@ -356,7 +356,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
|
||||
|
||||
// Generate CSS to show the icon in the activity bar
|
||||
const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${cssClass}`;
|
||||
createCSSRule(iconClass, `-webkit-mask: url('${asDomUri(icon)}') no-repeat 50% 50%; -webkit-mask-size: 24px;`);
|
||||
createCSSRule(iconClass, `-webkit-mask: ${asCSSUrl(icon)} no-repeat 50% 50%; -webkit-mask-size: 24px;`);
|
||||
}
|
||||
|
||||
return viewContainer;
|
||||
@@ -378,7 +378,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
|
||||
});
|
||||
}
|
||||
|
||||
private addViews(extensions: IExtensionPointUser<ViewExtensionPointType>[]): void {
|
||||
private addViews(extensions: readonly IExtensionPointUser<ViewExtensionPointType>[]): void {
|
||||
for (const extension of extensions) {
|
||||
const { value, collector } = extension;
|
||||
|
||||
@@ -442,7 +442,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
|
||||
return this.viewContainersRegistry.get(EXPLORER)!;
|
||||
}
|
||||
|
||||
private removeViews(extensions: IExtensionPointUser<ViewExtensionPointType>[]): void {
|
||||
private removeViews(extensions: readonly IExtensionPointUser<ViewExtensionPointType>[]): void {
|
||||
const removedExtensions: Set<string> = extensions.reduce((result, e) => { result.add(ExtensionIdentifier.toKey(e.description.identifier)); return result; }, new Set<string>());
|
||||
for (const viewContainer of this.viewContainersRegistry.all) {
|
||||
const removedViews = this.viewsRegistry.getViews(viewContainer).filter((v: ICustomViewDescriptor) => v.extensionId && removedExtensions.has(ExtensionIdentifier.toKey(v.extensionId)));
|
||||
|
||||
@@ -719,8 +719,8 @@ export interface MainThreadDebugServiceShape extends IDisposable {
|
||||
$customDebugAdapterRequest(id: DebugSessionUUID, command: string, args: any): Promise<any>;
|
||||
$appendDebugConsole(value: string): void;
|
||||
$startBreakpointEvents(): void;
|
||||
$registerBreakpoints(breakpoints: Array<ISourceMultiBreakpointDto | IFunctionBreakpointDto>): Promise<void>;
|
||||
$unregisterBreakpoints(breakpointIds: string[], functionBreakpointIds: string[]): Promise<void>;
|
||||
$registerBreakpoints(breakpoints: Array<ISourceMultiBreakpointDto | IFunctionBreakpointDto | IDataBreakpointDto>): Promise<void>;
|
||||
$unregisterBreakpoints(breakpointIds: string[], functionBreakpointIds: string[], dataBreakpointIds: string[]): Promise<void>;
|
||||
}
|
||||
|
||||
export interface IOpenUriOptions {
|
||||
@@ -1203,6 +1203,13 @@ export interface IFunctionBreakpointDto extends IBreakpointDto {
|
||||
functionName: string;
|
||||
}
|
||||
|
||||
export interface IDataBreakpointDto extends IBreakpointDto {
|
||||
type: 'data';
|
||||
dataId: string;
|
||||
canPersist: boolean;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export interface ISourceBreakpointDto extends IBreakpointDto {
|
||||
type: 'source';
|
||||
uri: UriComponents;
|
||||
@@ -1211,9 +1218,9 @@ export interface ISourceBreakpointDto extends IBreakpointDto {
|
||||
}
|
||||
|
||||
export interface IBreakpointsDeltaDto {
|
||||
added?: Array<ISourceBreakpointDto | IFunctionBreakpointDto>;
|
||||
added?: Array<ISourceBreakpointDto | IFunctionBreakpointDto | IDataBreakpointDto>;
|
||||
removed?: string[];
|
||||
changed?: Array<ISourceBreakpointDto | IFunctionBreakpointDto>;
|
||||
changed?: Array<ISourceBreakpointDto | IFunctionBreakpointDto | IDataBreakpointDto>;
|
||||
}
|
||||
|
||||
export interface ISourceMultiBreakpointDto {
|
||||
|
||||
@@ -2166,6 +2166,24 @@ export class FunctionBreakpoint extends Breakpoint {
|
||||
}
|
||||
}
|
||||
|
||||
@es5ClassCompat
|
||||
export class DataBreakpoint extends Breakpoint {
|
||||
readonly label: string;
|
||||
readonly dataId: string;
|
||||
readonly canPersist: boolean;
|
||||
|
||||
constructor(label: string, dataId: string, canPersist: boolean, enabled?: boolean, condition?: string, hitCondition?: string, logMessage?: string) {
|
||||
super(enabled, condition, hitCondition, logMessage);
|
||||
if (!dataId) {
|
||||
throw illegalArgument('dataId');
|
||||
}
|
||||
this.label = label;
|
||||
this.dataId = dataId;
|
||||
this.canPersist = canPersist;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@es5ClassCompat
|
||||
export class DebugAdapterExecutable implements vscode.DebugAdapterExecutable {
|
||||
readonly command: string;
|
||||
|
||||
@@ -12,7 +12,7 @@ import { IExtensionPointUser, ExtensionMessageCollector, ExtensionsRegistry } fr
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { MenuId, MenuRegistry, ILocalizedString, IMenuItem } from 'vs/platform/actions/common/actions';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
|
||||
namespace schema {
|
||||
|
||||
@@ -334,7 +334,7 @@ namespace schema {
|
||||
};
|
||||
}
|
||||
|
||||
let _commandRegistrations: IDisposable[] = [];
|
||||
const _commandRegistrations = new DisposableStore();
|
||||
|
||||
export const commandsExtensionPoint = ExtensionsRegistry.registerExtensionPoint<schema.IUserFriendlyCommand | schema.IUserFriendlyCommand[]>({
|
||||
extensionPoint: 'commands',
|
||||
@@ -343,7 +343,7 @@ export const commandsExtensionPoint = ExtensionsRegistry.registerExtensionPoint<
|
||||
|
||||
commandsExtensionPoint.setHandler(extensions => {
|
||||
|
||||
function handleCommand(userFriendlyCommand: schema.IUserFriendlyCommand, extension: IExtensionPointUser<any>, disposables: IDisposable[]) {
|
||||
function handleCommand(userFriendlyCommand: schema.IUserFriendlyCommand, extension: IExtensionPointUser<any>) {
|
||||
|
||||
if (!schema.isValidCommand(userFriendlyCommand, extension.collector)) {
|
||||
return;
|
||||
@@ -373,20 +373,20 @@ commandsExtensionPoint.setHandler(extensions => {
|
||||
precondition: ContextKeyExpr.deserialize(enablement),
|
||||
iconLocation: absoluteIcon
|
||||
});
|
||||
disposables.push(registration);
|
||||
_commandRegistrations.add(registration);
|
||||
}
|
||||
|
||||
// remove all previous command registrations
|
||||
_commandRegistrations = dispose(_commandRegistrations);
|
||||
_commandRegistrations.clear();
|
||||
|
||||
for (let extension of extensions) {
|
||||
for (const extension of extensions) {
|
||||
const { value } = extension;
|
||||
if (Array.isArray<schema.IUserFriendlyCommand>(value)) {
|
||||
for (let command of value) {
|
||||
handleCommand(command, extension, _commandRegistrations);
|
||||
if (Array.isArray(value)) {
|
||||
for (const command of value) {
|
||||
handleCommand(command, extension);
|
||||
}
|
||||
} else {
|
||||
handleCommand(value, extension, _commandRegistrations);
|
||||
handleCommand(value, extension);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
IBreakpointsDeltaDto, ISourceMultiBreakpointDto, IFunctionBreakpointDto, IDebugSessionDto
|
||||
} from 'vs/workbench/api/common/extHost.protocol';
|
||||
import * as vscode from 'vscode';
|
||||
import { Disposable, Position, Location, SourceBreakpoint, FunctionBreakpoint, DebugAdapterServer, DebugAdapterExecutable } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { Disposable, Position, Location, SourceBreakpoint, FunctionBreakpoint, DebugAdapterServer, DebugAdapterExecutable, DataBreakpoint } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { ExecutableDebugAdapter, SocketDebugAdapter } from 'vs/workbench/contrib/debug/node/debugAdapter';
|
||||
import { AbstractDebugAdapter } from 'vs/workbench/contrib/debug/common/abstractDebugAdapter';
|
||||
import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
@@ -248,7 +248,8 @@ export class ExtHostDebugService implements IExtHostDebugService, ExtHostDebugSe
|
||||
// unregister with VS Code
|
||||
const ids = breakpoints.filter(bp => bp instanceof SourceBreakpoint).map(bp => bp.id);
|
||||
const fids = breakpoints.filter(bp => bp instanceof FunctionBreakpoint).map(bp => bp.id);
|
||||
return this._debugServiceProxy.$unregisterBreakpoints(ids, fids);
|
||||
const dids = breakpoints.filter(bp => bp instanceof DataBreakpoint).map(bp => bp.id);
|
||||
return this._debugServiceProxy.$unregisterBreakpoints(ids, fids, dids);
|
||||
}
|
||||
|
||||
public startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration, parentSession?: vscode.DebugSession): Promise<boolean> {
|
||||
@@ -554,6 +555,8 @@ export class ExtHostDebugService implements IExtHostDebugService, ExtHostDebugSe
|
||||
let bp: vscode.Breakpoint;
|
||||
if (bpd.type === 'function') {
|
||||
bp = new FunctionBreakpoint(bpd.functionName, bpd.enabled, bpd.condition, bpd.hitCondition, bpd.logMessage);
|
||||
} else if (bpd.type === 'data') {
|
||||
bp = new DataBreakpoint(bpd.label, bpd.dataId, bpd.canPersist, bpd.enabled, bpd.hitCondition, bpd.condition, bpd.logMessage);
|
||||
} else {
|
||||
const uri = URI.revive(bpd.uri);
|
||||
bp = new SourceBreakpoint(new Location(uri, new Position(bpd.line, bpd.character)), bpd.enabled, bpd.condition, bpd.hitCondition, bpd.logMessage);
|
||||
|
||||
@@ -46,6 +46,9 @@ enum Settings {
|
||||
PANEL_POSITION = 'workbench.panel.defaultLocation',
|
||||
|
||||
ZEN_MODE_RESTORE = 'zenMode.restore',
|
||||
|
||||
// TODO @misolori update this when finished
|
||||
OCTICONS_UPDATE_ENABLED = 'workbench.octiconsUpdate.enabled',
|
||||
}
|
||||
|
||||
enum Storage {
|
||||
@@ -173,6 +176,11 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
|
||||
wasSideBarVisible: false,
|
||||
wasPanelVisible: false,
|
||||
transitionDisposables: new DisposableStore()
|
||||
},
|
||||
|
||||
// TODO @misolori update this when finished
|
||||
octiconsUpdate: {
|
||||
enabled: false
|
||||
}
|
||||
};
|
||||
|
||||
@@ -314,6 +322,10 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
|
||||
const newMenubarVisibility = this.configurationService.getValue<MenuBarVisibility>(Settings.MENUBAR_VISIBLE);
|
||||
this.setMenubarVisibility(newMenubarVisibility, !!skipLayout);
|
||||
|
||||
// TODO @misolori update this when finished
|
||||
const newOcticonsUpdate = this.configurationService.getValue<boolean>(Settings.OCTICONS_UPDATE_ENABLED);
|
||||
this.setOcticonsUpdate(newOcticonsUpdate);
|
||||
|
||||
}
|
||||
|
||||
private setSideBarPosition(position: Position): void {
|
||||
@@ -426,6 +438,10 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
|
||||
// Zen mode enablement
|
||||
this.state.zenMode.restore = this.storageService.getBoolean(Storage.ZEN_MODE_ENABLED, StorageScope.WORKSPACE, false) && this.configurationService.getValue(Settings.ZEN_MODE_RESTORE);
|
||||
|
||||
// TODO @misolori update this when finished
|
||||
this.state.octiconsUpdate.enabled = this.configurationService.getValue<boolean>(Settings.OCTICONS_UPDATE_ENABLED);
|
||||
this.setOcticonsUpdate(this.state.octiconsUpdate.enabled);
|
||||
|
||||
}
|
||||
|
||||
private resolveEditorsToOpen(fileService: IFileService): Promise<IResourceEditor[]> | IResourceEditor[] {
|
||||
@@ -729,6 +745,19 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
|
||||
}
|
||||
}
|
||||
|
||||
// TODO @misolori update this when finished
|
||||
private setOcticonsUpdate(enabled: boolean): void {
|
||||
this.state.octiconsUpdate.enabled = enabled;
|
||||
|
||||
// Update DOM
|
||||
if (enabled) {
|
||||
document.body.dataset.octiconsUpdate = 'enabled';
|
||||
} else {
|
||||
document.body.dataset.octiconsUpdate = '';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected createWorkbenchLayout(instantiationService: IInstantiationService): void {
|
||||
const titleBar = this.getPart(Parts.TITLEBAR_PART);
|
||||
const editorPart = this.getPart(Parts.EDITOR_PART);
|
||||
|
||||
@@ -171,7 +171,7 @@ export class PlaceHolderViewletActivityAction extends ViewletActivityAction {
|
||||
super({ id, name: id, cssClass: `extensionViewlet-placeholder-${id.replace(/\./g, '-')}` }, viewletService, layoutService, telemetryService);
|
||||
|
||||
const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${this.class}`; // Generate Placeholder CSS to show the icon in the activity bar
|
||||
DOM.createCSSRule(iconClass, `-webkit-mask: url('${DOM.asDomUri(iconUrl) || ''}') no-repeat 50% 50%; -webkit-mask-size: 24px;`);
|
||||
DOM.createCSSRule(iconClass, `-webkit-mask: ${DOM.asCSSUrl(iconUrl)} no-repeat 50% 50%; -webkit-mask-size: 24px;`);
|
||||
}
|
||||
|
||||
setActivity(activity: IActivity): void {
|
||||
|
||||
@@ -22,8 +22,8 @@ export function getIconClass(iconPath: { dark: URI; light?: URI; } | undefined):
|
||||
iconClass = iconPathToClass[key];
|
||||
} else {
|
||||
iconClass = iconClassGenerator.nextId();
|
||||
dom.createCSSRule(`.${iconClass}`, `background-image: url("${dom.asDomUri(iconPath.light || iconPath.dark).toString()}")`);
|
||||
dom.createCSSRule(`.vs-dark .${iconClass}, .hc-black .${iconClass}`, `background-image: url("${dom.asDomUri(iconPath.dark).toString()}")`);
|
||||
dom.createCSSRule(`.${iconClass}`, `background-image: ${dom.asCSSUrl(iconPath.light || iconPath.dark)}`);
|
||||
dom.createCSSRule(`.vs-dark .${iconClass}, .hc-black .${iconClass}`, `background-image: ${dom.asCSSUrl(iconPath.dark)}`);
|
||||
iconPathToClass[key] = iconClass;
|
||||
}
|
||||
|
||||
|
||||
@@ -756,7 +756,7 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
|
||||
templateData.resourceLabel.setResource({ name: label, description }, { title, hideIcon: true, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches: createMatches(element.filterData) });
|
||||
}
|
||||
|
||||
templateData.icon.style.backgroundImage = iconUrl ? `url('${DOM.asDomUri(iconUrl).toString(true)}')` : '';
|
||||
templateData.icon.style.backgroundImage = iconUrl ? DOM.asCSSUrl(iconUrl) : '';
|
||||
DOM.toggleClass(templateData.icon, 'custom-view-tree-node-item-icon', !!iconUrl);
|
||||
templateData.actionBar.context = <TreeViewItemHandleArg>{ $treeViewId: this.treeViewId, $treeItemHandle: node.handle };
|
||||
templateData.actionBar.push(this.menus.getResourceActions(node), { icon: true, label: false });
|
||||
|
||||
@@ -41,6 +41,7 @@ import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { getThemeTypeSelector, DARK, HIGH_CONTRAST, LIGHT } from 'vs/platform/theme/common/themeService';
|
||||
import { InMemoryUserDataProvider } from 'vs/workbench/services/userData/common/inMemoryUserDataProvider';
|
||||
import { registerWindowDriver } from 'vs/platform/driver/browser/driver';
|
||||
import { StaticExtensionsService, IStaticExtensionsService } from 'vs/workbench/services/extensions/common/staticExtensions';
|
||||
|
||||
class CodeRendererMain extends Disposable {
|
||||
|
||||
@@ -145,6 +146,10 @@ class CodeRendererMain extends Disposable {
|
||||
const fileService = this._register(new FileService(logService));
|
||||
serviceCollection.set(IFileService, fileService);
|
||||
|
||||
// Static Extensions
|
||||
const staticExtensions = new StaticExtensionsService(this.configuration.staticExtensions || []);
|
||||
serviceCollection.set(IStaticExtensionsService, staticExtensions);
|
||||
|
||||
let userDataProvider: IFileSystemProvider | undefined = this.configuration.userDataProvider;
|
||||
const connection = remoteAgentService.getConnection();
|
||||
if (connection) {
|
||||
|
||||
@@ -239,6 +239,11 @@ import { isMacintosh, isWindows, isLinux, isWeb } from 'vs/base/common/platform'
|
||||
'description': nls.localize('workbench.useExperimentalGridLayout', "Enables the grid layout for the workbench. This setting may enable additional layout options for workbench components."),
|
||||
'default': true,
|
||||
'scope': ConfigurationScope.APPLICATION
|
||||
},
|
||||
'workbench.octiconsUpdate.enabled': {
|
||||
'type': 'boolean',
|
||||
'default': true,
|
||||
'description': nls.localize('workbench.octiconsUpdate.enabled', "Controls the visibility of the new Octicons style in the workbench.")
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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[] {
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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({
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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 });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -22,10 +22,16 @@ import { WebWorkerExtensionHostStarter } from 'vs/workbench/services/extensions/
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { isWebExtension } from 'vs/workbench/services/extensions/common/extensionsUtil';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { FetchFileSystemProvider } from 'vs/workbench/services/extensions/browser/webWorkerFileSystemProvider';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IStaticExtensionsService } from 'vs/workbench/services/extensions/common/staticExtensions';
|
||||
|
||||
export class ExtensionService extends AbstractExtensionService implements IExtensionService {
|
||||
|
||||
private _remoteExtensionsEnvironmentData: IRemoteAgentEnvironment | null;
|
||||
private _disposables = new DisposableStore();
|
||||
private _remoteExtensionsEnvironmentData: IRemoteAgentEnvironment | null = null;
|
||||
|
||||
constructor(
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@@ -37,6 +43,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
||||
@IProductService productService: IProductService,
|
||||
@IRemoteAgentService private readonly _remoteAgentService: IRemoteAgentService,
|
||||
@IConfigurationService private readonly _configService: IConfigurationService,
|
||||
@IStaticExtensionsService private readonly _staticExtensions: IStaticExtensionsService,
|
||||
) {
|
||||
super(
|
||||
instantiationService,
|
||||
@@ -48,8 +55,19 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
||||
productService,
|
||||
);
|
||||
|
||||
this._remoteExtensionsEnvironmentData = null;
|
||||
this._initialize();
|
||||
this._initFetchFileSystem();
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._disposables.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
private _initFetchFileSystem(): void {
|
||||
const provider = new FetchFileSystemProvider();
|
||||
this._disposables.add(this._fileService.registerProvider(Schemas.http, provider));
|
||||
this._disposables.add(this._fileService.registerProvider(Schemas.https, provider));
|
||||
}
|
||||
|
||||
private _createProvider(remoteAuthority: string): IInitDataProvider {
|
||||
@@ -84,23 +102,31 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
||||
|
||||
protected async _scanAndHandleExtensions(): Promise<void> {
|
||||
// fetch the remote environment
|
||||
const remoteEnv = (await this._remoteAgentService.getEnvironment())!;
|
||||
let [remoteEnv, localExtensions] = await Promise.all([
|
||||
<Promise<IRemoteAgentEnvironment>>this._remoteAgentService.getEnvironment(),
|
||||
this._staticExtensions.getExtensions()
|
||||
]);
|
||||
|
||||
// enable or disable proposed API per extension
|
||||
// local: only enabled and web'ish extension
|
||||
localExtensions = localExtensions.filter(ext => this._isEnabled(ext) && isWebExtension(ext, this._configService));
|
||||
this._checkEnableProposedApi(localExtensions);
|
||||
|
||||
// remote: only enabled and none-web'ish extension
|
||||
remoteEnv.extensions = remoteEnv.extensions.filter(extension => this._isEnabled(extension) && !isWebExtension(extension, this._configService));
|
||||
this._checkEnableProposedApi(remoteEnv.extensions);
|
||||
|
||||
// remove disabled extensions
|
||||
remoteEnv.extensions = remoteEnv.extensions.filter(extension => this._isEnabled(extension));
|
||||
// in case of overlap, the remote wins
|
||||
const isRemoteExtension = new Set<string>();
|
||||
remoteEnv.extensions.forEach(extension => isRemoteExtension.add(ExtensionIdentifier.toKey(extension.identifier)));
|
||||
localExtensions = localExtensions.filter(extension => !isRemoteExtension.has(ExtensionIdentifier.toKey(extension.identifier)));
|
||||
|
||||
// save for remote extension's init data
|
||||
this._remoteExtensionsEnvironmentData = remoteEnv;
|
||||
|
||||
// this._handleExtensionPoints((<IExtensionDescription[]>[]).concat(remoteEnv.extensions).concat(localExtensions));
|
||||
const result = this._registry.deltaExtensions(remoteEnv.extensions, []);
|
||||
const result = this._registry.deltaExtensions(remoteEnv.extensions.concat(localExtensions), []);
|
||||
if (result.removedDueToLooping.length > 0) {
|
||||
this._logOrShowMessage(Severity.Error, nls.localize('looping', "The following extensions contain dependency loops and have been disabled: {0}", result.removedDueToLooping.map(e => `'${e.identifier.value}'`).join(', ')));
|
||||
}
|
||||
|
||||
this._doHandleExtensionPoints(this._registry.getAllExtensionDescriptions());
|
||||
}
|
||||
|
||||
|
||||
@@ -65,8 +65,8 @@ export class WebWorkerExtensionHostStarter implements IExtensionHostStarter {
|
||||
};
|
||||
|
||||
worker.onerror = (event) => {
|
||||
console.error(event.error);
|
||||
this._onDidExit.fire([81, event.error]);
|
||||
console.error(event.message, event.error);
|
||||
this._onDidExit.fire([81, event.message || event.error]);
|
||||
};
|
||||
|
||||
// keep for cleanup
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IFileSystemProvider, FileSystemProviderCapabilities, IStat, FileType, FileDeleteOptions, FileOverwriteOptions, FileWriteOptions, FileSystemProviderError, FileSystemProviderErrorCode } from 'vs/platform/files/common/files';
|
||||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { NotImplementedError } from 'vs/base/common/errors';
|
||||
|
||||
export class FetchFileSystemProvider implements IFileSystemProvider {
|
||||
|
||||
readonly capabilities = FileSystemProviderCapabilities.Readonly + FileSystemProviderCapabilities.FileReadWrite + FileSystemProviderCapabilities.PathCaseSensitive;
|
||||
readonly onDidChangeCapabilities = Event.None;
|
||||
readonly onDidChangeFile = Event.None;
|
||||
|
||||
// working implementations
|
||||
async readFile(resource: URI): Promise<Uint8Array> {
|
||||
try {
|
||||
const res = await fetch(resource.toString(true));
|
||||
if (res.status === 200) {
|
||||
return new Uint8Array(await res.arrayBuffer());
|
||||
}
|
||||
throw new FileSystemProviderError(res.statusText, FileSystemProviderErrorCode.Unknown);
|
||||
} catch (err) {
|
||||
throw new FileSystemProviderError(err, FileSystemProviderErrorCode.Unknown);
|
||||
}
|
||||
}
|
||||
|
||||
// fake implementations
|
||||
async stat(_resource: URI): Promise<IStat> {
|
||||
return {
|
||||
type: FileType.File,
|
||||
size: 0,
|
||||
mtime: 0,
|
||||
ctime: 0
|
||||
};
|
||||
}
|
||||
|
||||
watch(): IDisposable {
|
||||
return Disposable.None;
|
||||
}
|
||||
|
||||
// error implementations
|
||||
writeFile(_resource: URI, _content: Uint8Array, _opts: FileWriteOptions): Promise<void> {
|
||||
throw new NotImplementedError();
|
||||
}
|
||||
readdir(_resource: URI): Promise<[string, FileType][]> {
|
||||
throw new NotImplementedError();
|
||||
}
|
||||
mkdir(_resource: URI): Promise<void> {
|
||||
throw new NotImplementedError();
|
||||
}
|
||||
delete(_resource: URI, _opts: FileDeleteOptions): Promise<void> {
|
||||
throw new NotImplementedError();
|
||||
}
|
||||
rename(_from: URI, _to: URI, _opts: FileOverwriteOptions): Promise<void> {
|
||||
throw new NotImplementedError();
|
||||
}
|
||||
}
|
||||
@@ -61,9 +61,7 @@ export interface IExtensionPointUser<T> {
|
||||
collector: ExtensionMessageCollector;
|
||||
}
|
||||
|
||||
export interface IExtensionPointHandler<T> {
|
||||
(extensions: IExtensionPointUser<T>[], delta: ExtensionPointUserDelta<T>): void;
|
||||
}
|
||||
export type IExtensionPointHandler<T> = (extensions: readonly IExtensionPointUser<T>[], delta: ExtensionPointUserDelta<T>) => void;
|
||||
|
||||
export interface IExtensionPoint<T> {
|
||||
name: string;
|
||||
@@ -73,7 +71,7 @@ export interface IExtensionPoint<T> {
|
||||
|
||||
export class ExtensionPointUserDelta<T> {
|
||||
|
||||
private static _toSet<T>(arr: IExtensionPointUser<T>[]): Set<string> {
|
||||
private static _toSet<T>(arr: readonly IExtensionPointUser<T>[]): Set<string> {
|
||||
const result = new Set<string>();
|
||||
for (let i = 0, len = arr.length; i < len; i++) {
|
||||
result.add(ExtensionIdentifier.toKey(arr[i].description.identifier));
|
||||
@@ -81,7 +79,7 @@ export class ExtensionPointUserDelta<T> {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static compute<T>(previous: IExtensionPointUser<T>[] | null, current: IExtensionPointUser<T>[]): ExtensionPointUserDelta<T> {
|
||||
public static compute<T>(previous: readonly IExtensionPointUser<T>[] | null, current: readonly IExtensionPointUser<T>[]): ExtensionPointUserDelta<T> {
|
||||
if (!previous || !previous.length) {
|
||||
return new ExtensionPointUserDelta<T>(current, []);
|
||||
}
|
||||
@@ -99,8 +97,8 @@ export class ExtensionPointUserDelta<T> {
|
||||
}
|
||||
|
||||
constructor(
|
||||
public readonly added: IExtensionPointUser<T>[],
|
||||
public readonly removed: IExtensionPointUser<T>[],
|
||||
public readonly added: readonly IExtensionPointUser<T>[],
|
||||
public readonly removed: readonly IExtensionPointUser<T>[],
|
||||
) { }
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtensionDescription, IExtensionManifest, ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { UriComponents, URI } from 'vs/base/common/uri';
|
||||
|
||||
export const IStaticExtensionsService = createDecorator<IStaticExtensionsService>('IStaticExtensionsService');
|
||||
|
||||
export interface IStaticExtensionsService {
|
||||
_serviceBrand: any;
|
||||
getExtensions(): Promise<IExtensionDescription[]>;
|
||||
}
|
||||
|
||||
export class StaticExtensionsService implements IStaticExtensionsService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
private readonly _descriptions: IExtensionDescription[] = [];
|
||||
|
||||
constructor(staticExtensions: { packageJSON: IExtensionManifest, extensionLocation: UriComponents }[]) {
|
||||
this._descriptions = staticExtensions.map(data => <IExtensionDescription>{
|
||||
identifier: new ExtensionIdentifier(`${data.packageJSON.publisher}.${data.packageJSON.name}`),
|
||||
extensionLocation: URI.revive(data.extensionLocation),
|
||||
...data.packageJSON,
|
||||
});
|
||||
}
|
||||
|
||||
async getExtensions(): Promise<IExtensionDescription[]> {
|
||||
return this._descriptions;
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,8 @@ import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { PersistentConnectionEventType } from 'vs/platform/remote/common/remoteAgentConnection';
|
||||
import { IProductService } from 'vs/platform/product/common/product';
|
||||
import { Logger } from 'vs/workbench/services/extensions/common/extensionPoints';
|
||||
import { flatten } from 'vs/base/common/arrays';
|
||||
import { IStaticExtensionsService } from 'vs/workbench/services/extensions/common/staticExtensions';
|
||||
|
||||
class DeltaExtensionsQueueItem {
|
||||
constructor(
|
||||
@@ -64,6 +66,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
@ILifecycleService private readonly _lifecycleService: ILifecycleService,
|
||||
@IWindowService protected readonly _windowService: IWindowService,
|
||||
@IStaticExtensionsService private readonly _staticExtensions: IStaticExtensionsService,
|
||||
) {
|
||||
super(
|
||||
instantiationService,
|
||||
@@ -72,7 +75,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
||||
telemetryService,
|
||||
extensionEnablementService,
|
||||
fileService,
|
||||
productService,
|
||||
productService
|
||||
);
|
||||
|
||||
if (this._extensionEnablementService.allUserExtensionsDisabled) {
|
||||
@@ -437,7 +440,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
||||
const remoteAuthority = this._environmentService.configuration.remoteAuthority;
|
||||
const extensionHost = this._extensionHostProcessManagers[0];
|
||||
|
||||
let localExtensions = await this._extensionScanner.scannedExtensions;
|
||||
let localExtensions = flatten(await Promise.all([this._extensionScanner.scannedExtensions, this._staticExtensions.getExtensions()]));
|
||||
|
||||
// enable or disable proposed API per extension
|
||||
this._checkEnableProposedApi(localExtensions);
|
||||
@@ -463,7 +466,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
||||
this._remoteAuthorityResolverService.setResolvedAuthorityError(remoteAuthority, err);
|
||||
|
||||
// Proceed with the local extension host
|
||||
await this._startLocalExtensionHost(extensionHost, localExtensions);
|
||||
await this._startLocalExtensionHost(extensionHost, localExtensions, localExtensions.map(extension => extension.identifier));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -508,20 +511,18 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
||||
// save for remote extension's init data
|
||||
this._remoteExtensionsEnvironmentData.set(remoteAuthority, remoteEnv);
|
||||
|
||||
this._handleExtensionPoints((<IExtensionDescription[]>[]).concat(remoteEnv.extensions).concat(localExtensions));
|
||||
extensionHost.start(localExtensions.map(extension => extension.identifier));
|
||||
|
||||
await this._startLocalExtensionHost(extensionHost, remoteEnv.extensions.concat(localExtensions), localExtensions.map(extension => extension.identifier));
|
||||
} else {
|
||||
await this._startLocalExtensionHost(extensionHost, localExtensions);
|
||||
await this._startLocalExtensionHost(extensionHost, localExtensions, localExtensions.map(extension => extension.identifier));
|
||||
}
|
||||
}
|
||||
|
||||
private async _startLocalExtensionHost(extensionHost: ExtensionHostProcessManager, localExtensions: IExtensionDescription[]): Promise<void> {
|
||||
this._handleExtensionPoints(localExtensions);
|
||||
extensionHost.start(localExtensions.map(extension => extension.identifier).filter(id => this._registry.containsExtension(id)));
|
||||
private async _startLocalExtensionHost(extensionHost: ExtensionHostProcessManager, allExtensions: IExtensionDescription[], localExtensions: ExtensionIdentifier[]): Promise<void> {
|
||||
this._registerAndHandleExtensions(allExtensions);
|
||||
extensionHost.start(localExtensions.filter(id => this._registry.containsExtension(id)));
|
||||
}
|
||||
|
||||
private _handleExtensionPoints(allExtensions: IExtensionDescription[]): void {
|
||||
private _registerAndHandleExtensions(allExtensions: IExtensionDescription[]): void {
|
||||
const result = this._registry.deltaExtensions(allExtensions, []);
|
||||
if (result.removedDueToLooping.length > 0) {
|
||||
this._logOrShowMessage(Severity.Error, nls.localize('looping', "The following extensions contain dependency loops and have been disabled: {0}", result.removedDueToLooping.map(e => `'${e.identifier.value}'`).join(', ')));
|
||||
|
||||
@@ -13,8 +13,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { StorageScope, IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { INotificationService, Severity, NeverShowAgainScope } from 'vs/platform/notification/common/notification';
|
||||
import { localize } from 'vs/nls';
|
||||
import { FileService } from 'vs/platform/files/common/fileService';
|
||||
|
||||
@@ -26,8 +25,7 @@ export class WorkspaceWatcher extends Disposable {
|
||||
@IFileService private readonly fileService: FileService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IStorageService private readonly storageService: IStorageService
|
||||
@INotificationService private readonly notificationService: INotificationService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -73,38 +71,34 @@ export class WorkspaceWatcher extends Disposable {
|
||||
onUnexpectedError(msg);
|
||||
|
||||
// Detect if we run < .NET Framework 4.5
|
||||
if (msg.indexOf('System.MissingMethodException') >= 0 && !this.storageService.getBoolean('ignoreNetVersionError', StorageScope.WORKSPACE)) {
|
||||
if (msg.indexOf('System.MissingMethodException') >= 0) {
|
||||
this.notificationService.prompt(
|
||||
Severity.Warning,
|
||||
localize('netVersionError', "The Microsoft .NET Framework 4.5 is required. Please follow the link to install it."),
|
||||
[{
|
||||
label: localize('installNet', "Download .NET Framework 4.5"),
|
||||
run: () => window.open('https://go.microsoft.com/fwlink/?LinkId=786533')
|
||||
},
|
||||
{
|
||||
label: localize('neverShowAgain', "Don't Show Again"),
|
||||
isSecondary: true,
|
||||
run: () => this.storageService.store('ignoreNetVersionError', true, StorageScope.WORKSPACE)
|
||||
}],
|
||||
{ sticky: true }
|
||||
{
|
||||
sticky: true,
|
||||
neverShowAgain: { id: 'ignoreNetVersionError', isSecondary: true, scope: NeverShowAgainScope.WORKSPACE }
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Detect if we run into ENOSPC issues
|
||||
if (msg.indexOf('ENOSPC') >= 0 && !this.storageService.getBoolean('ignoreEnospcError', StorageScope.WORKSPACE)) {
|
||||
if (msg.indexOf('ENOSPC') >= 0) {
|
||||
this.notificationService.prompt(
|
||||
Severity.Warning,
|
||||
localize('enospcError', "Unable to watch for file changes in this large workspace. Please follow the instructions link to resolve this issue."),
|
||||
[{
|
||||
label: localize('learnMore', "Instructions"),
|
||||
run: () => window.open('https://go.microsoft.com/fwlink/?linkid=867693')
|
||||
},
|
||||
{
|
||||
label: localize('neverShowAgain', "Don't Show Again"),
|
||||
isSecondary: true,
|
||||
run: () => this.storageService.store('ignoreEnospcError', true, StorageScope.WORKSPACE)
|
||||
}],
|
||||
{ sticky: true }
|
||||
{
|
||||
sticky: true,
|
||||
neverShowAgain: { id: 'ignoreEnospcError', isSecondary: true, scope: NeverShowAgainScope.WORKSPACE }
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -157,4 +151,4 @@ export class WorkspaceWatcher extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(WorkspaceWatcher, LifecyclePhase.Restored);
|
||||
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(WorkspaceWatcher, LifecyclePhase.Restored);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice, IPromptOptions, IStatusMessageOptions, NoOpNotification } from 'vs/platform/notification/common/notification';
|
||||
import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice, IPromptOptions, IStatusMessageOptions, NoOpNotification, NeverShowAgainScope } from 'vs/platform/notification/common/notification';
|
||||
import { INotificationsModel, NotificationsModel, ChoiceAction } from 'vs/workbench/common/notifications';
|
||||
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
@@ -63,11 +63,12 @@ export class NotificationService extends Disposable implements INotificationServ
|
||||
// Handle neverShowAgain option accordingly
|
||||
let handle: INotificationHandle;
|
||||
if (notification.neverShowAgain) {
|
||||
const scope = notification.neverShowAgain.scope === NeverShowAgainScope.WORKSPACE ? StorageScope.WORKSPACE : StorageScope.GLOBAL;
|
||||
|
||||
// If the user already picked to not show the notification
|
||||
// again, we return with a no-op notification here
|
||||
const id = notification.neverShowAgain.id;
|
||||
if (this.storageService.getBoolean(id, StorageScope.GLOBAL)) {
|
||||
if (this.storageService.getBoolean(id, scope)) {
|
||||
return new NoOpNotification();
|
||||
}
|
||||
|
||||
@@ -80,7 +81,7 @@ export class NotificationService extends Disposable implements INotificationServ
|
||||
handle.close();
|
||||
|
||||
// Remember choice
|
||||
this.storageService.store(id, true, StorageScope.GLOBAL);
|
||||
this.storageService.store(id, true, scope);
|
||||
|
||||
return Promise.resolve();
|
||||
}));
|
||||
@@ -110,17 +111,18 @@ export class NotificationService extends Disposable implements INotificationServ
|
||||
|
||||
// Handle neverShowAgain option accordingly
|
||||
if (options && options.neverShowAgain) {
|
||||
const scope = options.neverShowAgain.scope === NeverShowAgainScope.WORKSPACE ? StorageScope.WORKSPACE : StorageScope.GLOBAL;
|
||||
|
||||
// If the user already picked to not show the notification
|
||||
// again, we return with a no-op notification here
|
||||
const id = options.neverShowAgain.id;
|
||||
if (this.storageService.getBoolean(id, StorageScope.GLOBAL)) {
|
||||
if (this.storageService.getBoolean(id, scope)) {
|
||||
return new NoOpNotification();
|
||||
}
|
||||
|
||||
const neverShowAgainChoice = {
|
||||
label: nls.localize('neverShowAgain', "Don't Show Again"),
|
||||
run: () => this.storageService.store(id, true, StorageScope.GLOBAL),
|
||||
run: () => this.storageService.store(id, true, scope),
|
||||
isSecondary: options.neverShowAgain.isSecondary
|
||||
};
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import * as Json from 'vs/base/common/json';
|
||||
import { ExtensionData, IThemeExtensionPoint, IFileIconTheme } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { getParseErrorMessage } from 'vs/base/common/jsonErrorMessages';
|
||||
import { asDomUri } from 'vs/base/browser/dom';
|
||||
import { asCSSUrl } from 'vs/base/browser/dom';
|
||||
|
||||
export class FileIconThemeData implements IFileIconTheme {
|
||||
id: string;
|
||||
@@ -332,7 +332,7 @@ function _processIconThemeDocument(id: string, iconThemeDocumentLocation: URI, i
|
||||
let fonts = iconThemeDocument.fonts;
|
||||
if (Array.isArray(fonts)) {
|
||||
fonts.forEach(font => {
|
||||
let src = font.src.map(l => `url('${asDomUri(resolvePath(l.path))}') format('${l.format}')`).join(', ');
|
||||
let src = font.src.map(l => `${asCSSUrl(resolvePath(l.path))} format('${l.format}')`).join(', ');
|
||||
cssRules.push(`@font-face { src: ${src}; font-family: '${font.id}'; font-weight: ${font.weight}; font-style: ${font.style}; }`);
|
||||
});
|
||||
cssRules.push(`.show-file-icons .file-icon::before, .show-file-icons .folder-icon::before, .show-file-icons .rootfolder-icon::before { font-family: '${fonts[0].id}'; font-size: ${fonts[0].size || '150%'}}`);
|
||||
@@ -343,7 +343,7 @@ function _processIconThemeDocument(id: string, iconThemeDocumentLocation: URI, i
|
||||
let definition = iconThemeDocument.iconDefinitions[defId];
|
||||
if (definition) {
|
||||
if (definition.iconPath) {
|
||||
cssRules.push(`${selectors.join(', ')} { content: ' '; background-image: url("${asDomUri(resolvePath(definition.iconPath))}"); }`);
|
||||
cssRules.push(`${selectors.join(', ')} { content: ' '; background-image: ${asCSSUrl(resolvePath(definition.iconPath))}; }`);
|
||||
}
|
||||
if (definition.fontCharacter || definition.fontColor) {
|
||||
let body = '';
|
||||
|
||||
@@ -74,6 +74,7 @@ import { IMenubarService } from 'vs/platform/menubar/common/menubar';
|
||||
import { MenubarService } from 'vs/platform/menubar/electron-browser/menubarService';
|
||||
import { IURLService } from 'vs/platform/url/common/url';
|
||||
import { RelayURLService } from 'vs/platform/url/electron-browser/urlService';
|
||||
import { StaticExtensionsService, IStaticExtensionsService } from 'vs/workbench/services/extensions/common/staticExtensions';
|
||||
|
||||
registerSingleton(IClipboardService, ClipboardService, true);
|
||||
registerSingleton(IRequestService, RequestService, true);
|
||||
@@ -86,6 +87,7 @@ registerSingleton(IIssueService, IssueService);
|
||||
registerSingleton(IWorkspacesService, WorkspacesService);
|
||||
registerSingleton(IMenubarService, MenubarService);
|
||||
registerSingleton(IURLService, RelayURLService);
|
||||
registerSingleton(IStaticExtensionsService, class extends StaticExtensionsService { constructor() { super([]); } });
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import { UriComponents } from 'vs/base/common/uri';
|
||||
import { IFileSystemProvider } from 'vs/platform/files/common/files';
|
||||
import { IWebSocketFactory } from 'vs/platform/remote/browser/browserSocketFactory';
|
||||
import { ICredentialsProvider } from 'vs/workbench/services/credentials/browser/credentialsService';
|
||||
import { IExtensionManifest } from 'vs/platform/extensions/common/extensions';
|
||||
|
||||
export interface IWorkbenchConstructionOptions {
|
||||
|
||||
@@ -59,6 +60,11 @@ export interface IWorkbenchConstructionOptions {
|
||||
* Experimental: The credentials provider to store and retrieve secrets.
|
||||
*/
|
||||
credentialsProvider?: ICredentialsProvider;
|
||||
|
||||
/**
|
||||
* Experimental: Add static extensions that cannot be uninstalled but only be disabled.
|
||||
*/
|
||||
staticExtensions?: { packageJSON: IExtensionManifest, extensionLocation: UriComponents }[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user