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

@@ -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);
}
});