Merge from vscode 1df23554b2e3d5f1efc6fbc76ee61d3f7f186c6d

This commit is contained in:
ADS Merger
2020-03-12 06:51:03 +00:00
parent a68a6b9e44
commit b5592959c7
56 changed files with 1091 additions and 558 deletions

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
import { PickerQuickAccessProvider, IPickerQuickAccessItem } from 'vs/platform/quickinput/common/quickAccess';
import { PickerQuickAccessProvider, IPickerQuickAccessItem, TriggerAction } from 'vs/platform/quickinput/common/quickAccess';
import { localize } from 'vs/nls';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IDebugService } from 'vs/workbench/contrib/debug/common/debug';
@@ -47,9 +47,18 @@ export class StartDebugQuickAccessProvider extends PickerQuickAccessProvider<IPi
// Launch entry
picks.push({
label: config.name,
ariaLabel: localize('entryAriaLabel', "{0}, debug", config.name),
ariaLabel: localize('entryAriaLabel', "{0}, debug picker", config.name),
description: this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? config.launch.name : '',
highlights: { label: highlights },
buttons: [{
iconClass: 'codicon-gear',
tooltip: localize('customizeTask', "Configure Launch Configuration")
}],
trigger: () => {
config.launch.openConfigFile(false, false);
return TriggerAction.CLOSE_PICKER;
},
accept: async () => {
if (StartAction.isEnabled(this.debugService)) {
this.debugService.getConfigurationManager().selectConfiguration(config.launch, config.name);
@@ -80,7 +89,7 @@ export class StartDebugQuickAccessProvider extends PickerQuickAccessProvider<IPi
// Add Config entry
picks.push({
label,
ariaLabel: localize('entryAriaLabel', "{0}, debug", label),
ariaLabel: localize('entryAriaLabel', "{0}, debug picker", label),
description: this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? launch.name : '',
highlights: { label: withNullAsUndefined(matchesFuzzy(filter, label, true)) },
accept: () => this.commandService.executeCommand('debug.addConfiguration', launch.uri.toString())

View File

@@ -5,7 +5,6 @@
import { URI } from 'vs/base/common/uri';
import * as resources from 'vs/base/common/resources';
import * as nls from 'vs/nls';
import * as platform from 'vs/base/common/platform';
import severity from 'vs/base/common/severity';
import { Event, Emitter } from 'vs/base/common/event';
@@ -34,6 +33,7 @@ import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cance
import { distinct } from 'vs/base/common/arrays';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { localize } from 'vs/nls';
export class DebugSession implements IDebugSession {
@@ -232,7 +232,7 @@ export class DebugSession implements IDebugSession {
*/
async launchOrAttach(config: IConfig): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'launch or attach'));
}
// __sessionID only used for EH debugging (but we add it always for now...)
@@ -250,7 +250,7 @@ export class DebugSession implements IDebugSession {
*/
async terminate(restart = false): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'terminate'));
}
this.cancelAllRequests();
@@ -266,7 +266,7 @@ export class DebugSession implements IDebugSession {
*/
async disconnect(restart = false): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'disconnect'));
}
this.cancelAllRequests();
@@ -278,7 +278,7 @@ export class DebugSession implements IDebugSession {
*/
async restart(): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'restart'));
}
this.cancelAllRequests();
@@ -287,7 +287,7 @@ export class DebugSession implements IDebugSession {
async sendBreakpoints(modelUri: URI, breakpointsToSend: IBreakpoint[], sourceModified: boolean): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'breakpoints'));
}
if (!this.raw.readyForBreakpoints) {
@@ -321,7 +321,7 @@ export class DebugSession implements IDebugSession {
async sendFunctionBreakpoints(fbpts: IFunctionBreakpoint[]): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'function breakpoints'));
}
if (this.raw.readyForBreakpoints) {
@@ -338,7 +338,7 @@ export class DebugSession implements IDebugSession {
async sendExceptionBreakpoints(exbpts: IExceptionBreakpoint[]): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'exception breakpoints'));
}
if (this.raw.readyForBreakpoints) {
@@ -348,10 +348,10 @@ export class DebugSession implements IDebugSession {
async dataBreakpointInfo(name: string, variablesReference?: number): Promise<{ dataId: string | null, description: string, canPersist?: boolean }> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'data breakpoints info'));
}
if (!this.raw.readyForBreakpoints) {
throw new Error(nls.localize('sessionNotReadyForBreakpoints', "Session is not ready for breakpoints"));
throw new Error(localize('sessionNotReadyForBreakpoints', "Session is not ready for breakpoints"));
}
const response = await this.raw.dataBreakpointInfo({ name, variablesReference });
@@ -360,7 +360,7 @@ export class DebugSession implements IDebugSession {
async sendDataBreakpoints(dataBreakpoints: IDataBreakpoint[]): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'data breakpoints'));
}
if (this.raw.readyForBreakpoints) {
@@ -377,7 +377,7 @@ export class DebugSession implements IDebugSession {
async breakpointsLocations(uri: URI, lineNumber: number): Promise<IPosition[]> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'breakpoints locations'));
}
const source = this.getRawSource(uri);
@@ -393,7 +393,7 @@ export class DebugSession implements IDebugSession {
customRequest(request: string, args: any): Promise<DebugProtocol.Response> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", request));
}
return this.raw.custom(request, args);
@@ -401,7 +401,7 @@ export class DebugSession implements IDebugSession {
stackTrace(threadId: number, startFrame: number, levels: number): Promise<DebugProtocol.StackTraceResponse> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'stackTrace'));
}
const token = this.getNewCancellationToken(threadId);
@@ -410,7 +410,7 @@ export class DebugSession implements IDebugSession {
async exceptionInfo(threadId: number): Promise<IExceptionInfo | undefined> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'exceptionInfo'));
}
const response = await this.raw.exceptionInfo({ threadId });
@@ -428,7 +428,7 @@ export class DebugSession implements IDebugSession {
scopes(frameId: number, threadId: number): Promise<DebugProtocol.ScopesResponse> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'scopes'));
}
const token = this.getNewCancellationToken(threadId);
@@ -437,7 +437,7 @@ export class DebugSession implements IDebugSession {
variables(variablesReference: number, threadId: number | undefined, filter: 'indexed' | 'named' | undefined, start: number | undefined, count: number | undefined): Promise<DebugProtocol.VariablesResponse> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'variables'));
}
const token = threadId ? this.getNewCancellationToken(threadId) : undefined;
@@ -446,7 +446,7 @@ export class DebugSession implements IDebugSession {
evaluate(expression: string, frameId: number, context?: string): Promise<DebugProtocol.EvaluateResponse> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'evaluate'));
}
return this.raw.evaluate({ expression, frameId, context });
@@ -454,7 +454,7 @@ export class DebugSession implements IDebugSession {
async restartFrame(frameId: number, threadId: number): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'restartFrame'));
}
await this.raw.restartFrame({ frameId }, threadId);
@@ -462,7 +462,7 @@ export class DebugSession implements IDebugSession {
async next(threadId: number): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'next'));
}
await this.raw.next({ threadId });
@@ -470,7 +470,7 @@ export class DebugSession implements IDebugSession {
async stepIn(threadId: number): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'stepIn'));
}
await this.raw.stepIn({ threadId });
@@ -478,7 +478,7 @@ export class DebugSession implements IDebugSession {
async stepOut(threadId: number): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'stepOut'));
}
await this.raw.stepOut({ threadId });
@@ -486,7 +486,7 @@ export class DebugSession implements IDebugSession {
async stepBack(threadId: number): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'stepBack'));
}
await this.raw.stepBack({ threadId });
@@ -494,7 +494,7 @@ export class DebugSession implements IDebugSession {
async continue(threadId: number): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'continue'));
}
await this.raw.continue({ threadId });
@@ -502,7 +502,7 @@ export class DebugSession implements IDebugSession {
async reverseContinue(threadId: number): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'reverse continue'));
}
await this.raw.reverseContinue({ threadId });
@@ -510,7 +510,7 @@ export class DebugSession implements IDebugSession {
async pause(threadId: number): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'pause'));
}
await this.raw.pause({ threadId });
@@ -518,7 +518,7 @@ export class DebugSession implements IDebugSession {
async terminateThreads(threadIds?: number[]): Promise<void> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'terminateThreads'));
}
await this.raw.terminateThreads({ threadIds });
@@ -526,7 +526,7 @@ export class DebugSession implements IDebugSession {
setVariable(variablesReference: number, name: string, value: string): Promise<DebugProtocol.SetVariableResponse> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'setVariable'));
}
return this.raw.setVariable({ variablesReference, name, value });
@@ -534,7 +534,7 @@ export class DebugSession implements IDebugSession {
gotoTargets(source: DebugProtocol.Source, line: number, column?: number): Promise<DebugProtocol.GotoTargetsResponse> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'gotoTargets'));
}
return this.raw.gotoTargets({ source, line, column });
@@ -542,7 +542,7 @@ export class DebugSession implements IDebugSession {
goto(threadId: number, targetId: number): Promise<DebugProtocol.GotoResponse> {
if (!this.raw) {
throw new Error('no debug adapter');
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'goto'));
}
return this.raw.goto({ threadId, targetId });
@@ -550,7 +550,7 @@ export class DebugSession implements IDebugSession {
loadSource(resource: URI): Promise<DebugProtocol.SourceResponse> {
if (!this.raw) {
return Promise.reject(new Error('no debug adapter'));
return Promise.reject(new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'loadSource')));
}
const source = this.getSourceForUri(resource);
@@ -568,7 +568,7 @@ export class DebugSession implements IDebugSession {
async getLoadedSources(): Promise<Source[]> {
if (!this.raw) {
return Promise.reject(new Error('no debug adapter'));
return Promise.reject(new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'getLoadedSources')));
}
const response = await this.raw.loadedSources({});
@@ -581,7 +581,7 @@ export class DebugSession implements IDebugSession {
async completions(frameId: number | undefined, text: string, position: Position, overwriteBefore: number, token: CancellationToken): Promise<DebugProtocol.CompletionsResponse> {
if (!this.raw) {
return Promise.reject(new Error('no debug adapter'));
return Promise.reject(new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'completions')));
}
return this.raw.completions({
@@ -700,7 +700,7 @@ export class DebugSession implements IDebugSession {
}
this.rawListeners.push(this.raw.onDidInitialize(async () => {
aria.status(nls.localize('debuggingStarted', "Debugging started."));
aria.status(localize('debuggingStarted', "Debugging started."));
const sendConfigurationDone = async () => {
if (this.raw && this.raw.capabilities.supportsConfigurationDoneRequest) {
try {
@@ -782,7 +782,7 @@ export class DebugSession implements IDebugSession {
}));
this.rawListeners.push(this.raw.onDidTerminateDebugee(async event => {
aria.status(nls.localize('debuggingStopped', "Debugging stopped."));
aria.status(localize('debuggingStopped', "Debugging stopped."));
if (event.body && event.body.restart) {
await this.debugService.restartSession(this, event.body.restart);
} else if (this.raw) {

View File

@@ -230,7 +230,7 @@ export class RawDebugSession implements IDisposable {
*/
async start(): Promise<void> {
if (!this.debugAdapter) {
return Promise.reject(new Error('no debug adapter'));
return Promise.reject(new Error(nls.localize('noDebugAdapterStart', "No debug adapter, can not start debug session.")));
}
await this.debugAdapter.startSession();

View File

@@ -754,18 +754,24 @@ export class ShowOpenedFileInNewWindow extends Action {
}
}
export function validateFileName(item: ExplorerItem, name: string): string | null {
export function validateFileName(item: ExplorerItem, name: string): { content: string, severity: Severity } | null {
// Produce a well formed file name
name = getWellFormedFileName(name);
// Name not provided
if (!name || name.length === 0 || /^\s+$/.test(name)) {
return nls.localize('emptyFileNameError', "A file or folder name must be provided.");
return {
content: nls.localize('emptyFileNameError', "A file or folder name must be provided."),
severity: Severity.Error
};
}
// Relative paths only
if (name[0] === '/' || name[0] === '\\') {
return nls.localize('fileNameStartsWithSlashError', "A file or folder name cannot start with a slash.");
return {
content: nls.localize('fileNameStartsWithSlashError', "A file or folder name cannot start with a slash."),
severity: Severity.Error
};
}
const names = coalesce(name.split(/[\\/]/));
@@ -775,14 +781,27 @@ export function validateFileName(item: ExplorerItem, name: string): string | nul
// Do not allow to overwrite existing file
const child = parent?.getChild(name);
if (child && child !== item) {
return nls.localize('fileNameExistsError', "A file or folder **{0}** already exists at this location. Please choose a different name.", name);
return {
content: nls.localize('fileNameExistsError', "A file or folder **{0}** already exists at this location. Please choose a different name.", name),
severity: Severity.Error
};
}
}
// Invalid File name
const windowsBasenameValidity = item.resource.scheme === Schemas.file && isWindows;
if (names.some((folderName) => !extpath.isValidBasename(folderName, windowsBasenameValidity))) {
return nls.localize('invalidFileNameError', "The name **{0}** is not valid as a file or folder name. Please choose a different name.", trimLongName(name));
return {
content: nls.localize('invalidFileNameError', "The name **{0}** is not valid as a file or folder name. Please choose a different name.", trimLongName(name)),
severity: Severity.Error
};
}
if (names.some(name => /^\s|\s$/.test(name))) {
return {
content: nls.localize('fileNameWhitespaceWarning', "Leading or trailing whitespace detected in file or folder name."),
severity: Severity.Warning
};
}
return null;
@@ -804,7 +823,7 @@ export function getWellFormedFileName(filename: string): string {
// Trim tabs
filename = strings.trim(filename, '\t');
// Remove trailing dots, slashes, and spaces
// Remove trailing dots and slashes
filename = strings.rtrim(filename, '.');
filename = strings.rtrim(filename, '/');
filename = strings.rtrim(filename, '\\');

View File

@@ -376,13 +376,13 @@ export class FilesRenderer implements ICompressibleTreeRenderer<ExplorerItem, Fu
const inputBox = new InputBox(label.element, this.contextViewService, {
validationOptions: {
validation: (value) => {
const content = editableData.validationMessage(value);
if (!content) {
const message = editableData.validationMessage(value);
if (!message || message.severity !== Severity.Error) {
return null;
}
return {
content,
content: message.content,
formatContent: true,
type: MessageType.ERROR
};
@@ -392,10 +392,6 @@ export class FilesRenderer implements ICompressibleTreeRenderer<ExplorerItem, Fu
});
const styler = attachInputBoxStyler(inputBox, this.themeService);
inputBox.onDidChange(value => {
label.setFile(joinPath(parent, value || ' '), labelOptions); // update label icon while typing!
});
const lastDot = value.lastIndexOf('.');
inputBox.value = value;
@@ -412,8 +408,27 @@ export class FilesRenderer implements ICompressibleTreeRenderer<ExplorerItem, Fu
}
});
const showInputBoxNotification = () => {
if (inputBox.isInputValid()) {
const message = editableData.validationMessage(inputBox.value);
if (message) {
inputBox.showMessage({
content: message.content,
formatContent: true,
type: message.severity === Severity.Info ? MessageType.INFO : message.severity === Severity.Warning ? MessageType.WARNING : MessageType.ERROR
});
} else {
inputBox.hideMessage();
}
}
};
showInputBoxNotification();
const toDispose = [
inputBox,
inputBox.onDidChange(value => {
label.setFile(joinPath(parent, value || ' '), labelOptions); // update label icon while typing!
}),
DOM.addStandardDisposableListener(inputBox.inputElement, DOM.EventType.KEY_DOWN, (e: IKeyboardEvent) => {
if (e.equals(KeyCode.Enter)) {
if (inputBox.validate()) {
@@ -423,6 +438,9 @@ export class FilesRenderer implements ICompressibleTreeRenderer<ExplorerItem, Fu
done(false, true);
}
}),
DOM.addStandardDisposableListener(inputBox.inputElement, DOM.EventType.KEY_UP, (e: IKeyboardEvent) => {
showInputBoxNotification();
}),
DOM.addDisposableListener(inputBox.inputElement, DOM.EventType.BLUR, () => {
done(inputBox.isInputValid(), true);
}),

View File

@@ -95,6 +95,7 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider<IViewQuic
if (this.contextKeyService.contextMatchesRules(view.when)) {
result.push({
label: view.name,
ariaLabel: localize('viewPickAriaLabel', "{0}, view picker", view.name),
containerLabel: viewlet.name,
accept: () => this.viewsService.openView(view.id, true)
});
@@ -110,6 +111,7 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider<IViewQuic
if (this.includeViewlet(viewlet)) {
viewEntries.push({
label: viewlet.name,
ariaLabel: localize('viewPickAriaLabel', "{0}, view picker", viewlet.name),
containerLabel: localize('views', "Side Bar"),
accept: () => this.viewletService.openViewlet(viewlet.id, true)
});
@@ -121,6 +123,7 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider<IViewQuic
for (const panel of panels) {
viewEntries.push({
label: panel.name,
ariaLabel: localize('viewPickAriaLabel', "{0}, view picker", panel.name),
containerLabel: localize('panels', "Panel"),
accept: () => this.panelService.openPanel(panel.id, true)
});
@@ -137,8 +140,10 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider<IViewQuic
// Terminals
this.terminalService.terminalTabs.forEach((tab, tabIndex) => {
tab.terminalInstances.forEach((terminal, terminalIndex) => {
const label = localize('terminalTitle', "{0}: {1}", `${tabIndex + 1}.${terminalIndex + 1}`, terminal.title);
viewEntries.push({
label: localize('terminalTitle', "{0}: {1}", `${tabIndex + 1}.${terminalIndex + 1}`, terminal.title),
label,
ariaLabel: localize('viewPickAriaLabel', "{0}, view picker", label),
containerLabel: localize('terminals', "Terminal"),
accept: async () => {
await this.terminalService.showPanel(true);
@@ -152,8 +157,10 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider<IViewQuic
// Output Channels
const channels = this.outputService.getChannelDescriptors();
for (const channel of channels) {
const label = channel.log ? localize('logChannel', "Log ({0})", channel.label) : channel.label;
viewEntries.push({
label: channel.log ? localize('logChannel', "Log ({0})", channel.label) : channel.label,
label,
ariaLabel: localize('viewPickAriaLabel', "{0}, view picker", label),
containerLabel: localize('channels', "Output"),
accept: () => this.outputService.showChannel(channel.id)
});

View File

@@ -28,7 +28,7 @@ import { IMenuService, MenuId, IMenu, MenuRegistry, MenuItemAction } from 'vs/pl
import { createAndFillInContextMenuActions, createAndFillInActionBarActions, ContextAwareMenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { IRemoteExplorerService, TunnelModel, MakeAddress, TunnelType, ITunnelItem, Tunnel } from 'vs/workbench/services/remote/common/remoteExplorerService';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox';
import { attachInputBoxStyler } from 'vs/platform/theme/common/styler';
import { once } from 'vs/base/common/functional';
@@ -282,13 +282,13 @@ class TunnelTreeRenderer extends Disposable implements ITreeRenderer<ITunnelGrou
ariaLabel: nls.localize('remote.tunnelsView.input', "Press Enter to confirm or Escape to cancel."),
validationOptions: {
validation: (value) => {
const content = editableData.validationMessage(value);
if (!content) {
const message = editableData.validationMessage(value);
if (!message || message.severity !== Severity.Error) {
return null;
}
return {
content,
content: message.content,
formatContent: true,
type: MessageType.ERROR
};
@@ -657,6 +657,17 @@ export class TunnelPanelDescriptor implements IViewDescriptor {
}
}
function validationMessage(validationString: string | null): { content: string, severity: Severity } | null {
if (!validationString) {
return null;
}
return {
content: validationString,
severity: Severity.Error
};
}
namespace LabelTunnelAction {
export const ID = 'remote.tunnel.label';
export const LABEL = nls.localize('remote.tunnel.label', "Set Label");
@@ -733,7 +744,7 @@ namespace ForwardPortAction {
}
remoteExplorerService.setEditable(undefined, null);
},
validationMessage: validateInput,
validationMessage: (value) => validationMessage(validateInput(value)),
placeholder: forwardPrompt
});
}
@@ -916,7 +927,7 @@ namespace ChangeLocalPortAction {
}
}
},
validationMessage: validateInput,
validationMessage: (value) => validationMessage(validateInput(value)),
placeholder: nls.localize('remote.tunnelsView.changePort', "New local port")
});
}

View File

@@ -5,7 +5,7 @@
import { localize } from 'vs/nls';
import { IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
import { IPickerQuickAccessItem, PickerQuickAccessProvider } from 'vs/platform/quickinput/common/quickAccess';
import { IPickerQuickAccessItem, PickerQuickAccessProvider, TriggerAction } from 'vs/platform/quickinput/common/quickAccess';
import { matchesFuzzy } from 'vs/base/common/filters';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { ITaskService } from 'vs/workbench/contrib/tasks/common/taskService';
@@ -59,14 +59,12 @@ export class TasksQuickAccessProvider extends PickerQuickAccessProvider<IPickerQ
taskMap[key] = task;
}
}
recentlyUsedTasks.keys().forEach(key => {
for (const key of recentlyUsedTasks.keys()) {
const task = taskMap[key];
if (task) {
recent.push(task);
}
});
}
for (const task of tasks) {
const key = task.getRecentlyUsedKey();
if (!key || !recentlyUsedTasks.has(key)) {
@@ -83,13 +81,13 @@ export class TasksQuickAccessProvider extends PickerQuickAccessProvider<IPickerQ
// Fill picks in sorted order
this.fillPicks(taskPicks, filter, recent, localize('recentlyUsed', 'recently used tasks'));
this.fillPicks(taskPicks, filter, recent, localize('recentlyUsed', "recently used tasks"));
configured.sort((a, b) => sorter.compare(a, b));
this.fillPicks(taskPicks, filter, configured, localize('configured', 'configured tasks'));
this.fillPicks(taskPicks, filter, configured, localize('configured', "configured tasks"));
detected.sort((a, b) => sorter.compare(a, b));
this.fillPicks(taskPicks, filter, detected, localize('detected', 'detected tasks'));
this.fillPicks(taskPicks, filter, detected, localize('detected', "detected tasks"));
return taskPicks;
}
@@ -107,7 +105,7 @@ export class TasksQuickAccessProvider extends PickerQuickAccessProvider<IPickerQ
}
taskPicks.push({
label: task._label,
ariaLabel: localize('entryAriaLabel', "{0}, tasks", task._label),
ariaLabel: localize('entryAriaLabel', "{0}, tasks picker", task._label),
description: this.taskService.getTaskDescription(task),
highlights: { label: highlights },
buttons: (() => {
@@ -122,9 +120,6 @@ export class TasksQuickAccessProvider extends PickerQuickAccessProvider<IPickerQ
return buttons;
})(),
accept: () => {
this.taskService.run(task, { attachProblemMatcher: true });
},
trigger: () => {
if (ContributedTask.is(task)) {
this.taskService.customize(task, undefined, true);
@@ -132,7 +127,10 @@ export class TasksQuickAccessProvider extends PickerQuickAccessProvider<IPickerQ
this.taskService.openConfig(task);
}
return true; // close picker
return TriggerAction.CLOSE_PICKER;
},
accept: () => {
this.taskService.run(task, { attachProblemMatcher: true });
}
});
}

View File

@@ -0,0 +1,86 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
import { IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
import { IPickerQuickAccessItem, PickerQuickAccessProvider, TriggerAction } from 'vs/platform/quickinput/common/quickAccess';
import { matchesFuzzy } from 'vs/base/common/filters';
import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminal';
export class TerminalQuickAccessProvider extends PickerQuickAccessProvider<IPickerQuickAccessItem> {
static PREFIX = 'term ';
constructor(
@ITerminalService private readonly terminalService: ITerminalService,
@ICommandService private readonly commandService: ICommandService,
) {
super(TerminalQuickAccessProvider.PREFIX);
}
protected getPicks(filter: string): Array<IPickerQuickAccessItem | IQuickPickSeparator> {
const terminalPicks: Array<IPickerQuickAccessItem | IQuickPickSeparator> = [];
const terminalTabs = this.terminalService.terminalTabs;
for (let tabIndex = 0; tabIndex < terminalTabs.length; tabIndex++) {
const terminalTab = terminalTabs[tabIndex];
for (let terminalIndex = 0; terminalIndex < terminalTab.terminalInstances.length; terminalIndex++) {
const terminal = terminalTab.terminalInstances[terminalIndex];
const label = `${tabIndex + 1}.${terminalIndex + 1}: ${terminal.title}`;
const highlights = matchesFuzzy(filter, label, true);
if (highlights) {
terminalPicks.push({
label,
ariaLabel: localize('termEntryAriaLabel', "{0}, terminal picker", label),
highlights: { label: highlights },
buttons: [
{
iconClass: 'codicon-gear',
tooltip: localize('renameTerminal', "Rename Terminal")
},
{
iconClass: 'codicon-trash',
tooltip: localize('killTerminal', "Kill Terminal Instance")
}
],
trigger: buttonIndex => {
switch (buttonIndex) {
case 0:
this.commandService.executeCommand(TERMINAL_COMMAND_ID.RENAME, terminal);
return TriggerAction.NO_ACTION;
case 1:
terminal.dispose(true);
return TriggerAction.REFRESH_PICKER;
}
return TriggerAction.NO_ACTION;
},
accept: () => {
this.terminalService.setActiveInstance(terminal);
this.terminalService.showPanel(true);
}
});
}
}
}
if (terminalPicks.length > 0) {
terminalPicks.push({ type: 'separator' });
}
const createTerminalLabel = localize("workbench.action.terminal.newplus", "Create New Integrated Terminal");
terminalPicks.push({
label: `$(plus) ${createTerminalLabel}`,
ariaLabel: localize('termEntryAriaLabel', "{0}, terminal picker", createTerminalLabel),
accept: () => this.commandService.executeCommand('workbench.action.terminal.new')
});
return terminalPicks;
}
}

View File

@@ -39,6 +39,8 @@ import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal
import { BrowserFeatures } from 'vs/base/browser/canIUse';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/platform/quickinput/common/quickAccess';
import { TerminalQuickAccessProvider } from 'vs/workbench/contrib/terminal/browser/terminaQuickAccess';
registerSingleton(ITerminalService, TerminalService, true);
@@ -60,6 +62,16 @@ quickOpenRegistry.registerQuickOpenHandler(
)
);
const quickAccessRegistry = (Registry.as<IQuickAccessRegistry>(QuickAccessExtensions.Quickaccess));
quickAccessRegistry.registerQuickAccessProvider({
ctor: TerminalQuickAccessProvider,
prefix: TerminalQuickAccessProvider.PREFIX,
contextKey: inTerminalsPicker,
placeholder: nls.localize('tasksQuickAccessPlaceholder', "Type the name of a terminal to open."),
helpEntries: [{ description: nls.localize('tasksQuickAccessHelp', "Show All Opened Terminals"), needsEditor: false }]
});
const quickOpenNavigateNextInTerminalPickerId = 'workbench.action.quickOpenNavigateNextInTerminalPicker';
CommandsRegistry.registerCommand(
{ id: quickOpenNavigateNextInTerminalPickerId, handler: getQuickNavigateHandler(quickOpenNavigateNextInTerminalPickerId, true) });

View File

@@ -24,7 +24,7 @@ import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiati
import { ITimelineService, TimelineChangeEvent, TimelineItem, TimelineOptions, TimelineProvidersChangeEvent, TimelineRequest, Timeline, TimelinePaneId } from 'vs/workbench/contrib/timeline/common/timeline';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { SideBySideEditor, toResource } from 'vs/workbench/common/editor';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IThemeService, LIGHT, ThemeIcon } from 'vs/platform/theme/common/themeService';
import { IViewDescriptorService } from 'vs/workbench/common/views';
import { basename } from 'vs/base/common/path';
@@ -34,7 +34,7 @@ import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IActionViewItemProvider, ActionBar, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { IAction, ActionRunner } from 'vs/base/common/actions';
import { ContextAwareMenuEntryActionViewItem, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { MenuItemAction, IMenuService, MenuId, registerAction2, Action2 } from 'vs/platform/actions/common/actions';
import { MenuItemAction, IMenuService, MenuId, registerAction2, Action2, MenuRegistry } from 'vs/platform/actions/common/actions';
import { fromNow } from 'vs/base/common/date';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { escapeRegExpCharacters } from 'vs/base/common/strings';
@@ -403,7 +403,7 @@ export class TimelinePane extends ViewPane {
private async handleRequest(request: TimelineRequest) {
let timeline: Timeline | undefined;
try {
timeline = await this.progressService.withProgress({ location: this.getProgressLocation() }, () => request.result);
timeline = await this.progressService.withProgress({ location: this.id }, () => request.result);
}
finally {
this._pendingRequests.delete(request.source);
@@ -932,38 +932,35 @@ class TimelinePaneCommands extends Disposable {
}
}));
this._register(registerAction2(class extends Action2 {
constructor() {
super({
id: 'timeline.toggleFollowActiveEditor',
title: { value: localize('timeline.toggleFollowActiveEditorCommand', "Toggle Active Editor Following"), original: 'Toggle Active Editor Following' },
category: { value: localize('timeline', "Timeline"), original: 'Timeline' },
menu: [{
id: MenuId.TimelineTitle,
command: {
// title: localize(`timeline.toggleFollowActiveEditorCommand.stop`, "Stop following the Active Editor"),
icon: { id: 'codicon/eye' }
},
group: 'navigation',
order: 98,
when: TimelineFollowActiveEditorContext
},
{
id: MenuId.TimelineTitle,
command: {
// title: localize(`ToggleFollowActiveEditorCommand.follow`, "Follow the Active Editor"),
icon: { id: 'codicon/eye-closed' }
},
group: 'navigation',
order: 98,
when: TimelineFollowActiveEditorContext.toNegated()
}]
});
}
run(accessor: ServicesAccessor, ...args: any[]) {
pane.followActiveEditor = !pane.followActiveEditor;
}
}));
this._register(CommandsRegistry.registerCommand('timeline.toggleFollowActiveEditor',
(accessor: ServicesAccessor, ...args: any[]) => pane.followActiveEditor = !pane.followActiveEditor
));
this._register(MenuRegistry.appendMenuItem(MenuId.TimelineTitle, ({
command: {
id: 'timeline.toggleFollowActiveEditor',
title: { value: localize('timeline.toggleFollowActiveEditorCommand', "Toggle Active Editor Following"), original: 'Toggle Active Editor Following' },
// title: localize(`timeline.toggleFollowActiveEditorCommand.stop`, "Stop following the Active Editor"),
icon: { id: 'codicon/eye' },
category: { value: localize('timeline', "Timeline"), original: 'Timeline' },
},
group: 'navigation',
order: 98,
when: TimelineFollowActiveEditorContext
})));
this._register(MenuRegistry.appendMenuItem(MenuId.TimelineTitle, ({
command: {
id: 'timeline.toggleFollowActiveEditor',
title: { value: localize('timeline.toggleFollowActiveEditorCommand', "Toggle Active Editor Following"), original: 'Toggle Active Editor Following' },
// title: localize(`timeline.toggleFollowActiveEditorCommand.stop`, "Stop following the Active Editor"),
icon: { id: 'codicon/eye-closed' },
category: { value: localize('timeline', "Timeline"), original: 'Timeline' },
},
group: 'navigation',
order: 98,
when: TimelineFollowActiveEditorContext.toNegated()
})));
this._register(timelineService.onDidChangeProviders(() => this.updateTimelineSourceFilters()));
this.updateTimelineSourceFilters();

View File

@@ -30,7 +30,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { IQuickInputService, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { CONTEXT_SYNC_STATE, getUserDataSyncStore, ISyncConfiguration, IUserDataAutoSyncService, IUserDataSyncService, IUserDataSyncStore, registerConfiguration, SyncSource, SyncStatus, UserDataSyncError, UserDataSyncErrorCode, USER_DATA_SYNC_SCHEME, IUserDataSyncEnablementService, ResourceKey, getSyncSourceFromPreviewResource, CONTEXT_SYNC_ENABLEMENT, toRemoteSyncResourceFromSource, PREVIEW_QUERY, resolveSyncResource, getSyncSourceFromResourceKey } from 'vs/platform/userDataSync/common/userDataSync';
import { CONTEXT_SYNC_STATE, getUserDataSyncStore, ISyncConfiguration, IUserDataAutoSyncService, IUserDataSyncService, IUserDataSyncStore, registerConfiguration, SyncResource, SyncStatus, UserDataSyncError, UserDataSyncErrorCode, USER_DATA_SYNC_SCHEME, IUserDataSyncEnablementService, getSyncSourceFromPreviewResource, CONTEXT_SYNC_ENABLEMENT, PREVIEW_QUERY, resolveSyncResource, toRemoteSyncResource } from 'vs/platform/userDataSync/common/userDataSync';
import { FloatingClickWidget } from 'vs/workbench/browser/parts/editor/editorWidgets';
import { GLOBAL_ACTIVITY_ID } from 'vs/workbench/common/activity';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
@@ -60,14 +60,14 @@ const enum AuthStatus {
const CONTEXT_AUTH_TOKEN_STATE = new RawContextKey<string>('authTokenStatus', AuthStatus.Initializing);
const CONTEXT_CONFLICTS_SOURCES = new RawContextKey<string>('conflictsSources', '');
type ConfigureSyncQuickPickItem = { id: ResourceKey, label: string, description?: string };
type ConfigureSyncQuickPickItem = { id: SyncResource, label: string, description?: string };
function getSyncAreaLabel(source: SyncSource): string {
function getSyncAreaLabel(source: SyncResource): string {
switch (source) {
case SyncSource.Settings: return localize('settings', "Settings");
case SyncSource.Keybindings: return localize('keybindings', "Keyboard Shortcuts");
case SyncSource.Extensions: return localize('extensions', "Extensions");
case SyncSource.GlobalState: return localize('ui state label', "UI State");
case SyncResource.Settings: return localize('settings', "Settings");
case SyncResource.Keybindings: return localize('keybindings', "Keyboard Shortcuts");
case SyncResource.Extensions: return localize('extensions', "Extensions");
case SyncResource.GlobalState: return localize('ui state label', "UI State");
}
}
@@ -283,8 +283,8 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
this.updateBadge();
}
private readonly conflictsDisposables = new Map<SyncSource, IDisposable>();
private onDidChangeConflicts(conflicts: SyncSource[]) {
private readonly conflictsDisposables = new Map<SyncResource, IDisposable>();
private onDidChangeConflicts(conflicts: SyncResource[]) {
this.updateBadge();
if (conflicts.length) {
this.conflictsSources.set(this.userDataSyncService.conflictsSources.join(','));
@@ -352,22 +352,22 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
}
}
private async acceptRemote(syncSource: SyncSource) {
private async acceptRemote(syncResource: SyncResource) {
try {
const contents = await this.userDataSyncService.resolveContent(toRemoteSyncResourceFromSource(syncSource).with({ query: PREVIEW_QUERY }));
const contents = await this.userDataSyncService.resolveContent(toRemoteSyncResource(syncResource).with({ query: PREVIEW_QUERY }));
if (contents) {
await this.userDataSyncService.accept(syncSource, contents);
await this.userDataSyncService.accept(syncResource, contents);
}
} catch (e) {
this.notificationService.error(e);
}
}
private async acceptLocal(syncSource: SyncSource): Promise<void> {
private async acceptLocal(syncSource: SyncResource): Promise<void> {
try {
const previewResource = syncSource === SyncSource.Settings
const previewResource = syncSource === SyncResource.Settings
? this.workbenchEnvironmentService.settingsSyncPreviewResource
: syncSource === SyncSource.Keybindings
: syncSource === SyncResource.Keybindings
? this.workbenchEnvironmentService.keybindingsSyncPreviewResource
: null;
if (previewResource) {
@@ -415,15 +415,15 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
});
return;
case UserDataSyncErrorCode.TooLarge:
if (error.source === SyncSource.Keybindings || error.source === SyncSource.Settings) {
this.disableSync(error.source);
const sourceArea = getSyncAreaLabel(error.source);
if (error.resource === SyncResource.Keybindings || error.resource === SyncResource.Settings) {
this.disableSync(error.resource);
const sourceArea = getSyncAreaLabel(error.resource);
this.notificationService.notify({
severity: Severity.Error,
message: localize('too large', "Disabled syncing {0} because size of the {1} file to sync is larger than {2}. Please open the file and reduce the size and enable sync", sourceArea.toLowerCase(), sourceArea.toLowerCase(), '100kb'),
actions: {
primary: [new Action('open sync file', localize('open file', "Open {0} File", sourceArea), undefined, true,
() => error.source === SyncSource.Settings ? this.preferencesService.openGlobalSettings(true) : this.preferencesService.openGlobalKeybindingSettings(true))]
() => error.resource === SyncResource.Settings ? this.preferencesService.openGlobalSettings(true) : this.preferencesService.openGlobalKeybindingSettings(true))]
}
});
}
@@ -438,8 +438,8 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
}
}
private readonly invalidContentErrorDisposables = new Map<SyncSource, IDisposable>();
private onSyncErrors(errors: [SyncSource, UserDataSyncError][]): void {
private readonly invalidContentErrorDisposables = new Map<SyncResource, IDisposable>();
private onSyncErrors(errors: [SyncResource, UserDataSyncError][]): void {
if (errors.length) {
for (const [source, error] of errors) {
switch (error.code) {
@@ -460,14 +460,14 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
}
}
private handleInvalidContentError(source: SyncSource): void {
private handleInvalidContentError(source: SyncResource): void {
if (this.invalidContentErrorDisposables.has(source)) {
return;
}
if (source !== SyncSource.Settings && source !== SyncSource.Keybindings) {
if (source !== SyncResource.Settings && source !== SyncResource.Keybindings) {
return;
}
const resource = source === SyncSource.Settings ? this.workbenchEnvironmentService.settingsResource : this.workbenchEnvironmentService.keybindingsResource;
const resource = source === SyncResource.Settings ? this.workbenchEnvironmentService.settingsResource : this.workbenchEnvironmentService.keybindingsResource;
if (isEqual(resource, toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.MASTER }))) {
// Do not show notification if the file in error is active
return;
@@ -478,7 +478,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
message: localize('errorInvalidConfiguration', "Unable to sync {0} because there are some errors/warnings in the file. Please open the file to correct errors/warnings in it.", errorArea.toLowerCase()),
actions: {
primary: [new Action('open sync file', localize('open file', "Open {0} File", errorArea), undefined, true,
() => source === SyncSource.Settings ? this.preferencesService.openGlobalSettings(true) : this.preferencesService.openGlobalKeybindingSettings(true))]
() => source === SyncResource.Settings ? this.preferencesService.openGlobalSettings(true) : this.preferencesService.openGlobalKeybindingSettings(true))]
}
});
this.invalidContentErrorDisposables.set(source, toDisposable(() => {
@@ -602,17 +602,17 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
private getConfigureSyncQuickPickItems(): ConfigureSyncQuickPickItem[] {
return [{
id: 'settings',
label: getSyncAreaLabel(SyncSource.Settings)
id: SyncResource.Settings,
label: getSyncAreaLabel(SyncResource.Settings)
}, {
id: 'keybindings',
label: getSyncAreaLabel(SyncSource.Keybindings)
id: SyncResource.Keybindings,
label: getSyncAreaLabel(SyncResource.Keybindings)
}, {
id: 'extensions',
label: getSyncAreaLabel(SyncSource.Extensions)
id: SyncResource.Extensions,
label: getSyncAreaLabel(SyncResource.Extensions)
}, {
id: 'globalState',
label: getSyncAreaLabel(SyncSource.GlobalState),
id: SyncResource.GlobalState,
label: getSyncAreaLabel(SyncResource.GlobalState),
description: localize('ui state description', "only 'Display Language' for now")
}];
}
@@ -707,15 +707,15 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
}
}
private disableSync(source?: SyncSource): void {
private disableSync(source?: SyncResource): void {
if (source === undefined) {
this.userDataSyncEnablementService.setEnablement(false);
} else {
switch (source) {
case SyncSource.Settings: return this.userDataSyncEnablementService.setResourceEnablement('settings', false);
case SyncSource.Keybindings: return this.userDataSyncEnablementService.setResourceEnablement('keybindings', false);
case SyncSource.Extensions: return this.userDataSyncEnablementService.setResourceEnablement('extensions', false);
case SyncSource.GlobalState: return this.userDataSyncEnablementService.setResourceEnablement('globalState', false);
case SyncResource.Settings: return this.userDataSyncEnablementService.setResourceEnablement(SyncResource.Settings, false);
case SyncResource.Keybindings: return this.userDataSyncEnablementService.setResourceEnablement(SyncResource.Keybindings, false);
case SyncResource.Extensions: return this.userDataSyncEnablementService.setResourceEnablement(SyncResource.Extensions, false);
case SyncResource.GlobalState: return this.userDataSyncEnablementService.setResourceEnablement(SyncResource.GlobalState, false);
}
}
}
@@ -729,9 +729,9 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
}
}
private getConflictsEditorInput(source: SyncSource): IEditorInput | undefined {
const previewResource = source === SyncSource.Settings ? this.workbenchEnvironmentService.settingsSyncPreviewResource
: source === SyncSource.Keybindings ? this.workbenchEnvironmentService.keybindingsSyncPreviewResource
private getConflictsEditorInput(source: SyncResource): IEditorInput | undefined {
const previewResource = source === SyncResource.Settings ? this.workbenchEnvironmentService.settingsSyncPreviewResource
: source === SyncResource.Keybindings ? this.workbenchEnvironmentService.keybindingsSyncPreviewResource
: null;
return previewResource ? this.editorService.editors.filter(input => input instanceof DiffEditorInput && isEqual(previewResource, input.master.resource))[0] : undefined;
}
@@ -743,18 +743,18 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
});
}
private async handleConflicts(source: SyncSource): Promise<void> {
private async handleConflicts(resource: SyncResource): Promise<void> {
let previewResource: URI | undefined = undefined;
let label: string = '';
if (source === SyncSource.Settings) {
if (resource === SyncResource.Settings) {
previewResource = this.workbenchEnvironmentService.settingsSyncPreviewResource;
label = localize('settings conflicts preview', "Settings Conflicts (Remote ↔ Local)");
} else if (source === SyncSource.Keybindings) {
} else if (resource === SyncResource.Keybindings) {
previewResource = this.workbenchEnvironmentService.keybindingsSyncPreviewResource;
label = localize('keybindings conflicts preview', "Keybindings Conflicts (Remote ↔ Local)");
}
if (previewResource) {
const remoteContentResource = toRemoteSyncResourceFromSource(source).with({ query: PREVIEW_QUERY });
const remoteContentResource = toRemoteSyncResource(resource).with({ query: PREVIEW_QUERY });
await this.editorService.openEditor({
leftResource: remoteContentResource,
rightResource: previewResource,
@@ -846,7 +846,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
private registerShowSettingsConflictsAction(): void {
const resolveSettingsConflictsWhenContext = ContextKeyExpr.regex(CONTEXT_CONFLICTS_SOURCES.keys()[0], /.*settings.*/i);
CommandsRegistry.registerCommand(resolveSettingsConflictsCommand.id, () => this.handleConflicts(SyncSource.Settings));
CommandsRegistry.registerCommand(resolveSettingsConflictsCommand.id, () => this.handleConflicts(SyncResource.Settings));
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {
group: '5_sync',
command: {
@@ -873,7 +873,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
private registerShowKeybindingsConflictsAction(): void {
const resolveKeybindingsConflictsWhenContext = ContextKeyExpr.regex(CONTEXT_CONFLICTS_SOURCES.keys()[0], /.*keybindings.*/i);
CommandsRegistry.registerCommand(resolveKeybindingsConflictsCommand.id, () => this.handleConflicts(SyncSource.Keybindings));
CommandsRegistry.registerCommand(resolveKeybindingsConflictsCommand.id, () => this.handleConflicts(SyncResource.Keybindings));
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {
group: '5_sync',
command: {
@@ -934,10 +934,10 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
if (that.userDataSyncService.conflictsSources.length) {
for (const source of that.userDataSyncService.conflictsSources) {
switch (source) {
case SyncSource.Settings:
case SyncResource.Settings:
items.push({ id: resolveSettingsConflictsCommand.id, label: resolveSettingsConflictsCommand.title });
break;
case SyncSource.Keybindings:
case SyncResource.Keybindings:
items.push({ id: resolveKeybindingsConflictsCommand.id, label: resolveKeybindingsConflictsCommand.title });
break;
}
@@ -1130,7 +1130,7 @@ class AcceptChangesContribution extends Disposable implements IEditorContributio
this._register(this.acceptChangesButton.onClick(async () => {
const model = this.editor.getModel();
if (model) {
const conflictsSource = (getSyncSourceFromPreviewResource(model.uri, this.environmentService) || getSyncSourceFromResourceKey(resolveSyncResource(model.uri)!.resourceKey))!;
const conflictsSource = (getSyncSourceFromPreviewResource(model.uri, this.environmentService) || resolveSyncResource(model.uri)!.resource)!;
this.telemetryService.publicLog2<{ source: string, action: string }, SyncConflictsClassification>('sync/handleConflicts', { source: conflictsSource, action: isRemote ? 'acceptRemote' : 'acceptLocal' });
const syncAreaLabel = getSyncAreaLabel(conflictsSource);
const result = await this.dialogService.confirm({

View File

@@ -10,7 +10,7 @@ import { localize } from 'vs/nls';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { TreeViewPane, TreeView } from 'vs/workbench/browser/parts/views/treeView';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ALL_RESOURCE_KEYS, CONTEXT_SYNC_ENABLEMENT, IUserDataSyncStoreService, toRemoteSyncResource, resolveSyncResource, IUserDataSyncBackupStoreService, IResourceRefHandle, ResourceKey, toLocalBackupSyncResource } from 'vs/platform/userDataSync/common/userDataSync';
import { ALL_SYNC_RESOURCES, CONTEXT_SYNC_ENABLEMENT, IUserDataSyncStoreService, toRemoteSyncResource, resolveSyncResource, IUserDataSyncBackupStoreService, IResourceRefHandle, toLocalBackupSyncResource, SyncResource } from 'vs/platform/userDataSync/common/userDataSync';
import { registerAction2, Action2, MenuId } from 'vs/platform/actions/common/actions';
import { IContextKeyService, RawContextKey, ContextKeyExpr, ContextKeyEqualsExpr } from 'vs/platform/contextkey/common/contextkey';
import { URI } from 'vs/base/common/uri';
@@ -61,8 +61,8 @@ export class UserDataSyncViewContribution implements IWorkbenchContribution {
if (visible && !treeView.dataProvider) {
disposable.dispose();
treeView.dataProvider = this.instantiationService.createInstance(UserDataSyncHistoryViewDataProvider, id,
(resourceKey: ResourceKey) => remote ? this.userDataSyncStoreService.getAllRefs(resourceKey) : this.userDataSyncBackupStoreService.getAllRefs(resourceKey),
(resourceKey: ResourceKey, ref: string) => remote ? toRemoteSyncResource(resourceKey, ref) : toLocalBackupSyncResource(resourceKey, ref));
(resource: SyncResource) => remote ? this.userDataSyncStoreService.getAllRefs(resource) : this.userDataSyncBackupStoreService.getAllRefs(resource),
(resource: SyncResource, ref: string) => remote ? toRemoteSyncResource(resource, ref) : toLocalBackupSyncResource(resource, ref));
}
});
const viewsRegistry = Registry.as<IViewsRegistry>(Extensions.ViewsRegistry);
@@ -114,7 +114,7 @@ export class UserDataSyncViewContribution implements IWorkbenchContribution {
let resource = URI.parse(handle.$treeItemHandle);
const result = resolveSyncResource(resource);
if (result) {
resource = resource.with({ fragment: result.resourceKey });
resource = resource.with({ fragment: result.resource });
await editorService.openEditor({ resource });
}
}
@@ -152,8 +152,8 @@ export class UserDataSyncViewContribution implements IWorkbenchContribution {
const resource = URI.parse(handle.$treeItemHandle);
const result = resolveSyncResource(resource);
if (result) {
const leftResource: URI = resource.with({ fragment: result.resourceKey });
const rightResource: URI = result.resourceKey === 'settings' ? environmentService.settingsResource : environmentService.keybindingsResource;
const leftResource: URI = resource.with({ fragment: result.resource });
const rightResource: URI = result.resource === 'settings' ? environmentService.settingsResource : environmentService.keybindingsResource;
await editorService.openEditor({
leftResource,
rightResource,
@@ -174,8 +174,8 @@ class UserDataSyncHistoryViewDataProvider implements ITreeViewDataProvider {
constructor(
private readonly viewId: string,
private getAllRefs: (resourceKey: ResourceKey) => Promise<IResourceRefHandle[]>,
private toResource: (resourceKey: ResourceKey, ref: string) => URI
private getAllRefs: (resource: SyncResource) => Promise<IResourceRefHandle[]>,
private toResource: (resource: SyncResource, ref: string) => URI
) {
}
@@ -183,7 +183,7 @@ class UserDataSyncHistoryViewDataProvider implements ITreeViewDataProvider {
if (element) {
return this.getResources(element.handle);
}
return ALL_RESOURCE_KEYS.map(resourceKey => ({
return ALL_SYNC_RESOURCES.map(resourceKey => ({
handle: resourceKey,
collapsibleState: TreeItemCollapsibleState.Collapsed,
label: { label: resourceKey },
@@ -193,7 +193,7 @@ class UserDataSyncHistoryViewDataProvider implements ITreeViewDataProvider {
}
private async getResources(handle: string): Promise<ITreeItem[]> {
const resourceKey = ALL_RESOURCE_KEYS.filter(key => key === handle)[0];
const resourceKey = ALL_SYNC_RESOURCES.filter(key => key === handle)[0];
if (resourceKey) {
const refHandles = await this.getAllRefs(resourceKey);
return refHandles.map(({ ref, created }) => {