Merge from vscode a234f13c45b40a0929777cb440ee011b7549eed2 (#8911)

* Merge from vscode a234f13c45b40a0929777cb440ee011b7549eed2

* update distro

* fix layering

* update distro

* fix tests
This commit is contained in:
Anthony Dresser
2020-01-22 13:42:37 -08:00
committed by GitHub
parent 977111eb21
commit bd7aac8ee0
895 changed files with 24651 additions and 14520 deletions

View File

@@ -59,6 +59,7 @@ import './mainThreadComments';
// import './mainThreadTask'; {{SQL CARBON EDIT}} @anthonydresser comment out task
import './mainThreadLabelService';
import './mainThreadTunnelService';
import './mainThreadAuthentication';
import 'vs/workbench/api/common/apiCommands';
export class ExtensionPoints implements IWorkbenchContribution {

View File

@@ -0,0 +1,55 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Disposable } from 'vs/base/common/lifecycle';
import * as modes from 'vs/editor/common/modes';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService';
import { ExtHostAuthenticationShape, ExtHostContext, IExtHostContext, MainContext, MainThreadAuthenticationShape } from '../common/extHost.protocol';
export class MainThreadAuthenticationProvider {
constructor(
private readonly _proxy: ExtHostAuthenticationShape,
public readonly id: string
) { }
getSessions(): Promise<ReadonlyArray<modes.Session>> {
return this._proxy.$getSessions(this.id);
}
login(): Promise<modes.Session> {
return this._proxy.$login(this.id);
}
logout(accountId: string): Promise<void> {
return this._proxy.$logout(this.id, accountId);
}
}
@extHostNamedCustomer(MainContext.MainThreadAuthentication)
export class MainThreadAuthentication extends Disposable implements MainThreadAuthenticationShape {
private readonly _proxy: ExtHostAuthenticationShape;
constructor(
extHostContext: IExtHostContext,
@IAuthenticationService private readonly authenticationService: IAuthenticationService,
) {
super();
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostAuthentication);
}
$registerAuthenticationProvider(id: string): void {
const provider = new MainThreadAuthenticationProvider(this._proxy, id);
this.authenticationService.registerAuthenticationProvider(id, provider);
}
$unregisterAuthenticationProvider(id: string): void {
this.authenticationService.unregisterAuthenticationProvider(id);
}
$onDidChangeSessions(id: string) {
this.authenticationService.sessionsUpdate(id);
}
}

View File

@@ -154,7 +154,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
return Promise.resolve();
}
public $registerDebugConfigurationProvider(debugType: string, hasProvide: boolean, hasResolve: boolean, hasProvideDebugAdapter: boolean, handle: number): Promise<void> {
public $registerDebugConfigurationProvider(debugType: string, hasProvide: boolean, hasResolve: boolean, hasResolve2: boolean, hasProvideDebugAdapter: boolean, handle: number): Promise<void> {
const provider = <IDebugConfigurationProvider>{
type: debugType
@@ -169,6 +169,11 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
return this._proxy.$resolveDebugConfiguration(handle, folder, config, token);
};
}
if (hasResolve2) {
provider.resolveDebugConfigurationWithSubstitutedVariables = (folder, config, token) => {
return this._proxy.$resolveDebugConfigurationWithSubstitutedVariables(handle, folder, config, token);
};
}
if (hasProvideDebugAdapter) {
console.info('DebugConfigurationProvider.debugAdapterExecutable is deprecated and will be removed soon; please use DebugAdapterDescriptorFactory.createDebugAdapterDescriptor instead.');
provider.debugAdapterExecutable = (folder) => {

View File

@@ -8,15 +8,13 @@ import { IDisposable, IReference, dispose, DisposableStore } from 'vs/base/commo
import { Schemas } from 'vs/base/common/network';
import { URI, UriComponents } from 'vs/base/common/uri';
import { ITextModel } from 'vs/editor/common/model';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IModelService, shouldSynchronizeModel } from 'vs/editor/common/services/modelService';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { IFileService } from 'vs/platform/files/common/files';
import { MainThreadDocumentsAndEditors } from 'vs/workbench/api/browser/mainThreadDocumentsAndEditors';
import { ExtHostContext, ExtHostDocumentsShape, IExtHostContext, MainThreadDocumentsShape } from 'vs/workbench/api/common/extHost.protocol';
import { ITextEditorModel } from 'vs/workbench/common/editor';
import { ITextFileService, TextFileModelChangeEvent } from 'vs/workbench/services/textfile/common/textfiles';
import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { toLocalResource } from 'vs/base/common/resources';
@@ -70,7 +68,6 @@ export class MainThreadDocuments implements MainThreadDocumentsShape {
private readonly _textModelResolverService: ITextModelService;
private readonly _textFileService: ITextFileService;
private readonly _fileService: IFileService;
private readonly _untitledTextEditorService: IUntitledTextEditorService;
private readonly _environmentService: IWorkbenchEnvironmentService;
private readonly _toDispose = new DisposableStore();
@@ -83,18 +80,15 @@ export class MainThreadDocuments implements MainThreadDocumentsShape {
documentsAndEditors: MainThreadDocumentsAndEditors,
extHostContext: IExtHostContext,
@IModelService modelService: IModelService,
@IModeService modeService: IModeService,
@ITextFileService textFileService: ITextFileService,
@IFileService fileService: IFileService,
@ITextModelService textModelResolverService: ITextModelService,
@IUntitledTextEditorService untitledTextEditorService: IUntitledTextEditorService,
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService
) {
this._modelService = modelService;
this._textModelResolverService = textModelResolverService;
this._textFileService = textFileService;
this._fileService = fileService;
this._untitledTextEditorService = untitledTextEditorService;
this._environmentService = environmentService;
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDocuments);
@@ -104,19 +98,14 @@ export class MainThreadDocuments implements MainThreadDocumentsShape {
this._toDispose.add(this._modelReferenceCollection);
this._toDispose.add(modelService.onModelModeChanged(this._onModelModeChanged, this));
this._toDispose.add(textFileService.models.onModelSaved(e => {
if (this._shouldHandleFileEvent(e)) {
this._proxy.$acceptModelSaved(e.resource);
this._toDispose.add(textFileService.files.onDidSave(e => {
if (this._shouldHandleFileEvent(e.model.resource)) {
this._proxy.$acceptModelSaved(e.model.resource);
}
}));
this._toDispose.add(textFileService.models.onModelReverted(e => {
if (this._shouldHandleFileEvent(e)) {
this._proxy.$acceptDirtyStateChanged(e.resource, false);
}
}));
this._toDispose.add(textFileService.models.onModelDirty(e => {
if (this._shouldHandleFileEvent(e)) {
this._proxy.$acceptDirtyStateChanged(e.resource, true);
this._toDispose.add(textFileService.files.onDidChangeDirty(m => {
if (this._shouldHandleFileEvent(m.resource)) {
this._proxy.$acceptDirtyStateChanged(m.resource, m.isDirty());
}
}));
@@ -131,8 +120,8 @@ export class MainThreadDocuments implements MainThreadDocumentsShape {
this._toDispose.dispose();
}
private _shouldHandleFileEvent(e: TextFileModelChangeEvent): boolean {
const model = this._modelService.getModel(e.resource);
private _shouldHandleFileEvent(resource: URI): boolean {
const model = this._modelService.getModel(resource);
return !!model && shouldSynchronizeModel(model);
}
@@ -222,16 +211,15 @@ export class MainThreadDocuments implements MainThreadDocumentsShape {
// don't create a new file ontop of an existing file
return Promise.reject(new Error('file already exists'));
}, err => {
return this._doCreateUntitled(uri).then(resource => !!resource);
return this._doCreateUntitled(Boolean(uri.path) ? uri : undefined).then(resource => !!resource);
});
}
private _doCreateUntitled(resource?: URI, mode?: string, initialValue?: string): Promise<URI> {
return this._untitledTextEditorService.loadOrCreate({
resource,
private _doCreateUntitled(associatedResource?: URI, mode?: string, initialValue?: string): Promise<URI> {
return this._textFileService.untitled.resolve({
associatedResource,
mode,
initialValue,
useResourcePath: Boolean(resource && resource.path)
initialValue
}).then(model => {
const resource = model.resource;

View File

@@ -12,7 +12,6 @@ import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { IEditor } from 'vs/editor/common/editorCommon';
import { ITextModel } from 'vs/editor/common/model';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IModelService, shouldSynchronizeModel } from 'vs/editor/common/services/modelService';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { IFileService } from 'vs/platform/files/common/files';
@@ -28,7 +27,6 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
namespace delta {
@@ -324,10 +322,8 @@ export class MainThreadDocumentsAndEditors {
@ITextFileService private readonly _textFileService: ITextFileService,
@IEditorService private readonly _editorService: IEditorService,
@ICodeEditorService codeEditorService: ICodeEditorService,
@IModeService modeService: IModeService,
@IFileService fileService: IFileService,
@ITextModelService textModelResolverService: ITextModelService,
@IUntitledTextEditorService untitledTextEditorService: IUntitledTextEditorService,
@IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService,
@IBulkEditService bulkEditService: IBulkEditService,
@IPanelService panelService: IPanelService,
@@ -335,7 +331,7 @@ export class MainThreadDocumentsAndEditors {
) {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDocumentsAndEditors);
const mainThreadDocuments = this._toDispose.add(new MainThreadDocuments(this, extHostContext, this._modelService, modeService, this._textFileService, fileService, textModelResolverService, untitledTextEditorService, environmentService));
const mainThreadDocuments = this._toDispose.add(new MainThreadDocuments(this, extHostContext, this._modelService, this._textFileService, fileService, textModelResolverService, environmentService));
extHostContext.set(MainContext.MainThreadDocuments, mainThreadDocuments);
const mainThreadTextEditors = this._toDispose.add(new MainThreadTextEditors(this, extHostContext, codeEditorService, bulkEditService, this._editorService, this._editorGroupService));

View File

@@ -9,7 +9,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { RenderLineNumbersType, TextEditorCursorStyle, cursorStyleToString, EditorOption } from 'vs/editor/common/config/editorOptions';
import { IRange, Range } from 'vs/editor/common/core/range';
import { ISelection, Selection } from 'vs/editor/common/core/selection';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { IDecorationOptions, ScrollType } from 'vs/editor/common/editorCommon';
import { IIdentifiedSingleEditOperation, ISingleEditOperation, ITextModel, ITextModelUpdateOptions } from 'vs/editor/common/model';
import { IModelService } from 'vs/editor/common/services/modelService';
import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2';
@@ -365,7 +365,7 @@ export class MainThreadTextEditor {
}
}
public setDecorations(key: string, ranges: editorCommon.IDecorationOptions[]): void {
public setDecorations(key: string, ranges: IDecorationOptions[]): void {
if (!this._codeEditor) {
return;
}
@@ -389,16 +389,16 @@ export class MainThreadTextEditor {
}
switch (revealType) {
case TextEditorRevealType.Default:
this._codeEditor.revealRange(range, editorCommon.ScrollType.Smooth);
this._codeEditor.revealRange(range, ScrollType.Smooth);
break;
case TextEditorRevealType.InCenter:
this._codeEditor.revealRangeInCenter(range, editorCommon.ScrollType.Smooth);
this._codeEditor.revealRangeInCenter(range, ScrollType.Smooth);
break;
case TextEditorRevealType.InCenterIfOutsideViewport:
this._codeEditor.revealRangeInCenterIfOutsideViewport(range, editorCommon.ScrollType.Smooth);
this._codeEditor.revealRangeInCenterIfOutsideViewport(range, ScrollType.Smooth);
break;
case TextEditorRevealType.AtTop:
this._codeEditor.revealRangeAtTop(range, editorCommon.ScrollType.Smooth);
this._codeEditor.revealRangeAtTop(range, ScrollType.Smooth);
break;
default:
console.warn(`Unknown revealType: ${revealType}`);

View File

@@ -217,7 +217,7 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
$tryApplyWorkspaceEdit(dto: IWorkspaceEditDto): Promise<boolean> {
const { edits } = reviveWorkspaceEditDto(dto);
return this._bulkEditService.apply({ edits }, undefined).then(() => true, err => false);
return this._bulkEditService.apply({ edits }).then(() => true, _err => false);
}
$tryInsertSnippet(id: string, template: string, ranges: readonly IRange[], opts: IUndoStopOptions): Promise<boolean> {

View File

@@ -327,8 +327,12 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- semantic tokens
$registerSemanticTokensProvider(handle: number, selector: IDocumentFilterDto[], legend: modes.SemanticTokensLegend): void {
this._registrations.set(handle, modes.SemanticTokensProviderRegistry.register(selector, new MainThreadSemanticTokensProvider(this._proxy, handle, legend)));
$registerDocumentSemanticTokensProvider(handle: number, selector: IDocumentFilterDto[], legend: modes.SemanticTokensLegend): void {
this._registrations.set(handle, modes.DocumentSemanticTokensProviderRegistry.register(selector, new MainThreadDocumentSemanticTokensProvider(this._proxy, handle, legend)));
}
$registerDocumentRangeSemanticTokensProvider(handle: number, selector: IDocumentFilterDto[], legend: modes.SemanticTokensLegend): void {
this._registrations.set(handle, modes.DocumentRangeSemanticTokensProviderRegistry.register(selector, new MainThreadDocumentRangeSemanticTokensProvider(this._proxy, handle, legend)));
}
// --- suggest
@@ -368,6 +372,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
return {
suggestions: result.b.map(d => MainThreadLanguageFeatures._inflateSuggestDto(result.a, d)),
incomplete: result.c,
isDetailsResolved: result.d,
dispose: () => typeof result.x === 'number' && this._proxy.$releaseCompletionItems(handle, result.x)
};
});
@@ -607,7 +612,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
}
export class MainThreadSemanticTokensProvider implements modes.SemanticTokensProvider {
export class MainThreadDocumentSemanticTokensProvider implements modes.DocumentSemanticTokensProvider {
constructor(
private readonly _proxy: ExtHostLanguageFeaturesShape,
@@ -616,9 +621,9 @@ export class MainThreadSemanticTokensProvider implements modes.SemanticTokensPro
) {
}
public releaseSemanticTokens(resultId: string | undefined): void {
public releaseDocumentSemanticTokens(resultId: string | undefined): void {
if (resultId) {
this._proxy.$releaseSemanticTokens(this._handle, parseInt(resultId, 10));
this._proxy.$releaseDocumentSemanticTokens(this._handle, parseInt(resultId, 10));
}
}
@@ -626,9 +631,9 @@ export class MainThreadSemanticTokensProvider implements modes.SemanticTokensPro
return this._legend;
}
async provideSemanticTokens(model: ITextModel, lastResultId: string | null, ranges: EditorRange[] | null, token: CancellationToken): Promise<modes.SemanticTokens | modes.SemanticTokensEdits | null> {
async provideDocumentSemanticTokens(model: ITextModel, lastResultId: string | null, token: CancellationToken): Promise<modes.SemanticTokens | modes.SemanticTokensEdits | null> {
const nLastResultId = lastResultId ? parseInt(lastResultId, 10) : 0;
const encodedDto = await this._proxy.$provideSemanticTokens(this._handle, model.uri, ranges, nLastResultId, token);
const encodedDto = await this._proxy.$provideDocumentSemanticTokens(this._handle, model.uri, nLastResultId, token);
if (!encodedDto) {
return null;
}
@@ -648,3 +653,35 @@ export class MainThreadSemanticTokensProvider implements modes.SemanticTokensPro
};
}
}
export class MainThreadDocumentRangeSemanticTokensProvider implements modes.DocumentRangeSemanticTokensProvider {
constructor(
private readonly _proxy: ExtHostLanguageFeaturesShape,
private readonly _handle: number,
private readonly _legend: modes.SemanticTokensLegend,
) {
}
public getLegend(): modes.SemanticTokensLegend {
return this._legend;
}
async provideDocumentRangeSemanticTokens(model: ITextModel, range: EditorRange, token: CancellationToken): Promise<modes.SemanticTokens | null> {
const encodedDto = await this._proxy.$provideDocumentRangeSemanticTokens(this._handle, model.uri, range, token);
if (!encodedDto) {
return null;
}
if (token.isCancellationRequested) {
return null;
}
const dto = decodeSemanticTokensDto(encodedDto);
if (dto.type === 'full') {
return {
resultId: String(dto.id),
data: dto.data
};
}
throw new Error(`Unexpected`);
}
}

View File

@@ -3,11 +3,10 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IdleValue, sequence } from 'vs/base/common/async';
import { IdleValue } from 'vs/base/common/async';
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';
import * as strings from 'vs/base/common/strings';
import { IActiveCodeEditor } from 'vs/editor/browser/editorBrowser';
import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { trimTrailingWhitespace } from 'vs/editor/common/commands/trimTrailingWhitespaceCommand';
import { EditOperation } from 'vs/editor/common/core/editOperation';
@@ -15,7 +14,7 @@ import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { ITextModel } from 'vs/editor/common/model';
import { CodeAction } from 'vs/editor/common/modes';
import { CodeAction, CodeActionTriggerType } from 'vs/editor/common/modes';
import { shouldSynchronizeModel } from 'vs/editor/common/services/modelService';
import { getCodeActions } from 'vs/editor/contrib/codeAction/codeAction';
import { applyCodeAction } from 'vs/editor/contrib/codeAction/codeActionCommands';
@@ -23,22 +22,34 @@ import { CodeActionKind } from 'vs/editor/contrib/codeAction/types';
import { formatDocumentWithSelectedProvider, FormattingMode } from 'vs/editor/contrib/format/format';
import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2';
import { localize } from 'vs/nls';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ILogService } from 'vs/platform/log/common/log';
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
import { IProgressService, ProgressLocation, IProgressStep, IProgress } from 'vs/platform/progress/common/progress';
import { extHostCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel';
import { ISaveParticipant, IResolvedTextFileEditorModel, ITextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles';
import { SaveReason } from 'vs/workbench/common/editor';
import { ExtHostContext, ExtHostDocumentSaveParticipantShape, IExtHostContext } from '../common/extHost.protocol';
import { INotebookService } from 'sql/workbench/services/notebook/browser/notebookService'; // {{SQL CARBON EDIT}}
import { IStatusbarService, StatusbarAlignment } from 'vs/workbench/services/statusbar/common/statusbar';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { SettingsEditor2 } from 'vs/workbench/contrib/preferences/browser/settingsEditor2';
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
import { ILabelService } from 'vs/platform/label/common/label';
import { canceled, isPromiseCanceledError } from 'vs/base/common/errors';
export interface ICodeActionsOnSaveOptions {
[kind: string]: boolean;
}
class SaveParticipantError extends Error {
constructor(message: string, readonly setting?: string) {
super(message);
}
}
/*
* An update participant that ensures any un-tracked changes are synced to the JSON file contents for a
* Notebook before save occurs. While every effort is made to ensure model changes are notified and a listener
@@ -63,8 +74,8 @@ class NotebookUpdateParticipant implements ISaveParticipantParticipant { // {{SQ
}
}
export interface ISaveParticipantParticipant extends ISaveParticipant {
// progressMessage: string;
export interface ISaveParticipantParticipant {
participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason }, progress: IProgress<IProgressStep>, token: CancellationToken): Promise<void>;
}
class TrimWhitespaceParticipant implements ISaveParticipantParticipant {
@@ -107,7 +118,7 @@ class TrimWhitespaceParticipant implements ISaveParticipantParticipant {
return; // Nothing to do
}
model.pushEditOperations(prevSelection, ops, (edits) => prevSelection);
model.pushEditOperations(prevSelection, ops, (_edits) => prevSelection);
}
}
@@ -138,7 +149,7 @@ export class FinalNewLineParticipant implements ISaveParticipantParticipant {
// Nothing
}
async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise<void> {
async participate(model: IResolvedTextFileEditorModel, _env: { reason: SaveReason; }): Promise<void> {
if (this.configurationService.getValue('files.insertFinalNewline', { overrideIdentifier: model.textEditorModel.getLanguageIdentifier().language, resource: model.resource })) {
this.doInsertFinalNewLine(model.textEditorModel);
}
@@ -224,7 +235,7 @@ export class TrimFinalNewLinesParticipant implements ISaveParticipantParticipant
return;
}
model.pushEditOperations(prevSelection, [EditOperation.delete(deletionRange)], edits => prevSelection);
model.pushEditOperations(prevSelection, [EditOperation.delete(deletionRange)], _edits => prevSelection);
if (editor) {
editor.setSelections(prevSelection);
@@ -242,7 +253,7 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant {
// Nothing
}
async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise<void> {
async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason; }, progress: IProgress<IProgressStep>, token: CancellationToken): Promise<void> {
const model = editorModel.textEditorModel;
const overrides = { overrideIdentifier: model.getLanguageIdentifier().language, resource: model.uri };
@@ -251,32 +262,20 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant {
return undefined;
}
return new Promise<any>((resolve, reject) => {
const source = new CancellationTokenSource();
const editorOrModel = findEditor(model, this._codeEditorService) || model;
const timeout = this._configurationService.getValue<number>('editor.formatOnSaveTimeout', overrides);
const request = this._instantiationService.invokeFunction(formatDocumentWithSelectedProvider, editorOrModel, FormattingMode.Silent, source.token);
setTimeout(() => {
reject(localize('timeout.formatOnSave', "Aborted format on save after {0}ms", timeout));
source.cancel();
}, timeout);
request.then(resolve, reject);
});
progress.report({ message: localize('formatting', "Formatting") });
const editorOrModel = findEditor(model, this._codeEditorService) || model;
await this._instantiationService.invokeFunction(formatDocumentWithSelectedProvider, editorOrModel, FormattingMode.Silent, token);
}
}
class CodeActionOnSaveParticipant implements ISaveParticipant {
class CodeActionOnSaveParticipant implements ISaveParticipantParticipant {
constructor(
@IBulkEditService private readonly _bulkEditService: IBulkEditService,
@ICommandService private readonly _commandService: ICommandService,
@IConfigurationService private readonly _configurationService: IConfigurationService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
) { }
async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise<void> {
async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason; }, progress: IProgress<IProgressStep>, token: CancellationToken): Promise<void> {
if (env.reason === SaveReason.AUTO) {
return undefined;
}
@@ -312,20 +311,8 @@ class CodeActionOnSaveParticipant implements ISaveParticipant {
.filter(x => setting[x] === false)
.map(x => new CodeActionKind(x));
const tokenSource = new CancellationTokenSource();
const timeout = this._configurationService.getValue<number>('editor.codeActionsOnSaveTimeout', settingsOverrides);
return Promise.race([
new Promise<void>((_resolve, reject) =>
setTimeout(() => {
tokenSource.cancel();
reject(localize('codeActionsOnSave.didTimeout', "Aborted codeActionsOnSave after {0}ms", timeout));
}, timeout)),
this.applyOnSaveActions(model, codeActionsOnSave, excludedActions, tokenSource.token)
]).finally(() => {
tokenSource.cancel();
});
progress.report({ message: localize('codeaction', "Quick Fixes") });
await this.applyOnSaveActions(model, codeActionsOnSave, excludedActions, token);
}
private async applyOnSaveActions(model: ITextModel, codeActionsOnSave: readonly CodeActionKind[], excludes: readonly CodeActionKind[], token: CancellationToken): Promise<void> {
@@ -343,13 +330,13 @@ class CodeActionOnSaveParticipant implements ISaveParticipant {
private async applyCodeActions(actionsToRun: readonly CodeAction[]) {
for (const action of actionsToRun) {
await this._instantiationService.invokeFunction(applyCodeAction, action, this._bulkEditService, this._commandService);
await this._instantiationService.invokeFunction(applyCodeAction, action);
}
}
private getActionsToRun(model: ITextModel, codeActionKind: CodeActionKind, excludes: readonly CodeActionKind[], token: CancellationToken) {
return getCodeActions(model, model.getFullModelRange(), {
type: 'auto',
type: CodeActionTriggerType.Auto,
filter: { include: codeActionKind, excludes: excludes, includeSourceActions: true },
}, token);
}
@@ -363,7 +350,7 @@ class ExtHostSaveParticipant implements ISaveParticipantParticipant {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDocumentSaveParticipant);
}
async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise<void> {
async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason; }, _progress: IProgress<IProgressStep>, token: CancellationToken): Promise<void> {
if (!shouldSynchronizeModel(editorModel.textEditorModel)) {
// the model never made it to the extension
@@ -372,7 +359,13 @@ class ExtHostSaveParticipant implements ISaveParticipantParticipant {
}
return new Promise<any>((resolve, reject) => {
setTimeout(() => reject(localize('timeout.onWillSave', "Aborted onWillSaveTextDocument-event after 1750ms")), 1750);
token.onCancellationRequested(() => reject(canceled()));
setTimeout(
() => reject(new SaveParticipantError(localize('timeout.onWillSave', "Aborted onWillSaveTextDocument-event after 1750ms"))),
1750
);
this._proxy.$participateInSave(editorModel.resource, env.reason).then(values => {
if (!values.every(success => success)) {
return Promise.reject(new Error('listener failed'));
@@ -393,7 +386,9 @@ export class SaveParticipant implements ISaveParticipant {
extHostContext: IExtHostContext,
@IInstantiationService instantiationService: IInstantiationService,
@IProgressService private readonly _progressService: IProgressService,
@ILogService private readonly _logService: ILogService
@IStatusbarService private readonly _statusbarService: IStatusbarService,
@ILogService private readonly _logService: ILogService,
@ILabelService private readonly _labelService: ILabelService,
) {
this._saveParticipants = new IdleValue(() => [
instantiationService.createInstance(TrimWhitespaceParticipant),
@@ -415,12 +410,72 @@ export class SaveParticipant implements ISaveParticipant {
}
async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise<void> {
return this._progressService.withProgress({ location: ProgressLocation.Window }, progress => {
progress.report({ message: localize('saveParticipants', "Running Save Participants...") });
const promiseFactory = this._saveParticipants.getValue().map(p => () => {
return p.participate(model, env);
});
return sequence(promiseFactory).then(() => { }, err => this._logService.warn(err));
const cts = new CancellationTokenSource();
return this._progressService.withProgress({
title: localize('saveParticipants', "Running Save Participants for '{0}'", this._labelService.getUriLabel(model.resource, { relative: true })),
location: ProgressLocation.Notification,
cancellable: true,
delay: model.isDirty() ? 3000 : 5000
}, async progress => {
let firstError: SaveParticipantError | undefined;
for (let p of this._saveParticipants.getValue()) {
if (cts.token.isCancellationRequested) {
break;
}
try {
await p.participate(model, env, progress, cts.token);
} catch (err) {
if (!isPromiseCanceledError(err)) {
this._logService.warn(err);
firstError = !firstError && err instanceof SaveParticipantError ? err : firstError;
}
}
}
if (firstError) {
this._showParticipantError(firstError);
}
}, () => {
// user cancel
cts.dispose(true);
});
}
private _showParticipantError(err: SaveParticipantError): void {
let entry: any = {
text: localize('title', "$(error) Save Participants Failed: {0}", err.message)
};
if (err.setting) {
entry.command = '_showSettings';
entry.arguments = [err.setting];
}
const handle = this._statusbarService.addEntry(
entry,
'saveParticipants.error',
localize('status.message', "Save Participants Errors"),
StatusbarAlignment.LEFT,
-Number.MAX_VALUE /* far right on left hand side */
);
setTimeout(() => handle.dispose(), 5000);
}
}
CommandsRegistry.registerCommand('_showSettings', (accessor, ...args: any[]) => {
const [setting] = args;
const control = accessor.get(IEditorService).activeControl as SettingsEditor2;
if (control instanceof SettingsEditor2) {
control.focusSearch(`@tag:usesOnlineServices`);
} else {
accessor.get(IPreferencesService).openSettings(false, setting);
}
});

View File

@@ -621,7 +621,10 @@ export class MainThreadTask implements MainThreadTaskShape {
for (let i = 0; i < partiallyResolvedVars.length; i++) {
const variableName = vars[i].substring(2, vars[i].length - 1);
if (resolvedVars && values.variables[vars[i]] === vars[i]) {
result.variables.set(variableName, resolvedVars.get(variableName));
const resolved = resolvedVars.get(variableName);
if (typeof resolved === 'string') {
result.variables.set(variableName, resolved);
}
} else {
result.variables.set(variableName, partiallyResolvedVars[i]);
}

View File

@@ -343,7 +343,7 @@ class TerminalDataEventTracker extends Disposable {
) {
super();
this._register(this._bufferer = new TerminalDataBufferer());
this._register(this._bufferer = new TerminalDataBufferer(this._callback));
this._terminalService.terminalInstances.forEach(instance => this._registerInstance(instance));
this._register(this._terminalService.onInstanceCreated(instance => this._registerInstance(instance)));
@@ -352,6 +352,6 @@ class TerminalDataEventTracker extends Disposable {
private _registerInstance(instance: ITerminalInstance): void {
// Buffer data events to reduce the amount of messages going to the extension host
this._register(this._bufferer.startBuffering(instance.id, instance.onData, this._callback));
this._register(this._bufferer.startBuffering(instance.id, instance.onData));
}
}

View File

@@ -22,7 +22,7 @@ export class MainThreadTunnelService implements MainThreadTunnelServiceShape {
}
async $openTunnel(tunnelOptions: TunnelOptions): Promise<TunnelDto | undefined> {
const tunnel = await this.remoteExplorerService.forward(tunnelOptions.remoteAddress, tunnelOptions.localPort, tunnelOptions.label);
const tunnel = await this.remoteExplorerService.forward(tunnelOptions.remoteAddress, tunnelOptions.localAddressPort, tunnelOptions.label);
if (tunnel) {
return TunnelDto.fromServiceTunnel(tunnel);
}

View File

@@ -12,6 +12,7 @@ import { URI, UriComponents } from 'vs/base/common/uri';
import * as modes from 'vs/editor/common/modes';
import { localize } from 'vs/nls';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IFileService } from 'vs/platform/files/common/files';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IProductService } from 'vs/platform/product/common/productService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@@ -107,6 +108,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
@IProductService private readonly _productService: IProductService,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
@IWebviewWorkbenchService private readonly _webviewWorkbenchService: IWebviewWorkbenchService,
@IFileService private readonly _fileService: IFileService,
) {
super();
@@ -307,7 +309,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
}
private async retainCustomEditorModel(webviewInput: WebviewInput, resource: URI, viewType: string, capabilities: readonly extHostProtocol.WebviewEditorCapabilities[]) {
const model = await this._customEditorService.models.loadOrCreate(webviewInput.getResource(), webviewInput.viewType);
const model = await this._customEditorService.models.resolve(webviewInput.getResource(), webviewInput.viewType);
const existingEntry = this._customEditorModels.get(model);
if (existingEntry) {
@@ -319,7 +321,8 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
this._customEditorModels.set(model, { referenceCount: 1 });
const capabilitiesSet = new Set(capabilities);
if (capabilitiesSet.has(extHostProtocol.WebviewEditorCapabilities.Editable)) {
const isEditable = capabilitiesSet.has(extHostProtocol.WebviewEditorCapabilities.Editable);
if (isEditable) {
model.onUndo(edits => {
this._proxy.$undoEdits(resource, viewType, edits.map(x => x.data));
});
@@ -335,10 +338,17 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
e.waitUntil(this._proxy.$onSave(resource.toJSON(), viewType));
});
model.onWillSaveAs(e => {
e.waitUntil(this._proxy.$onSaveAs(e.resource.toJSON(), viewType, e.targetResource.toJSON()));
});
}
// Save as should always be implemented even if the model is readonly
model.onWillSaveAs(e => {
if (isEditable) {
e.waitUntil(this._proxy.$onSaveAs(e.resource.toJSON(), viewType, e.targetResource.toJSON()));
} else {
// Since the editor is readonly, just copy the file over
e.waitUntil(this._fileService.copy(e.resource, e.targetResource, false /* overwrite */));
}
});
return model;
}

View File

@@ -36,6 +36,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
export interface IUserFriendlyViewsContainerDescriptor {
id: string;
@@ -332,7 +333,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
viewContainer = this.viewContainersRegistry.registerViewContainer({
id,
name: title, extensionId,
ctorDescriptor: { ctor: CustomViewPaneContainer },
ctorDescriptor: new SyncDescriptor(CustomViewPaneContainer),
hideIfEmpty: true,
icon,
}, ViewContainerLocation.Sidebar);
@@ -416,7 +417,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
const viewDescriptor = <ICustomViewDescriptor>{
id: item.id,
name: item.name,
ctorDescriptor: { ctor: CustomTreeViewPane },
ctorDescriptor: new SyncDescriptor(CustomTreeViewPane),
when: ContextKeyExpr.deserialize(item.when),
canToggleVisibility: true,
collapsed: this.showCollapsed(container),