Merge from vscode ad407028575a77ea387eb7cc219b323dc017b686

This commit is contained in:
ADS Merger
2020-08-22 06:06:52 +00:00
committed by Anthony Dresser
parent 404260b8a0
commit 4ad73d381c
480 changed files with 14360 additions and 14122 deletions

View File

@@ -16,9 +16,29 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IProductService } from 'vs/platform/product/common/productService';
import { isString } from 'vs/base/common/types';
export function getAuthenticationProviderActivationEvent(id: string): string { return `onAuthenticationRequest:${id}`; }
export type AuthenticationSessionInfo = { readonly id: string, readonly accessToken: string, readonly providerId: string };
export async function getCurrentAuthenticationSessionInfo(environmentService: IWorkbenchEnvironmentService, productService: IProductService): Promise<AuthenticationSessionInfo | undefined> {
if (environmentService.options?.credentialsProvider) {
const authenticationSessionValue = await environmentService.options.credentialsProvider.getPassword(`${productService.urlProtocol}.login`, 'account');
if (authenticationSessionValue) {
const authenticationSessionInfo: AuthenticationSessionInfo = JSON.parse(authenticationSessionValue);
if (authenticationSessionInfo
&& isString(authenticationSessionInfo.id)
&& isString(authenticationSessionInfo.accessToken)
&& isString(authenticationSessionInfo.providerId)
) {
return authenticationSessionInfo;
}
}
}
return undefined;
}
export const IAuthenticationService = createDecorator<IAuthenticationService>('IAuthenticationService');
export interface IAuthenticationService {
@@ -227,8 +247,22 @@ export class AuthenticationService extends Disposable implements IAuthentication
}
}
requestNewSession(providerId: string, scopes: string[], extensionId: string, extensionName: string): void {
const provider = this._authenticationProviders.get(providerId);
async requestNewSession(providerId: string, scopes: string[], extensionId: string, extensionName: string): Promise<void> {
let provider = this._authenticationProviders.get(providerId);
if (!provider) {
// Activate has already been called for the authentication provider, but it cannot block on registering itself
// since this is sync and returns a disposable. So, wait for registration event to fire that indicates the
// provider is now in the map.
await new Promise((resolve, _) => {
this.onDidRegisterAuthenticationProvider(e => {
if (e.id === providerId) {
provider = this._authenticationProviders.get(providerId);
resolve();
}
});
});
}
if (provider) {
const providerRequests = this._signInRequestItems.get(providerId);
const scopesList = scopes.sort().join('');

View File

@@ -353,8 +353,9 @@ export class ConfigurationEditingService {
}
}
return nls.localize('errorInvalidConfigurationFolder', "Unable to write into folder settings. Please open the '{0}' folder settings to correct errors/warnings in it and try again.", workspaceFolderName);
default:
return '';
}
return '';
}
case ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY: {
if (operation.workspaceStandAloneConfigurationKey === TASKS_CONFIGURATION_KEY) {
@@ -379,8 +380,9 @@ export class ConfigurationEditingService {
}
}
return nls.localize('errorConfigurationFileDirtyFolder', "Unable to write into folder settings because the file is dirty. Please save the '{0}' folder settings file first and then try again.", workspaceFolderName);
default:
return '';
}
return '';
}
case ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_MODIFIED_SINCE:
if (operation.workspaceStandAloneConfigurationKey === TASKS_CONFIGURATION_KEY) {
@@ -412,8 +414,9 @@ export class ConfigurationEditingService {
return nls.localize('workspaceTarget', "Workspace Settings");
case EditableConfigurationTarget.WORKSPACE_FOLDER:
return nls.localize('folderTarget', "Folder Settings");
default:
return '';
}
return '';
}
private getEdits(model: ITextModel, edit: IConfigurationEditOperation): Edit[] {

View File

@@ -264,7 +264,7 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR
if (!Types.isString(info.description)) {
missingAttribute('description');
}
const inputOptions: IInputOptions = { prompt: info.description };
const inputOptions: IInputOptions = { prompt: info.description, ignoreFocusLost: true };
if (info.default) {
inputOptions.value = info.default;
}
@@ -310,7 +310,7 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR
picks.push(item);
}
});
const pickOptions: IPickOptions<PickStringItem> = { placeHolder: info.description, matchOnDetail: true };
const pickOptions: IPickOptions<PickStringItem> = { placeHolder: info.description, matchOnDetail: true, ignoreFocusLost: true };
return this.quickInputService.pick(picks, pickOptions, undefined).then(resolvedInput => {
if (resolvedInput) {
return resolvedInput.value;

View File

@@ -142,10 +142,9 @@ class NativeContextMenuService extends Disposable implements IContextMenuService
return undefined;
}
const actions = Array.isArray(entry.actions) ? entry.actions : entry.actions();
return {
label: unmnemonicLabel(stripCodicons(entry.label)).trim(),
submenu: this.createMenu(delegate, actions, onHide, new Set([...submenuIds, entry.id]))
submenu: this.createMenu(delegate, entry.actions, onHide, new Set([...submenuIds, entry.id]))
};
}

View File

@@ -3,21 +3,11 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
import { ICredentialsProvider, ICredentialsService } from 'vs/platform/credentials/common/credentials';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { find } from 'vs/base/common/arrays';
export interface ICredentialsProvider {
getPassword(service: string, account: string): Promise<string | null>;
setPassword(service: string, account: string, password: string): Promise<void>;
deletePassword(service: string, account: string): Promise<boolean>;
findPassword(service: string): Promise<string | null>;
findCredentials(service: string): Promise<Array<{ account: string, password: string; }>>;
}
export class BrowserCredentialsService implements ICredentialsService {
declare readonly _serviceBrand: undefined;

View File

@@ -24,7 +24,7 @@ export class DialogService implements IDialogService {
declare readonly _serviceBrand: undefined;
private allowableCommands = ['copy', 'cut'];
private allowableCommands = ['copy', 'cut', 'editor.action.clipboardCopyAction', 'editor.action.clipboardCutAction'];
constructor(
@ILogService private readonly logService: ILogService,

View File

@@ -747,9 +747,9 @@ export class EditorService extends Disposable implements EditorServiceImpl {
//#region replaceEditors()
replaceEditors(editors: IResourceEditorReplacement[], group: IEditorGroup | GroupIdentifier): Promise<void>;
replaceEditors(editors: IEditorReplacement[], group: IEditorGroup | GroupIdentifier): Promise<void>;
replaceEditors(editors: Array<IEditorReplacement | IResourceEditorReplacement>, group: IEditorGroup | GroupIdentifier): Promise<void> {
async replaceEditors(editors: IResourceEditorReplacement[], group: IEditorGroup | GroupIdentifier): Promise<void>;
async replaceEditors(editors: IEditorReplacement[], group: IEditorGroup | GroupIdentifier): Promise<void>;
async replaceEditors(editors: Array<IEditorReplacement | IResourceEditorReplacement>, group: IEditorGroup | GroupIdentifier): Promise<void> {
const typedEditors: IEditorReplacement[] = [];
editors.forEach(replaceEditorArg => {
@@ -776,8 +776,6 @@ export class EditorService extends Disposable implements EditorServiceImpl {
if (targetGroup) {
return targetGroup.replaceEditors(typedEditors);
}
return Promise.resolve();
}
//#endregion

View File

@@ -17,8 +17,8 @@ export interface INativeWorkbenchEnvironmentService extends IWorkbenchEnvironmen
readonly configuration: INativeEnvironmentConfiguration;
readonly disableCrashReporter: boolean;
readonly crashReporterDirectory?: string;
readonly crashReporterId?: string;
readonly cliPath: string;

View File

@@ -12,9 +12,10 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
import { ITelemetryData } from 'vs/base/common/actions';
import { ITASExperimentService } from 'vs/workbench/services/experiment/common/experimentService';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
const storageKey = 'VSCode.ABExp.FeatureData';
const refetchInterval = 1000 * 60 * 30; // By default it's set up to 30 minutes.
const refetchInterval = 0; // no polling
class MementoKeyValueStorage implements IKeyValueStorage {
constructor(private mementoObj: MementoObject) { }
@@ -160,13 +161,18 @@ export class ExperimentService implements ITASExperimentService {
private tasClient: Promise<TASClient> | undefined;
private static MEMENTO_ID = 'experiment.service.memento';
private get experimentsEnabled(): boolean {
return this.configurationService.getValue('workbench.enableExperiments') === true;
}
constructor(
@IProductService private productService: IProductService,
@ITelemetryService private telemetryService: ITelemetryService,
@IStorageService private storageService: IStorageService
@IStorageService private storageService: IStorageService,
@IConfigurationService private configurationService: IConfigurationService,
) {
if (this.productService.tasConfig) {
if (this.productService.tasConfig && this.experimentsEnabled && this.telemetryService.isOptedIn) {
this.tasClient = this.setupTASClient();
}
}
@@ -176,6 +182,10 @@ export class ExperimentService implements ITASExperimentService {
return undefined;
}
if (!this.experimentsEnabled) {
return undefined;
}
return (await this.tasClient).getTreatmentVariable<T>('vscode', name);
}

View File

@@ -29,38 +29,54 @@ export class BuiltinExtensionsScannerService implements IBuiltinExtensionsScanne
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
@IUriIdentityService uriIdentityService: IUriIdentityService,
) {
if (isWeb) {
const builtinExtensionsServiceUrl = this._getBuiltinExtensionsUrl(environmentService);
if (builtinExtensionsServiceUrl) {
let scannedBuiltinExtensions: IScannedBuiltinExtension[] = [];
const builtinExtensionsServiceUrl = environmentService.options?.builtinExtensionsServiceUrl ? URI.parse(environmentService.options?.builtinExtensionsServiceUrl) : undefined;
if (isWeb && builtinExtensionsServiceUrl) {
let scannedBuiltinExtensions: IScannedBuiltinExtension[] = [];
if (environmentService.isBuilt) {
// Built time configuration (do NOT modify)
scannedBuiltinExtensions = [/*BUILD->INSERT_BUILTIN_EXTENSIONS*/];
} else {
// Find builtin extensions by checking for DOM
const builtinExtensionsElement = document.getElementById('vscode-workbench-builtin-extensions');
const builtinExtensionsElementAttribute = builtinExtensionsElement ? builtinExtensionsElement.getAttribute('data-settings') : undefined;
if (builtinExtensionsElementAttribute) {
try {
scannedBuiltinExtensions = JSON.parse(builtinExtensionsElementAttribute);
} catch (error) { /* ignore error*/ }
if (environmentService.isBuilt) {
// Built time configuration (do NOT modify)
scannedBuiltinExtensions = [/*BUILD->INSERT_BUILTIN_EXTENSIONS*/];
} else {
// Find builtin extensions by checking for DOM
const builtinExtensionsElement = document.getElementById('vscode-workbench-builtin-extensions');
const builtinExtensionsElementAttribute = builtinExtensionsElement ? builtinExtensionsElement.getAttribute('data-settings') : undefined;
if (builtinExtensionsElementAttribute) {
try {
scannedBuiltinExtensions = JSON.parse(builtinExtensionsElementAttribute);
} catch (error) { /* ignore error*/ }
}
}
}
this.builtinExtensions = scannedBuiltinExtensions.map(e => ({
identifier: { id: getGalleryExtensionId(e.packageJSON.publisher, e.packageJSON.name) },
location: uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.extensionPath),
type: ExtensionType.System,
packageJSON: e.packageJSON,
packageNLS: e.packageNLS,
readmeUrl: e.readmePath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.readmePath) : undefined,
changelogUrl: e.changelogPath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.changelogPath) : undefined,
}));
this.builtinExtensions = scannedBuiltinExtensions.map(e => ({
identifier: { id: getGalleryExtensionId(e.packageJSON.publisher, e.packageJSON.name) },
location: uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.extensionPath),
type: ExtensionType.System,
packageJSON: e.packageJSON,
packageNLS: e.packageNLS,
readmeUrl: e.readmePath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.readmePath) : undefined,
changelogUrl: e.changelogPath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.changelogPath) : undefined,
}));
}
}
}
private _getBuiltinExtensionsUrl(environmentService: IWorkbenchEnvironmentService): URI | undefined {
if (environmentService.options?.builtinExtensionsServiceUrl) {
return URI.parse(environmentService.options?.builtinExtensionsServiceUrl);
}
let enableBuiltinExtensions: boolean;
if (environmentService.options && typeof environmentService.options._enableBuiltinExtensions !== 'undefined') {
enableBuiltinExtensions = environmentService.options._enableBuiltinExtensions;
} else {
enableBuiltinExtensions = environmentService.configuration.remoteAuthority ? false : true;
}
if (enableBuiltinExtensions) {
return URI.parse(require.toUrl('../../../../../../extensions'));
}
return undefined;
}
async scanBuiltinExtensions(): Promise<IScannedExtension[]> {
if (isWeb) {
return this.builtinExtensions;

View File

@@ -93,7 +93,7 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
.map(e => ({
identifier: { id: getGalleryExtensionId(e.packageJSON.publisher, e.packageJSON.name) },
location: e.extensionLocation,
type: ExtensionType.System,
type: e.isBuiltin ? ExtensionType.System : ExtensionType.User,
packageJSON: e.packageJSON,
}))
);

View File

@@ -24,6 +24,8 @@ import { FetchFileSystemProvider } from 'vs/workbench/services/extensions/browse
import { Schemas } from 'vs/base/common/network';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { IUserDataInitializationService } from 'vs/workbench/services/userData/browser/userDataInit';
export class ExtensionService extends AbstractExtensionService implements IExtensionService {
@@ -43,6 +45,8 @@ export class ExtensionService extends AbstractExtensionService implements IExten
@IRemoteAgentService private readonly _remoteAgentService: IRemoteAgentService,
@IConfigurationService private readonly _configService: IConfigurationService,
@IWebExtensionsScannerService private readonly _webExtensionsScannerService: IWebExtensionsScannerService,
@ILifecycleService private readonly _lifecycleService: ILifecycleService,
@IUserDataInitializationService private readonly _userDataInitializationService: IUserDataInitializationService,
) {
super(
instantiationService,
@@ -56,7 +60,12 @@ export class ExtensionService extends AbstractExtensionService implements IExten
this._runningLocation = new Map<string, ExtensionRunningLocation>();
this._initialize();
// Initialize extensions first and do it only after workbench is ready
this._lifecycleService.when(LifecyclePhase.Ready).then(async () => {
await this._userDataInitializationService.initializeExtensions(this._instantiationService);
this._initialize();
});
this._initFetchFileSystem();
}

View File

@@ -29,8 +29,6 @@ import { generateUuid } from 'vs/base/common/uuid';
import { canceled, onUnexpectedError } from 'vs/base/common/errors';
import { WEB_WORKER_IFRAME } from 'vs/workbench/services/extensions/common/webWorkerIframe';
const WRAP_IN_IFRAME = true;
export interface IWebWorkerExtensionHostInitData {
readonly autoStart: boolean;
readonly extensions: IExtensionDescription[];
@@ -74,7 +72,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost
public async start(): Promise<IMessagePassingProtocol> {
if (!this._protocolPromise) {
if (WRAP_IN_IFRAME && platform.isWeb) {
if (platform.isWeb && this._environmentService.options && this._environmentService.options._wrapWebWorkerExtHostInIframe) {
this._protocolPromise = this._startInsideIframe();
} else {
this._protocolPromise = this._startOutsideIframe();
@@ -98,10 +96,11 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost
const escapeAttribute = (value: string): string => {
return value.replace(/"/g, '&quot;');
};
const isBuilt = this._environmentService.isBuilt;
const html = `<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-eval' '${WEB_WORKER_IFRAME.sha}' *; worker-src data:; connect-src *" />
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-eval' '${WEB_WORKER_IFRAME.sha}' ${isBuilt ? 'https:' : 'http: https:'}; worker-src data:; connect-src ${isBuilt ? 'https:' : 'http: https:'}" />
<meta id="vscode-worker-src" data-value="${escapeAttribute(workerSrc)}" />
<meta id="vscode-web-worker-ext-host-id" data-value="${escapeAttribute(vscodeWebWorkerExtHostId)}" />
</head>

View File

@@ -44,6 +44,7 @@ import { joinPath } from 'vs/base/common/resources';
import { Registry } from 'vs/platform/registry/common/platform';
import { IOutputChannelRegistry, Extensions } from 'vs/workbench/services/output/common/output';
import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService';
import { isUUID } from 'vs/base/common/uuid';
export interface ILocalProcessExtensionHostInitData {
readonly autoStart: boolean;
@@ -182,18 +183,23 @@ export class LocalProcessExtensionHost implements IExtensionHost {
opts.execArgv = ['--inspect-port=0'];
}
// Enable the crash reporter depending on environment for local reporting
const crashesDirectory = this._environmentService.crashReporterDirectory;
if (crashesDirectory) {
const crashReporterOptions: CrashReporterStartOptions = {
// On linux crash reporter needs to be started on child node processes explicitly
if (platform.isLinux) {
const crashReporterStartOptions: CrashReporterStartOptions = {
companyName: this._productService.crashReporter?.companyName || 'Microsoft',
productName: this._productService.crashReporter?.productName || this._productService.nameShort,
submitURL: '',
uploadToServer: false,
crashesDirectory
uploadToServer: false
};
opts.env.CRASH_REPORTER_START_OPTIONS = JSON.stringify(crashReporterOptions);
const crashReporterId = this._environmentService.crashReporterId; // crashReporterId is set by the main process only when crash reporting is enabled by the user.
const appcenter = this._productService.appCenter;
const uploadCrashesToServer = !this._environmentService.crashReporterDirectory; // only upload unless --crash-reporter-directory is provided
if (uploadCrashesToServer && appcenter && crashReporterId && isUUID(crashReporterId)) {
const submitURL = appcenter[`linux-x64`];
crashReporterStartOptions.submitURL = submitURL.concat('&uid=', crashReporterId, '&iid=', crashReporterId, '&sid=', crashReporterId);
crashReporterStartOptions.uploadToServer = true;
}
opts.env.CRASH_REPORTER_START_OPTIONS = JSON.stringify(crashReporterStartOptions);
}
// Run Extension Host as fork of current process

View File

@@ -139,11 +139,9 @@ suite('RPCProtocol', () => {
let p = bProxy.$m(4, tokenSource.token);
p.then((res: number) => {
assert.equal(res, 7);
done(null);
}, (err) => {
assert.fail('should not receive error');
done();
});
}).finally(done);
tokenSource.cancel();
});
@@ -153,11 +151,9 @@ suite('RPCProtocol', () => {
};
bProxy.$m(4, 1).then((res) => {
assert.fail('unexpected');
done(null);
}, (err) => {
assert.equal(err.message, 'nope');
done(null);
});
}).finally(done);
});
test('error promise', function (done) {
@@ -166,11 +162,9 @@ suite('RPCProtocol', () => {
};
bProxy.$m(4, 1).then((res) => {
assert.fail('unexpected');
done(null);
}, (err) => {
assert.equal(err, undefined);
done(null);
});
}).finally(done);
});
test('issue #60450: Converting circular structure to JSON', function (done) {
@@ -181,11 +175,9 @@ suite('RPCProtocol', () => {
};
bProxy.$m(4, 1).then((res) => {
assert.equal(res, null);
done(null);
}, (err) => {
assert.fail('unexpected');
done(null);
});
}).finally(done);
});
test('issue #72798: null errors are hard to digest', function (done) {
@@ -195,11 +187,9 @@ suite('RPCProtocol', () => {
};
bProxy.$m(4, 1).then((res) => {
assert.fail('unexpected');
done(null);
}, (err) => {
assert.equal(err.what, 'what');
done(null);
});
}).finally(done);
});
test('undefined arguments arrive as null', function () {

View File

@@ -109,4 +109,10 @@ export interface IHoverTarget extends IDisposable {
* wrapped text.
*/
readonly targetElements: readonly HTMLElement[];
/**
* An optional absolute x coordinate to position the hover with, for example to position the
* hover using `MouseEvent.pageX`.
*/
x?: number;
}

View File

@@ -136,11 +136,12 @@ export class HoverWidget extends Widget {
this._hover.containerDomNode.classList.remove('right-aligned');
this._hover.contentsDomNode.style.maxHeight = '';
// Get horizontal alignment and position
const targetBounds = this._target.targetElements.map(e => e.getBoundingClientRect());
const targetLeft = Math.min(...targetBounds.map(e => e.left));
// Get horizontal alignment and position
let targetLeft = this._target.x !== undefined ? this._target.x : Math.min(...targetBounds.map(e => e.left));
if (targetLeft + this._hover.containerDomNode.clientWidth >= document.documentElement.clientWidth) {
this._x = document.documentElement.clientWidth;
this._x = document.documentElement.clientWidth - 1;
this._hover.containerDomNode.classList.add('right-aligned');
} else {
this._x = targetLeft;

View File

@@ -18,6 +18,11 @@
color: #3794ff;
}
.monaco-workbench .workbench-hover.right-aligned {
/* The context view service wraps strangely when it's right up against the edge without this */
left: 1px;
}
.monaco-workbench .workbench-hover.right-aligned .hover-row.status-bar .actions {
flex-direction: row-reverse;
}

View File

@@ -33,9 +33,8 @@ export function positionToString(position: Position): string {
case Position.LEFT: return 'left';
case Position.RIGHT: return 'right';
case Position.BOTTOM: return 'bottom';
default: return 'bottom';
}
return 'bottom';
}
const positionsByString: { [key: string]: Position } = {

View File

@@ -135,16 +135,16 @@ export class NativeLifecycleService extends AbstractLifecycleService {
let message: string;
switch (reason) {
case ShutdownReason.CLOSE:
message = localize('errorClose', "An unexpected error prevented the window from closing ({0}).", toErrorMessage(error));
message = localize('errorClose', "An unexpected error was thrown while attempting to close the window ({0}).", toErrorMessage(error));
break;
case ShutdownReason.QUIT:
message = localize('errorQuit', "An unexpected error prevented the application from closing ({0}).", toErrorMessage(error));
message = localize('errorQuit', "An unexpected error was thrown while attempting to quit the application ({0}).", toErrorMessage(error));
break;
case ShutdownReason.RELOAD:
message = localize('errorReload', "An unexpected error prevented the window from reloading ({0}).", toErrorMessage(error));
message = localize('errorReload', "An unexpected error was thrown while attempting to reload the window ({0}).", toErrorMessage(error));
break;
case ShutdownReason.LOAD:
message = localize('errorLoad', "An unexpected error prevented the window from changing it's workspace ({0}).", toErrorMessage(error));
message = localize('errorLoad', "An unexpected error was thrown while attempting to change the workspace of the window ({0}).", toErrorMessage(error));
break;
}

View File

@@ -40,7 +40,7 @@ export interface ISettingsGroup {
title: string;
titleRange: IRange;
sections: ISettingsSection[];
contributedByExtension: boolean;
extensionInfo?: IConfigurationExtensionInfo;
}
export interface ISettingsSection {

View File

@@ -3,12 +3,11 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { flatten, tail, find, coalesce } from 'vs/base/common/arrays';
import { flatten, tail, coalesce } from 'vs/base/common/arrays';
import { IStringDictionary } from 'vs/base/common/collections';
import { Emitter, Event } from 'vs/base/common/event';
import { JSONVisitor, visit } from 'vs/base/common/json';
import { Disposable, IReference } from 'vs/base/common/lifecycle';
import { assign } from 'vs/base/common/objects';
import { URI } from 'vs/base/common/uri';
import { IRange, Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
@@ -198,7 +197,7 @@ export class SettingsEditorModel extends AbstractSettingsModel implements ISetti
}],
title: modelGroup.title,
titleRange: modelGroup.titleRange,
contributedByExtension: !!modelGroup.contributedByExtension
extensionInfo: modelGroup.extensionInfo
};
}
@@ -291,7 +290,7 @@ function parse(model: ITextModel, isSettingsProperty: (currentProperty: string,
endLineNumber: valueEndPosition.lineNumber,
endColumn: valueEndPosition.column
};
setting.range = assign(setting.range, {
setting.range = Object.assign(setting.range, {
endLineNumber: valueEndPosition.lineNumber,
endColumn: valueEndPosition.column
});
@@ -357,11 +356,11 @@ function parse(model: ITextModel, isSettingsProperty: (currentProperty: string,
const setting = previousParents.length === settingsPropertyIndex + 1 ? settings[settings.length - 1] : overrideSetting!.overrides![overrideSetting!.overrides!.length - 1];
if (setting) {
const valueEndPosition = model.getPositionAt(offset + length);
setting.valueRange = assign(setting.valueRange, {
setting.valueRange = Object.assign(setting.valueRange, {
endLineNumber: valueEndPosition.lineNumber,
endColumn: valueEndPosition.column
});
setting.range = assign(setting.range, {
setting.range = Object.assign(setting.range, {
endLineNumber: valueEndPosition.lineNumber,
endColumn: valueEndPosition.column
});
@@ -393,11 +392,11 @@ function parse(model: ITextModel, isSettingsProperty: (currentProperty: string,
const setting = previousParents.length === settingsPropertyIndex + 1 ? settings[settings.length - 1] : overrideSetting!.overrides![overrideSetting!.overrides!.length - 1];
if (setting) {
const valueEndPosition = model.getPositionAt(offset + length);
setting.valueRange = assign(setting.valueRange, {
setting.valueRange = Object.assign(setting.valueRange, {
endLineNumber: valueEndPosition.lineNumber,
endColumn: valueEndPosition.column
});
setting.range = assign(setting.range, {
setting.range = Object.assign(setting.range, {
endLineNumber: valueEndPosition.lineNumber,
endColumn: valueEndPosition.column
});
@@ -558,16 +557,16 @@ export class DefaultSettings extends Disposable {
seenSettings = seenSettings ? seenSettings : {};
let title = config.title;
if (!title) {
const configWithTitleAndSameId = find(configurations, c => (c.id === config.id) && c.title);
const configWithTitleAndSameId = configurations.find(c => (c.id === config.id) && c.title);
if (configWithTitleAndSameId) {
title = configWithTitleAndSameId.title;
}
}
if (title) {
if (!settingsGroup) {
settingsGroup = find(result, g => g.title === title);
settingsGroup = result.find(g => g.title === title && g.extensionInfo?.id === config.extensionInfo?.id);
if (!settingsGroup) {
settingsGroup = { sections: [{ settings: [] }], id: config.id || '', title: title || '', titleRange: nullRange, range: nullRange, contributedByExtension: !!config.extensionInfo };
settingsGroup = { sections: [{ settings: [] }], id: config.id || '', title: title || '', titleRange: nullRange, range: nullRange, extensionInfo: config.extensionInfo };
result.push(settingsGroup);
}
} else {
@@ -576,7 +575,7 @@ export class DefaultSettings extends Disposable {
}
if (config.properties) {
if (!settingsGroup) {
settingsGroup = { sections: [{ settings: [] }], id: config.id || '', title: config.id || '', titleRange: nullRange, range: nullRange, contributedByExtension: !!config.extensionInfo };
settingsGroup = { sections: [{ settings: [] }], id: config.id || '', title: config.id || '', titleRange: nullRange, range: nullRange, extensionInfo: config.extensionInfo };
result.push(settingsGroup);
}
const configurationSettings: ISetting[] = [];

View File

@@ -509,7 +509,9 @@ export class ProgressService extends Disposable implements IProgressService {
'workbench.action.quit',
'workbench.action.reloadWindow',
'copy',
'cut'
'cut',
'editor.action.clipboardCopyAction',
'editor.action.clipboardCutAction'
];
let dialog: Dialog;

View File

@@ -48,15 +48,8 @@ export interface Tunnel {
closeable?: boolean;
}
function ToLocalHost(host: string): string {
if (host === '127.0.0.1') {
host = 'localhost';
}
return host;
}
export function MakeAddress(host: string, port: number): string {
return ToLocalHost(host) + ':' + port;
return host + ':' + port;
}
export class TunnelModel extends Disposable {
@@ -218,7 +211,7 @@ export class TunnelModel extends Disposable {
const nullIndex = value.detail.indexOf('\0');
const detail = value.detail.substr(0, nullIndex > 0 ? nullIndex : value.detail.length).trim();
return {
host: ToLocalHost(value.host),
host: value.host,
port: value.port,
detail
};

View File

@@ -10,8 +10,6 @@ import { ILogService } from 'vs/platform/log/common/log';
import { RequestChannelClient } from 'vs/platform/request/common/requestIpc';
import { IRemoteAgentService, IRemoteAgentConnection } from 'vs/workbench/services/remote/common/remoteAgentService';
import { RequestService } from 'vs/platform/request/browser/requestService';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IRequestService } from 'vs/platform/request/common/request';
export class BrowserRequestService extends RequestService {
@@ -44,5 +42,3 @@ export class BrowserRequestService extends RequestService {
return connection.withChannel('request', channel => RequestChannelClient.request(channel, options, token));
}
}
registerSingleton(IRequestService, BrowserRequestService, true);

View File

@@ -54,7 +54,7 @@ export class TextSearchManager {
const newResultSize = this.resultSize(result);
this.resultCount += newResultSize;
if (newResultSize > 0) {
if (newResultSize > 0 || !extensionResultIsMatch(result)) {
this.collector!.add(result, folderIdx);
}
}
@@ -83,10 +83,15 @@ export class TextSearchManager {
}
private resultSize(result: TextSearchResult): number {
const match = <TextSearchMatch>result;
return Array.isArray(match.ranges) ?
match.ranges.length :
1;
if (extensionResultIsMatch(result)) {
return Array.isArray(result.ranges) ?
result.ranges.length :
1;
}
else {
// #104400 context lines shoudn't count towards result count
return 0;
}
}
private trimResultToSize(result: TextSearchMatch, size: number): TextSearchMatch {

View File

@@ -462,15 +462,17 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
}
suggestFilename(mode: string, untitledName: string) {
// {{SQL CARBON EDIT}} - pass language not mode for getting the extension.
const langName = this.modeService.getLanguageName(mode);
const extension = langName ? this.modeService.getExtensions(langName)[0] : undefined;
const languageName = this.modeService.getLanguageName(mode);
if (!languageName) {
return untitledName;
}
const extension = this.modeService.getExtensions(languageName)[0];
if (extension) {
if (!untitledName.endsWith(extension)) {
return untitledName + extension;
}
}
const filename = this.modeService.getFilenames(mode)[0];
const filename = this.modeService.getFilenames(languageName)[0];
return filename || untitledName;
}

View File

@@ -126,7 +126,7 @@ export class NativeTextFileService extends AbstractTextFileService {
}
try {
return super.write(resource, value, options);
return await super.write(resource, value, options);
} catch (error) {
// In case of permission denied, we need to check for readonly

View File

@@ -0,0 +1,170 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { AbstractInitializer } from 'vs/platform/userDataSync/common/abstractSynchronizer';
import { ExtensionsInitializer } from 'vs/platform/userDataSync/common/extensionsSync';
import { GlobalStateInitializer } from 'vs/platform/userDataSync/common/globalStateSync';
import { KeybindingsInitializer } from 'vs/platform/userDataSync/common/keybindingsSync';
import { SettingsInitializer } from 'vs/platform/userDataSync/common/settingsSync';
import { SnippetsInitializer } from 'vs/platform/userDataSync/common/snippetsSync';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IFileService } from 'vs/platform/files/common/files';
import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ILogService } from 'vs/platform/log/common/log';
import { UserDataSyncStoreClient } from 'vs/platform/userDataSync/common/userDataSyncStoreService';
import { IProductService } from 'vs/platform/product/common/productService';
import { IRequestService } from 'vs/platform/request/common/request';
import { CONFIGURATION_SYNC_STORE_KEY, IUserDataSyncStoreClient, SyncResource } from 'vs/platform/userDataSync/common/userDataSync';
import { URI } from 'vs/base/common/uri';
import { getCurrentAuthenticationSessionInfo } from 'vs/workbench/services/authentication/browser/authenticationService';
import { getSyncAreaLabel } from 'vs/workbench/services/userDataSync/common/userDataSync';
import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions } from 'vs/workbench/common/contributions';
import { Registry } from 'vs/platform/registry/common/platform';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { isWeb } from 'vs/base/common/platform';
export const IUserDataInitializationService = createDecorator<IUserDataInitializationService>('IUserDataInitializationService');
export interface IUserDataInitializationService {
_serviceBrand: any;
initializeRequiredResources(): Promise<void>;
initializeOtherResources(): Promise<void>;
initializeExtensions(instantiationService: IInstantiationService): Promise<void>;
}
export class UserDataInitializationService implements IUserDataInitializationService {
_serviceBrand: any;
private readonly initialized: SyncResource[] = [];
constructor(
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
@IFileService private readonly fileService: IFileService,
@IStorageService private readonly storageService: IStorageService,
@IProductService private readonly productService: IProductService,
@IRequestService private readonly requestService: IRequestService,
@ILogService private readonly logService: ILogService
) { }
private _userDataSyncStoreClientPromise: Promise<IUserDataSyncStoreClient | undefined> | undefined;
private createUserDataSyncStoreClient(): Promise<IUserDataSyncStoreClient | undefined> {
if (!this._userDataSyncStoreClientPromise) {
this._userDataSyncStoreClientPromise = (async (): Promise<IUserDataSyncStoreClient | undefined> => {
if (!isWeb) {
this.logService.trace(`Skipping initializing user data in desktop`);
return undefined; // {{SQL CARBON EDIT}} strict-null-check
}
if (!this.environmentService.options?.enableSyncByDefault) {
this.logService.trace(`Skipping initializing user data as sync is not enabled by default`);
return undefined; // {{SQL CARBON EDIT}} strict-null-check
}
if (!this.storageService.isNew(StorageScope.GLOBAL)) {
this.logService.trace(`Skipping initializing user data as application was opened before`);
return undefined; // {{SQL CARBON EDIT}} strict-null-check
}
if (!this.storageService.isNew(StorageScope.WORKSPACE)) {
this.logService.trace(`Skipping initializing user data as workspace was opened before`);
return undefined; // {{SQL CARBON EDIT}} strict-null-check
}
const userDataSyncStore = this.productService[CONFIGURATION_SYNC_STORE_KEY];
if (!userDataSyncStore) {
this.logService.trace(`Skipping initializing user data as sync service is not provided`);
return undefined; // {{SQL CARBON EDIT}} strict-null-check
}
if (!this.environmentService.options?.credentialsProvider) {
this.logService.trace(`Skipping initializing user data as credentials provider is not provided`);
return undefined; // {{SQL CARBON EDIT}} strict-null-check
}
let authenticationSession;
try {
authenticationSession = await getCurrentAuthenticationSessionInfo(this.environmentService, this.productService);
} catch (error) {
this.logService.error(error);
}
if (!authenticationSession) {
this.logService.trace(`Skipping initializing user data as authentication session is not set`);
return undefined; // {{SQL CARBON EDIT}} strict-null-check
}
const userDataSyncStoreClient = new UserDataSyncStoreClient(URI.parse(userDataSyncStore.url), this.productService, this.requestService, this.logService, this.environmentService, this.fileService, this.storageService);
userDataSyncStoreClient.setAuthToken(authenticationSession.accessToken, authenticationSession.providerId);
return userDataSyncStoreClient;
})();
}
return this._userDataSyncStoreClientPromise;
}
async initializeRequiredResources(): Promise<void> {
return this.initialize([SyncResource.Settings, SyncResource.GlobalState]);
}
async initializeOtherResources(): Promise<void> {
return this.initialize([SyncResource.Keybindings, SyncResource.Snippets]);
}
async initializeExtensions(instantiationService: IInstantiationService): Promise<void> {
return this.initialize([SyncResource.Extensions], instantiationService);
}
private async initialize(syncResources: SyncResource[], instantiationService?: IInstantiationService): Promise<void> {
const userDataSyncStoreClient = await this.createUserDataSyncStoreClient();
if (!userDataSyncStoreClient) {
return;
}
await Promise.all(syncResources.map(async syncResource => {
try {
if (this.initialized.includes(syncResource)) {
this.logService.info(`${getSyncAreaLabel(syncResource)} initialized already.`);
return;
}
this.initialized.push(syncResource);
this.logService.trace(`Initializing ${getSyncAreaLabel(syncResource)}`);
const initializer = this.createSyncResourceInitializer(syncResource, instantiationService);
const userData = await userDataSyncStoreClient.read(syncResource, null);
await initializer.initialize(userData);
this.logService.info(`Initialized ${getSyncAreaLabel(syncResource)}`);
} catch (error) {
this.logService.info(`Error while initializing ${getSyncAreaLabel(syncResource)}`);
this.logService.error(error);
}
}));
}
private createSyncResourceInitializer(syncResource: SyncResource, instantiationService?: IInstantiationService): AbstractInitializer {
switch (syncResource) {
case SyncResource.Settings: return new SettingsInitializer(this.fileService, this.environmentService, this.logService);
case SyncResource.Keybindings: return new KeybindingsInitializer(this.fileService, this.environmentService, this.logService);
case SyncResource.Snippets: return new SnippetsInitializer(this.fileService, this.environmentService, this.logService);
case SyncResource.GlobalState: return new GlobalStateInitializer(this.storageService, this.fileService, this.environmentService, this.logService);
case SyncResource.Extensions:
if (!instantiationService) {
throw new Error('Instantiation Service is required to initialize extension');
}
return instantiationService.createInstance(ExtensionsInitializer);
}
}
}
class InitializeOtherResourcesContribution implements IWorkbenchContribution {
constructor(@IUserDataInitializationService userDataInitializeService: IUserDataInitializationService) {
userDataInitializeService.initializeOtherResources();
}
}
if (isWeb) {
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(Extensions.Workbench);
workbenchRegistry.registerWorkbenchContribution(InitializeOtherResourcesContribution, LifecyclePhase.Restored);
}

View File

@@ -11,7 +11,7 @@ import { AuthenticationSession, AuthenticationSessionsChangeEvent } from 'vs/edi
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { Emitter, Event } from 'vs/base/common/event';
import { flatten, equals } from 'vs/base/common/arrays';
import { getAuthenticationProviderActivationEvent, IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService';
import { getAuthenticationProviderActivationEvent, getCurrentAuthenticationSessionInfo, IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService';
import { IUserDataSyncAccountService } from 'vs/platform/userDataSync/common/userDataSyncAccount';
import { IQuickInputService, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
import { IStorageService, IWorkspaceStorageChangeEvent, StorageScope } from 'vs/platform/storage/common/storage';
@@ -153,8 +153,9 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat
}
private async initialize(): Promise<void> {
if (this.currentSessionId === undefined && this.useWorkbenchSessionId && this.environmentService.options?.authenticationSessionId) {
this.currentSessionId = this.environmentService.options.authenticationSessionId;
const authenticationSession = this.environmentService.options?.credentialsProvider ? await getCurrentAuthenticationSessionInfo(this.environmentService, this.productService) : undefined;
if (this.currentSessionId === undefined && this.useWorkbenchSessionId && (authenticationSession?.id || this.environmentService.options?.authenticationSessionId)) {
this.currentSessionId = authenticationSession?.id || this.environmentService.options?.authenticationSessionId;
this.useWorkbenchSessionId = false;
}
@@ -331,9 +332,14 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat
}
});
if (manualSyncTask.status === SyncStatus.HasConflicts) {
await this.dialogService.show(Severity.Warning, localize('conflicts detected', "Conflicts Detected"), [], {
detail: localize('resolve', "Unable to merge due to conflicts. Please merge manually to continue...")
});
await this.dialogService.show(
Severity.Warning,
localize('conflicts detected', "Conflicts Detected"),
[localize('merge Manually', "Merge Manually...")],
{
detail: localize('resolve', "Unable to merge due to conflicts. Please merge manually to continue..."),
}
);
await manualSyncTask.discardConflicts();
action = 'manual';
}

View File

@@ -692,7 +692,7 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
});
});
this.getViewContainerModel(container).add(views.map(view => { return { viewDescriptor: view, collapsed: expandViews ? false : undefined }; }));
this.getViewContainerModel(container).add(views.map(view => { return { viewDescriptor: view, collapsed: expandViews ? false : undefined, visible: expandViews }; }));
}
private removeViews(container: ViewContainer, views: IViewDescriptor[]): void {

View File

@@ -478,16 +478,16 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode
if (state) {
// set defaults if not set
if (viewDescriptor.workspace) {
state.visibleWorkspace = isUndefinedOrNull(state.visibleWorkspace) ? !viewDescriptor.hideByDefault : state.visibleWorkspace;
state.visibleWorkspace = isUndefinedOrNull(addedViewDescriptorState.visible) ? (isUndefinedOrNull(state.visibleWorkspace) ? !viewDescriptor.hideByDefault : state.visibleWorkspace) : addedViewDescriptorState.visible;
} else {
state.visibleGlobal = isUndefinedOrNull(state.visibleGlobal) ? !viewDescriptor.hideByDefault : state.visibleGlobal;
state.visibleGlobal = isUndefinedOrNull(addedViewDescriptorState.visible) ? (isUndefinedOrNull(state.visibleGlobal) ? !viewDescriptor.hideByDefault : state.visibleGlobal) : addedViewDescriptorState.visible;
}
state.collapsed = isUndefinedOrNull(addedViewDescriptorState.collapsed) ? (isUndefinedOrNull(state.collapsed) ? !!viewDescriptor.collapsed : state.collapsed) : addedViewDescriptorState.collapsed;
} else {
state = {
active: false,
visibleGlobal: !viewDescriptor.hideByDefault,
visibleWorkspace: !viewDescriptor.hideByDefault,
visibleGlobal: isUndefinedOrNull(addedViewDescriptorState.visible) ? !viewDescriptor.hideByDefault : addedViewDescriptorState.visible,
visibleWorkspace: isUndefinedOrNull(addedViewDescriptorState.visible) ? !viewDescriptor.hideByDefault : addedViewDescriptorState.visible,
collapsed: isUndefinedOrNull(addedViewDescriptorState.collapsed) ? !!viewDescriptor.collapsed : addedViewDescriptorState.collapsed,
};
}