mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-05 01:25:38 -05:00
Merge from vscode 6e530127a1bb8ffbd1bfb77dc680c321dc0d71f5 (#6844)
This commit is contained in:
@@ -17,9 +17,9 @@ export const folderSettingsSchemaId = 'vscode://schemas/settings/folder';
|
||||
export const launchSchemaId = 'vscode://schemas/launch';
|
||||
|
||||
export const LOCAL_MACHINE_SCOPES = [ConfigurationScope.APPLICATION, ConfigurationScope.WINDOW, ConfigurationScope.RESOURCE];
|
||||
export const REMOTE_MACHINE_SCOPES = [ConfigurationScope.MACHINE, ConfigurationScope.WINDOW, ConfigurationScope.RESOURCE];
|
||||
export const WORKSPACE_SCOPES = [ConfigurationScope.WINDOW, ConfigurationScope.RESOURCE];
|
||||
export const FOLDER_SCOPES = [ConfigurationScope.RESOURCE];
|
||||
export const REMOTE_MACHINE_SCOPES = [ConfigurationScope.MACHINE, ConfigurationScope.WINDOW, ConfigurationScope.RESOURCE, ConfigurationScope.MACHINE_OVERRIDABLE];
|
||||
export const WORKSPACE_SCOPES = [ConfigurationScope.WINDOW, ConfigurationScope.RESOURCE, ConfigurationScope.MACHINE_OVERRIDABLE];
|
||||
export const FOLDER_SCOPES = [ConfigurationScope.RESOURCE, ConfigurationScope.MACHINE_OVERRIDABLE];
|
||||
|
||||
export const TASKS_CONFIGURATION_KEY = 'tasks';
|
||||
export const LAUNCH_CONFIGURATION_KEY = 'launch';
|
||||
@@ -36,4 +36,4 @@ export interface IConfigurationCache {
|
||||
write(key: ConfigurationKey, content: string): Promise<void>;
|
||||
remove(key: ConfigurationKey): Promise<void>;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import { joinPath } from 'vs/base/common/resources';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IWorkbenchConstructionOptions } from 'vs/workbench/workbench.web.api';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
|
||||
export class BrowserWindowConfiguration implements IWindowConfiguration {
|
||||
|
||||
@@ -80,6 +81,7 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
|
||||
this.appNameLong = 'Visual Studio Code - Web';
|
||||
|
||||
this.configuration.remoteAuthority = options.remoteAuthority;
|
||||
this.configuration.machineId = generateUuid();
|
||||
this.userRoamingDataHome = URI.file('/User').with({ scheme: Schemas.userData });
|
||||
this.settingsResource = joinPath(this.userRoamingDataHome, 'settings.json');
|
||||
this.keybindingsResource = joinPath(this.userRoamingDataHome, 'keybindings.json');
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
IExtensionManagementService, ILocalExtension, IGalleryExtension, InstallExtensionEvent, DidInstallExtensionEvent, IExtensionIdentifier, DidUninstallExtensionEvent, IReportedExtension, IGalleryMetadata, IExtensionGalleryService
|
||||
} from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionManagementServer, IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionType, isLanguagePackExtension } from 'vs/platform/extensions/common/extensions';
|
||||
import { ExtensionType, isLanguagePackExtension, IExtensionManifest } from 'vs/platform/extensions/common/extensions';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
@@ -17,6 +17,8 @@ import { areSameExtensions } from 'vs/platform/extensionManagement/common/extens
|
||||
import { localize } from 'vs/nls';
|
||||
import { isUIExtension } from 'vs/workbench/services/extensions/common/extensionsUtil';
|
||||
import { IProductService } from 'vs/platform/product/common/product';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IDownloadService } from 'vs/platform/download/common/download';
|
||||
|
||||
export class ExtensionManagementService extends Disposable implements IExtensionManagementService {
|
||||
|
||||
@@ -34,6 +36,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
||||
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService,
|
||||
@IConfigurationService protected readonly configurationService: IConfigurationService,
|
||||
@IProductService protected readonly productService: IProductService,
|
||||
@IDownloadService protected readonly downloadService: IDownloadService,
|
||||
) {
|
||||
super();
|
||||
if (this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
@@ -142,15 +145,43 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
||||
}
|
||||
|
||||
async install(vsix: URI): Promise<ILocalExtension> {
|
||||
if (this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
const manifest = await this.getManifest(vsix);
|
||||
if (isLanguagePackExtension(manifest)) {
|
||||
// Install on both servers
|
||||
const [local] = await Promise.all(this.servers.map(server => this.installVSIX(vsix, server)));
|
||||
return local;
|
||||
}
|
||||
if (isUIExtension(manifest, this.productService, this.configurationService)) {
|
||||
// Install only on local server
|
||||
return this.installVSIX(vsix, this.extensionManagementServerService.localExtensionManagementServer);
|
||||
}
|
||||
// Install only on remote server
|
||||
return this.installVSIX(vsix, this.extensionManagementServerService.remoteExtensionManagementServer);
|
||||
}
|
||||
if (this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.install(vsix);
|
||||
return this.installVSIX(vsix, this.extensionManagementServerService.localExtensionManagementServer);
|
||||
}
|
||||
if (this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
return this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.install(vsix);
|
||||
return this.installVSIX(vsix, this.extensionManagementServerService.remoteExtensionManagementServer);
|
||||
}
|
||||
return Promise.reject('No Servers to Install');
|
||||
}
|
||||
|
||||
protected installVSIX(vsix: URI, server: IExtensionManagementServer): Promise<ILocalExtension> {
|
||||
return server.extensionManagementService.install(vsix);
|
||||
}
|
||||
|
||||
getManifest(vsix: URI): Promise<IExtensionManifest> {
|
||||
if (vsix.scheme === Schemas.file && this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.getManifest(vsix);
|
||||
}
|
||||
if (vsix.scheme === Schemas.vscodeRemote && this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
return this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.getManifest(vsix);
|
||||
}
|
||||
return Promise.reject('No Servers');
|
||||
}
|
||||
|
||||
async installFromGallery(gallery: IGalleryExtension): Promise<ILocalExtension> {
|
||||
if (this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
const manifest = await this.extensionGalleryService.getManifest(gallery, CancellationToken.None);
|
||||
|
||||
@@ -3,35 +3,25 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { tmpdir } from 'os';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { ILocalExtension, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { isLanguagePackExtension } from 'vs/platform/extensions/common/extensions';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { getManifest } from 'vs/platform/extensionManagement/node/extensionManagementUtil';
|
||||
import { isUIExtension } from 'vs/workbench/services/extensions/common/extensionsUtil';
|
||||
import { ExtensionManagementService as BaseExtensionManagementService } from 'vs/workbench/services/extensionManagement/common/extensionManagementService';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import * as path from 'vs/base/common/path';
|
||||
|
||||
export class ExtensionManagementService extends BaseExtensionManagementService {
|
||||
|
||||
async install(vsix: URI): Promise<ILocalExtension> {
|
||||
if (this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
const manifest = await getManifest(vsix.fsPath);
|
||||
if (isLanguagePackExtension(manifest)) {
|
||||
// Install on both servers
|
||||
const [local] = await Promise.all(this.servers.map(server => server.extensionManagementService.install(vsix)));
|
||||
return local;
|
||||
}
|
||||
if (isUIExtension(manifest, this.productService, this.configurationService)) {
|
||||
// Install only on local server
|
||||
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.install(vsix);
|
||||
}
|
||||
// Install only on remote server
|
||||
return this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.install(vsix);
|
||||
protected async installVSIX(vsix: URI, server: IExtensionManagementServer): Promise<ILocalExtension> {
|
||||
if (vsix.scheme === Schemas.vscodeRemote && server === this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
const downloadedLocation = URI.file(path.join(tmpdir(), generateUuid()));
|
||||
await this.downloadService.download(vsix, downloadedLocation);
|
||||
vsix = downloadedLocation;
|
||||
}
|
||||
if (this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.install(vsix);
|
||||
}
|
||||
return Promise.reject('No Servers to Install');
|
||||
return server.extensionManagementService.install(vsix);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import { FetchFileSystemProvider } from 'vs/workbench/services/extensions/browse
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IStaticExtensionsService } from 'vs/workbench/services/extensions/common/staticExtensions';
|
||||
import { DeltaExtensionsResult } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
|
||||
|
||||
export class ExtensionService extends AbstractExtensionService implements IExtensionService {
|
||||
|
||||
@@ -81,21 +82,21 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
||||
};
|
||||
}
|
||||
|
||||
protected _createExtensionHosts(isInitialStart: boolean, initialActivationEvents: string[]): ExtensionHostProcessManager[] {
|
||||
protected _createExtensionHosts(_isInitialStart: boolean, initialActivationEvents: string[]): ExtensionHostProcessManager[] {
|
||||
const result: ExtensionHostProcessManager[] = [];
|
||||
|
||||
const remoteAgentConnection = this._remoteAgentService.getConnection()!;
|
||||
|
||||
const webExtensions = this.getExtensions().then(extensions => extensions.filter(ext => isWebExtension(ext, this._configService)));
|
||||
const remoteExtensions = this.getExtensions().then(extensions => extensions.filter(ext => !isWebExtension(ext, this._configService)));
|
||||
|
||||
const webHostProcessWorker = this._instantiationService.createInstance(WebWorkerExtensionHostStarter, true, webExtensions, URI.parse('empty:value')); //todo@joh
|
||||
const webHostProcessManager = this._instantiationService.createInstance(ExtensionHostProcessManager, false, webHostProcessWorker, remoteAgentConnection.remoteAuthority, initialActivationEvents);
|
||||
const webHostProcessManager = this._instantiationService.createInstance(ExtensionHostProcessManager, false, webHostProcessWorker, null, initialActivationEvents);
|
||||
result.push(webHostProcessManager);
|
||||
|
||||
const remoteExtHostProcessWorker = this._instantiationService.createInstance(RemoteExtensionHostClient, remoteExtensions, this._createProvider(remoteAgentConnection.remoteAuthority), this._remoteAgentService.socketFactory);
|
||||
const remoteExtHostProcessManager = this._instantiationService.createInstance(ExtensionHostProcessManager, false, remoteExtHostProcessWorker, remoteAgentConnection.remoteAuthority, initialActivationEvents);
|
||||
result.push(remoteExtHostProcessManager);
|
||||
const remoteAgentConnection = this._remoteAgentService.getConnection();
|
||||
if (remoteAgentConnection) {
|
||||
const remoteExtensions = this.getExtensions().then(extensions => extensions.filter(ext => !isWebExtension(ext, this._configService)));
|
||||
const remoteExtHostProcessWorker = this._instantiationService.createInstance(RemoteExtensionHostClient, remoteExtensions, this._createProvider(remoteAgentConnection.remoteAuthority), this._remoteAgentService.socketFactory);
|
||||
const remoteExtHostProcessManager = this._instantiationService.createInstance(ExtensionHostProcessManager, false, remoteExtHostProcessWorker, remoteAgentConnection.remoteAuthority, initialActivationEvents);
|
||||
result.push(remoteExtHostProcessManager);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -103,27 +104,35 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
||||
protected async _scanAndHandleExtensions(): Promise<void> {
|
||||
// fetch the remote environment
|
||||
let [remoteEnv, localExtensions] = await Promise.all([
|
||||
<Promise<IRemoteAgentEnvironment>>this._remoteAgentService.getEnvironment(),
|
||||
this._remoteAgentService.getEnvironment(),
|
||||
this._staticExtensions.getExtensions()
|
||||
]);
|
||||
|
||||
let result: DeltaExtensionsResult;
|
||||
|
||||
// local: only enabled and web'ish extension
|
||||
localExtensions = localExtensions.filter(ext => this._isEnabled(ext) && isWebExtension(ext, this._configService));
|
||||
this._checkEnableProposedApi(localExtensions);
|
||||
|
||||
// remote: only enabled and none-web'ish extension
|
||||
remoteEnv.extensions = remoteEnv.extensions.filter(extension => this._isEnabled(extension) && !isWebExtension(extension, this._configService));
|
||||
this._checkEnableProposedApi(remoteEnv.extensions);
|
||||
if (!remoteEnv) {
|
||||
result = this._registry.deltaExtensions(localExtensions, []);
|
||||
|
||||
// in case of overlap, the remote wins
|
||||
const isRemoteExtension = new Set<string>();
|
||||
remoteEnv.extensions.forEach(extension => isRemoteExtension.add(ExtensionIdentifier.toKey(extension.identifier)));
|
||||
localExtensions = localExtensions.filter(extension => !isRemoteExtension.has(ExtensionIdentifier.toKey(extension.identifier)));
|
||||
} else {
|
||||
// remote: only enabled and none-web'ish extension
|
||||
remoteEnv.extensions = remoteEnv.extensions.filter(extension => this._isEnabled(extension) && !isWebExtension(extension, this._configService));
|
||||
this._checkEnableProposedApi(remoteEnv.extensions);
|
||||
|
||||
// save for remote extension's init data
|
||||
this._remoteExtensionsEnvironmentData = remoteEnv;
|
||||
// in case of overlap, the remote wins
|
||||
const isRemoteExtension = new Set<string>();
|
||||
remoteEnv.extensions.forEach(extension => isRemoteExtension.add(ExtensionIdentifier.toKey(extension.identifier)));
|
||||
localExtensions = localExtensions.filter(extension => !isRemoteExtension.has(ExtensionIdentifier.toKey(extension.identifier)));
|
||||
|
||||
// save for remote extension's init data
|
||||
this._remoteExtensionsEnvironmentData = remoteEnv;
|
||||
|
||||
result = this._registry.deltaExtensions(remoteEnv.extensions.concat(localExtensions), []);
|
||||
}
|
||||
|
||||
const result = this._registry.deltaExtensions(remoteEnv.extensions.concat(localExtensions), []);
|
||||
if (result.removedDueToLooping.length > 0) {
|
||||
this._logOrShowMessage(Severity.Error, nls.localize('looping', "The following extensions contain dependency loops and have been disabled: {0}", result.removedDueToLooping.map(e => `'${e.identifier.value}'`).join(', ')));
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ function patchProcess(allowExit: boolean) {
|
||||
}
|
||||
} as (code?: number) => never;
|
||||
|
||||
// override Electron's process.crash() method
|
||||
process.crash = function () {
|
||||
const err = new Error('An extension called process.crash() and this was prevented.');
|
||||
console.warn(err.stack);
|
||||
|
||||
@@ -16,6 +16,7 @@ import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { INotificationService, Severity, NeverShowAgainScope } from 'vs/platform/notification/common/notification';
|
||||
import { localize } from 'vs/nls';
|
||||
import { FileService } from 'vs/platform/files/common/fileService';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
|
||||
export class WorkspaceWatcher extends Disposable {
|
||||
|
||||
@@ -25,7 +26,8 @@ export class WorkspaceWatcher extends Disposable {
|
||||
@IFileService private readonly fileService: FileService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@INotificationService private readonly notificationService: INotificationService
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IOpenerService private readonly openerService: IOpenerService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -77,7 +79,7 @@ export class WorkspaceWatcher extends Disposable {
|
||||
localize('netVersionError', "The Microsoft .NET Framework 4.5 is required. Please follow the link to install it."),
|
||||
[{
|
||||
label: localize('installNet', "Download .NET Framework 4.5"),
|
||||
run: () => window.open('https://go.microsoft.com/fwlink/?LinkId=786533')
|
||||
run: () => this.openerService.open(URI.parse('https://go.microsoft.com/fwlink/?LinkId=786533'))
|
||||
}],
|
||||
{
|
||||
sticky: true,
|
||||
@@ -93,7 +95,7 @@ export class WorkspaceWatcher extends Disposable {
|
||||
localize('enospcError', "Unable to watch for file changes in this large workspace. Please follow the instructions link to resolve this issue."),
|
||||
[{
|
||||
label: localize('learnMore', "Instructions"),
|
||||
run: () => window.open('https://go.microsoft.com/fwlink/?linkid=867693')
|
||||
run: () => this.openerService.open(URI.parse('https://go.microsoft.com/fwlink/?linkid=867693'))
|
||||
}],
|
||||
{
|
||||
sticky: true,
|
||||
|
||||
@@ -15,6 +15,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
|
||||
interface IStorageData {
|
||||
dontShowPrompt: boolean;
|
||||
@@ -64,7 +65,8 @@ export class IntegrityServiceImpl implements IIntegrityService {
|
||||
constructor(
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@ILifecycleService private readonly lifecycleService: ILifecycleService
|
||||
@ILifecycleService private readonly lifecycleService: ILifecycleService,
|
||||
@IOpenerService private readonly openerService: IOpenerService
|
||||
) {
|
||||
this._storage = new IntegrityStorage(storageService);
|
||||
|
||||
@@ -91,7 +93,7 @@ export class IntegrityServiceImpl implements IIntegrityService {
|
||||
[
|
||||
{
|
||||
label: nls.localize('integrity.moreInformation', "More Information"),
|
||||
run: () => window.open(URI.parse(product.checksumFailMoreInfoUrl).toString(true))
|
||||
run: () => this.openerService.open(URI.parse(product.checksumFailMoreInfoUrl))
|
||||
},
|
||||
{
|
||||
label: nls.localize('integrity.dontShowAgain', "Don't Show Again"),
|
||||
|
||||
@@ -45,7 +45,7 @@ import * as objects from 'vs/base/common/objects';
|
||||
import { IKeymapService } from 'vs/workbench/services/keybinding/common/keymapInfo';
|
||||
import { getDispatchConfig } from 'vs/workbench/services/keybinding/common/dispatchConfig';
|
||||
import { isArray } from 'vs/base/common/types';
|
||||
import { INavigatorWithKeyboard } from 'vs/workbench/services/keybinding/common/navigatorKeyboard';
|
||||
import { INavigatorWithKeyboard } from 'vs/workbench/services/keybinding/browser/navigatorKeyboard';
|
||||
import { ScanCodeUtils, IMMUTABLE_CODE_TO_KEY_CODE } from 'vs/base/common/scanCode';
|
||||
|
||||
interface ContributedKeyBinding {
|
||||
|
||||
@@ -25,7 +25,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Extensions as ConfigExtensions, IConfigurationRegistry, IConfigurationNode } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { INavigatorWithKeyboard } from 'vs/workbench/services/keybinding/common/navigatorKeyboard';
|
||||
import { INavigatorWithKeyboard } from 'vs/workbench/services/keybinding/browser/navigatorKeyboard';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { OpenerService as BaseOpenerService } from 'vs/editor/browser/services/openerService';
|
||||
import { IWindowsService } from 'vs/platform/windows/common/windows';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
|
||||
export class OpenerService extends BaseOpenerService {
|
||||
|
||||
_serviceBrand!: ServiceIdentifier<any>;
|
||||
|
||||
constructor(
|
||||
@ICodeEditorService codeEditorService: ICodeEditorService,
|
||||
@ICommandService commandService: ICommandService,
|
||||
@IWindowsService private readonly windowsService: IWindowsService
|
||||
) {
|
||||
super(codeEditorService, commandService);
|
||||
}
|
||||
|
||||
async openExternal(resource: URI): Promise<boolean> {
|
||||
const success = this.windowsService.openExternal(encodeURI(resource.toString(true)));
|
||||
if (!success && resource.scheme === Schemas.file) {
|
||||
await this.windowsService.showItemInFolder(resource);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(IOpenerService, OpenerService, true);
|
||||
@@ -23,6 +23,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { EditorModel } from 'vs/workbench/common/editor';
|
||||
import { IFilterMetadata, IFilterResult, IGroupFilter, IKeybindingsEditorModel, ISearchResultGroup, ISetting, ISettingMatch, ISettingMatcher, ISettingsEditorModel, ISettingsGroup } from 'vs/workbench/services/preferences/common/preferences';
|
||||
import { withNullAsUndefined, isArray } from 'vs/base/common/types';
|
||||
import { FOLDER_SCOPES, WORKSPACE_SCOPES } from 'vs/workbench/services/configuration/common/configuration';
|
||||
|
||||
export const nullRange: IRange = { startLineNumber: -1, startColumn: -1, endLineNumber: -1, endColumn: -1 };
|
||||
export function isNullRange(range: IRange): boolean { return range.startLineNumber === -1 && range.startColumn === -1 && range.endLineNumber === -1 && range.endColumn === -1; }
|
||||
@@ -659,11 +660,14 @@ export class DefaultSettings extends Disposable {
|
||||
}
|
||||
|
||||
private matchesScope(property: IConfigurationNode): boolean {
|
||||
if (!property.scope) {
|
||||
return true;
|
||||
}
|
||||
if (this.target === ConfigurationTarget.WORKSPACE_FOLDER) {
|
||||
return property.scope === ConfigurationScope.RESOURCE;
|
||||
return FOLDER_SCOPES.indexOf(property.scope) !== -1;
|
||||
}
|
||||
if (this.target === ConfigurationTarget.WORKSPACE) {
|
||||
return property.scope === ConfigurationScope.WINDOW || property.scope === ConfigurationScope.RESOURCE;
|
||||
return WORKSPACE_SCOPES.indexOf(property.scope) !== -1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { IPatternInfo } from 'vs/workbench/services/search/common/search';
|
||||
import { CharCode } from 'vs/base/common/charCode';
|
||||
import { buildReplaceStringWithCasePreserved } from 'vs/base/common/search';
|
||||
|
||||
export class ReplacePattern {
|
||||
|
||||
@@ -54,7 +55,7 @@ export class ReplacePattern {
|
||||
* Returns the replace string for the first match in the given text.
|
||||
* If text has no matches then returns null.
|
||||
*/
|
||||
getReplaceString(text: string): string | null {
|
||||
getReplaceString(text: string, preserveCase?: boolean): string | null {
|
||||
this._regExp.lastIndex = 0;
|
||||
let match = this._regExp.exec(text);
|
||||
if (match) {
|
||||
@@ -65,12 +66,20 @@ export class ReplacePattern {
|
||||
let replaceString = text.replace(this._regExp, this.pattern);
|
||||
return replaceString.substr(match.index, match[0].length - (text.length - replaceString.length));
|
||||
}
|
||||
return this.pattern;
|
||||
return this.buildReplaceString(match, preserveCase);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public buildReplaceString(matches: string[] | null, preserveCase?: boolean): string {
|
||||
if (preserveCase) {
|
||||
return buildReplaceStringWithCasePreserved(matches, this._replacePattern);
|
||||
} else {
|
||||
return this._replacePattern;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \n => LF
|
||||
* \t => TAB
|
||||
|
||||
@@ -17,15 +17,15 @@ export class BrowserTextFileService extends TextFileService {
|
||||
}
|
||||
};
|
||||
|
||||
protected beforeShutdown(reason: ShutdownReason): boolean {
|
||||
protected onBeforeShutdown(reason: ShutdownReason): boolean {
|
||||
// Web: we cannot perform long running in the shutdown phase
|
||||
// As such we need to check sync if there are any dirty files
|
||||
// that have not been backed up yet and then prevent the shutdown
|
||||
// if that is the case.
|
||||
return this.doBeforeShutdownSync(reason);
|
||||
return this.doBeforeShutdownSync();
|
||||
}
|
||||
|
||||
private doBeforeShutdownSync(reason: ShutdownReason): boolean {
|
||||
private doBeforeShutdownSync(): boolean {
|
||||
const dirtyResources = this.getDirty();
|
||||
if (!dirtyResources.length) {
|
||||
return false; // no dirty: no veto
|
||||
|
||||
@@ -107,7 +107,7 @@ export abstract class TextFileService extends Disposable implements ITextFileSer
|
||||
private registerListeners(): void {
|
||||
|
||||
// Lifecycle
|
||||
this.lifecycleService.onBeforeShutdown(event => event.veto(this.beforeShutdown(event.reason)));
|
||||
this.lifecycleService.onBeforeShutdown(event => event.veto(this.onBeforeShutdown(event.reason)));
|
||||
this.lifecycleService.onShutdown(this.dispose, this);
|
||||
|
||||
// Files configuration changes
|
||||
@@ -118,7 +118,7 @@ export abstract class TextFileService extends Disposable implements ITextFileSer
|
||||
}));
|
||||
}
|
||||
|
||||
protected beforeShutdown(reason: ShutdownReason): boolean | Promise<boolean> {
|
||||
protected onBeforeShutdown(reason: ShutdownReason): boolean | Promise<boolean> {
|
||||
|
||||
// Dirty files need treatment on shutdown
|
||||
const dirty = this.getDirty();
|
||||
|
||||
@@ -209,8 +209,7 @@ export class InMemoryUserDataProvider extends Disposable implements IFileSystemP
|
||||
readonly onDidChangeFile: Event<IFileChange[]> = this._onDidChangeFile.event;
|
||||
|
||||
private _bufferedChanges: IFileChange[] = [];
|
||||
private _fireSoonHandle?: NodeJS.Timer;
|
||||
|
||||
private _fireSoonHandle?: any;
|
||||
|
||||
watch(resource: URI, opts: IWatchOptions): IDisposable {
|
||||
// ignore, fires for all changes...
|
||||
@@ -229,4 +228,4 @@ export class InMemoryUserDataProvider extends Disposable implements IFileSystemP
|
||||
this._bufferedChanges.length = 0;
|
||||
}, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user