mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode 313ede61cbad8f9dc748907b3384e059ddddb79a (#7436)
* Merge from vscode 313ede61cbad8f9dc748907b3384e059ddddb79a * fix strict null checks
This commit is contained in:
@@ -75,9 +75,10 @@ class DecorationRule {
|
||||
}
|
||||
|
||||
// bubble badge
|
||||
// TODO @misolori update bubble badge to use class name instead of unicode
|
||||
createCSSRule(
|
||||
`.${this.bubbleBadgeClassName}::after`,
|
||||
`content: "\uf052"; color: ${getColor(theme, color)}; font-family: octicons; font-size: 14px; padding-right: 14px; opacity: 0.4;`,
|
||||
`content: "\uf052"; color: ${getColor(theme, color)}; font-family: octicons; font-size: 14px; padding-right: 10px; opacity: 0.4;`,
|
||||
element
|
||||
);
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ export abstract class AbstractFileDialogService {
|
||||
|
||||
const toOpen: IWindowOpenable = stat.isDirectory ? { folderUri: uri } : { fileUri: uri };
|
||||
if (stat.isDirectory || options.forceNewWindow || preferNewWindow) {
|
||||
return this.hostService.openInWindow([toOpen], { forceNewWindow: options.forceNewWindow });
|
||||
return this.hostService.openWindow([toOpen], { forceNewWindow: options.forceNewWindow });
|
||||
} else {
|
||||
return this.openerService.open(uri);
|
||||
}
|
||||
@@ -105,7 +105,7 @@ export abstract class AbstractFileDialogService {
|
||||
const uri = await this.pickResource({ canSelectFiles: true, canSelectFolders: false, canSelectMany: false, defaultUri: options.defaultUri, title, availableFileSystems });
|
||||
if (uri) {
|
||||
if (options.forceNewWindow || preferNewWindow) {
|
||||
return this.hostService.openInWindow([{ fileUri: uri }], { forceNewWindow: options.forceNewWindow });
|
||||
return this.hostService.openWindow([{ fileUri: uri }], { forceNewWindow: options.forceNewWindow });
|
||||
} else {
|
||||
return this.openerService.open(uri);
|
||||
}
|
||||
@@ -118,7 +118,7 @@ export abstract class AbstractFileDialogService {
|
||||
|
||||
const uri = await this.pickResource({ canSelectFiles: false, canSelectFolders: true, canSelectMany: false, defaultUri: options.defaultUri, title, availableFileSystems });
|
||||
if (uri) {
|
||||
return this.hostService.openInWindow([{ folderUri: uri }], { forceNewWindow: options.forceNewWindow });
|
||||
return this.hostService.openWindow([{ folderUri: uri }], { forceNewWindow: options.forceNewWindow });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ export abstract class AbstractFileDialogService {
|
||||
|
||||
const uri = await this.pickResource({ canSelectFiles: true, canSelectFolders: false, canSelectMany: false, defaultUri: options.defaultUri, title, filters, availableFileSystems });
|
||||
if (uri) {
|
||||
return this.hostService.openInWindow([{ workspaceUri: uri }], { forceNewWindow: options.forceNewWindow });
|
||||
return this.hostService.openWindow([{ workspaceUri: uri }], { forceNewWindow: options.forceNewWindow });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ export class FileDialogService extends AbstractFileDialogService implements IFil
|
||||
return this.pickFileToSaveSimplified(schema, options);
|
||||
} else {
|
||||
const result = await this.electronService.showSaveDialog(this.toNativeSaveDialogOptions(options));
|
||||
if (result && !result.canceled && result.filePath) {
|
||||
if (result && result.filePath) {
|
||||
return URI.file(result.filePath);
|
||||
}
|
||||
}
|
||||
@@ -134,7 +134,7 @@ export class FileDialogService extends AbstractFileDialogService implements IFil
|
||||
}
|
||||
|
||||
const result = await this.electronService.showSaveDialog(this.toNativeSaveDialogOptions(options));
|
||||
if (result && !result.canceled && result.filePath) {
|
||||
if (result && result.filePath) {
|
||||
return URI.file(result.filePath);
|
||||
}
|
||||
|
||||
|
||||
@@ -364,12 +364,16 @@ export class RPCProtocol extends Disposable implements IRPCProtocol {
|
||||
const pendingReply = this._pendingRPCReplies[callId];
|
||||
delete this._pendingRPCReplies[callId];
|
||||
|
||||
let err: Error | null = null;
|
||||
if (value && value.$isError) {
|
||||
err = new Error();
|
||||
err.name = value.name;
|
||||
err.message = value.message;
|
||||
err.stack = value.stack;
|
||||
let err: any = undefined;
|
||||
if (value) {
|
||||
if (value.$isError) {
|
||||
err = new Error();
|
||||
err.name = value.name;
|
||||
err.message = value.message;
|
||||
err.stack = value.stack;
|
||||
} else {
|
||||
err = value;
|
||||
}
|
||||
}
|
||||
pendingReply.resolveErr(err);
|
||||
}
|
||||
@@ -725,7 +729,7 @@ class MessageIO {
|
||||
}
|
||||
|
||||
public static serializeReplyErr(req: number, err: any): VSBuffer {
|
||||
if (err instanceof Error) {
|
||||
if (err) {
|
||||
return this._serializeReplyErrEror(req, err);
|
||||
}
|
||||
return this._serializeReplyErrEmpty(req);
|
||||
|
||||
@@ -187,4 +187,17 @@ suite('RPCProtocol', () => {
|
||||
done(null);
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #72798: null errors are hard to digest', function (done) {
|
||||
delegate = (a1: number, a2: number) => {
|
||||
throw { 'what': 'what' };
|
||||
};
|
||||
bProxy.$m(4, 1).then((res) => {
|
||||
assert.fail('unexpected');
|
||||
done(null);
|
||||
}, (err) => {
|
||||
assert.equal(err.what, 'what');
|
||||
done(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { IResourceEditor, IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IWindowSettings, IWindowOpenable, IOpenInWindowOptions, isFolderToOpen, isWorkspaceToOpen, isFileToOpen, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
|
||||
import { IWindowSettings, IWindowOpenable, IOpenWindowOptions, isFolderToOpen, isWorkspaceToOpen, isFileToOpen, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
|
||||
import { pathsToEditors } from 'vs/workbench/common/editor';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
@@ -46,13 +46,6 @@ export class BrowserHostService extends Disposable implements IHostService {
|
||||
|
||||
_serviceBrand: undefined;
|
||||
|
||||
//#region Events
|
||||
|
||||
get onDidChangeFocus(): Event<boolean> { return this._onDidChangeFocus; }
|
||||
private _onDidChangeFocus: Event<boolean>;
|
||||
|
||||
//#endregion
|
||||
|
||||
private workspaceProvider: IWorkspaceProvider;
|
||||
|
||||
constructor(
|
||||
@@ -87,11 +80,28 @@ export class BrowserHostService extends Disposable implements IHostService {
|
||||
);
|
||||
}
|
||||
|
||||
//#region Window
|
||||
get onDidChangeFocus(): Event<boolean> { return this._onDidChangeFocus; }
|
||||
private _onDidChangeFocus: Event<boolean>;
|
||||
|
||||
readonly windowCount = Promise.resolve(1);
|
||||
get hasFocus(): boolean {
|
||||
return document.hasFocus();
|
||||
}
|
||||
|
||||
async openInWindow(toOpen: IWindowOpenable[], options?: IOpenInWindowOptions): Promise<void> {
|
||||
async focus(): Promise<void> {
|
||||
window.focus();
|
||||
}
|
||||
|
||||
openWindow(options?: IOpenEmptyWindowOptions): Promise<void>;
|
||||
openWindow(toOpen: IWindowOpenable[], options?: IOpenWindowOptions): Promise<void>;
|
||||
openWindow(arg1?: IOpenEmptyWindowOptions | IWindowOpenable[], arg2?: IOpenWindowOptions): Promise<void> {
|
||||
if (Array.isArray(arg1)) {
|
||||
return this.doOpenWindow(arg1, arg2);
|
||||
}
|
||||
|
||||
return this.doOpenEmptyWindow(arg1);
|
||||
}
|
||||
|
||||
private async doOpenWindow(toOpen: IWindowOpenable[], options?: IOpenWindowOptions): Promise<void> {
|
||||
for (let i = 0; i < toOpen.length; i++) {
|
||||
const openable = toOpen[i];
|
||||
openable.label = openable.label || this.getRecentLabel(openable);
|
||||
@@ -126,7 +136,7 @@ export class BrowserHostService extends Disposable implements IHostService {
|
||||
return this.labelService.getUriLabel(openable.fileUri);
|
||||
}
|
||||
|
||||
private shouldReuse(options: IOpenInWindowOptions = {}): boolean {
|
||||
private shouldReuse(options: IOpenWindowOptions = {}): boolean {
|
||||
const windowConfig = this.configurationService.getValue<IWindowSettings>('window');
|
||||
const openFolderInNewWindowConfig = (windowConfig && windowConfig.openFoldersInNewWindow) || 'default' /* default */;
|
||||
|
||||
@@ -138,8 +148,8 @@ export class BrowserHostService extends Disposable implements IHostService {
|
||||
return !openFolderInNewWindow;
|
||||
}
|
||||
|
||||
async openEmptyWindow(options?: IOpenEmptyWindowOptions): Promise<void> {
|
||||
this.workspaceProvider.open(undefined, { reuse: options && options.reuse });
|
||||
private async doOpenEmptyWindow(options?: IOpenEmptyWindowOptions): Promise<void> {
|
||||
this.workspaceProvider.open(undefined, { reuse: options && options.forceReuseWindow });
|
||||
}
|
||||
|
||||
async toggleFullScreen(): Promise<void> {
|
||||
@@ -176,16 +186,6 @@ export class BrowserHostService extends Disposable implements IHostService {
|
||||
}
|
||||
}
|
||||
|
||||
get hasFocus(): boolean {
|
||||
return document.hasFocus();
|
||||
}
|
||||
|
||||
async focus(): Promise<void> {
|
||||
window.focus();
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
async restart(): Promise<void> {
|
||||
this.reload();
|
||||
}
|
||||
@@ -195,7 +195,7 @@ export class BrowserHostService extends Disposable implements IHostService {
|
||||
}
|
||||
|
||||
async closeWorkspace(): Promise<void> {
|
||||
return this.openEmptyWindow({ reuse: true });
|
||||
return this.doOpenEmptyWindow({ forceReuseWindow: true });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IWindowOpenable, IOpenInWindowOptions, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
|
||||
import { IWindowOpenable, IOpenWindowOptions, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
|
||||
|
||||
export const IHostService = createDecorator<IHostService>('hostService');
|
||||
|
||||
@@ -13,38 +13,13 @@ export interface IHostService {
|
||||
|
||||
_serviceBrand: undefined;
|
||||
|
||||
//#region Events
|
||||
//#region Focus
|
||||
|
||||
/**
|
||||
* Emitted when the window focus changes.
|
||||
*/
|
||||
readonly onDidChangeFocus: Event<boolean>;
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Window
|
||||
|
||||
/**
|
||||
* The number of windows that belong to the current client session.
|
||||
*/
|
||||
readonly windowCount: Promise<number>;
|
||||
|
||||
/**
|
||||
* Opens the provided array of openables in a window with the provided options.
|
||||
*/
|
||||
openInWindow(toOpen: IWindowOpenable[], options?: IOpenInWindowOptions): Promise<void>;
|
||||
|
||||
/**
|
||||
* Opens an empty window. The optional parameter allows to define if
|
||||
* a new window should open or the existing one change to an empty.
|
||||
*/
|
||||
openEmptyWindow(options?: IOpenEmptyWindowOptions): Promise<void>;
|
||||
|
||||
/**
|
||||
* Switch between fullscreen and normal window.
|
||||
*/
|
||||
toggleFullScreen(): Promise<void>;
|
||||
|
||||
/**
|
||||
* Find out if the window has focus or not.
|
||||
*/
|
||||
@@ -57,6 +32,28 @@ export interface IHostService {
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
//#region Window
|
||||
|
||||
/**
|
||||
* Opens an empty window. The optional parameter allows to define if
|
||||
* a new window should open or the existing one change to an empty.
|
||||
*/
|
||||
openWindow(options?: IOpenEmptyWindowOptions): Promise<void>;
|
||||
|
||||
/**
|
||||
* Opens the provided array of openables in a window with the provided options.
|
||||
*/
|
||||
openWindow(toOpen: IWindowOpenable[], options?: IOpenWindowOptions): Promise<void>;
|
||||
|
||||
/**
|
||||
* Switch between fullscreen and normal window.
|
||||
*/
|
||||
toggleFullScreen(): Promise<void>;
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
//#region Lifecycle
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,7 +9,7 @@ import { IElectronService } from 'vs/platform/electron/node/electron';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IWindowOpenable, IOpenInWindowOptions, isFolderToOpen, isWorkspaceToOpen, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
|
||||
import { IWindowOpenable, IOpenWindowOptions, isFolderToOpen, isWorkspaceToOpen, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IElectronEnvironmentService } from 'vs/workbench/services/electron/electron-browser/electronEnvironmentService';
|
||||
|
||||
@@ -17,16 +17,6 @@ export class DesktopHostService extends Disposable implements IHostService {
|
||||
|
||||
_serviceBrand: undefined;
|
||||
|
||||
//#region Events
|
||||
|
||||
get onDidChangeFocus(): Event<boolean> { return this._onDidChangeFocus; }
|
||||
private _onDidChangeFocus: Event<boolean> = Event.any(
|
||||
Event.map(Event.filter(this.electronService.onWindowFocus, id => id === this.electronEnvironmentService.windowId), _ => true),
|
||||
Event.map(Event.filter(this.electronService.onWindowBlur, id => id === this.electronEnvironmentService.windowId), _ => false)
|
||||
);
|
||||
|
||||
//#endregion
|
||||
|
||||
constructor(
|
||||
@IElectronService private readonly electronService: IElectronService,
|
||||
@ILabelService private readonly labelService: ILabelService,
|
||||
@@ -46,19 +36,31 @@ export class DesktopHostService extends Disposable implements IHostService {
|
||||
this._register(this.onDidChangeFocus(focus => this._hasFocus = focus));
|
||||
}
|
||||
|
||||
//#region Window
|
||||
get onDidChangeFocus(): Event<boolean> { return this._onDidChangeFocus; }
|
||||
private _onDidChangeFocus: Event<boolean> = Event.any(
|
||||
Event.map(Event.filter(this.electronService.onWindowFocus, id => id === this.electronEnvironmentService.windowId), _ => true),
|
||||
Event.map(Event.filter(this.electronService.onWindowBlur, id => id === this.electronEnvironmentService.windowId), _ => false)
|
||||
);
|
||||
|
||||
private _hasFocus: boolean;
|
||||
get hasFocus(): boolean { return this._hasFocus; }
|
||||
|
||||
get windowCount(): Promise<number> { return this.electronService.getWindowCount(); }
|
||||
openWindow(options?: IOpenEmptyWindowOptions): Promise<void>;
|
||||
openWindow(toOpen: IWindowOpenable[], options?: IOpenWindowOptions): Promise<void>;
|
||||
openWindow(arg1?: IOpenEmptyWindowOptions | IWindowOpenable[], arg2?: IOpenWindowOptions): Promise<void> {
|
||||
if (Array.isArray(arg1)) {
|
||||
return this.doOpenWindow(arg1, arg2);
|
||||
}
|
||||
|
||||
openInWindow(toOpen: IWindowOpenable[], options?: IOpenInWindowOptions): Promise<void> {
|
||||
return this.doOpenEmptyWindow(arg1);
|
||||
}
|
||||
|
||||
private doOpenWindow(toOpen: IWindowOpenable[], options?: IOpenWindowOptions): Promise<void> {
|
||||
if (!!this.environmentService.configuration.remoteAuthority) {
|
||||
toOpen.forEach(openable => openable.label = openable.label || this.getRecentLabel(openable));
|
||||
}
|
||||
|
||||
return this.electronService.openInWindow(toOpen, options);
|
||||
return this.electronService.openWindow(toOpen, options);
|
||||
}
|
||||
|
||||
private getRecentLabel(openable: IWindowOpenable): string {
|
||||
@@ -73,8 +75,8 @@ export class DesktopHostService extends Disposable implements IHostService {
|
||||
return this.labelService.getUriLabel(openable.fileUri);
|
||||
}
|
||||
|
||||
openEmptyWindow(options?: IOpenEmptyWindowOptions): Promise<void> {
|
||||
return this.electronService.openEmptyWindow(options);
|
||||
private doOpenEmptyWindow(options?: IOpenEmptyWindowOptions): Promise<void> {
|
||||
return this.electronService.openWindow(options);
|
||||
}
|
||||
|
||||
toggleFullScreen(): Promise<void> {
|
||||
@@ -85,8 +87,6 @@ export class DesktopHostService extends Disposable implements IHostService {
|
||||
return this.electronService.focusWindow();
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
restart(): Promise<void> {
|
||||
return this.electronService.relaunch();
|
||||
}
|
||||
@@ -96,7 +96,7 @@ export class DesktopHostService extends Disposable implements IHostService {
|
||||
}
|
||||
|
||||
closeWorkspace(): Promise<void> {
|
||||
return this.electronService.closeWorkpsace();
|
||||
return this.electronService.closeWorkspace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import { nodeSocketFactory } from 'vs/platform/remote/node/nodeSocketFactory';
|
||||
import { ISignService } from 'vs/platform/sign/common/sign';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { findFreePort } from 'vs/base/node/ports';
|
||||
|
||||
export async function createRemoteTunnel(options: IConnectionOptions, tunnelRemotePort: number): Promise<RemoteTunnel> {
|
||||
const tunnel = new NodeRemoteTunnel(options, tunnelRemotePort);
|
||||
@@ -25,7 +26,7 @@ export async function createRemoteTunnel(options: IConnectionOptions, tunnelRemo
|
||||
class NodeRemoteTunnel extends Disposable implements RemoteTunnel {
|
||||
|
||||
public readonly tunnelRemotePort: number;
|
||||
public readonly tunnelLocalPort: number;
|
||||
public tunnelLocalPort: number;
|
||||
|
||||
private readonly _options: IConnectionOptions;
|
||||
private readonly _server: net.Server;
|
||||
@@ -47,7 +48,7 @@ class NodeRemoteTunnel extends Disposable implements RemoteTunnel {
|
||||
this._server.on('connection', this._connectionListener);
|
||||
|
||||
this.tunnelRemotePort = tunnelRemotePort;
|
||||
this.tunnelLocalPort = (<net.AddressInfo>this._server.listen(0).address()).port;
|
||||
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
@@ -58,6 +59,13 @@ class NodeRemoteTunnel extends Disposable implements RemoteTunnel {
|
||||
}
|
||||
|
||||
public async waitForReady(): Promise<this> {
|
||||
|
||||
// try to get the same port number as the remote port number...
|
||||
const localPort = await findFreePort(this.tunnelRemotePort, 1, 1000);
|
||||
|
||||
// if that fails, the method above returns 0, which works out fine below...
|
||||
this.tunnelLocalPort = (<net.AddressInfo>this._server.listen(localPort).address()).port;
|
||||
|
||||
await this._barrier.wait();
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -57,6 +57,10 @@ export class BrowserTextFileService extends AbstractTextFileService {
|
||||
|
||||
return false; // dirty with backups: no veto
|
||||
}
|
||||
|
||||
protected async getWindowCount(): Promise<number> {
|
||||
return 1; // Browser only ever is 1 window
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(ITextFileService, BrowserTextFileService);
|
||||
|
||||
@@ -39,7 +39,6 @@ import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { ITextSnapshot } from 'vs/editor/common/model';
|
||||
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
|
||||
import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
|
||||
/**
|
||||
* The workbench file service implementation implements the raw file service spec and adds additional methods on top.
|
||||
@@ -74,14 +73,13 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
|
||||
@IFileService protected readonly fileService: IFileService,
|
||||
@IUntitledEditorService protected readonly untitledEditorService: IUntitledEditorService,
|
||||
@ILifecycleService private readonly lifecycleService: ILifecycleService,
|
||||
@IInstantiationService protected instantiationService: IInstantiationService,
|
||||
@IInstantiationService protected readonly instantiationService: IInstantiationService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
@IModelService private readonly modelService: IModelService,
|
||||
@IWorkbenchEnvironmentService protected readonly environmentService: IWorkbenchEnvironmentService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IBackupFileService private readonly backupFileService: IBackupFileService,
|
||||
@IHostService private readonly hostService: IHostService,
|
||||
@IHistoryService private readonly historyService: IHistoryService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IDialogService private readonly dialogService: IDialogService,
|
||||
@@ -180,7 +178,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
|
||||
case ShutdownReason.CLOSE:
|
||||
if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY && this.configuredHotExit === HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) {
|
||||
doBackup = true; // backup if a folder is open and onExitAndWindowClose is configured
|
||||
} else if (await this.hostService.windowCount > 1 || platform.isMacintosh) {
|
||||
} else if (await this.getWindowCount() > 1 || platform.isMacintosh) {
|
||||
doBackup = false; // do not backup if a window is closed that does not cause quitting of the application
|
||||
} else {
|
||||
doBackup = true; // backup if last window is closed on win/linux where the application quits right after
|
||||
@@ -213,6 +211,8 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract getWindowCount(): Promise<number>;
|
||||
|
||||
private backupAll(dirtyToBackup: URI[]): Promise<void> {
|
||||
|
||||
// split up between files and untitled
|
||||
|
||||
@@ -77,10 +77,10 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
||||
|
||||
private resource: URI;
|
||||
|
||||
private contentEncoding: string; // encoding as reported from disk
|
||||
private preferredEncoding: string; // encoding as chosen by the user
|
||||
private contentEncoding: string; // encoding as reported from disk
|
||||
private preferredEncoding: string | undefined; // encoding as chosen by the user
|
||||
|
||||
private preferredMode: string | undefined; // mode as chosen by the user
|
||||
private preferredMode: string | undefined; // mode as chosen by the user
|
||||
|
||||
private versionId: number;
|
||||
private bufferSavedVersionId: number;
|
||||
@@ -107,7 +107,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
||||
|
||||
constructor(
|
||||
resource: URI,
|
||||
preferredEncoding: string,
|
||||
preferredEncoding: string | undefined,
|
||||
preferredMode: string | undefined,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IModeService modeService: IModeService,
|
||||
|
||||
@@ -27,9 +27,46 @@ import { Readable } from 'stream';
|
||||
import { createTextBufferFactoryFromStream } from 'vs/editor/common/model/textModel';
|
||||
import { ITextSnapshot } from 'vs/editor/common/model';
|
||||
import { nodeReadableToString, streamToNodeReadable, nodeStreamToVSBufferReadable } from 'vs/base/node/stream';
|
||||
import { IElectronService } from 'vs/platform/electron/node/electron';
|
||||
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
|
||||
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
|
||||
import { IHistoryService } from 'vs/workbench/services/history/common/history';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IDialogService, IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
|
||||
export class NativeTextFileService extends AbstractTextFileService {
|
||||
|
||||
constructor(
|
||||
@IWorkspaceContextService contextService: IWorkspaceContextService,
|
||||
@IFileService fileService: IFileService,
|
||||
@IUntitledEditorService untitledEditorService: IUntitledEditorService,
|
||||
@ILifecycleService lifecycleService: ILifecycleService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IModeService modeService: IModeService,
|
||||
@IModelService modelService: IModelService,
|
||||
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
|
||||
@INotificationService notificationService: INotificationService,
|
||||
@IBackupFileService backupFileService: IBackupFileService,
|
||||
@IHistoryService historyService: IHistoryService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IDialogService dialogService: IDialogService,
|
||||
@IFileDialogService fileDialogService: IFileDialogService,
|
||||
@IEditorService editorService: IEditorService,
|
||||
@ITextResourceConfigurationService textResourceConfigurationService: ITextResourceConfigurationService,
|
||||
@IElectronService private readonly electronService: IElectronService
|
||||
) {
|
||||
super(contextService, fileService, untitledEditorService, lifecycleService, instantiationService, configurationService, modeService, modelService, environmentService, notificationService, backupFileService, historyService, contextKeyService, dialogService, fileDialogService, editorService, textResourceConfigurationService);
|
||||
}
|
||||
|
||||
private _encoding!: EncodingOracle;
|
||||
get encoding(): EncodingOracle {
|
||||
if (!this._encoding) {
|
||||
@@ -255,6 +292,10 @@ export class NativeTextFileService extends AbstractTextFileService {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
protected getWindowCount(): Promise<number> {
|
||||
return this.electronService.getWindowCount();
|
||||
}
|
||||
}
|
||||
|
||||
export interface IEncodingOverride {
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as sinon from 'sinon';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ILifecycleService, BeforeShutdownEvent, ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { workbenchInstantiationService, TestLifecycleService, TestTextFileService, TestContextService, TestFileService, TestHostService } from 'vs/workbench/test/workbenchTestServices';
|
||||
import { workbenchInstantiationService, TestLifecycleService, TestTextFileService, TestContextService, TestFileService, TestElectronService } from 'vs/workbench/test/workbenchTestServices';
|
||||
import { toResource } from 'vs/base/test/common/utils';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel';
|
||||
@@ -20,7 +20,7 @@ import { IWorkspaceContextService, Workspace } from 'vs/platform/workspace/commo
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
import { IElectronService } from 'vs/platform/electron/node/electron';
|
||||
|
||||
class ServiceAccessor {
|
||||
constructor(
|
||||
@@ -30,7 +30,7 @@ class ServiceAccessor {
|
||||
@IWorkspaceContextService public contextService: TestContextService,
|
||||
@IModelService public modelService: ModelServiceImpl,
|
||||
@IFileService public fileService: TestFileService,
|
||||
@IHostService public hostService: TestHostService
|
||||
@IElectronService public electronService: TestElectronService
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -424,7 +424,7 @@ suite('Files - TextFileService', () => {
|
||||
}
|
||||
// Set multiple windows if required
|
||||
if (multipleWindows) {
|
||||
accessor.hostService.windowCount = Promise.resolve(2);
|
||||
accessor.electronService.windowCount = Promise.resolve(2);
|
||||
}
|
||||
// Set cancel to force a veto if hot exit does not trigger
|
||||
service.setConfirmResult(ConfirmResult.CANCEL);
|
||||
|
||||
@@ -7,7 +7,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
|
||||
import { virtualMachineHint } from 'vs/base/node/id';
|
||||
import * as perf from 'vs/base/common/performance';
|
||||
import * as os from 'os';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
import { IElectronService } from 'vs/platform/electron/node/electron';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
@@ -308,7 +308,7 @@ class TimerService implements ITimerService {
|
||||
private _startupMetrics?: Promise<IStartupMetrics>;
|
||||
|
||||
constructor(
|
||||
@IHostService private readonly _hostService: IHostService,
|
||||
@IElectronService private readonly _electronService: IElectronService,
|
||||
@IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService,
|
||||
@ILifecycleService private readonly _lifecycleService: ILifecycleService,
|
||||
@IWorkspaceContextService private readonly _contextService: IWorkspaceContextService,
|
||||
@@ -380,7 +380,7 @@ class TimerService implements ITimerService {
|
||||
isLatestVersion: Boolean(await this._updateService.isLatestVersion()),
|
||||
didUseCachedData: didUseCachedData(),
|
||||
windowKind: this._lifecycleService.startupKind,
|
||||
windowCount: await this._hostService.windowCount,
|
||||
windowCount: await this._electronService.getWindowCount(),
|
||||
viewletId: activeViewlet ? activeViewlet.getId() : undefined,
|
||||
editorIds: this._editorService.visibleEditors.map(input => input.getTypeId()),
|
||||
panelId: activePanel ? activePanel.getId() : undefined,
|
||||
|
||||
@@ -13,6 +13,7 @@ import product from 'vs/platform/product/common/product';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IElectronEnvironmentService } from 'vs/workbench/services/electron/electron-browser/electronEnvironmentService';
|
||||
import { createChannelSender } from 'vs/base/parts/ipc/node/ipc';
|
||||
import { IElectronService } from 'vs/platform/electron/node/electron';
|
||||
|
||||
export class RelayURLService extends URLService implements IURLHandler {
|
||||
|
||||
@@ -21,7 +22,8 @@ export class RelayURLService extends URLService implements IURLHandler {
|
||||
constructor(
|
||||
@IMainProcessService mainProcessService: IMainProcessService,
|
||||
@IOpenerService openerService: IOpenerService,
|
||||
@IElectronEnvironmentService private electronEnvironmentService: IElectronEnvironmentService
|
||||
@IElectronEnvironmentService private electronEnvironmentService: IElectronEnvironmentService,
|
||||
@IElectronService private electronService: IElectronService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -52,8 +54,14 @@ export class RelayURLService extends URLService implements IURLHandler {
|
||||
return await this.urlService.open(resource);
|
||||
}
|
||||
|
||||
handleURL(uri: URI): Promise<boolean> {
|
||||
return super.open(uri);
|
||||
async handleURL(uri: URI): Promise<boolean> {
|
||||
const result = await super.open(uri);
|
||||
|
||||
if (result) {
|
||||
await this.electronService.focusWindow();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ export class BrowserWorkspacesService extends Disposable implements IWorkspacesS
|
||||
|
||||
//#region Workspace Management
|
||||
|
||||
enterWorkspace(path: URI): Promise<IEnterWorkspaceResult | undefined> {
|
||||
enterWorkspace(path: URI): Promise<IEnterWorkspaceResult | null> {
|
||||
throw new Error('Untitled workspaces are currently unsupported in Web');
|
||||
}
|
||||
|
||||
|
||||
@@ -78,8 +78,7 @@ export class NativeWorkspaceEditingService extends AbstractWorkspaceEditingServi
|
||||
return false; // only care about untitled workspaces to ask for saving
|
||||
}
|
||||
|
||||
const windowCount = await this.hostService.windowCount;
|
||||
|
||||
const windowCount = await this.electronService.getWindowCount();
|
||||
if (reason === ShutdownReason.CLOSE && !isMacintosh && windowCount === 1) {
|
||||
return false; // Windows/Linux: quits when last window is closed, so do not ask then
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user