mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-04 09:35:38 -05:00
Merge from vscode a234f13c45b40a0929777cb440ee011b7549eed2 (#8911)
* Merge from vscode a234f13c45b40a0929777cb440ee011b7549eed2 * update distro * fix layering * update distro * fix tests
This commit is contained in:
@@ -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 {
|
||||
|
||||
55
src/vs/workbench/api/browser/mainThreadAuthentication.ts
Normal file
55
src/vs/workbench/api/browser/mainThreadAuthentication.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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}`);
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user