mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 21:09:43 +00:00
Merge branch 'master' into aeschli/productIconsTheme
This commit is contained in:
commit
f837b41d7c
74
.vscode/searches/es6.code-search
vendored
Normal file
74
.vscode/searches/es6.code-search
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
# Query: @deprecated ES6
|
||||
# Flags: CaseSensitive WordMatch
|
||||
# ContextLines: 2
|
||||
|
||||
11 results - 3 files
|
||||
|
||||
src/vs/base/common/arrays.ts:
|
||||
401
|
||||
402 /**
|
||||
403: * @deprecated ES6: use `Array.findIndex`
|
||||
404 */
|
||||
405 export function firstIndex<T>(array: ReadonlyArray<T>, fn: (item: T) => boolean): number {
|
||||
|
||||
417
|
||||
418 /**
|
||||
419: * @deprecated ES6: use `Array.find`
|
||||
420 */
|
||||
421 export function first<T>(array: ReadonlyArray<T>, fn: (item: T) => boolean, notFoundValue: T): T;
|
||||
|
||||
474
|
||||
475 /**
|
||||
476: * @deprecated ES6: use `Array.fill`
|
||||
477 */
|
||||
478 export function fill<T>(num: number, value: T, arr: T[] = []): T[] {
|
||||
|
||||
571
|
||||
572 /**
|
||||
573: * @deprecated ES6: use `Array.find`
|
||||
574 */
|
||||
575 export function find<T>(arr: ArrayLike<T>, predicate: (value: T, index: number, arr: ArrayLike<T>) => any): T | undefined {
|
||||
|
||||
src/vs/base/common/map.ts:
|
||||
9
|
||||
10 /**
|
||||
11: * @deprecated ES6: use `[...SetOrMap.values()]`
|
||||
12 */
|
||||
13 export function values<V = any>(set: Set<V>): V[];
|
||||
|
||||
20
|
||||
21 /**
|
||||
22: * @deprecated ES6: use `[...map.keys()]`
|
||||
23 */
|
||||
24 export function keys<K, V>(map: Map<K, V>): K[] {
|
||||
|
||||
58
|
||||
59 /**
|
||||
60: * @deprecated ES6: use `...Map.entries()`
|
||||
61 */
|
||||
62 export function mapToSerializable(map: Map<string, string>): [string, string][] {
|
||||
|
||||
71
|
||||
72 /**
|
||||
73: * @deprecated ES6: use `new Map([[key1, value1],[key2, value2]])`
|
||||
74 */
|
||||
75 export function serializableToMap(serializable: [string, string][]): Map<string, string> {
|
||||
|
||||
src/vs/base/common/strings.ts:
|
||||
16
|
||||
17 /**
|
||||
18: * @deprecated ES6: use `String.padStart`
|
||||
19 */
|
||||
20 export function pad(n: number, l: number, char: string = '0'): string {
|
||||
|
||||
147
|
||||
148 /**
|
||||
149: * @deprecated ES6: use `String.startsWith`
|
||||
150 */
|
||||
151 export function startsWith(haystack: string, needle: string): boolean {
|
||||
|
||||
168
|
||||
169 /**
|
||||
170: * @deprecated ES6: use `String.endsWith`
|
||||
171 */
|
||||
172 export function endsWith(haystack: string, needle: string): boolean {
|
|
@ -135,6 +135,23 @@ steps:
|
|||
displayName: Run integration tests (Browser)
|
||||
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
APP_ROOT=$(agent.builddirectory)/VSCode-darwin
|
||||
APP_NAME="`ls $APP_ROOT | head -n 1`"
|
||||
yarn smoketest --build "$APP_ROOT/$APP_NAME"
|
||||
continueOnError: true
|
||||
displayName: Run smoke tests (Electron)
|
||||
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-darwin" \
|
||||
yarn smoketest --web --headless
|
||||
continueOnError: true
|
||||
displayName: Run smoke tests (Browser)
|
||||
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
security create-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain
|
||||
|
|
|
@ -20,9 +20,7 @@ function main() {
|
|||
}
|
||||
}
|
||||
|
||||
if (Object.keys(content).length > 0) {
|
||||
fs.writeFileSync(path.join(__dirname, '../src/common/config.json'), JSON.stringify(content));
|
||||
}
|
||||
fs.writeFileSync(path.join(__dirname, '../src/common/config.json'), JSON.stringify(content));
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
|
@ -180,16 +180,16 @@ class Trait<T> implements ISpliceable<boolean>, IDisposable {
|
|||
}
|
||||
}
|
||||
|
||||
class FocusTrait<T> extends Trait<T> {
|
||||
class SelectionTrait<T> extends Trait<T> {
|
||||
|
||||
constructor(private isAriaSelected: (index: number) => boolean) {
|
||||
super('focused');
|
||||
constructor() {
|
||||
super('selected');
|
||||
}
|
||||
|
||||
renderIndex(index: number, container: HTMLElement): void {
|
||||
super.renderIndex(index, container);
|
||||
|
||||
if (this.contains(index) || this.isAriaSelected(index)) {
|
||||
if (this.contains(index)) {
|
||||
container.setAttribute('aria-selected', 'true');
|
||||
} else {
|
||||
container.setAttribute('aria-selected', 'false');
|
||||
|
@ -1198,8 +1198,8 @@ export class List<T> implements ISpliceable<T>, IDisposable {
|
|||
renderers: IListRenderer<any /* TODO@joao */, any>[],
|
||||
private _options: IListOptions<T> = DefaultOptions
|
||||
) {
|
||||
this.selection = new Trait('selected');
|
||||
this.focus = new FocusTrait(this.selection.contains);
|
||||
this.selection = new SelectionTrait();
|
||||
this.focus = new Trait('focused');
|
||||
|
||||
mixin(_options, defaultStyles, false);
|
||||
|
||||
|
|
|
@ -49,7 +49,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, registerConfiguration, IUserDataSyncLogService, IUserDataSyncUtilService, ISettingsSyncService, IUserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { IUserDataSyncService, IUserDataSyncStoreService, registerConfiguration, IUserDataSyncLogService, IUserDataSyncUtilService, ISettingsSyncService, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { UserDataSyncService } from 'vs/platform/userDataSync/common/userDataSyncService';
|
||||
import { UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService';
|
||||
import { UserDataSyncChannel, UserDataSyncUtilServiceClient, SettingsSyncChannel, UserDataAutoSyncChannel, UserDataSyncStoreServiceChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc';
|
||||
|
@ -67,6 +67,7 @@ import { GlobalExtensionEnablementService } from 'vs/platform/extensionManagemen
|
|||
import { UserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSyncEnablementService';
|
||||
import { IAuthenticationTokenService, AuthenticationTokenService } from 'vs/platform/authentication/common/authentication';
|
||||
import { AuthenticationTokenServiceChannel } from 'vs/platform/authentication/common/authenticationIpc';
|
||||
import { UserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSyncBackupStoreService';
|
||||
|
||||
export interface ISharedProcessConfiguration {
|
||||
readonly machineId: string;
|
||||
|
@ -194,6 +195,7 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat
|
|||
services.set(IUserDataSyncUtilService, new UserDataSyncUtilServiceClient(server.getChannel('userDataSyncUtil', client => client.ctx !== 'main')));
|
||||
services.set(IGlobalExtensionEnablementService, new SyncDescriptor(GlobalExtensionEnablementService));
|
||||
services.set(IUserDataSyncStoreService, new SyncDescriptor(UserDataSyncStoreService));
|
||||
services.set(IUserDataSyncBackupStoreService, new SyncDescriptor(UserDataSyncBackupStoreService));
|
||||
services.set(IUserDataSyncEnablementService, new SyncDescriptor(UserDataSyncEnablementService));
|
||||
services.set(ISettingsSyncService, new SyncDescriptor(SettingsSynchroniser));
|
||||
services.set(IUserDataSyncService, new SyncDescriptor(UserDataSyncService));
|
||||
|
|
|
@ -925,6 +925,23 @@ export class MouseTargetFactory {
|
|||
}
|
||||
}
|
||||
|
||||
// For inline decorations, Gecko returns the `<span>` of the line and the offset is the `<span>` with the inline decoration
|
||||
if (hitResult.offsetNode.nodeType === hitResult.offsetNode.ELEMENT_NODE) {
|
||||
const parent1 = hitResult.offsetNode.parentNode; // expected to be the view line div
|
||||
const parent1ClassName = parent1 && parent1.nodeType === parent1.ELEMENT_NODE ? (<HTMLElement>parent1).className : null;
|
||||
|
||||
if (parent1ClassName === ViewLine.CLASS_NAME) {
|
||||
const tokenSpan = hitResult.offsetNode.childNodes[Math.min(hitResult.offset, hitResult.offsetNode.childNodes.length - 1)];
|
||||
if (tokenSpan) {
|
||||
const p = ctx.getPositionFromDOMInfo(<HTMLElement>tokenSpan, 0);
|
||||
return {
|
||||
position: p,
|
||||
hitTarget: null
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
position: null,
|
||||
hitTarget: <HTMLElement>hitResult.offsetNode
|
||||
|
|
|
@ -779,7 +779,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
|
|||
}
|
||||
|
||||
private _type(source: string, text: string): void {
|
||||
if (!this._isDoingComposition && source === 'keyboard') {
|
||||
if (source === 'keyboard') {
|
||||
// If this event is coming straight from the keyboard, look for electric characters and enter
|
||||
|
||||
const len = text.length;
|
||||
|
@ -790,7 +790,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
|
|||
|
||||
// Here we must interpret each typed character individually
|
||||
const autoClosedCharacters = AutoClosedAction.getAllAutoClosedCharacters(this._autoClosedActions);
|
||||
this._executeEditOperation(TypeOperations.typeWithInterceptors(this._prevEditOperationType, this.context.config, this.context.model, this.getSelections(), autoClosedCharacters, chr));
|
||||
this._executeEditOperation(TypeOperations.typeWithInterceptors(this._isDoingComposition, this._prevEditOperationType, this.context.config, this.context.model, this.getSelections(), autoClosedCharacters, chr));
|
||||
|
||||
offset += charLength;
|
||||
}
|
||||
|
|
|
@ -269,9 +269,15 @@ export class TypeOperations {
|
|||
commands[i] = null;
|
||||
continue;
|
||||
}
|
||||
let pos = selection.getPosition();
|
||||
let startColumn = Math.max(1, pos.column - replaceCharCnt);
|
||||
let range = new Range(pos.lineNumber, startColumn, pos.lineNumber, pos.column);
|
||||
const pos = selection.getPosition();
|
||||
const startColumn = Math.max(1, pos.column - replaceCharCnt);
|
||||
const range = new Range(pos.lineNumber, startColumn, pos.lineNumber, pos.column);
|
||||
const oldText = model.getValueInRange(range);
|
||||
if (oldText === txt) {
|
||||
// => ignore composition that doesn't do anything
|
||||
commands[i] = null;
|
||||
continue;
|
||||
}
|
||||
commands[i] = new ReplaceCommand(range, txt);
|
||||
}
|
||||
return new EditOperationResult(EditOperationType.Typing, commands, {
|
||||
|
@ -796,9 +802,9 @@ export class TypeOperations {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static typeWithInterceptors(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITextModel, selections: Selection[], autoClosedCharacters: Range[], ch: string): EditOperationResult {
|
||||
public static typeWithInterceptors(isDoingComposition: boolean, prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITextModel, selections: Selection[], autoClosedCharacters: Range[], ch: string): EditOperationResult {
|
||||
|
||||
if (ch === '\n') {
|
||||
if (!isDoingComposition && ch === '\n') {
|
||||
let commands: ICommand[] = [];
|
||||
for (let i = 0, len = selections.length; i < len; i++) {
|
||||
commands[i] = TypeOperations._enter(config, model, false, selections[i]);
|
||||
|
@ -809,7 +815,7 @@ export class TypeOperations {
|
|||
});
|
||||
}
|
||||
|
||||
if (this._isAutoIndentType(config, model, selections)) {
|
||||
if (!isDoingComposition && this._isAutoIndentType(config, model, selections)) {
|
||||
let commands: Array<ICommand | null> = [];
|
||||
let autoIndentFails = false;
|
||||
for (let i = 0, len = selections.length; i < len; i++) {
|
||||
|
@ -827,13 +833,15 @@ export class TypeOperations {
|
|||
}
|
||||
}
|
||||
|
||||
if (this._isAutoClosingOvertype(config, model, selections, autoClosedCharacters, ch)) {
|
||||
if (!isDoingComposition && this._isAutoClosingOvertype(config, model, selections, autoClosedCharacters, ch)) {
|
||||
return this._runAutoClosingOvertype(prevEditOperationType, config, model, selections, ch);
|
||||
}
|
||||
|
||||
const autoClosingPairOpenCharType = this._isAutoClosingOpenCharType(config, model, selections, ch, true);
|
||||
if (autoClosingPairOpenCharType) {
|
||||
return this._runAutoClosingOpenCharType(prevEditOperationType, config, model, selections, ch, true, autoClosingPairOpenCharType);
|
||||
if (!isDoingComposition) {
|
||||
const autoClosingPairOpenCharType = this._isAutoClosingOpenCharType(config, model, selections, ch, true);
|
||||
if (autoClosingPairOpenCharType) {
|
||||
return this._runAutoClosingOpenCharType(prevEditOperationType, config, model, selections, ch, true, autoClosingPairOpenCharType);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._isSurroundSelectionType(config, model, selections, ch)) {
|
||||
|
@ -842,7 +850,7 @@ export class TypeOperations {
|
|||
|
||||
// Electric characters make sense only when dealing with a single cursor,
|
||||
// as multiple cursors typing brackets for example would interfer with bracket matching
|
||||
if (this._isTypeInterceptorElectricChar(config, model, selections)) {
|
||||
if (!isDoingComposition && this._isTypeInterceptorElectricChar(config, model, selections)) {
|
||||
const r = this._typeInterceptorElectricChar(prevEditOperationType, config, model, selections[0], ch);
|
||||
if (r) {
|
||||
return r;
|
||||
|
|
|
@ -108,8 +108,9 @@ export class ClickLinkGesture extends Disposable {
|
|||
private readonly _editor: ICodeEditor;
|
||||
private _opts: ClickLinkOptions;
|
||||
|
||||
private lastMouseMoveEvent: ClickLinkMouseEvent | null;
|
||||
private hasTriggerKeyOnMouseDown: boolean;
|
||||
private _lastMouseMoveEvent: ClickLinkMouseEvent | null;
|
||||
private _hasTriggerKeyOnMouseDown: boolean;
|
||||
private _lineNumberOnMouseDown: number;
|
||||
|
||||
constructor(editor: ICodeEditor) {
|
||||
super();
|
||||
|
@ -117,8 +118,9 @@ export class ClickLinkGesture extends Disposable {
|
|||
this._editor = editor;
|
||||
this._opts = createOptions(this._editor.getOption(EditorOption.multiCursorModifier));
|
||||
|
||||
this.lastMouseMoveEvent = null;
|
||||
this.hasTriggerKeyOnMouseDown = false;
|
||||
this._lastMouseMoveEvent = null;
|
||||
this._hasTriggerKeyOnMouseDown = false;
|
||||
this._lineNumberOnMouseDown = 0;
|
||||
|
||||
this._register(this._editor.onDidChangeConfiguration((e) => {
|
||||
if (e.hasChanged(EditorOption.multiCursorModifier)) {
|
||||
|
@ -127,77 +129,80 @@ export class ClickLinkGesture extends Disposable {
|
|||
return;
|
||||
}
|
||||
this._opts = newOpts;
|
||||
this.lastMouseMoveEvent = null;
|
||||
this.hasTriggerKeyOnMouseDown = false;
|
||||
this._lastMouseMoveEvent = null;
|
||||
this._hasTriggerKeyOnMouseDown = false;
|
||||
this._lineNumberOnMouseDown = 0;
|
||||
this._onCancel.fire();
|
||||
}
|
||||
}));
|
||||
this._register(this._editor.onMouseMove((e: IEditorMouseEvent) => this.onEditorMouseMove(new ClickLinkMouseEvent(e, this._opts))));
|
||||
this._register(this._editor.onMouseDown((e: IEditorMouseEvent) => this.onEditorMouseDown(new ClickLinkMouseEvent(e, this._opts))));
|
||||
this._register(this._editor.onMouseUp((e: IEditorMouseEvent) => this.onEditorMouseUp(new ClickLinkMouseEvent(e, this._opts))));
|
||||
this._register(this._editor.onKeyDown((e: IKeyboardEvent) => this.onEditorKeyDown(new ClickLinkKeyboardEvent(e, this._opts))));
|
||||
this._register(this._editor.onKeyUp((e: IKeyboardEvent) => this.onEditorKeyUp(new ClickLinkKeyboardEvent(e, this._opts))));
|
||||
this._register(this._editor.onMouseDrag(() => this.resetHandler()));
|
||||
this._register(this._editor.onMouseMove((e: IEditorMouseEvent) => this._onEditorMouseMove(new ClickLinkMouseEvent(e, this._opts))));
|
||||
this._register(this._editor.onMouseDown((e: IEditorMouseEvent) => this._onEditorMouseDown(new ClickLinkMouseEvent(e, this._opts))));
|
||||
this._register(this._editor.onMouseUp((e: IEditorMouseEvent) => this._onEditorMouseUp(new ClickLinkMouseEvent(e, this._opts))));
|
||||
this._register(this._editor.onKeyDown((e: IKeyboardEvent) => this._onEditorKeyDown(new ClickLinkKeyboardEvent(e, this._opts))));
|
||||
this._register(this._editor.onKeyUp((e: IKeyboardEvent) => this._onEditorKeyUp(new ClickLinkKeyboardEvent(e, this._opts))));
|
||||
this._register(this._editor.onMouseDrag(() => this._resetHandler()));
|
||||
|
||||
this._register(this._editor.onDidChangeCursorSelection((e) => this.onDidChangeCursorSelection(e)));
|
||||
this._register(this._editor.onDidChangeModel((e) => this.resetHandler()));
|
||||
this._register(this._editor.onDidChangeModelContent(() => this.resetHandler()));
|
||||
this._register(this._editor.onDidChangeCursorSelection((e) => this._onDidChangeCursorSelection(e)));
|
||||
this._register(this._editor.onDidChangeModel((e) => this._resetHandler()));
|
||||
this._register(this._editor.onDidChangeModelContent(() => this._resetHandler()));
|
||||
this._register(this._editor.onDidScrollChange((e) => {
|
||||
if (e.scrollTopChanged || e.scrollLeftChanged) {
|
||||
this.resetHandler();
|
||||
this._resetHandler();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private onDidChangeCursorSelection(e: ICursorSelectionChangedEvent): void {
|
||||
private _onDidChangeCursorSelection(e: ICursorSelectionChangedEvent): void {
|
||||
if (e.selection && e.selection.startColumn !== e.selection.endColumn) {
|
||||
this.resetHandler(); // immediately stop this feature if the user starts to select (https://github.com/Microsoft/vscode/issues/7827)
|
||||
this._resetHandler(); // immediately stop this feature if the user starts to select (https://github.com/Microsoft/vscode/issues/7827)
|
||||
}
|
||||
}
|
||||
|
||||
private onEditorMouseMove(mouseEvent: ClickLinkMouseEvent): void {
|
||||
this.lastMouseMoveEvent = mouseEvent;
|
||||
private _onEditorMouseMove(mouseEvent: ClickLinkMouseEvent): void {
|
||||
this._lastMouseMoveEvent = mouseEvent;
|
||||
|
||||
this._onMouseMoveOrRelevantKeyDown.fire([mouseEvent, null]);
|
||||
}
|
||||
|
||||
private onEditorMouseDown(mouseEvent: ClickLinkMouseEvent): void {
|
||||
private _onEditorMouseDown(mouseEvent: ClickLinkMouseEvent): void {
|
||||
// We need to record if we had the trigger key on mouse down because someone might select something in the editor
|
||||
// holding the mouse down and then while mouse is down start to press Ctrl/Cmd to start a copy operation and then
|
||||
// release the mouse button without wanting to do the navigation.
|
||||
// With this flag we prevent goto definition if the mouse was down before the trigger key was pressed.
|
||||
this.hasTriggerKeyOnMouseDown = mouseEvent.hasTriggerModifier;
|
||||
this._hasTriggerKeyOnMouseDown = mouseEvent.hasTriggerModifier;
|
||||
this._lineNumberOnMouseDown = mouseEvent.target.position ? mouseEvent.target.position.lineNumber : 0;
|
||||
}
|
||||
|
||||
private onEditorMouseUp(mouseEvent: ClickLinkMouseEvent): void {
|
||||
if (this.hasTriggerKeyOnMouseDown) {
|
||||
private _onEditorMouseUp(mouseEvent: ClickLinkMouseEvent): void {
|
||||
const currentLineNumber = mouseEvent.target.position ? mouseEvent.target.position.lineNumber : 0;
|
||||
if (this._hasTriggerKeyOnMouseDown && this._lineNumberOnMouseDown && this._lineNumberOnMouseDown === currentLineNumber) {
|
||||
this._onExecute.fire(mouseEvent);
|
||||
}
|
||||
}
|
||||
|
||||
private onEditorKeyDown(e: ClickLinkKeyboardEvent): void {
|
||||
private _onEditorKeyDown(e: ClickLinkKeyboardEvent): void {
|
||||
if (
|
||||
this.lastMouseMoveEvent
|
||||
this._lastMouseMoveEvent
|
||||
&& (
|
||||
e.keyCodeIsTriggerKey // User just pressed Ctrl/Cmd (normal goto definition)
|
||||
|| (e.keyCodeIsSideBySideKey && e.hasTriggerModifier) // User pressed Ctrl/Cmd+Alt (goto definition to the side)
|
||||
)
|
||||
) {
|
||||
this._onMouseMoveOrRelevantKeyDown.fire([this.lastMouseMoveEvent, e]);
|
||||
this._onMouseMoveOrRelevantKeyDown.fire([this._lastMouseMoveEvent, e]);
|
||||
} else if (e.hasTriggerModifier) {
|
||||
this._onCancel.fire(); // remove decorations if user holds another key with ctrl/cmd to prevent accident goto declaration
|
||||
}
|
||||
}
|
||||
|
||||
private onEditorKeyUp(e: ClickLinkKeyboardEvent): void {
|
||||
private _onEditorKeyUp(e: ClickLinkKeyboardEvent): void {
|
||||
if (e.keyCodeIsTriggerKey) {
|
||||
this._onCancel.fire();
|
||||
}
|
||||
}
|
||||
|
||||
private resetHandler(): void {
|
||||
this.lastMouseMoveEvent = null;
|
||||
this.hasTriggerKeyOnMouseDown = false;
|
||||
private _resetHandler(): void {
|
||||
this._lastMouseMoveEvent = null;
|
||||
this._hasTriggerKeyOnMouseDown = false;
|
||||
this._onCancel.fire();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5044,6 +5044,28 @@ suite('autoClosingPairs', () => {
|
|||
mode.dispose();
|
||||
});
|
||||
|
||||
test('issue #90016: allow accents on mac US intl keyboard to surround selection', () => {
|
||||
let mode = new AutoClosingMode();
|
||||
usingCursor({
|
||||
text: [
|
||||
'test'
|
||||
],
|
||||
languageIdentifier: mode.getLanguageIdentifier()
|
||||
}, (model, cursor) => {
|
||||
cursor.setSelections('test', [new Selection(1, 1, 1, 5)]);
|
||||
|
||||
// Typing ` + e on the mac US intl kb layout
|
||||
cursorCommand(cursor, H.CompositionStart, null, 'keyboard');
|
||||
cursorCommand(cursor, H.Type, { text: '\'' }, 'keyboard');
|
||||
cursorCommand(cursor, H.ReplacePreviousChar, { replaceCharCnt: 1, text: '\'' }, 'keyboard');
|
||||
cursorCommand(cursor, H.ReplacePreviousChar, { replaceCharCnt: 1, text: '\'' }, 'keyboard');
|
||||
cursorCommand(cursor, H.CompositionEnd, null, 'keyboard');
|
||||
|
||||
assert.equal(model.getValue(), '\'test\'');
|
||||
});
|
||||
mode.dispose();
|
||||
});
|
||||
|
||||
test('issue #53357: Over typing ignores characters after backslash', () => {
|
||||
let mode = new AutoClosingMode();
|
||||
usingCursor({
|
||||
|
|
|
@ -7,11 +7,10 @@ import { Disposable } from 'vs/base/common/lifecycle';
|
|||
import { IFileService, IFileContent, FileChangesEvent, FileSystemProviderError, FileSystemProviderErrorCode, FileOperationResult, FileOperationError } from 'vs/platform/files/common/files';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { SyncSource, SyncStatus, IUserData, IUserDataSyncStoreService, UserDataSyncErrorCode, UserDataSyncError, IUserDataSyncLogService, IUserDataSyncUtilService, ResourceKey, IUserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { SyncSource, SyncStatus, IUserData, IUserDataSyncStoreService, UserDataSyncErrorCode, UserDataSyncError, IUserDataSyncLogService, IUserDataSyncUtilService, ResourceKey, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { joinPath, dirname } from 'vs/base/common/resources';
|
||||
import { toLocalISOString } from 'vs/base/common/date';
|
||||
import { ThrottledDelayer, CancelablePromise } from 'vs/base/common/async';
|
||||
import { CancelablePromise } from 'vs/base/common/async';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ParseError, parse } from 'vs/base/common/json';
|
||||
|
@ -44,7 +43,6 @@ function isSyncData(thing: any): thing is ISyncData {
|
|||
export abstract class AbstractSynchroniser extends Disposable {
|
||||
|
||||
protected readonly syncFolder: URI;
|
||||
private cleanUpDelayer: ThrottledDelayer<void>;
|
||||
|
||||
private _status: SyncStatus = SyncStatus.Idle;
|
||||
get status(): SyncStatus { return this._status; }
|
||||
|
@ -58,9 +56,11 @@ export abstract class AbstractSynchroniser extends Disposable {
|
|||
|
||||
constructor(
|
||||
readonly source: SyncSource,
|
||||
readonly resourceKey: ResourceKey,
|
||||
@IFileService protected readonly fileService: IFileService,
|
||||
@IEnvironmentService environmentService: IEnvironmentService,
|
||||
@IUserDataSyncStoreService protected readonly userDataSyncStoreService: IUserDataSyncStoreService,
|
||||
@IUserDataSyncBackupStoreService protected readonly userDataSyncBackupStoreService: IUserDataSyncBackupStoreService,
|
||||
@IUserDataSyncEnablementService protected readonly userDataSyncEnablementService: IUserDataSyncEnablementService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@IUserDataSyncLogService protected readonly logService: IUserDataSyncLogService,
|
||||
|
@ -68,9 +68,7 @@ export abstract class AbstractSynchroniser extends Disposable {
|
|||
) {
|
||||
super();
|
||||
this.syncFolder = joinPath(environmentService.userDataSyncHome, source);
|
||||
this.lastSyncResource = joinPath(this.syncFolder, `lastSync${source}.json`);
|
||||
this.cleanUpDelayer = new ThrottledDelayer(50);
|
||||
this.cleanUpBackup();
|
||||
this.lastSyncResource = joinPath(this.syncFolder, `lastSync${this.resourceKey}.json`);
|
||||
}
|
||||
|
||||
protected setStatus(status: SyncStatus): void {
|
||||
|
@ -217,51 +215,11 @@ export abstract class AbstractSynchroniser extends Disposable {
|
|||
return { ref, syncData };
|
||||
}
|
||||
|
||||
protected async backupLocal(content: VSBuffer): Promise<void> {
|
||||
const resource = joinPath(this.syncFolder, `${toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '')}.json`);
|
||||
try {
|
||||
await this.fileService.writeFile(resource, content);
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
}
|
||||
this.cleanUpDelayer.trigger(() => this.cleanUpBackup());
|
||||
protected async backupLocal(content: string): Promise<void> {
|
||||
const syncData: ISyncData = { version: this.version, content };
|
||||
return this.userDataSyncBackupStoreService.backup(this.resourceKey, JSON.stringify(syncData));
|
||||
}
|
||||
|
||||
private async cleanUpBackup(): Promise<void> {
|
||||
try {
|
||||
if (!(await this.fileService.exists(this.syncFolder))) {
|
||||
return;
|
||||
}
|
||||
const stat = await this.fileService.resolve(this.syncFolder);
|
||||
if (stat.children) {
|
||||
const all = stat.children.filter(stat => stat.isFile && /^\d{8}T\d{6}(\.json)?$/.test(stat.name)).sort();
|
||||
const backUpMaxAge = 1000 * 60 * 60 * 24 * (this.configurationService.getValue<number>('sync.localBackupDuration') || 30 /* Default 30 days */);
|
||||
let toDelete = all.filter(stat => {
|
||||
const ctime = stat.ctime || new Date(
|
||||
parseInt(stat.name.substring(0, 4)),
|
||||
parseInt(stat.name.substring(4, 6)) - 1,
|
||||
parseInt(stat.name.substring(6, 8)),
|
||||
parseInt(stat.name.substring(9, 11)),
|
||||
parseInt(stat.name.substring(11, 13)),
|
||||
parseInt(stat.name.substring(13, 15))
|
||||
).getTime();
|
||||
return Date.now() - ctime > backUpMaxAge;
|
||||
});
|
||||
const remaining = all.length - toDelete.length;
|
||||
if (remaining < 10) {
|
||||
toDelete = toDelete.slice(10 - remaining);
|
||||
}
|
||||
await Promise.all(toDelete.map(stat => {
|
||||
this.logService.info('Deleting from backup', stat.resource.path);
|
||||
this.fileService.del(stat.resource);
|
||||
}));
|
||||
}
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
abstract readonly resourceKey: ResourceKey;
|
||||
protected abstract readonly version: number;
|
||||
protected abstract performSync(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null): Promise<SyncStatus>;
|
||||
}
|
||||
|
@ -283,15 +241,17 @@ export abstract class AbstractFileSynchroniser extends AbstractSynchroniser {
|
|||
constructor(
|
||||
protected readonly file: URI,
|
||||
source: SyncSource,
|
||||
resourceKey: ResourceKey,
|
||||
@IFileService fileService: IFileService,
|
||||
@IEnvironmentService environmentService: IEnvironmentService,
|
||||
@IUserDataSyncStoreService userDataSyncStoreService: IUserDataSyncStoreService,
|
||||
@IUserDataSyncBackupStoreService userDataSyncBackupStoreService: IUserDataSyncBackupStoreService,
|
||||
@IUserDataSyncEnablementService userDataSyncEnablementService: IUserDataSyncEnablementService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IUserDataSyncLogService logService: IUserDataSyncLogService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
) {
|
||||
super(source, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService, configurationService);
|
||||
super(source, resourceKey, fileService, environmentService, userDataSyncStoreService, userDataSyncBackupStoreService, userDataSyncEnablementService, telemetryService, logService, configurationService);
|
||||
this._register(this.fileService.watch(dirname(file)));
|
||||
this._register(this.fileService.onDidFilesChange(e => this.onFileChanges(e)));
|
||||
}
|
||||
|
@ -327,7 +287,6 @@ export abstract class AbstractFileSynchroniser extends AbstractSynchroniser {
|
|||
try {
|
||||
if (oldContent) {
|
||||
// file exists already
|
||||
await this.backupLocal(oldContent.value);
|
||||
await this.fileService.writeFile(this.file, VSBuffer.fromString(newContent), oldContent);
|
||||
} else {
|
||||
// file does not exist
|
||||
|
@ -382,16 +341,18 @@ export abstract class AbstractJsonFileSynchroniser extends AbstractFileSynchroni
|
|||
constructor(
|
||||
file: URI,
|
||||
source: SyncSource,
|
||||
resourceKey: ResourceKey,
|
||||
@IFileService fileService: IFileService,
|
||||
@IEnvironmentService environmentService: IEnvironmentService,
|
||||
@IUserDataSyncStoreService userDataSyncStoreService: IUserDataSyncStoreService,
|
||||
@IUserDataSyncBackupStoreService userDataSyncBackupStoreService: IUserDataSyncBackupStoreService,
|
||||
@IUserDataSyncEnablementService userDataSyncEnablementService: IUserDataSyncEnablementService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IUserDataSyncLogService logService: IUserDataSyncLogService,
|
||||
@IUserDataSyncUtilService protected readonly userDataSyncUtilService: IUserDataSyncUtilService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
) {
|
||||
super(file, source, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService, configurationService);
|
||||
super(file, source, resourceKey, fileService, environmentService, userDataSyncStoreService, userDataSyncBackupStoreService, userDataSyncEnablementService, telemetryService, logService, configurationService);
|
||||
}
|
||||
|
||||
protected hasErrors(content: string): boolean {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { SyncStatus, IUserDataSyncStoreService, ISyncExtension, IUserDataSyncLogService, IUserDataSynchroniser, SyncSource, ResourceKey, IUserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { SyncStatus, IUserDataSyncStoreService, ISyncExtension, IUserDataSyncLogService, IUserDataSynchroniser, SyncSource, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IExtensionManagementService, IExtensionGalleryService, IGlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
|
@ -16,7 +16,6 @@ import { merge } from 'vs/platform/userDataSync/common/extensionsMerge';
|
|||
import { isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { AbstractSynchroniser, IRemoteUserData, ISyncData } from 'vs/platform/userDataSync/common/abstractSynchronizer';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
|
||||
interface ISyncPreviewResult {
|
||||
readonly localExtensions: ISyncExtension[];
|
||||
|
@ -35,7 +34,6 @@ interface ILastSyncUserData extends IRemoteUserData {
|
|||
|
||||
export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUserDataSynchroniser {
|
||||
|
||||
readonly resourceKey: ResourceKey = 'extensions';
|
||||
protected readonly version: number = 2;
|
||||
protected isEnabled(): boolean { return super.isEnabled() && this.extensionGalleryService.isEnabled(); }
|
||||
|
||||
|
@ -43,6 +41,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
|
|||
@IEnvironmentService environmentService: IEnvironmentService,
|
||||
@IFileService fileService: IFileService,
|
||||
@IUserDataSyncStoreService userDataSyncStoreService: IUserDataSyncStoreService,
|
||||
@IUserDataSyncBackupStoreService userDataSyncBackupStoreService: IUserDataSyncBackupStoreService,
|
||||
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
|
||||
@IGlobalExtensionEnablementService private readonly extensionEnablementService: IGlobalExtensionEnablementService,
|
||||
@IUserDataSyncLogService logService: IUserDataSyncLogService,
|
||||
|
@ -51,7 +50,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
|
|||
@IUserDataSyncEnablementService userDataSyncEnablementService: IUserDataSyncEnablementService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
) {
|
||||
super(SyncSource.Extensions, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService, configurationService);
|
||||
super(SyncSource.Extensions, 'extensions', fileService, environmentService, userDataSyncStoreService, userDataSyncBackupStoreService, userDataSyncEnablementService, telemetryService, logService, configurationService);
|
||||
this._register(
|
||||
Event.debounce(
|
||||
Event.any<any>(
|
||||
|
@ -180,7 +179,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
|
|||
if (added.length || removed.length || updated.length) {
|
||||
// back up all disabled or market place extensions
|
||||
const backUpExtensions = localExtensions.filter(e => e.disabled || !!e.identifier.uuid);
|
||||
await this.backupLocal(VSBuffer.fromString(JSON.stringify(backUpExtensions, null, '\t')));
|
||||
await this.backupLocal(JSON.stringify(backUpExtensions));
|
||||
skippedExtensions = await this.updateLocalExtensions(added, removed, updated, skippedExtensions);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IGlobalState, SyncSource, IUserDataSynchroniser, ResourceKey, IUserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IGlobalState, SyncSource, IUserDataSynchroniser, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
|
@ -29,19 +29,19 @@ interface ISyncPreviewResult {
|
|||
|
||||
export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUserDataSynchroniser {
|
||||
|
||||
readonly resourceKey: ResourceKey = 'globalState';
|
||||
protected readonly version: number = 1;
|
||||
|
||||
constructor(
|
||||
@IFileService fileService: IFileService,
|
||||
@IUserDataSyncStoreService userDataSyncStoreService: IUserDataSyncStoreService,
|
||||
@IUserDataSyncBackupStoreService userDataSyncBackupStoreService: IUserDataSyncBackupStoreService,
|
||||
@IUserDataSyncLogService logService: IUserDataSyncLogService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@IUserDataSyncEnablementService userDataSyncEnablementService: IUserDataSyncEnablementService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
) {
|
||||
super(SyncSource.GlobalState, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService, configurationService);
|
||||
super(SyncSource.GlobalState, 'globalState', fileService, environmentService, userDataSyncStoreService, userDataSyncBackupStoreService, userDataSyncEnablementService, telemetryService, logService, configurationService);
|
||||
this._register(this.fileService.watch(dirname(this.environmentService.argvResource)));
|
||||
this._register(Event.filter(this.fileService.onDidFilesChange, e => e.contains(this.environmentService.argvResource))(() => this._onDidChangeLocal.fire()));
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs
|
|||
return SyncStatus.Idle;
|
||||
}
|
||||
|
||||
private async getPreview(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null,): Promise<ISyncPreviewResult> {
|
||||
private async getPreview(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null): Promise<ISyncPreviewResult> {
|
||||
const remoteGlobalState: IGlobalState = remoteUserData.syncData ? JSON.parse(remoteUserData.syncData.content) : null;
|
||||
const lastSyncGlobalState = lastSyncUserData && lastSyncUserData.syncData ? JSON.parse(lastSyncUserData.syncData.content) : null;
|
||||
|
||||
|
@ -158,7 +158,7 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs
|
|||
if (local) {
|
||||
// update local
|
||||
this.logService.trace('UI State: Updating local ui state...');
|
||||
await this.backupLocal(VSBuffer.fromString(JSON.stringify(localUserData, null, '\t')));
|
||||
await this.backupLocal(JSON.stringify(localUserData));
|
||||
await this.writeLocalGlobalState(local);
|
||||
this.logService.info('UI State: Updated local ui state');
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IFileService, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files';
|
||||
import { UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSyncUtilService, SyncSource, IUserDataSynchroniser, ResourceKey, IUserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSyncUtilService, SyncSource, IUserDataSynchroniser, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { merge } from 'vs/platform/userDataSync/common/keybindingsMerge';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { parse } from 'vs/base/common/json';
|
||||
|
@ -29,12 +29,12 @@ interface ISyncContent {
|
|||
|
||||
export class KeybindingsSynchroniser extends AbstractJsonFileSynchroniser implements IUserDataSynchroniser {
|
||||
|
||||
readonly resourceKey: ResourceKey = 'keybindings';
|
||||
protected get conflictsPreviewResource(): URI { return this.environmentService.keybindingsSyncPreviewResource; }
|
||||
protected readonly version: number = 1;
|
||||
|
||||
constructor(
|
||||
@IUserDataSyncStoreService userDataSyncStoreService: IUserDataSyncStoreService,
|
||||
@IUserDataSyncBackupStoreService userDataSyncBackupStoreService: IUserDataSyncBackupStoreService,
|
||||
@IUserDataSyncLogService logService: IUserDataSyncLogService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IUserDataSyncEnablementService userDataSyncEnablementService: IUserDataSyncEnablementService,
|
||||
|
@ -43,7 +43,7 @@ export class KeybindingsSynchroniser extends AbstractJsonFileSynchroniser implem
|
|||
@IUserDataSyncUtilService userDataSyncUtilService: IUserDataSyncUtilService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
) {
|
||||
super(environmentService.keybindingsResource, SyncSource.Keybindings, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService, userDataSyncUtilService, configurationService);
|
||||
super(environmentService.keybindingsResource, SyncSource.Keybindings, 'keybindings', fileService, environmentService, userDataSyncStoreService, userDataSyncBackupStoreService, userDataSyncEnablementService, telemetryService, logService, userDataSyncUtilService, configurationService);
|
||||
}
|
||||
|
||||
async pull(): Promise<void> {
|
||||
|
@ -197,13 +197,14 @@ export class KeybindingsSynchroniser extends AbstractJsonFileSynchroniser implem
|
|||
|
||||
if (hasLocalChanged) {
|
||||
this.logService.trace('Keybindings: Updating local keybindings...');
|
||||
await this.backupLocal(this.toSyncContent(content, null));
|
||||
await this.updateLocalFileContent(content, fileContent);
|
||||
this.logService.info('Keybindings: Updated local keybindings');
|
||||
}
|
||||
|
||||
if (hasRemoteChanged) {
|
||||
this.logService.trace('Keybindings: Updating remote keybindings...');
|
||||
const remoteContents = this.updateSyncContent(content, remoteUserData.syncData ? remoteUserData.syncData.content : null);
|
||||
const remoteContents = this.toSyncContent(content, remoteUserData.syncData ? remoteUserData.syncData.content : null);
|
||||
remoteUserData = await this.updateRemoteUserData(remoteContents, forcePush ? null : remoteUserData.ref);
|
||||
this.logService.info('Keybindings: Updated remote keybindings');
|
||||
}
|
||||
|
@ -218,7 +219,7 @@ export class KeybindingsSynchroniser extends AbstractJsonFileSynchroniser implem
|
|||
|
||||
if (lastSyncUserData?.ref !== remoteUserData.ref && (content !== null || fileContent !== null)) {
|
||||
this.logService.trace('Keybindings: Updating last synchronized keybindings...');
|
||||
const lastSyncContent = this.updateSyncContent(content !== null ? content : fileContent!.value.toString(), null);
|
||||
const lastSyncContent = this.toSyncContent(content !== null ? content : fileContent!.value.toString(), null);
|
||||
await this.updateLastSyncUserData({ ref: remoteUserData.ref, syncData: { version: remoteUserData.syncData!.version, content: lastSyncContent } });
|
||||
this.logService.info('Keybindings: Updated last synchronized keybindings');
|
||||
}
|
||||
|
@ -301,7 +302,7 @@ export class KeybindingsSynchroniser extends AbstractJsonFileSynchroniser implem
|
|||
}
|
||||
}
|
||||
|
||||
private updateSyncContent(keybindingsContent: string, syncContent: string | null): string {
|
||||
private toSyncContent(keybindingsContent: string, syncContent: string | null): string {
|
||||
let parsed: ISyncContent = {};
|
||||
try {
|
||||
parsed = JSON.parse(syncContent || '{}');
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IFileService, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files';
|
||||
import { UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSyncUtilService, IConflictSetting, ISettingsSyncService, CONFIGURATION_SYNC_STORE_KEY, SyncSource, ResourceKey, IUserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSyncUtilService, IConflictSetting, ISettingsSyncService, CONFIGURATION_SYNC_STORE_KEY, SyncSource, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { parse } from 'vs/base/common/json';
|
||||
import { localize } from 'vs/nls';
|
||||
|
@ -37,7 +37,6 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
|
|||
|
||||
_serviceBrand: any;
|
||||
|
||||
readonly resourceKey: ResourceKey = 'settings';
|
||||
protected readonly version: number = 1;
|
||||
protected get conflictsPreviewResource(): URI { return this.environmentService.settingsSyncPreviewResource; }
|
||||
|
||||
|
@ -50,6 +49,7 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
|
|||
@IFileService fileService: IFileService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@IUserDataSyncStoreService userDataSyncStoreService: IUserDataSyncStoreService,
|
||||
@IUserDataSyncBackupStoreService userDataSyncBackupStoreService: IUserDataSyncBackupStoreService,
|
||||
@IUserDataSyncLogService logService: IUserDataSyncLogService,
|
||||
@IUserDataSyncUtilService userDataSyncUtilService: IUserDataSyncUtilService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
|
@ -57,7 +57,7 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
|
|||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
|
||||
) {
|
||||
super(environmentService.settingsResource, SyncSource.Settings, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService, userDataSyncUtilService, configurationService);
|
||||
super(environmentService.settingsResource, SyncSource.Settings, 'settings', fileService, environmentService, userDataSyncStoreService, userDataSyncBackupStoreService, userDataSyncEnablementService, telemetryService, logService, userDataSyncUtilService, configurationService);
|
||||
}
|
||||
|
||||
protected setStatus(status: SyncStatus): void {
|
||||
|
@ -259,6 +259,7 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
|
|||
|
||||
if (hasLocalChanged) {
|
||||
this.logService.trace('Settings: Updating local settings...');
|
||||
await this.backupLocal(JSON.stringify(this.toSettingsSyncContent(content)));
|
||||
await this.updateLocalFileContent(content, fileContent);
|
||||
this.logService.info('Settings: Updated local settings');
|
||||
}
|
||||
|
@ -269,7 +270,7 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
|
|||
const ignoredSettings = await this.getIgnoredSettings(content);
|
||||
content = updateIgnoredSettings(content, remoteSettingsSyncContent ? remoteSettingsSyncContent.settings : '{}', ignoredSettings, formatUtils);
|
||||
this.logService.trace('Settings: Updating remote settings...');
|
||||
remoteUserData = await this.updateRemoteUserData(JSON.stringify(<ISettingsSyncContent>{ settings: content }), forcePush ? null : remoteUserData.ref);
|
||||
remoteUserData = await this.updateRemoteUserData(JSON.stringify(this.toSettingsSyncContent(content)), forcePush ? null : remoteUserData.ref);
|
||||
this.logService.info('Settings: Updated remote settings');
|
||||
}
|
||||
|
||||
|
@ -354,6 +355,10 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
|
|||
return null;
|
||||
}
|
||||
|
||||
private toSettingsSyncContent(settings: string): ISettingsSyncContent {
|
||||
return { settings };
|
||||
}
|
||||
|
||||
private _defaultIgnoredSettings: Promise<string[]> | undefined = undefined;
|
||||
protected async getIgnoredSettings(content?: string): Promise<string[]> {
|
||||
if (!this._defaultIgnoredSettings) {
|
||||
|
|
|
@ -156,6 +156,12 @@ export interface IUserDataSyncStoreService {
|
|||
delete(key: ResourceKey): Promise<void>;
|
||||
}
|
||||
|
||||
export const IUserDataSyncBackupStoreService = createDecorator<IUserDataSyncBackupStoreService>('IUserDataSyncBackupStoreService');
|
||||
export interface IUserDataSyncBackupStoreService {
|
||||
_serviceBrand: undefined;
|
||||
backup(resourceKey: ResourceKey, content: string): Promise<void>;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
// #region User Data Sync Error
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable, } from 'vs/base/common/lifecycle';
|
||||
import { IUserDataSyncLogService, ResourceKey, ALL_RESOURCE_KEYS, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { joinPath } from 'vs/base/common/resources';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { toLocalISOString } from 'vs/base/common/date';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
|
||||
export class UserDataSyncBackupStoreService extends Disposable implements IUserDataSyncBackupStoreService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
constructor(
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@IFileService private readonly fileService: IFileService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IUserDataSyncLogService private readonly logService: IUserDataSyncLogService,
|
||||
) {
|
||||
super();
|
||||
ALL_RESOURCE_KEYS.forEach(resourceKey => this.cleanUpBackup(resourceKey));
|
||||
}
|
||||
|
||||
async backup(resourceKey: ResourceKey, content: string): Promise<void> {
|
||||
const folder = joinPath(this.environmentService.userDataSyncHome, resourceKey);
|
||||
const resource = joinPath(folder, `${toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '')}.json`);
|
||||
try {
|
||||
await this.fileService.writeFile(resource, VSBuffer.fromString(content));
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
}
|
||||
try {
|
||||
this.cleanUpBackup(resourceKey);
|
||||
} catch (e) { /* Ignore */ }
|
||||
}
|
||||
|
||||
private async cleanUpBackup(resourceKey: ResourceKey): Promise<void> {
|
||||
const folder = joinPath(this.environmentService.userDataSyncHome, resourceKey);
|
||||
try {
|
||||
try {
|
||||
if (!(await this.fileService.exists(folder))) {
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
const stat = await this.fileService.resolve(folder);
|
||||
if (stat.children) {
|
||||
const all = stat.children.filter(stat => stat.isFile && /^\d{8}T\d{6}(\.json)?$/.test(stat.name)).sort();
|
||||
const backUpMaxAge = 1000 * 60 * 60 * 24 * (this.configurationService.getValue<number>('sync.localBackupDuration') || 30 /* Default 30 days */);
|
||||
let toDelete = all.filter(stat => {
|
||||
const ctime = stat.ctime || new Date(
|
||||
parseInt(stat.name.substring(0, 4)),
|
||||
parseInt(stat.name.substring(4, 6)) - 1,
|
||||
parseInt(stat.name.substring(6, 8)),
|
||||
parseInt(stat.name.substring(9, 11)),
|
||||
parseInt(stat.name.substring(11, 13)),
|
||||
parseInt(stat.name.substring(13, 15))
|
||||
).getTime();
|
||||
return Date.now() - ctime > backUpMaxAge;
|
||||
});
|
||||
const remaining = all.length - toDelete.length;
|
||||
if (remaining < 10) {
|
||||
toDelete = toDelete.slice(10 - remaining);
|
||||
}
|
||||
await Promise.all(toDelete.map(stat => {
|
||||
this.logService.info('Deleting from backup', stat.resource.path);
|
||||
this.fileService.del(stat.resource);
|
||||
}));
|
||||
}
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
import { IRequestService } from 'vs/platform/request/common/request';
|
||||
import { IRequestOptions, IRequestContext, IHeaders } from 'vs/base/parts/request/common/request';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IUserData, ResourceKey, IUserDataManifest, ALL_RESOURCE_KEYS, IUserDataSyncLogService, IUserDataSyncStoreService, IUserDataSyncUtilService, IUserDataSyncEnablementService, ISettingsSyncService, IUserDataSyncService, getDefaultIgnoredSettings } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { IUserData, ResourceKey, IUserDataManifest, ALL_RESOURCE_KEYS, IUserDataSyncLogService, IUserDataSyncStoreService, IUserDataSyncUtilService, IUserDataSyncEnablementService, ISettingsSyncService, IUserDataSyncService, getDefaultIgnoredSettings, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { bufferToStream, VSBuffer } from 'vs/base/common/buffer';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { UserDataSyncService } from 'vs/platform/userDataSync/common/userDataSyncService';
|
||||
|
@ -36,6 +36,7 @@ import { Emitter } from 'vs/base/common/event';
|
|||
import { IAuthenticationTokenService } from 'vs/platform/authentication/common/authentication';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { UserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSyncBackupStoreService';
|
||||
|
||||
export class UserDataSyncClient extends Disposable {
|
||||
|
||||
|
@ -89,6 +90,7 @@ export class UserDataSyncClient extends Disposable {
|
|||
this.instantiationService.stub(IUserDataSyncLogService, logService);
|
||||
this.instantiationService.stub(ITelemetryService, NullTelemetryService);
|
||||
this.instantiationService.stub(IUserDataSyncStoreService, this.instantiationService.createInstance(UserDataSyncStoreService));
|
||||
this.instantiationService.stub(IUserDataSyncBackupStoreService, this.instantiationService.createInstance(UserDataSyncBackupStoreService));
|
||||
this.instantiationService.stub(IUserDataSyncUtilService, new TestUserDataSyncUtilService());
|
||||
this.instantiationService.stub(IUserDataSyncEnablementService, this.instantiationService.createInstance(UserDataSyncEnablementService));
|
||||
|
||||
|
|
14
src/vs/vscode.proposed.d.ts
vendored
14
src/vs/vscode.proposed.d.ts
vendored
|
@ -1745,4 +1745,18 @@ declare module 'vscode' {
|
|||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region https://github.com/microsoft/vscode/issues/90517
|
||||
|
||||
export interface FileSystemError {
|
||||
/**
|
||||
* A code that identifies this error.
|
||||
*
|
||||
* Possible values are names of errors, like [`FileNotFound`](#FileSystemError.FileNotFound),
|
||||
* or `undefined` for an unspecified error.
|
||||
*/
|
||||
readonly code?: string;
|
||||
}
|
||||
|
||||
////#endregion
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import {
|
|||
RunOptionsDTO
|
||||
} from 'vs/workbench/api/common/shared/tasks';
|
||||
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
|
||||
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
|
||||
namespace TaskExecutionDTO {
|
||||
export function from(value: TaskExecution): TaskExecutionDTO {
|
||||
|
@ -604,7 +605,7 @@ export class MainThreadTask implements MainThreadTaskShape {
|
|||
return URI.parse(`${info.scheme}://${info.authority}${path}`);
|
||||
},
|
||||
context: this._extHostContext,
|
||||
resolveVariables: (workspaceFolder: IWorkspaceFolder, toResolve: ResolveSet): Promise<ResolvedVariables> => {
|
||||
resolveVariables: (workspaceFolder: IWorkspaceFolder, toResolve: ResolveSet, target: ConfigurationTarget): Promise<ResolvedVariables> => {
|
||||
const vars: string[] = [];
|
||||
toResolve.variables.forEach(item => vars.push(item));
|
||||
return Promise.resolve(this._proxy.$resolveVariables(workspaceFolder.uri, { process: toResolve.process, variables: vars })).then(values => {
|
||||
|
@ -613,7 +614,7 @@ export class MainThreadTask implements MainThreadTaskShape {
|
|||
partiallyResolvedVars.push(entry.value);
|
||||
});
|
||||
return new Promise<ResolvedVariables>((resolve, reject) => {
|
||||
this._configurationResolverService.resolveWithInteraction(workspaceFolder, partiallyResolvedVars, 'tasks').then(resolvedVars => {
|
||||
this._configurationResolverService.resolveWithInteraction(workspaceFolder, partiallyResolvedVars, 'tasks', undefined, target).then(resolvedVars => {
|
||||
const result: ResolvedVariables = {
|
||||
process: undefined,
|
||||
variables: new Map<string, string>()
|
||||
|
|
|
@ -252,7 +252,15 @@ export class ExtensionsActivator {
|
|||
return;
|
||||
}
|
||||
|
||||
const currentExtension = this._registry.getExtensionDescription(currentActivation.id)!;
|
||||
const currentExtension = this._registry.getExtensionDescription(currentActivation.id);
|
||||
if (!currentExtension) {
|
||||
// Error condition 0: unknown extension
|
||||
this._host.onExtensionActivationError(currentActivation.id, new MissingDependencyError(currentActivation.id.value));
|
||||
const error = new Error(`Unknown dependency '${currentActivation.id.value}'`);
|
||||
this._activatedExtensions.set(ExtensionIdentifier.toKey(currentActivation.id), new FailedExtension(error));
|
||||
return;
|
||||
}
|
||||
|
||||
const depIds = (typeof currentExtension.extensionDependencies === 'undefined' ? [] : currentExtension.extensionDependencies);
|
||||
let currentExtensionGetsGreenLight = true;
|
||||
|
||||
|
|
|
@ -148,7 +148,16 @@ class ConsumerFileSystem implements vscode.FileSystem {
|
|||
}
|
||||
|
||||
// file system error
|
||||
throw new FileSystemError(err.message, err.name as files.FileSystemProviderErrorCode);
|
||||
switch (err.name) {
|
||||
case files.FileSystemProviderErrorCode.FileExists: throw FileSystemError.FileExists(err.message);
|
||||
case files.FileSystemProviderErrorCode.FileNotFound: throw FileSystemError.FileNotFound(err.message);
|
||||
case files.FileSystemProviderErrorCode.FileNotADirectory: throw FileSystemError.FileNotADirectory(err.message);
|
||||
case files.FileSystemProviderErrorCode.FileIsADirectory: throw FileSystemError.FileIsADirectory(err.message);
|
||||
case files.FileSystemProviderErrorCode.NoPermissions: throw FileSystemError.NoPermissions(err.message);
|
||||
case files.FileSystemProviderErrorCode.Unavailable: throw FileSystemError.Unavailable(err.message);
|
||||
|
||||
default: throw new FileSystemError(err.message, err.name as files.FileSystemProviderErrorCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2333,9 +2333,13 @@ export class FileSystemError extends Error {
|
|||
return new FileSystemError(messageOrUri, FileSystemProviderErrorCode.Unavailable, FileSystemError.Unavailable);
|
||||
}
|
||||
|
||||
readonly code?: string;
|
||||
|
||||
constructor(uriOrMessage?: string | URI, code: FileSystemProviderErrorCode = FileSystemProviderErrorCode.Unknown, terminator?: Function) {
|
||||
super(URI.isUri(uriOrMessage) ? uriOrMessage.toString(true) : uriOrMessage);
|
||||
|
||||
this.code = terminator?.name;
|
||||
|
||||
// mark the error as file system provider error so that
|
||||
// we can extract the error code on the receiving side
|
||||
markAsFileSystemProviderError(this, code);
|
||||
|
|
|
@ -67,6 +67,7 @@ export class CustomTreeViewPane extends ViewPane {
|
|||
this._register(this.treeView.onDidChangeTitle((newTitle) => this.updateTitle(newTitle)));
|
||||
this._register(toDisposable(() => this.treeView.setVisibility(false)));
|
||||
this._register(this.onDidChangeBodyVisibility(() => this.updateTreeVisibility()));
|
||||
this._register(this.treeView.onDidChangeWelcomeState(() => this._onDidChangeViewWelcomeState.fire()));
|
||||
this.updateTreeVisibility();
|
||||
}
|
||||
|
||||
|
@ -83,6 +84,10 @@ export class CustomTreeViewPane extends ViewPane {
|
|||
}
|
||||
}
|
||||
|
||||
shouldShowWelcome(): boolean {
|
||||
return (this.treeView.dataProvider === undefined) && (this.treeView.message === undefined);
|
||||
}
|
||||
|
||||
layoutBody(height: number, width: number): void {
|
||||
this.treeView.layout(height, width);
|
||||
}
|
||||
|
@ -151,6 +156,9 @@ export class CustomTreeView extends Disposable implements ITreeView {
|
|||
private readonly _onDidChangeActions: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidChangeActions: Event<void> = this._onDidChangeActions.event;
|
||||
|
||||
private readonly _onDidChangeWelcomeState: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidChangeWelcomeState: Event<void> = this._onDidChangeWelcomeState.event;
|
||||
|
||||
private readonly _onDidChangeTitle: Emitter<string> = this._register(new Emitter<string>());
|
||||
readonly onDidChangeTitle: Event<string> = this._onDidChangeTitle.event;
|
||||
|
||||
|
@ -223,6 +231,8 @@ export class CustomTreeView extends Disposable implements ITreeView {
|
|||
this._dataProvider = undefined;
|
||||
this.updateMessage();
|
||||
}
|
||||
|
||||
this._onDidChangeWelcomeState.fire();
|
||||
}
|
||||
|
||||
private _message: string | undefined;
|
||||
|
@ -233,6 +243,7 @@ export class CustomTreeView extends Disposable implements ITreeView {
|
|||
set message(message: string | undefined) {
|
||||
this._message = message;
|
||||
this.updateMessage();
|
||||
this._onDidChangeWelcomeState.fire();
|
||||
}
|
||||
|
||||
get title(): string {
|
||||
|
|
|
@ -488,6 +488,8 @@ export interface ITreeView extends IDisposable {
|
|||
|
||||
readonly onDidChangeTitle: Event<string>;
|
||||
|
||||
readonly onDidChangeWelcomeState: Event<void>;
|
||||
|
||||
refresh(treeItems?: ITreeItem[]): Promise<void>;
|
||||
|
||||
setVisibility(visible: boolean): void;
|
||||
|
|
|
@ -44,7 +44,7 @@ import { WatchExpressionsView } from 'vs/workbench/contrib/debug/browser/watchEx
|
|||
import { VariablesView } from 'vs/workbench/contrib/debug/browser/variablesView';
|
||||
import { ClearReplAction, Repl } from 'vs/workbench/contrib/debug/browser/repl';
|
||||
import { DebugContentProvider } from 'vs/workbench/contrib/debug/common/debugContentProvider';
|
||||
import { StartView } from 'vs/workbench/contrib/debug/browser/startView';
|
||||
import { WelcomeView } from 'vs/workbench/contrib/debug/browser/welcomeView';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { DebugViewPaneContainer, OpenDebugPanelAction } from 'vs/workbench/contrib/debug/browser/debugViewlet';
|
||||
import { registerEditorContribution } from 'vs/editor/browser/editorExtensions';
|
||||
|
@ -108,7 +108,7 @@ viewsRegistry.registerViews([{ id: VARIABLES_VIEW_ID, name: nls.localize('variab
|
|||
viewsRegistry.registerViews([{ id: WATCH_VIEW_ID, name: nls.localize('watch', "Watch"), ctorDescriptor: new SyncDescriptor(WatchExpressionsView), order: 20, weight: 10, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusWatchView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer);
|
||||
viewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callStack', "Call Stack"), ctorDescriptor: new SyncDescriptor(CallStackView), order: 30, weight: 30, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusCallStackView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer);
|
||||
viewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), ctorDescriptor: new SyncDescriptor(BreakpointsView), order: 40, weight: 20, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' }, when: ContextKeyExpr.or(CONTEXT_BREAKPOINTS_EXIST, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer);
|
||||
viewsRegistry.registerViews([{ id: StartView.ID, name: StartView.LABEL, ctorDescriptor: new SyncDescriptor(StartView), order: 10, weight: 40, canToggleVisibility: true, when: CONTEXT_DEBUG_UX.isEqualTo('simple') }], viewContainer);
|
||||
viewsRegistry.registerViews([{ id: WelcomeView.ID, name: WelcomeView.LABEL, ctorDescriptor: new SyncDescriptor(WelcomeView), order: 10, weight: 40, canToggleVisibility: true, when: CONTEXT_DEBUG_UX.isEqualTo('simple') }], viewContainer);
|
||||
viewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), ctorDescriptor: new SyncDescriptor(LoadedScriptsView), order: 35, weight: 5, canToggleVisibility: true, canMoveView: true, collapsed: true, when: ContextKeyExpr.and(CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer);
|
||||
|
||||
registerCommands();
|
||||
|
|
|
@ -32,8 +32,8 @@ import { MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryAc
|
|||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { TogglePanelAction } from 'vs/workbench/browser/panel';
|
||||
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
|
||||
import { StartView } from 'vs/workbench/contrib/debug/browser/startView';
|
||||
import { IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
import { WelcomeView } from 'vs/workbench/contrib/debug/browser/welcomeView';
|
||||
|
||||
export class DebugViewPaneContainer extends ViewPaneContainer {
|
||||
|
||||
|
@ -92,7 +92,7 @@ export class DebugViewPaneContainer extends ViewPaneContainer {
|
|||
if (this.startDebugActionViewItem) {
|
||||
this.startDebugActionViewItem.focus();
|
||||
} else {
|
||||
this.focusView(StartView.ID);
|
||||
this.focusView(WelcomeView.ID);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,10 +29,10 @@ const debugStartLanguageKey = 'debugStartLanguage';
|
|||
const CONTEXT_DEBUG_START_LANGUAGE = new RawContextKey<string>(debugStartLanguageKey, undefined);
|
||||
const CONTEXT_DEBUGGER_INTERESTED_IN_ACTIVE_EDITOR = new RawContextKey<boolean>('debuggerInterestedInActiveEditor', false);
|
||||
|
||||
export class StartView extends ViewPane {
|
||||
export class WelcomeView extends ViewPane {
|
||||
|
||||
static ID = 'workbench.debug.startView';
|
||||
static LABEL = localize('start', "Start");
|
||||
static ID = 'workbench.debug.welcome';
|
||||
static LABEL = localize('run', "Run");
|
||||
|
||||
private debugStartLanguageContext: IContextKey<string | undefined>;
|
||||
private debuggerInterestedContext: IContextKey<boolean>;
|
||||
|
@ -52,7 +52,7 @@ export class StartView extends ViewPane {
|
|||
@IStorageService storageSevice: IStorageService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
) {
|
||||
super({ ...(options as IViewPaneOptions), ariaHeaderLabel: localize('debugStart', "Debug Start Section") }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
|
||||
super({ ...(options as IViewPaneOptions), ariaHeaderLabel: localize('debugStart', "Debug Welcome Section") }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
|
||||
|
||||
this.debugStartLanguageContext = CONTEXT_DEBUG_START_LANGUAGE.bindTo(contextKeyService);
|
||||
this.debuggerInterestedContext = CONTEXT_DEBUGGER_INTERESTED_IN_ACTIVE_EDITOR.bindTo(contextKeyService);
|
||||
|
@ -87,23 +87,23 @@ export class StartView extends ViewPane {
|
|||
}
|
||||
|
||||
const viewsRegistry = Registry.as<IViewsRegistry>(Extensions.ViewsRegistry);
|
||||
viewsRegistry.registerViewWelcomeContent(StartView.ID, {
|
||||
viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, {
|
||||
content: localize('openAFileWhichCanBeDebugged', "[Open a file](command:{0}) which can be debugged or run.", isMacintosh ? OpenFileFolderAction.ID : OpenFileAction.ID),
|
||||
when: CONTEXT_DEBUGGER_INTERESTED_IN_ACTIVE_EDITOR.toNegated()
|
||||
});
|
||||
|
||||
let debugKeybindingLabel = '';
|
||||
viewsRegistry.registerViewWelcomeContent(StartView.ID, {
|
||||
viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, {
|
||||
content: localize('runAndDebugAction', "[Run and Debug{0}](command:{1})", debugKeybindingLabel, StartAction.ID),
|
||||
preconditions: [CONTEXT_DEBUGGER_INTERESTED_IN_ACTIVE_EDITOR]
|
||||
});
|
||||
|
||||
viewsRegistry.registerViewWelcomeContent(StartView.ID, {
|
||||
viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, {
|
||||
content: localize('customizeRunAndDebug', "To customize Run and Debug [create a launch.json file](command:{0}).", ConfigureAction.ID),
|
||||
when: WorkbenchStateContext.notEqualsTo('empty')
|
||||
});
|
||||
|
||||
viewsRegistry.registerViewWelcomeContent(StartView.ID, {
|
||||
viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, {
|
||||
content: localize('customizeRunAndDebugOpenFolder', "To customize Run and Debug, [open a folder](command:{0}) and create a launch.json file.", isMacintosh ? OpenFileFolderAction.ID : OpenFolderAction.ID),
|
||||
when: WorkbenchStateContext.isEqualTo('empty')
|
||||
});
|
|
@ -33,7 +33,7 @@ import { IOutputService } from 'vs/workbench/contrib/output/common/output';
|
|||
import { StartStopProblemCollector, WatchingProblemCollector, ProblemCollectorEventKind, ProblemHandlingStrategy } from 'vs/workbench/contrib/tasks/common/problemCollectors';
|
||||
import {
|
||||
Task, CustomTask, ContributedTask, RevealKind, CommandOptions, ShellConfiguration, RuntimeType, PanelKind,
|
||||
TaskEvent, TaskEventKind, ShellQuotingOptions, ShellQuoting, CommandString, CommandConfiguration, ExtensionTaskSource, TaskScope, RevealProblemKind, DependsOrder
|
||||
TaskEvent, TaskEventKind, ShellQuotingOptions, ShellQuoting, CommandString, CommandConfiguration, ExtensionTaskSource, TaskScope, RevealProblemKind, DependsOrder, TaskSourceKind
|
||||
} from 'vs/workbench/contrib/tasks/common/tasks';
|
||||
import {
|
||||
ITaskSystem, ITaskSummary, ITaskExecuteResult, TaskExecuteKind, TaskError, TaskErrors, ITaskResolver,
|
||||
|
@ -545,7 +545,7 @@ export class TerminalTaskSystem implements ITaskSystem {
|
|||
resolveSet.process.path = envPath;
|
||||
}
|
||||
}
|
||||
resolvedVariables = taskSystemInfo.resolveVariables(workspaceFolder, resolveSet).then(async (resolved) => {
|
||||
resolvedVariables = taskSystemInfo.resolveVariables(workspaceFolder, resolveSet, TaskSourceKind.toConfigurationTarget(task._source.kind)).then(async (resolved) => {
|
||||
this.mergeMaps(alreadyResolved, resolved.variables);
|
||||
resolved.variables = new Map(alreadyResolved);
|
||||
if (isProcess) {
|
||||
|
@ -563,7 +563,7 @@ export class TerminalTaskSystem implements ITaskSystem {
|
|||
unresolved.forEach(variable => variablesArray.push(variable));
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this.configurationResolverService.resolveWithInteraction(workspaceFolder, variablesArray, 'tasks').then(async (resolvedVariablesMap: Map<string, string> | undefined) => {
|
||||
this.configurationResolverService.resolveWithInteraction(workspaceFolder, variablesArray, 'tasks', undefined, TaskSourceKind.toConfigurationTarget(task._source.kind)).then(async (resolvedVariablesMap: Map<string, string> | undefined) => {
|
||||
if (resolvedVariablesMap) {
|
||||
this.mergeMaps(alreadyResolved, resolvedVariablesMap);
|
||||
resolvedVariablesMap = new Map(alreadyResolved);
|
||||
|
|
|
@ -10,6 +10,7 @@ import { Event } from 'vs/base/common/event';
|
|||
import { Platform } from 'vs/base/common/platform';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { Task, TaskEvent, KeyedTaskIdentifier } from './tasks';
|
||||
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
|
||||
export const enum TaskErrors {
|
||||
NotConfigured,
|
||||
|
@ -118,7 +119,7 @@ export interface TaskSystemInfo {
|
|||
platform: Platform;
|
||||
context: any;
|
||||
uriProvider: (this: void, path: string) => URI;
|
||||
resolveVariables(workspaceFolder: IWorkspaceFolder, toResolve: ResolveSet): Promise<ResolvedVariables>;
|
||||
resolveVariables(workspaceFolder: IWorkspaceFolder, toResolve: ResolveSet, target: ConfigurationTarget): Promise<ResolvedVariables>;
|
||||
getDefaultShellAndArgs(): Promise<{ shell: string, args: string[] | string | undefined }>;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import { IWorkspaceFolder, IWorkspace } from 'vs/platform/workspace/common/works
|
|||
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { TaskDefinitionRegistry } from 'vs/workbench/contrib/tasks/common/taskDefinitionRegistry';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
|
||||
export const TASK_RUNNING_STATE = new RawContextKey<boolean>('taskRunning', false);
|
||||
|
||||
|
@ -377,6 +378,14 @@ export namespace TaskSourceKind {
|
|||
export const InMemory: 'inMemory' = 'inMemory';
|
||||
export const WorkspaceFile: 'workspaceFile' = 'workspaceFile';
|
||||
export const User: 'user' = 'user';
|
||||
|
||||
export function toConfigurationTarget(kind: string): ConfigurationTarget {
|
||||
switch (kind) {
|
||||
case TaskSourceKind.User: return ConfigurationTarget.USER;
|
||||
case TaskSourceKind.WorkspaceFile: return ConfigurationTarget.WORKSPACE;
|
||||
default: return ConfigurationTarget.WORKSPACE_FOLDER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface TaskSourceConfigElement {
|
||||
|
|
|
@ -22,7 +22,7 @@ export type ViewsWelcomeExtensionPoint = ViewWelcome[];
|
|||
|
||||
export const ViewIdentifierMap: { [key: string]: string } = {
|
||||
'explorer': 'workbench.explorer.emptyView',
|
||||
'debug': 'workbench.debug.startView',
|
||||
'debug': 'workbench.debug.welcome',
|
||||
'scm': 'workbench.scm',
|
||||
};
|
||||
|
||||
|
@ -40,7 +40,6 @@ const viewsWelcomeExtensionPointSchema = Object.freeze<IConfigurationPropertySch
|
|||
[ViewsWelcomeExtensionPointFields.view]: {
|
||||
type: 'string',
|
||||
description: nls.localize('contributes.viewsWelcome.view.view', "Target view identifier for this welcome content."),
|
||||
enum: Object.keys(ViewIdentifierMap),
|
||||
},
|
||||
[ViewsWelcomeExtensionPointFields.contents]: {
|
||||
type: 'string',
|
||||
|
|
|
@ -11,7 +11,7 @@ import { Schemas } from 'vs/base/common/network';
|
|||
import { toResource } from 'vs/workbench/common/editor';
|
||||
import { IStringDictionary, forEach, fromMap } from 'vs/base/common/collections';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IWorkspaceFolder, IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
|
@ -86,12 +86,12 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR
|
|||
}, envVariables);
|
||||
}
|
||||
|
||||
public async resolveWithInteractionReplace(folder: IWorkspaceFolder | undefined, config: any, section?: string, variables?: IStringDictionary<string>): Promise<any> {
|
||||
public async resolveWithInteractionReplace(folder: IWorkspaceFolder | undefined, config: any, section?: string, variables?: IStringDictionary<string>, target?: ConfigurationTarget): Promise<any> {
|
||||
// resolve any non-interactive variables and any contributed variables
|
||||
config = this.resolveAny(folder, config);
|
||||
|
||||
// resolve input variables in the order in which they are encountered
|
||||
return this.resolveWithInteraction(folder, config, section, variables).then(mapping => {
|
||||
return this.resolveWithInteraction(folder, config, section, variables, target).then(mapping => {
|
||||
// finally substitute evaluated command variables (if there are any)
|
||||
if (!mapping) {
|
||||
return null;
|
||||
|
@ -103,14 +103,14 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR
|
|||
});
|
||||
}
|
||||
|
||||
public async resolveWithInteraction(folder: IWorkspaceFolder | undefined, config: any, section?: string, variables?: IStringDictionary<string>): Promise<Map<string, string> | undefined> {
|
||||
public async resolveWithInteraction(folder: IWorkspaceFolder | undefined, config: any, section?: string, variables?: IStringDictionary<string>, target?: ConfigurationTarget): Promise<Map<string, string> | undefined> {
|
||||
// resolve any non-interactive variables and any contributed variables
|
||||
const resolved = await this.resolveAnyMap(folder, config);
|
||||
config = resolved.newConfig;
|
||||
const allVariableMapping: Map<string, string> = resolved.resolvedVariables;
|
||||
|
||||
// resolve input and command variables in the order in which they are encountered
|
||||
return this.resolveWithInputAndCommands(folder, config, variables, section).then(inputOrCommandMapping => {
|
||||
return this.resolveWithInputAndCommands(folder, config, variables, section, target).then(inputOrCommandMapping => {
|
||||
if (this.updateMapping(inputOrCommandMapping, allVariableMapping)) {
|
||||
return allVariableMapping;
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR
|
|||
*
|
||||
* @param variableToCommandMap Aliases for commands
|
||||
*/
|
||||
private async resolveWithInputAndCommands(folder: IWorkspaceFolder | undefined, configuration: any, variableToCommandMap?: IStringDictionary<string>, section?: string): Promise<IStringDictionary<string> | undefined> {
|
||||
private async resolveWithInputAndCommands(folder: IWorkspaceFolder | undefined, configuration: any, variableToCommandMap?: IStringDictionary<string>, section?: string, target?: ConfigurationTarget): Promise<IStringDictionary<string> | undefined> {
|
||||
|
||||
if (!configuration) {
|
||||
return Promise.resolve(undefined);
|
||||
|
@ -148,9 +148,18 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR
|
|||
// get all "inputs"
|
||||
let inputs: ConfiguredInput[] = [];
|
||||
if (folder && this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY && section) {
|
||||
let result = this.configurationService.getValue<any>(section, { resource: folder.uri });
|
||||
if (result) {
|
||||
inputs = result.inputs;
|
||||
let result = this.configurationService.inspect(section, { resource: folder.uri });
|
||||
if (result && (result.userValue || result.workspaceValue || result.workspaceFolderValue)) {
|
||||
switch (target) {
|
||||
case ConfigurationTarget.USER: inputs = (<any>result.userValue)?.inputs; break;
|
||||
case ConfigurationTarget.WORKSPACE: inputs = (<any>result.workspaceValue)?.inputs; break;
|
||||
default: inputs = (<any>result.workspaceFolderValue)?.inputs;
|
||||
}
|
||||
} else {
|
||||
const valueResult = this.configurationService.getValue<any>(section, { resource: folder.uri });
|
||||
if (valueResult) {
|
||||
inputs = valueResult.inputs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
import { IStringDictionary } from 'vs/base/common/collections';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
|
||||
export const IConfigurationResolverService = createDecorator<IConfigurationResolverService>('configurationResolverService');
|
||||
|
||||
|
@ -29,13 +30,13 @@ export interface IConfigurationResolverService {
|
|||
* @param section For example, 'tasks' or 'debug'. Used for resolving inputs.
|
||||
* @param variables Aliases for commands.
|
||||
*/
|
||||
resolveWithInteractionReplace(folder: IWorkspaceFolder | undefined, config: any, section?: string, variables?: IStringDictionary<string>): Promise<any>;
|
||||
resolveWithInteractionReplace(folder: IWorkspaceFolder | undefined, config: any, section?: string, variables?: IStringDictionary<string>, target?: ConfigurationTarget): Promise<any>;
|
||||
|
||||
/**
|
||||
* Similar to resolveWithInteractionReplace, except without the replace. Returns a map of variables and their resolution.
|
||||
* Keys in the map will be of the format input:variableName or command:variableName.
|
||||
*/
|
||||
resolveWithInteraction(folder: IWorkspaceFolder | undefined, config: any, section?: string, variables?: IStringDictionary<string>): Promise<Map<string, string> | undefined>;
|
||||
resolveWithInteraction(folder: IWorkspaceFolder | undefined, config: any, section?: string, variables?: IStringDictionary<string>, target?: ConfigurationTarget): Promise<Map<string, string> | undefined>;
|
||||
|
||||
/**
|
||||
* Contributes a variable that can be resolved later. Consumers that use resolveAny, resolveWithInteraction,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IFileSystemProviderWithFileReadWriteCapability, FileSystemProviderCapabilities, IFileChange, IWatchOptions, IStat, FileOverwriteOptions, FileType, FileDeleteOptions, FileWriteOptions, FileChangeType, FileSystemProviderErrorCode } from 'vs/platform/files/common/files';
|
||||
import { IFileSystemProviderWithFileReadWriteCapability, FileSystemProviderCapabilities, IFileChange, IWatchOptions, IStat, FileOverwriteOptions, FileType, FileDeleteOptions, FileWriteOptions, FileChangeType } from 'vs/platform/files/common/files';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
|
@ -53,13 +53,13 @@ export abstract class KeyValueLogProvider extends Disposable implements IFileSys
|
|||
size: 0
|
||||
};
|
||||
}
|
||||
return Promise.reject(new FileSystemError(resource, FileSystemProviderErrorCode.FileNotFound));
|
||||
return Promise.reject(FileSystemError.FileNotFound(resource));
|
||||
}
|
||||
|
||||
async readdir(resource: URI): Promise<[string, FileType][]> {
|
||||
const hasKey = await this.hasKey(resource.path);
|
||||
if (hasKey) {
|
||||
return Promise.reject(new FileSystemError(resource, FileSystemProviderErrorCode.FileNotADirectory));
|
||||
return Promise.reject(FileSystemError.FileNotADirectory(resource));
|
||||
}
|
||||
const keys = await this.getAllKeys();
|
||||
const files: Map<string, [string, FileType]> = new Map<string, [string, FileType]>();
|
||||
|
@ -79,7 +79,7 @@ export abstract class KeyValueLogProvider extends Disposable implements IFileSys
|
|||
async readFile(resource: URI): Promise<Uint8Array> {
|
||||
const hasKey = await this.hasKey(resource.path);
|
||||
if (!hasKey) {
|
||||
return Promise.reject(new FileSystemError(resource, FileSystemProviderErrorCode.FileNotFound));
|
||||
return Promise.reject(FileSystemError.FileNotFound(resource));
|
||||
}
|
||||
const value = await this.getValue(resource.path);
|
||||
return VSBuffer.fromString(value).buffer;
|
||||
|
@ -90,7 +90,7 @@ export abstract class KeyValueLogProvider extends Disposable implements IFileSys
|
|||
if (!hasKey) {
|
||||
const files = await this.readdir(resource);
|
||||
if (files.length) {
|
||||
return Promise.reject(new FileSystemError(resource, FileSystemProviderErrorCode.FileIsADirectory));
|
||||
return Promise.reject(FileSystemError.FileIsADirectory(resource));
|
||||
}
|
||||
}
|
||||
await this.setValue(resource.path, VSBuffer.wrap(content).toString());
|
||||
|
|
|
@ -62,10 +62,11 @@ import { ITunnelService } from 'vs/platform/remote/common/tunnel';
|
|||
import { TunnelService } from 'vs/workbench/services/remote/common/tunnelService';
|
||||
import { ILoggerService } from 'vs/platform/log/common/log';
|
||||
import { FileLoggerService } from 'vs/platform/log/common/fileLogService';
|
||||
import { IUserDataSyncStoreService, IUserDataSyncService, IUserDataSyncLogService, ISettingsSyncService, IUserDataAutoSyncService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { IUserDataSyncStoreService, IUserDataSyncService, IUserDataSyncLogService, ISettingsSyncService, IUserDataAutoSyncService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { AuthenticationService, IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService';
|
||||
import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog';
|
||||
import { UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService';
|
||||
import { UserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSyncBackupStoreService';
|
||||
import { UserDataSyncService } from 'vs/platform/userDataSync/common/userDataSyncService';
|
||||
import { SettingsSynchroniser } from 'vs/platform/userDataSync/common/settingsSync';
|
||||
import { IAuthenticationTokenService, AuthenticationTokenService } from 'vs/platform/authentication/common/authentication';
|
||||
|
@ -83,6 +84,7 @@ registerSingleton(ILoggerService, FileLoggerService);
|
|||
registerSingleton(IAuthenticationService, AuthenticationService);
|
||||
registerSingleton(IUserDataSyncLogService, UserDataSyncLogService);
|
||||
registerSingleton(IUserDataSyncStoreService, UserDataSyncStoreService);
|
||||
registerSingleton(IUserDataSyncBackupStoreService, UserDataSyncBackupStoreService);
|
||||
registerSingleton(IAuthenticationTokenService, AuthenticationTokenService);
|
||||
registerSingleton(IUserDataAutoSyncService, UserDataAutoSyncService);
|
||||
registerSingleton(ISettingsSyncService, SettingsSynchroniser);
|
||||
|
|
Loading…
Reference in a new issue