mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-04 17:23:45 -05:00
Merge from vscode a234f13c45b40a0929777cb440ee011b7549eed2 (#8911)
* Merge from vscode a234f13c45b40a0929777cb440ee011b7549eed2 * update distro * fix layering * update distro * fix tests
This commit is contained in:
@@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user