Merge remote-tracking branch 'origin/master' into rebornix/notebook

This commit is contained in:
rebornix
2020-01-27 10:51:28 -08:00
802 changed files with 29981 additions and 16676 deletions

View File

@@ -60,6 +60,7 @@ import './mainThreadNotebook';
import './mainThreadTask';
import './mainThreadLabelService';
import './mainThreadTunnelService';
import './mainThreadAuthentication';
import 'vs/workbench/api/common/apiCommands';
export class ExtensionPoints implements IWorkbenchContribution {

View File

@@ -0,0 +1,110 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. 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 * as nls from 'vs/nls';
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';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import Severity from 'vs/base/common/severity';
export class MainThreadAuthenticationProvider {
constructor(
private readonly _proxy: ExtHostAuthenticationShape,
public readonly id: string,
public readonly displayName: string
) { }
getSessions(): Promise<ReadonlyArray<modes.Session>> {
return this._proxy.$getSessions(this.id);
}
login(scopes: string[]): Promise<modes.Session> {
return this._proxy.$login(this.id, scopes);
}
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,
@IDialogService private readonly dialogService: IDialogService,
@IStorageService private readonly storageService: IStorageService
) {
super();
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostAuthentication);
}
$registerAuthenticationProvider(id: string, displayName: string): void {
const provider = new MainThreadAuthenticationProvider(this._proxy, id, displayName);
this.authenticationService.registerAuthenticationProvider(id, provider);
}
$unregisterAuthenticationProvider(id: string): void {
this.authenticationService.unregisterAuthenticationProvider(id);
}
$onDidChangeSessions(id: string): void {
this.authenticationService.sessionsUpdate(id);
}
async $getSessionsPrompt(providerId: string, providerName: string, extensionId: string, extensionName: string): Promise<boolean> {
const alwaysAllow = this.storageService.get(`${extensionId}-${providerId}`, StorageScope.GLOBAL);
if (alwaysAllow) {
return true;
}
const { choice } = await this.dialogService.show(
Severity.Info,
nls.localize('confirmAuthenticationAccess', "The extension '{0}' is trying to access authentication information from {1}.", extensionName, providerName),
[nls.localize('cancel', "Cancel"), nls.localize('allow', "Allow"), nls.localize('alwaysAllow', "Always Allow"),],
{ cancelId: 0 }
);
switch (choice) {
case 1/** Allow */:
return true;
case 2 /** Always Allow */:
this.storageService.store(`${extensionId}-${providerId}`, 'true', StorageScope.GLOBAL);
return true;
default:
return false;
}
}
async $loginPrompt(providerId: string, providerName: string, extensionId: string, extensionName: string): Promise<boolean> {
const alwaysAllow = this.storageService.get(`${extensionId}-${providerId}`, StorageScope.GLOBAL);
if (alwaysAllow) {
return true;
}
const { choice } = await this.dialogService.show(
Severity.Info,
nls.localize('confirmLogin', "The extension '{0}' wants to sign in using {1}.", extensionName, providerName),
[nls.localize('cancel', "Cancel"), nls.localize('continue', "Continue"), nls.localize('neverAgain', "Don't Show Again")],
{ cancelId: 0 }
);
switch (choice) {
case 1/** Allow */:
return true;
case 2 /** Always Allow */:
this.storageService.store(`${extensionId}-${providerId}`, 'true', StorageScope.GLOBAL);
return true;
default:
return false;
}
}
}

View File

@@ -83,7 +83,7 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape {
private deriveConfigurationTarget(key: string, overrides: IConfigurationOverrides): ConfigurationTarget {
if (overrides.resource && this._workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE) {
const configurationProperties = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).getConfigurationProperties();
if (configurationProperties[key] && (configurationProperties[key].scope === ConfigurationScope.RESOURCE || configurationProperties[key].scope === ConfigurationScope.RESOURCE_LANGUAGE)) {
if (configurationProperties[key] && (configurationProperties[key].scope === ConfigurationScope.RESOURCE || configurationProperties[key].scope === ConfigurationScope.LANGUAGE_OVERRIDABLE)) {
return ConfigurationTarget.WORKSPACE_FOLDER;
}
}

View File

@@ -54,6 +54,9 @@ export class MainThreadDiagnostics implements MainThreadDiagnosticsShape {
relatedInformation.resource = URI.revive(relatedInformation.resource);
}
}
if (marker.code && typeof marker.code !== 'string') {
marker.code.link = URI.revive(marker.code.link);
}
}
}
this._markerService.changeOne(owner, URI.revive(uri), markers);

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);
}
@@ -171,7 +160,7 @@ export class MainThreadDocuments implements MainThreadDocumentsShape {
// --- from extension host process
$trySaveDocument(uri: UriComponents): Promise<boolean> {
return this._textFileService.save(URI.revive(uri));
return this._textFileService.save(URI.revive(uri)).then(target => !!target);
}
$tryOpenDocument(_uri: UriComponents): Promise<any> {
@@ -222,17 +211,16 @@ 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.createOrGet({
resource,
private _doCreateUntitled(associatedResource?: URI, mode?: string, initialValue?: string): Promise<URI> {
return this._textFileService.untitled.resolve({
associatedResource,
mode,
initialValue,
useResourcePath: Boolean(resource && resource.path)
}).resolve().then(model => {
initialValue
}).then(model => {
const resource = model.resource;
if (!this._modelIsSynced.has(resource.toString())) {

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

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

View File

@@ -12,7 +12,7 @@ import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensio
import { INotificationService } from 'vs/platform/notification/common/notification';
import { localize } from 'vs/nls';
import { Action } from 'vs/base/common/actions';
import { IExtensionEnablementService, EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { IWorkbenchExtensionEnablementService, EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions';
@@ -27,7 +27,7 @@ export class MainThreadExtensionService implements MainThreadExtensionServiceSha
private readonly _notificationService: INotificationService;
private readonly _extensionsWorkbenchService: IExtensionsWorkbenchService;
private readonly _hostService: IHostService;
private readonly _extensionEnablementService: IExtensionEnablementService;
private readonly _extensionEnablementService: IWorkbenchExtensionEnablementService;
constructor(
extHostContext: IExtHostContext,
@@ -35,7 +35,7 @@ export class MainThreadExtensionService implements MainThreadExtensionServiceSha
@INotificationService notificationService: INotificationService,
@IExtensionsWorkbenchService extensionsWorkbenchService: IExtensionsWorkbenchService,
@IHostService hostService: IHostService,
@IExtensionEnablementService extensionEnablementService: IExtensionEnablementService
@IWorkbenchExtensionEnablementService extensionEnablementService: IWorkbenchExtensionEnablementService
) {
this._extensionService = extensionService;
this._notificationService = notificationService;

View File

@@ -11,7 +11,7 @@ import * as search from 'vs/workbench/contrib/search/common/search';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Position as EditorPosition } from 'vs/editor/common/core/position';
import { Range as EditorRange, IRange } from 'vs/editor/common/core/range';
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ILanguageConfigurationDto, IRegExpDto, IIndentationRuleDto, IOnEnterRuleDto, ILocationDto, IWorkspaceSymbolDto, reviveWorkspaceEditDto, IDocumentFilterDto, IDefinitionLinkDto, ISignatureHelpProviderMetadataDto, ILinkDto, ICallHierarchyItemDto, ISuggestDataDto, ICodeActionDto, ISuggestDataDtoField } from '../common/extHost.protocol';
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ILanguageConfigurationDto, IRegExpDto, IIndentationRuleDto, IOnEnterRuleDto, ILocationDto, IWorkspaceSymbolDto, reviveWorkspaceEditDto, IDocumentFilterDto, IDefinitionLinkDto, ISignatureHelpProviderMetadataDto, ILinkDto, ICallHierarchyItemDto, ISuggestDataDto, ICodeActionDto, ISuggestDataDtoField, ISuggestResultDtoField } from '../common/extHost.protocol';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { LanguageConfiguration, IndentationRule, OnEnterRule } from 'vs/editor/common/modes/languageConfiguration';
import { IModeService } from 'vs/editor/common/services/modeService';
@@ -316,7 +316,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
$registerRenameSupport(handle: number, selector: IDocumentFilterDto[], supportResolveLocation: boolean): void {
this._registrations.set(handle, modes.RenameProviderRegistry.register(selector, <modes.RenameProvider>{
provideRenameEdits: (model: ITextModel, position: EditorPosition, newName: string, token: CancellationToken): Promise<modes.WorkspaceEdit> => {
provideRenameEdits: (model: ITextModel, position: EditorPosition, newName: string, token: CancellationToken) => {
return this._proxy.$provideRenameEdits(handle, model.uri, position, newName, token).then(reviveWorkspaceEditDto);
},
resolveRenameLocation: supportResolveLocation
@@ -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
@@ -336,7 +340,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
private static _inflateSuggestDto(defaultRange: IRange | { insert: IRange, replace: IRange }, data: ISuggestDataDto): modes.CompletionItem {
return {
label: data[ISuggestDataDtoField.label],
label: data[ISuggestDataDtoField.label2] || data[ISuggestDataDtoField.label],
kind: data[ISuggestDataDtoField.kind],
tags: data[ISuggestDataDtoField.kindModifier],
detail: data[ISuggestDataDtoField.detail],
@@ -364,10 +368,15 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
if (!result) {
return result;
}
return {
suggestions: result.b.map(d => MainThreadLanguageFeatures._inflateSuggestDto(result.a, d)),
incomplete: result.c,
dispose: () => typeof result.x === 'number' && this._proxy.$releaseCompletionItems(handle, result.x)
suggestions: result[ISuggestResultDtoField.completions].map(d => MainThreadLanguageFeatures._inflateSuggestDto(result[ISuggestResultDtoField.defaultRanges], d)),
incomplete: result[ISuggestResultDtoField.isIncomplete] || false,
dispose: () => {
if (typeof result.x === 'number') {
this._proxy.$releaseCompletionItems(handle, result.x);
}
}
};
});
}
@@ -606,7 +615,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
}
export class MainThreadSemanticTokensProvider implements modes.SemanticTokensProvider {
export class MainThreadDocumentSemanticTokensProvider implements modes.DocumentSemanticTokensProvider {
constructor(
private readonly _proxy: ExtHostLanguageFeaturesShape,
@@ -615,9 +624,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));
}
}
@@ -625,9 +634,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;
}
@@ -647,3 +656,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

@@ -8,6 +8,7 @@ import { ExtHostContext, MainThreadQuickOpenShape, ExtHostQuickOpenShape, Transf
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { URI } from 'vs/base/common/uri';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
interface QuickInputSession {
input: IQuickInput;
@@ -185,14 +186,22 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
return this._quickInputService.backButton;
}
const { iconPath, tooltip, handle } = button;
return {
iconPath: iconPath && {
dark: URI.revive(iconPath.dark),
light: iconPath.light && URI.revive(iconPath.light)
},
tooltip,
handle
};
if ('id' in iconPath) {
return {
iconClass: ThemeIcon.asClassName(iconPath),
tooltip,
handle
};
} else {
return {
iconPath: {
dark: URI.revive(iconPath.dark),
light: iconPath.light && URI.revive(iconPath.light)
},
tooltip,
handle
};
}
});
} else {
(input as any)[param] = params[param];

View File

@@ -7,7 +7,6 @@ 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,33 +22,25 @@ 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, CommandsRegistry } 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, 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 } from 'vs/workbench/services/textfile/common/textfiles';
import { ISaveParticipant, IResolvedTextFileEditorModel, ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { SaveReason } from 'vs/workbench/common/editor';
import { ExtHostContext, ExtHostDocumentSaveParticipantShape, IExtHostContext } from '../common/extHost.protocol';
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';
import { canceled } from 'vs/base/common/errors';
export interface ICodeActionsOnSaveOptions {
[kind: string]: boolean;
}
class SaveParticipantError extends Error {
constructor(message: string, readonly setting?: string) {
super(message);
}
}
export interface ISaveParticipantParticipant {
participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason }, progress: IProgress<IProgressStep>, token: CancellationToken): Promise<void>;
}
@@ -247,8 +238,6 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant {
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,
) { }
@@ -308,13 +297,13 @@ class CodeActionOnSaveParticipant implements ISaveParticipantParticipant {
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);
}
@@ -341,7 +330,7 @@ class ExtHostSaveParticipant implements ISaveParticipantParticipant {
token.onCancellationRequested(() => reject(canceled()));
setTimeout(
() => reject(new SaveParticipantError(localize('timeout.onWillSave', "Aborted onWillSaveTextDocument-event after 1750ms"))),
() => reject(new Error(localize('timeout.onWillSave', "Aborted onWillSaveTextDocument-event after 1750ms"))),
1750
);
this._proxy.$participateInSave(editorModel.resource, env.reason).then(values => {
@@ -364,9 +353,9 @@ export class SaveParticipant implements ISaveParticipant {
extHostContext: IExtHostContext,
@IInstantiationService instantiationService: IInstantiationService,
@IProgressService private readonly _progressService: IProgressService,
@IStatusbarService private readonly _statusbarService: IStatusbarService,
@ILogService private readonly _logService: ILogService,
@ILabelService private readonly _labelService: ILabelService,
@ITextFileService private readonly _textFileService: ITextFileService
) {
this._saveParticipants = new IdleValue(() => [
instantiationService.createInstance(TrimWhitespaceParticipant),
@@ -376,12 +365,12 @@ export class SaveParticipant implements ISaveParticipant {
instantiationService.createInstance(TrimFinalNewLinesParticipant),
instantiationService.createInstance(ExtHostSaveParticipant, extHostContext),
]);
// Hook into model
TextFileEditorModel.setSaveParticipant(this);
// Set as save participant for all text files
this._textFileService.saveParticipant = this;
}
dispose(): void {
TextFileEditorModel.setSaveParticipant(null);
this._textFileService.saveParticipant = undefined;
this._saveParticipants.dispose();
}
@@ -396,54 +385,23 @@ export class SaveParticipant implements ISaveParticipant {
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;
}
this._logService.warn(err);
}
}
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[]) => {

View File

@@ -8,9 +8,11 @@ import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { IRemoteExplorerService } from 'vs/workbench/services/remote/common/remoteExplorerService';
import { ITunnelProvider, ITunnelService, TunnelOptions } from 'vs/platform/remote/common/tunnel';
import { Disposable } from 'vs/base/common/lifecycle';
import type { TunnelDescription } from 'vs/platform/remote/common/remoteAuthorityResolver';
@extHostNamedCustomer(MainContext.MainThreadTunnelService)
export class MainThreadTunnelService implements MainThreadTunnelServiceShape {
export class MainThreadTunnelService extends Disposable implements MainThreadTunnelServiceShape {
private readonly _proxy: ExtHostTunnelServiceShape;
constructor(
@@ -18,7 +20,10 @@ export class MainThreadTunnelService implements MainThreadTunnelServiceShape {
@IRemoteExplorerService private readonly remoteExplorerService: IRemoteExplorerService,
@ITunnelService private readonly tunnelService: ITunnelService
) {
super();
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTunnelService);
this._register(tunnelService.onTunnelOpened(() => this._proxy.$onDidTunnelsChange()));
this._register(tunnelService.onTunnelClosed(() => this._proxy.$onDidTunnelsChange()));
}
async $openTunnel(tunnelOptions: TunnelOptions): Promise<TunnelDto | undefined> {
@@ -33,6 +38,15 @@ export class MainThreadTunnelService implements MainThreadTunnelServiceShape {
return this.remoteExplorerService.close(remote);
}
async $getTunnels(): Promise<TunnelDescription[]> {
return (await this.tunnelService.tunnels).map(tunnel => {
return {
remoteAddress: { port: tunnel.tunnelRemotePort, host: tunnel.tunnelRemoteHost },
localAddress: tunnel.localAddress
};
});
}
async $registerCandidateFinder(): Promise<void> {
this.remoteExplorerService.registerCandidateFinder(() => this._proxy.$findCandidatePorts());
}
@@ -59,7 +73,23 @@ export class MainThreadTunnelService implements MainThreadTunnelServiceShape {
this.tunnelService.setTunnelProvider(tunnelProvider);
}
async $setCandidateFilter(): Promise<void> {
this._register(this.remoteExplorerService.setCandidateFilter(async (candidates: { host: string, port: number, detail: string }[]): Promise<{ host: string, port: number, detail: string }[]> => {
const filters: boolean[] = await this._proxy.$filterCandidates(candidates);
const filteredCandidates: { host: string, port: number, detail: string }[] = [];
if (filters.length !== candidates.length) {
return candidates;
}
for (let i = 0; i < candidates.length; i++) {
if (filters[i]) {
filteredCandidates.push(candidates[i]);
}
}
return filteredCandidates;
}));
}
dispose(): void {
//
}
}

View File

@@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createCancelablePromise } from 'vs/base/common/async';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import { Schemas } from 'vs/base/common/network';
@@ -12,6 +13,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 +109,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();
@@ -304,10 +307,12 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
provider.dispose();
this._editorProviders.delete(viewType);
this._customEditorService.models.disposeAllModelsForView(viewType);
}
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,26 +324,44 @@ 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)) {
model.onUndo(edits => {
this._proxy.$undoEdits(resource, viewType, edits.map(x => x.data));
const isEditable = capabilitiesSet.has(extHostProtocol.WebviewEditorCapabilities.Editable);
if (isEditable) {
model.onUndo(e => {
this._proxy.$undoEdits(resource, viewType, e.edits);
});
model.onApplyEdit(edits => {
const editsToApply = edits.filter(x => x.source !== model).map(x => x.data);
if (editsToApply.length) {
this._proxy.$applyEdits(resource, viewType, editsToApply);
model.onDisposeEdits(e => {
this._proxy.$disposeEdits(e.edits);
});
model.onApplyEdit(e => {
if (e.trigger !== model) {
this._proxy.$applyEdits(resource, viewType, e.edits);
}
});
model.onWillSave(e => {
e.waitUntil(this._proxy.$onSave(resource.toJSON(), viewType));
});
}
model.onWillSaveAs(e => {
// 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 */));
}
});
if (capabilitiesSet.has(extHostProtocol.WebviewEditorCapabilities.SupportsHotExit)) {
model.onBackup(() => {
return createCancelablePromise(token =>
this._proxy.$backup(model.resource.toJSON(), viewType, token));
});
}
return model;
}
@@ -355,13 +378,13 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
}
}
public $onEdit(resource: UriComponents, viewType: string, editData: any): void {
public $onEdit(resource: UriComponents, viewType: string, editId: number): void {
const model = this._customEditorService.models.get(URI.revive(resource), viewType);
if (!model) {
throw new Error('Could not find model for webview editor');
}
model.pushEdit({ source: model, data: editData });
model.pushEdit(editId, model);
}
private hookupWebviewEventDelegate(handle: extHostProtocol.WebviewPanelHandle, input: WebviewInput) {

View File

@@ -23,19 +23,13 @@ import { VIEWLET_ID as REMOTE } from 'vs/workbench/contrib/remote/common/remote.
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { URI } from 'vs/base/common/uri';
import { ViewletRegistry, Extensions as ViewletExtensions, ShowViewletAction } from 'vs/workbench/browser/viewlet';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
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;
@@ -312,27 +306,13 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
if (!viewContainer) {
class CustomViewPaneContainer extends ViewPaneContainer {
constructor(
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@ITelemetryService telemetryService: ITelemetryService,
@IWorkspaceContextService protected contextService: IWorkspaceContextService,
@IStorageService protected storageService: IStorageService,
@IConfigurationService configurationService: IConfigurationService,
@IInstantiationService protected instantiationService: IInstantiationService,
@IThemeService themeService: IThemeService,
@IContextMenuService contextMenuService: IContextMenuService,
@IExtensionService extensionService: IExtensionService,
) {
super(id, `${id}.state`, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService);
}
}
viewContainer = this.viewContainersRegistry.registerViewContainer({
id,
name: title, extensionId,
ctorDescriptor: { ctor: CustomViewPaneContainer },
ctorDescriptor: new SyncDescriptor(
ViewPaneContainer,
[id, `${id}.state`, { mergeViewWithContainerWhenSingleView: true }]
),
hideIfEmpty: true,
icon,
}, ViewContainerLocation.Sidebar);
@@ -416,11 +396,12 @@ 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,
canMoveView: true,
treeView: this.instantiationService.createInstance(CustomTreeView, item.id, item.name),
collapsed: this.showCollapsed(container),
treeView: this.instantiationService.createInstance(CustomTreeView, item.id, item.name, container),
order: order,
extensionId: extension.description.identifier,
originalContainerId: entry.key,