diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts index 822ba16de3c..27469c14739 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts @@ -50,7 +50,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { DiskFileSystemProvider } from 'vs/platform/files/electron-browser/diskFileSystemProvider'; import { Schemas } from 'vs/base/common/network'; import { IProductService } from 'vs/platform/product/common/productService'; -import { IUserDataSyncService, IUserDataSyncStoreService, ISettingsMergeService, registerConfiguration, IUserDataSyncLogService, IUserKeybindingsResolverService } from 'vs/platform/userDataSync/common/userDataSync'; +import { IUserDataSyncService, IUserDataSyncStoreService, ISettingsMergeService, registerConfiguration, IUserDataSyncLogService, IUserDataSyncUtilService } from 'vs/platform/userDataSync/common/userDataSync'; import { UserDataSyncService, UserDataAutoSync } from 'vs/platform/userDataSync/common/userDataSyncService'; import { UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService'; import { UserDataSyncChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc'; @@ -63,7 +63,7 @@ import { AuthTokenService } from 'vs/platform/auth/electron-browser/authTokenSer import { AuthTokenChannel } from 'vs/platform/auth/common/authTokenIpc'; import { ICredentialsService } from 'vs/platform/credentials/common/credentials'; import { KeytarCredentialsService } from 'vs/platform/credentials/node/credentialsService'; -import { UserKeybindingsResolverServiceClient } from 'vs/platform/userDataSync/common/keybindingsSyncIpc'; +import { UserDataSyncUtilServiceClient } from 'vs/platform/userDataSync/common/keybindingsSyncIpc'; export interface ISharedProcessConfiguration { readonly machineId: string; @@ -187,7 +187,7 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat services.set(IUserDataSyncLogService, new SyncDescriptor(UserDataSyncLogService)); const settingsMergeChannel = server.getChannel('settingsMerge', activeWindowRouter); services.set(ISettingsMergeService, new SettingsMergeChannelClient(settingsMergeChannel)); - services.set(IUserKeybindingsResolverService, new UserKeybindingsResolverServiceClient(server.getChannel('userKeybindingsResolver', activeWindowRouter))); + services.set(IUserDataSyncUtilService, new UserDataSyncUtilServiceClient(server.getChannel('userDataSyncUtil', activeWindowRouter))); services.set(IUserDataSyncStoreService, new SyncDescriptor(UserDataSyncStoreService)); services.set(IUserDataSyncService, new SyncDescriptor(UserDataSyncService)); registerConfiguration(); diff --git a/src/vs/platform/userDataSync/common/content.ts b/src/vs/platform/userDataSync/common/content.ts index f50d0c0bfb1..5dd3d97a427 100644 --- a/src/vs/platform/userDataSync/common/content.ts +++ b/src/vs/platform/userDataSync/common/content.ts @@ -3,13 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { OperatingSystem, OS } from 'vs/base/common/platform'; import { JSONPath } from 'vs/base/common/json'; import { setProperty } from 'vs/base/common/jsonEdit'; +import { FormattingOptions } from 'vs/base/common/jsonFormatter'; -export function edit(content: string, eol: string, originalPath: JSONPath, value: any): string { - const edit = setProperty(content, originalPath, value, { tabSize: 4, insertSpaces: false, eol })[0]; +export function edit(content: string, originalPath: JSONPath, value: any, formattingOptions: FormattingOptions): string { + const edit = setProperty(content, originalPath, value, formattingOptions)[0]; if (edit) { content = content.substring(0, edit.offset) + edit.content + content.substring(edit.offset + edit.length); } @@ -51,14 +51,3 @@ export function getLineEndOffset(content: string, eol: string, atOffset: number) } return content.length - 1; } - -export function getEol(content: string): string { - if (content.indexOf('\r\n') !== -1) { - return '\r\n'; - } - if (content.indexOf('\n') !== -1) { - return '\n'; - } - return OS === OperatingSystem.Linux || OS === OperatingSystem.Macintosh ? '\n' : '\r\n'; -} - diff --git a/src/vs/platform/userDataSync/common/keybindingsMerge.ts b/src/vs/platform/userDataSync/common/keybindingsMerge.ts index c41df367b34..3c9910a3095 100644 --- a/src/vs/platform/userDataSync/common/keybindingsMerge.ts +++ b/src/vs/platform/userDataSync/common/keybindingsMerge.ts @@ -11,6 +11,8 @@ import { firstIndex as findFirstIndex, equals } from 'vs/base/common/arrays'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import * as contentUtil from 'vs/platform/userDataSync/common/content'; import { IStringDictionary } from 'vs/base/common/collections'; +import { FormattingOptions } from 'vs/base/common/jsonFormatter'; +import { IUserDataSyncUtilService } from 'vs/platform/userDataSync/common/userDataSync'; interface ICompareResult { added: Set; @@ -27,11 +29,13 @@ interface IMergeResult { conflicts: Set; } -export function merge(localContent: string, remoteContent: string, baseContent: string | null, normalizedKeys: IStringDictionary): { mergeContent: string, hasChanges: boolean, hasConflicts: boolean } { +export async function merge(localContent: string, remoteContent: string, baseContent: string | null, formattingOptions: FormattingOptions, userDataSyncUtilService: IUserDataSyncUtilService): Promise<{ mergeContent: string, hasChanges: boolean, hasConflicts: boolean }> { const local = parse(localContent); const remote = parse(remoteContent); const base = baseContent ? parse(baseContent) : null; + const userbindings: string[] = [...local, ...remote, ...(base || [])].map(keybinding => keybinding.key); + const normalizedKeys = await userDataSyncUtilService.resolveUserBindings(userbindings); let keybindingsMergeResult = computeMergeResultByKeybinding(local, remote, base, normalizedKeys); if (!keybindingsMergeResult.hasLocalForwarded && !keybindingsMergeResult.hasRemoteForwarded) { @@ -57,7 +61,6 @@ export function merge(localContent: string, remoteContent: string, baseContent: const baseToRemoteByCommand = baseByCommand ? compareByCommand(baseByCommand, remoteByCommand, normalizedKeys) : { added: keys(remoteByCommand).reduce((r, k) => { r.add(k); return r; }, new Set()), removed: new Set(), updated: new Set() }; const commandsMergeResult = computeMergeResult(localToRemoteByCommand, baseToLocalByCommand, baseToRemoteByCommand); - const eol = contentUtil.getEol(localContent); let mergeContent = localContent; // Removed commands in Remote @@ -65,7 +68,7 @@ export function merge(localContent: string, remoteContent: string, baseContent: if (commandsMergeResult.conflicts.has(command)) { continue; } - mergeContent = removeKeybindings(mergeContent, eol, command); + mergeContent = removeKeybindings(mergeContent, command, formattingOptions); } // Added commands in remote @@ -79,7 +82,7 @@ export function merge(localContent: string, remoteContent: string, baseContent: commandsMergeResult.conflicts.add(command); continue; } - mergeContent = addKeybindings(mergeContent, eol, keybindings); + mergeContent = addKeybindings(mergeContent, keybindings, formattingOptions); } // Updated commands in Remote @@ -93,16 +96,16 @@ export function merge(localContent: string, remoteContent: string, baseContent: commandsMergeResult.conflicts.add(command); continue; } - mergeContent = updateKeybindings(mergeContent, eol, command, keybindings); + mergeContent = updateKeybindings(mergeContent, command, keybindings, formattingOptions); } const hasConflicts = commandsMergeResult.conflicts.size > 0; if (hasConflicts) { - mergeContent = `<<<<<<< local${eol}` + mergeContent = `<<<<<<< local${formattingOptions.eol}` + mergeContent - + `${eol}=======${eol}` + + `${formattingOptions.eol}=======${formattingOptions.eol}` + remoteContent - + `${eol}>>>>>>> remote`; + + `${formattingOptions.eol}>>>>>>> remote`; } return { mergeContent, hasChanges: true, hasConflicts }; @@ -330,35 +333,35 @@ function isSameKeybinding(a: IUserFriendlyKeybinding, b: IUserFriendlyKeybinding return true; } -function addKeybindings(content: string, eol: string, keybindings: IUserFriendlyKeybinding[]): string { +function addKeybindings(content: string, keybindings: IUserFriendlyKeybinding[], formattingOptions: FormattingOptions): string { for (const keybinding of keybindings) { - content = contentUtil.edit(content, eol, [-1], keybinding); + content = contentUtil.edit(content, [-1], keybinding, formattingOptions); } return content; } -function removeKeybindings(content: string, eol: string, command: string): string { +function removeKeybindings(content: string, command: string, formattingOptions: FormattingOptions): string { const keybindings = parse(content); for (let index = keybindings.length - 1; index >= 0; index--) { if (keybindings[index].command === command || keybindings[index].command === `-${command}`) { - content = contentUtil.edit(content, eol, [index], undefined); + content = contentUtil.edit(content, [index], undefined, formattingOptions); } } return content; } -function updateKeybindings(content: string, eol: string, command: string, keybindings: IUserFriendlyKeybinding[]): string { +function updateKeybindings(content: string, command: string, keybindings: IUserFriendlyKeybinding[], formattingOptions: FormattingOptions): string { const allKeybindings = parse(content); const location = findFirstIndex(allKeybindings, keybinding => keybinding.command === command || keybinding.command === `-${command}`); // Remove all entries with this command for (let index = allKeybindings.length - 1; index >= 0; index--) { if (allKeybindings[index].command === command || allKeybindings[index].command === `-${command}`) { - content = contentUtil.edit(content, eol, [index], undefined); + content = contentUtil.edit(content, [index], undefined, formattingOptions); } } // add all entries at the same location where the entry with this command was located. for (let index = keybindings.length - 1; index >= 0; index--) { - content = contentUtil.edit(content, eol, [location], keybindings[index]); + content = contentUtil.edit(content, [location], keybindings[index], formattingOptions); } return content; } diff --git a/src/vs/platform/userDataSync/common/keybindingsSync.ts b/src/vs/platform/userDataSync/common/keybindingsSync.ts index 20779f8687d..f278643a849 100644 --- a/src/vs/platform/userDataSync/common/keybindingsSync.ts +++ b/src/vs/platform/userDataSync/common/keybindingsSync.ts @@ -5,7 +5,7 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { IFileService, FileSystemProviderErrorCode, FileSystemProviderError, IFileContent } from 'vs/platform/files/common/files'; -import { IUserData, UserDataSyncStoreError, UserDataSyncStoreErrorCode, ISynchroniser, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserKeybindingsResolverService } from 'vs/platform/userDataSync/common/userDataSync'; +import { IUserData, UserDataSyncStoreError, UserDataSyncStoreErrorCode, ISynchroniser, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSyncUtilService } from 'vs/platform/userDataSync/common/userDataSync'; import { merge } from 'vs/platform/userDataSync/common/keybindingsMerge'; import { VSBuffer } from 'vs/base/common/buffer'; import { parse, ParseError } from 'vs/base/common/json'; @@ -58,7 +58,7 @@ export class KeybindingsSynchroniser extends Disposable implements ISynchroniser @IConfigurationService private readonly configurationService: IConfigurationService, @IFileService private readonly fileService: IFileService, @IEnvironmentService private readonly environmentService: IEnvironmentService, - @IUserKeybindingsResolverService private readonly userKeybindingsResolverService: IUserKeybindingsResolverService, + @IUserDataSyncUtilService private readonly userDataSyncUtilService: IUserDataSyncUtilService, ) { super(); this.lastSyncKeybindingsResource = joinPath(this.environmentService.userRoamingDataHome, '.lastSyncKeybindings.json'); @@ -234,8 +234,8 @@ export class KeybindingsSynchroniser extends Disposable implements ISynchroniser || lastSyncContent !== remoteContent // Remote has forwarded ) { this.logService.trace('Keybindings: Merging remote keybindings with local keybindings...'); - const keys = await this.userKeybindingsResolverService.resolveUserKeybindings(localContent, remoteContent, lastSyncContent); - const result = merge(localContent, remoteContent, lastSyncContent, keys); + const formattingOptions = await this.userDataSyncUtilService.resolveFormattingOptions(this.environmentService.keybindingsResource); + const result = await merge(localContent, remoteContent, lastSyncContent, formattingOptions, this.userDataSyncUtilService); // Sync only if there are changes if (result.hasChanges) { hasLocalChanged = result.mergeContent !== localContent; diff --git a/src/vs/platform/userDataSync/common/keybindingsSyncIpc.ts b/src/vs/platform/userDataSync/common/keybindingsSyncIpc.ts index c4c852604a9..f23b3c90c0b 100644 --- a/src/vs/platform/userDataSync/common/keybindingsSyncIpc.ts +++ b/src/vs/platform/userDataSync/common/keybindingsSyncIpc.ts @@ -5,12 +5,14 @@ import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; import { Event } from 'vs/base/common/event'; -import { IUserKeybindingsResolverService } from 'vs/platform/userDataSync/common/userDataSync'; +import { IUserDataSyncUtilService } from 'vs/platform/userDataSync/common/userDataSync'; import { IStringDictionary } from 'vs/base/common/collections'; +import { URI } from 'vs/base/common/uri'; +import { FormattingOptions } from 'vs/base/common/jsonFormatter'; -export class UserKeybindingsResolverServiceChannel implements IServerChannel { +export class UserDataSycnUtilServiceChannel implements IServerChannel { - constructor(private readonly service: IUserKeybindingsResolverService) { } + constructor(private readonly service: IUserDataSyncUtilService) { } listen(_: unknown, event: string): Event { throw new Error(`Event not found: ${event}`); @@ -18,21 +20,26 @@ export class UserKeybindingsResolverServiceChannel implements IServerChannel { call(context: any, command: string, args?: any): Promise { switch (command) { - case 'resolveUserKeybindings': return this.service.resolveUserKeybindings(args[0], args[1], args[2]); + case 'resolveUserKeybindings': return this.service.resolveUserBindings(args[0]); + case 'resolveFormattingOptions': return this.service.resolveFormattingOptions(URI.revive(args[0])); } throw new Error('Invalid call'); } } -export class UserKeybindingsResolverServiceClient implements IUserKeybindingsResolverService { +export class UserDataSyncUtilServiceClient implements IUserDataSyncUtilService { _serviceBrand: undefined; constructor(private readonly channel: IChannel) { } - async resolveUserKeybindings(localContent: string, remoteContent: string, baseContent: string | null): Promise> { - return this.channel.call('resolveUserKeybindings', [localContent, remoteContent, baseContent]); + async resolveUserBindings(userbindings: string[]): Promise> { + return this.channel.call('resolveUserKeybindings', [userbindings]); + } + + async resolveFormattingOptions(file: URI): Promise { + return this.channel.call('resolveFormattingOptions', [file]); } } diff --git a/src/vs/platform/userDataSync/common/userDataSync.ts b/src/vs/platform/userDataSync/common/userDataSync.ts index a809bdf74ca..bc76b41f9b0 100644 --- a/src/vs/platform/userDataSync/common/userDataSync.ts +++ b/src/vs/platform/userDataSync/common/userDataSync.ts @@ -16,6 +16,8 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { ILogService } from 'vs/platform/log/common/log'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IStringDictionary } from 'vs/base/common/collections'; +import { FormattingOptions } from 'vs/base/common/jsonFormatter'; +import { URI } from 'vs/base/common/uri'; const CONFIGURATION_SYNC_STORE_KEY = 'configurationSync.store'; @@ -187,13 +189,15 @@ export interface ISettingsMergeService { } -export const IUserKeybindingsResolverService = createDecorator('IUserKeybindingsResolverService'); +export const IUserDataSyncUtilService = createDecorator('IUserDataSyncUtilService'); -export interface IUserKeybindingsResolverService { +export interface IUserDataSyncUtilService { _serviceBrand: undefined; - resolveUserKeybindings(localContent: string, remoteContent: string, baseContent: string | null): Promise>; + resolveUserBindings(userbindings: string[]): Promise>; + + resolveFormattingOptions(resource: URI): Promise; } diff --git a/src/vs/platform/userDataSync/test/common/keybindingsMerge.test.ts b/src/vs/platform/userDataSync/test/common/keybindingsMerge.test.ts index 4d81421ed62..d6cce88a7bd 100644 --- a/src/vs/platform/userDataSync/test/common/keybindingsMerge.test.ts +++ b/src/vs/platform/userDataSync/test/common/keybindingsMerge.test.ts @@ -6,15 +6,17 @@ import * as assert from 'assert'; import { merge } from 'vs/platform/userDataSync/common/keybindingsMerge'; import { IStringDictionary } from 'vs/base/common/collections'; -import { IUserFriendlyKeybinding } from 'vs/platform/keybinding/common/keybinding'; -import { parse } from 'vs/base/common/json'; +import { OperatingSystem, OS } from 'vs/base/common/platform'; +import { IUserDataSyncUtilService } from 'vs/platform/userDataSync/common/userDataSync'; +import { FormattingOptions } from 'vs/base/common/jsonFormatter'; +import { URI } from 'vs/base/common/uri'; suite('KeybindingsMerge - No Conflicts', () => { test('merge when local and remote are same with one entry', async () => { const localContent = stringify([{ key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); const remoteContent = stringify([{ key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); - const actual = mergeKeybindings(localContent, remoteContent, null); + const actual = await mergeKeybindings(localContent, remoteContent, null); assert.ok(!actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, localContent); @@ -23,7 +25,7 @@ suite('KeybindingsMerge - No Conflicts', () => { test('merge when local and remote are same with similar when contexts', async () => { const localContent = stringify([{ key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); const remoteContent = stringify([{ key: 'alt+c', command: 'a', when: '!editorReadonly && editorTextFocus' }]); - const actual = mergeKeybindings(localContent, remoteContent, null); + const actual = await mergeKeybindings(localContent, remoteContent, null); assert.ok(!actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, localContent); @@ -38,7 +40,7 @@ suite('KeybindingsMerge - No Conflicts', () => { { key: 'alt+a', command: 'a', when: 'editorTextFocus' }, { key: 'alt+d', command: 'a', when: 'editorTextFocus && !editorReadonly' } ]); - const actual = mergeKeybindings(localContent, remoteContent, null); + const actual = await mergeKeybindings(localContent, remoteContent, null); assert.ok(!actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, localContent); @@ -55,7 +57,7 @@ suite('KeybindingsMerge - No Conflicts', () => { { key: 'alt+d', command: '-a' }, { key: 'cmd+c', command: 'b', args: { text: '`' } } ]); - const actual = mergeKeybindings(localContent, remoteContent, null); + const actual = await mergeKeybindings(localContent, remoteContent, null); assert.ok(!actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, localContent); @@ -76,7 +78,7 @@ suite('KeybindingsMerge - No Conflicts', () => { { key: 'alt+d', command: '-a' }, { key: 'cmd+c', command: 'b', args: { text: '`' } } ]); - const actual = mergeKeybindings(localContent, remoteContent, baseContent); + const actual = await mergeKeybindings(localContent, remoteContent, baseContent); assert.ok(!actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, localContent); @@ -93,7 +95,7 @@ suite('KeybindingsMerge - No Conflicts', () => { { key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }, { key: 'alt+d', command: '-a' }, ]); - const actual = mergeKeybindings(localContent, remoteContent, null); + const actual = await mergeKeybindings(localContent, remoteContent, null); assert.ok(!actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, localContent); @@ -110,7 +112,7 @@ suite('KeybindingsMerge - No Conflicts', () => { { key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }, { key: 'cmd+c', command: 'b', args: { text: '`' } }, ]); - const actual = mergeKeybindings(localContent, remoteContent, null); + const actual = await mergeKeybindings(localContent, remoteContent, null); assert.ok(!actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, localContent); @@ -126,7 +128,7 @@ suite('KeybindingsMerge - No Conflicts', () => { { key: 'alt+d', command: '-a' }, { key: 'cmd+c', command: 'b', args: { text: '`' } }, ]); - const actual = mergeKeybindings(localContent, remoteContent, null); + const actual = await mergeKeybindings(localContent, remoteContent, null); assert.ok(actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, remoteContent); @@ -143,7 +145,7 @@ suite('KeybindingsMerge - No Conflicts', () => { { key: 'cmd+c', command: 'b', args: { text: '`' } }, { key: 'cmd+d', command: 'c' }, ]); - const actual = mergeKeybindings(localContent, remoteContent, null); + const actual = await mergeKeybindings(localContent, remoteContent, null); assert.ok(actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, remoteContent); @@ -160,7 +162,7 @@ suite('KeybindingsMerge - No Conflicts', () => { { key: 'cmd+c', command: 'b', args: { text: '`' } }, { key: 'cmd+d', command: 'c' }, ]); - const actual = mergeKeybindings(localContent, remoteContent, localContent); + const actual = await mergeKeybindings(localContent, remoteContent, localContent); assert.ok(actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, remoteContent); @@ -176,7 +178,7 @@ suite('KeybindingsMerge - No Conflicts', () => { { key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }, { key: 'alt+d', command: '-a' }, ]); - const actual = mergeKeybindings(localContent, remoteContent, localContent); + const actual = await mergeKeybindings(localContent, remoteContent, localContent); assert.ok(actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, remoteContent); @@ -190,7 +192,7 @@ suite('KeybindingsMerge - No Conflicts', () => { const remoteContent = stringify([ { key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }, ]); - const actual = mergeKeybindings(localContent, remoteContent, localContent); + const actual = await mergeKeybindings(localContent, remoteContent, localContent); assert.ok(actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, remoteContent); @@ -203,7 +205,7 @@ suite('KeybindingsMerge - No Conflicts', () => { const remoteContent = stringify([ { key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }, ]); - const actual = mergeKeybindings(localContent, remoteContent, localContent); + const actual = await mergeKeybindings(localContent, remoteContent, localContent); assert.ok(actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, remoteContent); @@ -222,7 +224,7 @@ suite('KeybindingsMerge - No Conflicts', () => { { key: 'alt+d', command: 'b' }, { key: 'cmd+d', command: 'a' }, ]); - const actual = mergeKeybindings(localContent, remoteContent, localContent); + const actual = await mergeKeybindings(localContent, remoteContent, localContent); assert.ok(actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, remoteContent); @@ -245,7 +247,7 @@ suite('KeybindingsMerge - No Conflicts', () => { { key: 'cmd+d', command: 'c', when: 'context1' }, { key: 'cmd+c', command: '-c' }, ]); - const actual = mergeKeybindings(localContent, remoteContent, localContent); + const actual = await mergeKeybindings(localContent, remoteContent, localContent); assert.ok(actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, remoteContent); @@ -261,7 +263,7 @@ suite('KeybindingsMerge - No Conflicts', () => { { key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }, { key: 'alt+d', command: '-a' }, ]); - const actual = mergeKeybindings(localContent, remoteContent, null); + const actual = await mergeKeybindings(localContent, remoteContent, null); assert.ok(actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, localContent); @@ -278,7 +280,7 @@ suite('KeybindingsMerge - No Conflicts', () => { { key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }, { key: 'alt+d', command: '-a' }, ]); - const actual = mergeKeybindings(localContent, remoteContent, null); + const actual = await mergeKeybindings(localContent, remoteContent, null); assert.ok(actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, localContent); @@ -295,7 +297,7 @@ suite('KeybindingsMerge - No Conflicts', () => { { key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }, { key: 'alt+d', command: '-a' }, ]); - const actual = mergeKeybindings(localContent, remoteContent, remoteContent); + const actual = await mergeKeybindings(localContent, remoteContent, remoteContent); assert.ok(actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, localContent); @@ -311,7 +313,7 @@ suite('KeybindingsMerge - No Conflicts', () => { { key: 'alt+d', command: '-a' }, { key: 'cmd+c', command: 'b', args: { text: '`' } }, ]); - const actual = mergeKeybindings(localContent, remoteContent, remoteContent); + const actual = await mergeKeybindings(localContent, remoteContent, remoteContent); assert.ok(actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, localContent); @@ -325,7 +327,7 @@ suite('KeybindingsMerge - No Conflicts', () => { { key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }, { key: 'alt+d', command: '-a' }, ]); - const actual = mergeKeybindings(localContent, remoteContent, remoteContent); + const actual = await mergeKeybindings(localContent, remoteContent, remoteContent); assert.ok(actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, localContent); @@ -338,7 +340,7 @@ suite('KeybindingsMerge - No Conflicts', () => { const remoteContent = stringify([ { key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }, ]); - const actual = mergeKeybindings(localContent, remoteContent, remoteContent); + const actual = await mergeKeybindings(localContent, remoteContent, remoteContent); assert.ok(actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, localContent); @@ -357,7 +359,7 @@ suite('KeybindingsMerge - No Conflicts', () => { { key: 'alt+d', command: 'b' }, { key: 'cmd+d', command: 'a' }, ]); - const actual = mergeKeybindings(localContent, remoteContent, remoteContent); + const actual = await mergeKeybindings(localContent, remoteContent, remoteContent); assert.ok(actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, localContent); @@ -389,7 +391,7 @@ suite('KeybindingsMerge - No Conflicts', () => { { key: 'cmd+d', command: 'c', when: 'context1' }, { key: 'cmd+c', command: '-c' }, ]); - const actual = mergeKeybindings(localContent, remoteContent, remoteContent); + const actual = await mergeKeybindings(localContent, remoteContent, remoteContent); assert.ok(actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, expected); @@ -432,7 +434,7 @@ suite('KeybindingsMerge - No Conflicts', () => { ]); //'[\n\t{\n\t\t"key": "alt+d",\n\t\t"command": "-f"\n\t},\n\t{\n\t\t"key": "cmd+d",\n\t\t"command": "d"\n\t},\n\t{\n\t\t"key": "cmd+c",\n\t\t"command": "-c"\n\t},\n\t{\n\t\t"key": "cmd+d",\n\t\t"command": "c",\n\t\t"when": "context1"\n\t},\n\t{\n\t\t"key": "alt+a",\n\t\t"command": "f"\n\t},\n\t{\n\t\t"key": "alt+e",\n\t\t"command": "e"\n\t},\n\t{\n\t\t"key": "alt+g",\n\t\t"command": "g",\n\t\t"when": "context2"\n\t}\n]' //'[\n\t{\n\t\t"key": "alt+d",\n\t\t"command": "-f"\n\t},\n\t{\n\t\t"key": "cmd+d",\n\t\t"command": "d"\n\t},\n\t{\n\t\t"key": "cmd+c",\n\t\t"command": "-c"\n\t},\n\t{\n\t\t"key": "alt+c",\n\t\t"command": "c",\n\t\t"when": "context1"\n\t},\n\t{\n\t\t"key": "alt+a",\n\t\t"command": "f"\n\t},\n\t{\n\t\t"key": "alt+e",\n\t\t"command": "e"\n\t},\n\t{\n\t\t"key": "alt+g",\n\t\t"command": "g",\n\t\t"when": "context2"\n\t}\n]' - const actual = mergeKeybindings(localContent, remoteContent, baseContent); + const actual = await mergeKeybindings(localContent, remoteContent, baseContent); assert.ok(actual.hasChanges); assert.ok(!actual.hasConflicts); assert.equal(actual.mergeContent, expected); @@ -440,282 +442,297 @@ suite('KeybindingsMerge - No Conflicts', () => { }); -suite.skip('KeybindingsMerge - Conflicts', () => { +if (OS !== OperatingSystem.Windows) { + + suite('KeybindingsMerge - Conflicts', () => { + + test('merge when local and remote with one entry but different value', async () => { + const localContent = stringify([{ key: 'alt+d', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); + const remoteContent = stringify([{ key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); + const actual = await mergeKeybindings(localContent, remoteContent, null); + assert.ok(actual.hasChanges); + assert.ok(actual.hasConflicts); + assert.equal(actual.mergeContent, + `<<<<<<< local + [ + { + "key": "alt+d", + "command": "a", + "when": "editorTextFocus && !editorReadonly" + } + ] + ======= + [ + { + "key": "alt+c", + "command": "a", + "when": "editorTextFocus && !editorReadonly" + } + ] + >>>>>>> remote`); + }); + + test('merge when local and remote with different keybinding', async () => { + const localContent = stringify([ + { key: 'alt+d', command: 'a', when: 'editorTextFocus && !editorReadonly' }, + { key: 'alt+a', command: '-a', when: 'editorTextFocus && !editorReadonly' } + ]); + const remoteContent = stringify([ + { key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }, + { key: 'alt+a', command: '-a', when: 'editorTextFocus && !editorReadonly' } + ]); + const actual = await mergeKeybindings(localContent, remoteContent, null); + assert.ok(actual.hasChanges); + assert.ok(actual.hasConflicts); + assert.equal(actual.mergeContent, + `<<<<<<< local + [ + { + "key": "alt+d", + "command": "a", + "when": "editorTextFocus && !editorReadonly" + }, + { + "key": "alt+a", + "command": "-a", + "when": "editorTextFocus && !editorReadonly" + } + ] + ======= + [ + { + "key": "alt+c", + "command": "a", + "when": "editorTextFocus && !editorReadonly" + }, + { + "key": "alt+a", + "command": "-a", + "when": "editorTextFocus && !editorReadonly" + } + ] + >>>>>>> remote`); + }); + + test('merge when the entry is removed in local but updated in remote', async () => { + const baseContent = stringify([{ key: 'alt+d', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); + const localContent = stringify([]); + const remoteContent = stringify([{ key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); + const actual = await mergeKeybindings(localContent, remoteContent, baseContent); + assert.ok(actual.hasChanges); + assert.ok(actual.hasConflicts); + assert.equal(actual.mergeContent, + `<<<<<<< local + [] + ======= + [ + { + "key": "alt+c", + "command": "a", + "when": "editorTextFocus && !editorReadonly" + } + ] + >>>>>>> remote`); + }); + + test('merge when the entry is removed in local but updated in remote and a new entry is added in local', async () => { + const baseContent = stringify([{ key: 'alt+d', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); + const localContent = stringify([{ key: 'alt+b', command: 'b' }]); + const remoteContent = stringify([{ key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); + const actual = await mergeKeybindings(localContent, remoteContent, baseContent); + assert.ok(actual.hasChanges); + assert.ok(actual.hasConflicts); + assert.equal(actual.mergeContent, + `<<<<<<< local + [ + { + "key": "alt+b", + "command": "b" + } + ] + ======= + [ + { + "key": "alt+c", + "command": "a", + "when": "editorTextFocus && !editorReadonly" + } + ] + >>>>>>> remote`); + }); + + test('merge when the entry is removed in remote but updated in local', async () => { + const baseContent = stringify([{ key: 'alt+d', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); + const localContent = stringify([{ key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); + const remoteContent = stringify([]); + const actual = await mergeKeybindings(localContent, remoteContent, baseContent); + assert.ok(actual.hasChanges); + assert.ok(actual.hasConflicts); + assert.equal(actual.mergeContent, + `<<<<<<< local + [ + { + "key": "alt+c", + "command": "a", + "when": "editorTextFocus && !editorReadonly" + } + ] + ======= + [] + >>>>>>> remote`); + }); + + test('merge when the entry is removed in remote but updated in local and a new entry is added in remote', async () => { + const baseContent = stringify([{ key: 'alt+d', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); + const localContent = stringify([{ key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); + const remoteContent = stringify([{ key: 'alt+b', command: 'b' }]); + const actual = await mergeKeybindings(localContent, remoteContent, baseContent); + assert.ok(actual.hasChanges); + assert.ok(actual.hasConflicts); + assert.equal(actual.mergeContent, + `<<<<<<< local + [ + { + "key": "alt+c", + "command": "a", + "when": "editorTextFocus && !editorReadonly" + }, + { + "key": "alt+b", + "command": "b" + } + ] + ======= + [ + { + "key": "alt+b", + "command": "b" + } + ] + >>>>>>> remote`); + }); + + test('merge when local and remote has moved forwareded with conflicts', async () => { + const baseContent = stringify([ + { key: 'alt+d', command: 'a', when: 'editorTextFocus && !editorReadonly' }, + { key: 'alt+c', command: '-a' }, + { key: 'cmd+e', command: 'd' }, + { key: 'alt+a', command: 'f' }, + { key: 'alt+d', command: '-f' }, + { key: 'cmd+d', command: 'c', when: 'context1' }, + { key: 'cmd+c', command: '-c' }, + ]); + const localContent = stringify([ + { key: 'alt+d', command: '-f' }, + { key: 'cmd+e', command: 'd' }, + { key: 'cmd+c', command: '-c' }, + { key: 'cmd+d', command: 'c', when: 'context1' }, + { key: 'alt+a', command: 'f' }, + { key: 'alt+e', command: 'e' }, + ]); + const remoteContent = stringify([ + { key: 'alt+a', command: 'f' }, + { key: 'cmd+c', command: '-c' }, + { key: 'cmd+d', command: 'd' }, + { key: 'alt+d', command: '-f' }, + { key: 'alt+c', command: 'c', when: 'context1' }, + { key: 'alt+g', command: 'g', when: 'context2' }, + ]); + const actual = await mergeKeybindings(localContent, remoteContent, baseContent); + assert.ok(actual.hasChanges); + assert.ok(actual.hasConflicts); + assert.equal(actual.mergeContent, + `<<<<<<< local + [ + { + "key": "alt+d", + "command": "-f" + }, + { + "key": "cmd+d", + "command": "d" + }, + { + "key": "cmd+c", + "command": "-c" + }, + { + "key": "cmd+d", + "command": "c", + "when": "context1" + }, + { + "key": "alt+a", + "command": "f" + }, + { + "key": "alt+e", + "command": "e" + }, + { + "key": "alt+g", + "command": "g", + "when": "context2" + } + ] + ======= + [ + { + "key": "alt+a", + "command": "f" + }, + { + "key": "cmd+c", + "command": "-c" + }, + { + "key": "cmd+d", + "command": "d" + }, + { + "key": "alt+d", + "command": "-f" + }, + { + "key": "alt+c", + "command": "c", + "when": "context1" + }, + { + "key": "alt+g", + "command": "g", + "when": "context2" + } + ] + >>>>>>> remote`); + }); - test('merge when local and remote with one entry but different value', async () => { - const localContent = stringify([{ key: 'alt+d', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); - const remoteContent = stringify([{ key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); - const actual = mergeKeybindings(localContent, remoteContent, null); - assert.ok(actual.hasChanges); - assert.ok(actual.hasConflicts); - assert.equal(actual.mergeContent, - `<<<<<<< local -[ - { - "key": "alt+d", - "command": "a", - "when": "editorTextFocus && !editorReadonly" - } -] -======= -[ - { - "key": "alt+c", - "command": "a", - "when": "editorTextFocus && !editorReadonly" - } -] ->>>>>>> remote`); }); +} - test('merge when local and remote with different keybinding', async () => { - const localContent = stringify([ - { key: 'alt+d', command: 'a', when: 'editorTextFocus && !editorReadonly' }, - { key: 'alt+a', command: '-a', when: 'editorTextFocus && !editorReadonly' } - ]); - const remoteContent = stringify([ - { key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }, - { key: 'alt+a', command: '-a', when: 'editorTextFocus && !editorReadonly' } - ]); - const actual = mergeKeybindings(localContent, remoteContent, null); - assert.ok(actual.hasChanges); - assert.ok(actual.hasConflicts); - assert.equal(actual.mergeContent, - `<<<<<<< local -[ - { - "key": "alt+d", - "command": "a", - "when": "editorTextFocus && !editorReadonly" - }, - { - "key": "alt+a", - "command": "-a", - "when": "editorTextFocus && !editorReadonly" - } -] -======= -[ - { - "key": "alt+c", - "command": "a", - "when": "editorTextFocus && !editorReadonly" - }, - { - "key": "alt+a", - "command": "-a", - "when": "editorTextFocus && !editorReadonly" - } -] ->>>>>>> remote`); - }); - - test('merge when the entry is removed in local but updated in remote', async () => { - const baseContent = stringify([{ key: 'alt+d', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); - const localContent = stringify([]); - const remoteContent = stringify([{ key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); - const actual = mergeKeybindings(localContent, remoteContent, baseContent); - assert.ok(actual.hasChanges); - assert.ok(actual.hasConflicts); - assert.equal(actual.mergeContent, - `<<<<<<< local -[] -======= -[ - { - "key": "alt+c", - "command": "a", - "when": "editorTextFocus && !editorReadonly" - } -] ->>>>>>> remote`); - }); - - test('merge when the entry is removed in local but updated in remote and a new entry is added in local', async () => { - const baseContent = stringify([{ key: 'alt+d', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); - const localContent = stringify([{ key: 'alt+b', command: 'b' }]); - const remoteContent = stringify([{ key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); - const actual = mergeKeybindings(localContent, remoteContent, baseContent); - assert.ok(actual.hasChanges); - assert.ok(actual.hasConflicts); - assert.equal(actual.mergeContent, - `<<<<<<< local -[ - { - "key": "alt+b", - "command": "b" - } -] -======= -[ - { - "key": "alt+c", - "command": "a", - "when": "editorTextFocus && !editorReadonly" - } -] ->>>>>>> remote`); - }); - - test('merge when the entry is removed in remote but updated in local', async () => { - const baseContent = stringify([{ key: 'alt+d', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); - const localContent = stringify([{ key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); - const remoteContent = stringify([]); - const actual = mergeKeybindings(localContent, remoteContent, baseContent); - assert.ok(actual.hasChanges); - assert.ok(actual.hasConflicts); - assert.equal(actual.mergeContent, - `<<<<<<< local -[ - { - "key": "alt+c", - "command": "a", - "when": "editorTextFocus && !editorReadonly" - } -] -======= -[] ->>>>>>> remote`); - }); - - test('merge when the entry is removed in remote but updated in local and a new entry is added in remote', async () => { - const baseContent = stringify([{ key: 'alt+d', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); - const localContent = stringify([{ key: 'alt+c', command: 'a', when: 'editorTextFocus && !editorReadonly' }]); - const remoteContent = stringify([{ key: 'alt+b', command: 'b' }]); - const actual = mergeKeybindings(localContent, remoteContent, baseContent); - assert.ok(actual.hasChanges); - assert.ok(actual.hasConflicts); - assert.equal(actual.mergeContent, - `<<<<<<< local -[ - { - "key": "alt+c", - "command": "a", - "when": "editorTextFocus && !editorReadonly" - }, - { - "key": "alt+b", - "command": "b" - } -] -======= -[ - { - "key": "alt+b", - "command": "b" - } -] ->>>>>>> remote`); - }); - - test('merge when local and remote has moved forwareded with conflicts', async () => { - const baseContent = stringify([ - { key: 'alt+d', command: 'a', when: 'editorTextFocus && !editorReadonly' }, - { key: 'alt+c', command: '-a' }, - { key: 'cmd+e', command: 'd' }, - { key: 'alt+a', command: 'f' }, - { key: 'alt+d', command: '-f' }, - { key: 'cmd+d', command: 'c', when: 'context1' }, - { key: 'cmd+c', command: '-c' }, - ]); - const localContent = stringify([ - { key: 'alt+d', command: '-f' }, - { key: 'cmd+e', command: 'd' }, - { key: 'cmd+c', command: '-c' }, - { key: 'cmd+d', command: 'c', when: 'context1' }, - { key: 'alt+a', command: 'f' }, - { key: 'alt+e', command: 'e' }, - ]); - const remoteContent = stringify([ - { key: 'alt+a', command: 'f' }, - { key: 'cmd+c', command: '-c' }, - { key: 'cmd+d', command: 'd' }, - { key: 'alt+d', command: '-f' }, - { key: 'alt+c', command: 'c', when: 'context1' }, - { key: 'alt+g', command: 'g', when: 'context2' }, - ]); - const actual = mergeKeybindings(localContent, remoteContent, baseContent); - assert.ok(actual.hasChanges); - assert.ok(actual.hasConflicts); - assert.equal(actual.mergeContent, - `<<<<<<< local -[ - { - "key": "alt+d", - "command": "-f" - }, - { - "key": "cmd+d", - "command": "d" - }, - { - "key": "cmd+c", - "command": "-c" - }, - { - "key": "cmd+d", - "command": "c", - "when": "context1" - }, - { - "key": "alt+a", - "command": "f" - }, - { - "key": "alt+e", - "command": "e" - }, - { - "key": "alt+g", - "command": "g", - "when": "context2" - } -] -======= -[ - { - "key": "alt+a", - "command": "f" - }, - { - "key": "cmd+c", - "command": "-c" - }, - { - "key": "cmd+d", - "command": "d" - }, - { - "key": "alt+d", - "command": "-f" - }, - { - "key": "alt+c", - "command": "c", - "when": "context1" - }, - { - "key": "alt+g", - "command": "g", - "when": "context2" - } -] ->>>>>>> remote`); - }); - -}); - -function mergeKeybindings(localContent: string, remoteContent: string, baseContent: string | null) { - const local = parse(localContent); - const remote = parse(remoteContent); - const base = baseContent ? parse(baseContent) : null; - const keys: IStringDictionary = {}; - for (const keybinding of [...local, ...remote, ...(base || [])]) { - keys[keybinding.key] = keybinding.key; - } - return merge(localContent, remoteContent, baseContent, keys); +async function mergeKeybindings(localContent: string, remoteContent: string, baseContent: string | null) { + const userDataSyncUtilService = new MockUserDataSyncUtilService(); + const formattingOptions = await userDataSyncUtilService.resolveFormattingOptions(); + return merge(localContent, remoteContent, baseContent, formattingOptions, userDataSyncUtilService); } function stringify(value: any): any { return JSON.stringify(value, null, '\t'); } + +class MockUserDataSyncUtilService implements IUserDataSyncUtilService { + + _serviceBrand: any; + + async resolveUserBindings(userbindings: string[]): Promise> { + const keys: IStringDictionary = {}; + for (const keybinding of userbindings) { + keys[keybinding] = keybinding; + } + return keys; + } + + async resolveFormattingOptions(file?: URI): Promise { + return { eol: OS === OperatingSystem.Linux || OS === OperatingSystem.Macintosh ? '\n' : '\r\n', insertSpaces: false, tabSize: 4 }; + } +} diff --git a/src/vs/workbench/contrib/userDataSync/electron-browser/userDataSync.contribution.ts b/src/vs/workbench/contrib/userDataSync/electron-browser/userDataSync.contribution.ts index 3c94e35f321..1ff66d24159 100644 --- a/src/vs/workbench/contrib/userDataSync/electron-browser/userDataSync.contribution.ts +++ b/src/vs/workbench/contrib/userDataSync/electron-browser/userDataSync.contribution.ts @@ -4,22 +4,22 @@ *--------------------------------------------------------------------------------------------*/ import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { ISettingsMergeService, IUserKeybindingsResolverService } from 'vs/platform/userDataSync/common/userDataSync'; +import { ISettingsMergeService, IUserDataSyncUtilService } from 'vs/platform/userDataSync/common/userDataSync'; import { Registry } from 'vs/platform/registry/common/platform'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; import { SettingsMergeChannel } from 'vs/platform/userDataSync/common/settingsSyncIpc'; -import { UserKeybindingsResolverServiceChannel } from 'vs/platform/userDataSync/common/keybindingsSyncIpc'; +import { UserDataSycnUtilServiceChannel } from 'vs/platform/userDataSync/common/keybindingsSyncIpc'; class UserDataSyncServicesContribution implements IWorkbenchContribution { constructor( @ISettingsMergeService settingsMergeService: ISettingsMergeService, - @IUserKeybindingsResolverService keybindingsMergeService: IUserKeybindingsResolverService, + @IUserDataSyncUtilService userDataSyncUtilService: IUserDataSyncUtilService, @ISharedProcessService sharedProcessService: ISharedProcessService, ) { sharedProcessService.registerChannel('settingsMerge', new SettingsMergeChannel(settingsMergeService)); - sharedProcessService.registerChannel('userKeybindingsResolver', new UserKeybindingsResolverServiceChannel(keybindingsMergeService)); + sharedProcessService.registerChannel('userDataSyncUtil', new UserDataSycnUtilServiceChannel(userDataSyncUtilService)); } } diff --git a/src/vs/workbench/services/userDataSync/common/keybindingsMerge.ts b/src/vs/workbench/services/userDataSync/common/keybindingsMerge.ts deleted file mode 100644 index d263bfa18d5..00000000000 --- a/src/vs/workbench/services/userDataSync/common/keybindingsMerge.ts +++ /dev/null @@ -1,32 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parse } from 'vs/base/common/json'; -import { IUserFriendlyKeybinding, IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { IUserKeybindingsResolverService } from 'vs/platform/userDataSync/common/userDataSync'; -import { IStringDictionary } from 'vs/base/common/collections'; -import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; - -export class UserKeybindingsResolverService implements IUserKeybindingsResolverService { - - _serviceBrand: undefined; - - constructor( - @IKeybindingService private readonly keybindingsService: IKeybindingService - ) { } - - public async resolveUserKeybindings(localContent: string, remoteContent: string, baseContent: string | null): Promise> { - const local = parse(localContent); - const remote = parse(remoteContent); - const base = baseContent ? parse(baseContent) : null; - const keys: IStringDictionary = {}; - for (const keybinding of [...local, ...remote, ...(base || [])]) { - keys[keybinding.key] = this.keybindingsService.resolveUserBinding(keybinding.key).map(part => part.getUserSettingsLabel()).join(' '); - } - return keys; - } -} - -registerSingleton(IUserKeybindingsResolverService, UserKeybindingsResolverService); diff --git a/src/vs/workbench/services/userDataSync/common/userDataSyncUtil.ts b/src/vs/workbench/services/userDataSync/common/userDataSyncUtil.ts new file mode 100644 index 00000000000..237e55c17e4 --- /dev/null +++ b/src/vs/workbench/services/userDataSync/common/userDataSyncUtil.ts @@ -0,0 +1,40 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { IUserDataSyncUtilService } from 'vs/platform/userDataSync/common/userDataSync'; +import { IStringDictionary } from 'vs/base/common/collections'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { FormattingOptions } from 'vs/base/common/jsonFormatter'; +import { URI } from 'vs/base/common/uri'; +import { ITextModelService } from 'vs/editor/common/services/resolverService'; + +class UserDataSyncUtilService implements IUserDataSyncUtilService { + + _serviceBrand: undefined; + + constructor( + @IKeybindingService private readonly keybindingsService: IKeybindingService, + @ITextModelService private readonly textModelService: ITextModelService, + ) { } + + public async resolveUserBindings(userBindings: string[]): Promise> { + const keys: IStringDictionary = {}; + for (const userbinding of userBindings) { + keys[userbinding] = this.keybindingsService.resolveUserBinding(userbinding).map(part => part.getUserSettingsLabel()).join(' '); + } + return keys; + } + + async resolveFormattingOptions(resource: URI): Promise { + const modelReference = await this.textModelService.createModelReference(resource); + const { insertSpaces, tabSize } = modelReference.object.textEditorModel.getOptions(); + const eol = modelReference.object.textEditorModel.getEOL(); + modelReference.dispose(); + return { eol, insertSpaces, tabSize }; + } +} + +registerSingleton(IUserDataSyncUtilService, UserDataSyncUtilService); diff --git a/src/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index 316b630b15a..d7de6c214e4 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -80,7 +80,7 @@ import 'vs/workbench/services/extensionManagement/common/extensionEnablementServ import 'vs/workbench/services/notification/common/notificationService'; import 'vs/workbench/services/extensions/common/staticExtensions'; import 'vs/workbench/services/userDataSync/common/settingsMergeService'; -import 'vs/workbench/services/userDataSync/common/keybindingsMerge'; +import 'vs/workbench/services/userDataSync/common/userDataSyncUtil'; import 'vs/workbench/services/path/common/remotePathService'; import 'vs/workbench/services/remote/common/remoteExplorerService'; import 'vs/workbench/services/workingCopy/common/workingCopyService';