mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-10 10:12:34 -05:00
Merge from vscode 52dcb723a39ae75bee1bd56b3312d7fcdc87aeed (#6719)
This commit is contained in:
@@ -21,7 +21,7 @@ class EditorWebviewZone implements IViewZone {
|
||||
readonly afterColumn: number;
|
||||
readonly heightInLines: number;
|
||||
|
||||
private _id: number;
|
||||
private _id?: number;
|
||||
// suppressMouseDown?: boolean | undefined;
|
||||
// heightInPx?: number | undefined;
|
||||
// minWidthInPx?: number | undefined;
|
||||
@@ -46,7 +46,7 @@ class EditorWebviewZone implements IViewZone {
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.editor.changeViewZones(accessor => accessor.removeZone(this._id));
|
||||
this.editor.changeViewZones(accessor => this._id && accessor.removeZone(this._id));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,10 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { Extensions as PanelExtensions, PanelDescriptor, PanelRegistry } from 'vs/workbench/browser/panel';
|
||||
import { ICommentInfo, ICommentService } from 'vs/workbench/contrib/comments/browser/commentService';
|
||||
import { CommentsPanel, COMMENTS_PANEL_ID, COMMENTS_PANEL_TITLE } from 'vs/workbench/contrib/comments/browser/commentsPanel';
|
||||
import { CommentsPanel } from 'vs/workbench/contrib/comments/browser/commentsPanel';
|
||||
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
|
||||
import { CommentProviderFeatures, ExtHostCommentsShape, ExtHostContext, IExtHostContext, MainContext, MainThreadCommentsShape } from '../common/extHost.protocol';
|
||||
import { COMMENTS_PANEL_ID, COMMENTS_PANEL_TITLE } from 'vs/workbench/contrib/comments/browser/commentsTreeViewer';
|
||||
|
||||
|
||||
export class MainThreadCommentThread implements modes.CommentThread {
|
||||
@@ -35,13 +36,13 @@ export class MainThreadCommentThread implements modes.CommentThread {
|
||||
private _onDidChangeInput = new Emitter<modes.CommentInput | undefined>();
|
||||
get onDidChangeInput(): Event<modes.CommentInput | undefined> { return this._onDidChangeInput.event; }
|
||||
|
||||
private _label: string;
|
||||
private _label: string | undefined;
|
||||
|
||||
get label(): string {
|
||||
get label(): string | undefined {
|
||||
return this._label;
|
||||
}
|
||||
|
||||
set label(label: string) {
|
||||
set label(label: string | undefined) {
|
||||
this._label = label;
|
||||
this._onDidChangeLabel.fire(this._label);
|
||||
}
|
||||
@@ -56,8 +57,8 @@ export class MainThreadCommentThread implements modes.CommentThread {
|
||||
this._contextValue = context;
|
||||
}
|
||||
|
||||
private _onDidChangeLabel = new Emitter<string>();
|
||||
readonly onDidChangeLabel: Event<string> = this._onDidChangeLabel.event;
|
||||
private _onDidChangeLabel = new Emitter<string | undefined>();
|
||||
readonly onDidChangeLabel: Event<string | undefined> = this._onDidChangeLabel.event;
|
||||
|
||||
private _comments: modes.Comment[] | undefined;
|
||||
|
||||
@@ -348,7 +349,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments
|
||||
private _activeCommentThread?: MainThreadCommentThread;
|
||||
private readonly _activeCommentThreadDisposables = this._register(new DisposableStore());
|
||||
|
||||
private _openPanelListener: IDisposable | null;
|
||||
private _openPanelListener: IDisposable | null = null;
|
||||
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -153,13 +153,13 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
|
||||
type: debugType
|
||||
};
|
||||
if (hasProvide) {
|
||||
provider.provideDebugConfigurations = (folder) => {
|
||||
return this._proxy.$provideDebugConfigurations(handle, folder);
|
||||
provider.provideDebugConfigurations = (folder, token) => {
|
||||
return this._proxy.$provideDebugConfigurations(handle, folder, token);
|
||||
};
|
||||
}
|
||||
if (hasResolve) {
|
||||
provider.resolveDebugConfiguration = (folder, config) => {
|
||||
return this._proxy.$resolveDebugConfiguration(handle, folder, config);
|
||||
provider.resolveDebugConfiguration = (folder, config, token) => {
|
||||
return this._proxy.$resolveDebugConfiguration(handle, folder, config, token);
|
||||
};
|
||||
}
|
||||
if (hasProvideDebugAdapter) {
|
||||
|
||||
@@ -109,7 +109,7 @@ class DocumentAndEditorStateDelta {
|
||||
|
||||
class DocumentAndEditorState {
|
||||
|
||||
static compute(before: DocumentAndEditorState, after: DocumentAndEditorState): DocumentAndEditorStateDelta {
|
||||
static compute(before: DocumentAndEditorState | undefined, after: DocumentAndEditorState): DocumentAndEditorStateDelta {
|
||||
if (!before) {
|
||||
return new DocumentAndEditorStateDelta(
|
||||
[], values(after.documents),
|
||||
@@ -146,7 +146,7 @@ class MainThreadDocumentAndEditorStateComputer {
|
||||
|
||||
private readonly _toDispose = new DisposableStore();
|
||||
private _toDisposeOnEditorRemove = new Map<string, IDisposable>();
|
||||
private _currentState: DocumentAndEditorState;
|
||||
private _currentState?: DocumentAndEditorState;
|
||||
private _activeEditorOrder: ActiveEditorOrder = ActiveEditorOrder.Editor;
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -178,7 +178,7 @@ export class MainThreadTextEditor {
|
||||
private readonly _focusTracker: IFocusTracker;
|
||||
private readonly _codeEditorListeners = new DisposableStore();
|
||||
|
||||
private _properties: MainThreadTextEditorProperties;
|
||||
private _properties: MainThreadTextEditorProperties | null;
|
||||
private readonly _onPropertiesChanged: Emitter<IEditorPropertiesChangeData>;
|
||||
|
||||
constructor(
|
||||
@@ -191,6 +191,7 @@ export class MainThreadTextEditor {
|
||||
this._id = id;
|
||||
this._model = model;
|
||||
this._codeEditor = null;
|
||||
this._properties = null;
|
||||
this._focusTracker = focusTracker;
|
||||
this._modelService = modelService;
|
||||
|
||||
@@ -289,7 +290,7 @@ export class MainThreadTextEditor {
|
||||
}
|
||||
|
||||
public getProperties(): MainThreadTextEditorProperties {
|
||||
return this._properties;
|
||||
return this._properties!;
|
||||
}
|
||||
|
||||
public get onPropertiesChanged(): Event<IEditorPropertiesChangeData> {
|
||||
@@ -304,7 +305,7 @@ export class MainThreadTextEditor {
|
||||
|
||||
const newSelections = selections.map(Selection.liftSelection);
|
||||
this._setProperties(
|
||||
new MainThreadTextEditorProperties(newSelections, this._properties.options, this._properties.visibleRanges),
|
||||
new MainThreadTextEditorProperties(newSelections, this._properties!.options, this._properties!.visibleRanges),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { MainThreadDocumentsAndEditors } from 'vs/workbench/api/browser/mainThreadDocumentsAndEditors';
|
||||
import { MainThreadTextEditor } from 'vs/workbench/api/browser/mainThreadEditor';
|
||||
import { ExtHostContext, ExtHostEditorsShape, IApplyEditsOptions, IExtHostContext, ITextDocumentShowOptions, ITextEditorConfigurationUpdate, ITextEditorPositionData, IUndoStopOptions, MainThreadTextEditorsShape, TextEditorRevealType, WorkspaceEditDto, reviveWorkspaceEditDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostContext, ExtHostEditorsShape, IApplyEditsOptions, IExtHostContext, ITextDocumentShowOptions, ITextEditorConfigurationUpdate, ITextEditorPositionData, IUndoStopOptions, MainThreadTextEditorsShape, TextEditorRevealType, IWorkspaceEditDto, reviveWorkspaceEditDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { EditorViewColumn, editorGroupToViewColumn, viewColumnToEditorGroup } from 'vs/workbench/api/common/shared/editor';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
@@ -212,7 +212,7 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
|
||||
return Promise.resolve(editor.applyEdits(modelVersionId, edits, opts));
|
||||
}
|
||||
|
||||
$tryApplyWorkspaceEdit(dto: WorkspaceEditDto): Promise<boolean> {
|
||||
$tryApplyWorkspaceEdit(dto: IWorkspaceEditDto): Promise<boolean> {
|
||||
const { edits } = reviveWorkspaceEditDto(dto);
|
||||
return this._bulkEditService.apply({ edits }, undefined).then(() => true, err => false);
|
||||
}
|
||||
|
||||
@@ -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, ISerializedLanguageConfiguration, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, LocationDto, WorkspaceSymbolDto, reviveWorkspaceEditDto, ISerializedDocumentFilter, DefinitionLinkDto, ISerializedSignatureHelpProviderMetadata, LinkDto, CallHierarchyDto, SuggestDataDto, CodeActionDto } from '../common/extHost.protocol';
|
||||
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ILanguageConfigurationDto, IRegExpDto, IIndentationRuleDto, IOnEnterRuleDto, ILocationDto, IWorkspaceSymbolDto, reviveWorkspaceEditDto, IDocumentFilterDto, IDefinitionLinkDto, ISignatureHelpProviderMetadataDto, ILinkDto, ICallHierarchyDto, ISuggestDataDto, ICodeActionDto } 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';
|
||||
@@ -54,9 +54,9 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
//#region --- revive functions
|
||||
|
||||
private static _reviveLocationDto(data: LocationDto): modes.Location;
|
||||
private static _reviveLocationDto(data: LocationDto[]): modes.Location[];
|
||||
private static _reviveLocationDto(data: LocationDto | LocationDto[]): modes.Location | modes.Location[] {
|
||||
private static _reviveLocationDto(data: ILocationDto): modes.Location;
|
||||
private static _reviveLocationDto(data: ILocationDto[]): modes.Location[];
|
||||
private static _reviveLocationDto(data: ILocationDto | ILocationDto[]): modes.Location | modes.Location[] {
|
||||
if (!data) {
|
||||
return <modes.Location>data;
|
||||
} else if (Array.isArray(data)) {
|
||||
@@ -68,9 +68,9 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
}
|
||||
}
|
||||
|
||||
private static _reviveLocationLinkDto(data: DefinitionLinkDto): modes.LocationLink;
|
||||
private static _reviveLocationLinkDto(data: DefinitionLinkDto[]): modes.LocationLink[];
|
||||
private static _reviveLocationLinkDto(data: DefinitionLinkDto | DefinitionLinkDto[]): modes.LocationLink | modes.LocationLink[] {
|
||||
private static _reviveLocationLinkDto(data: IDefinitionLinkDto): modes.LocationLink;
|
||||
private static _reviveLocationLinkDto(data: IDefinitionLinkDto[]): modes.LocationLink[];
|
||||
private static _reviveLocationLinkDto(data: IDefinitionLinkDto | IDefinitionLinkDto[]): modes.LocationLink | modes.LocationLink[] {
|
||||
if (!data) {
|
||||
return <modes.LocationLink>data;
|
||||
} else if (Array.isArray(data)) {
|
||||
@@ -82,10 +82,10 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
}
|
||||
}
|
||||
|
||||
private static _reviveWorkspaceSymbolDto(data: WorkspaceSymbolDto): search.IWorkspaceSymbol;
|
||||
private static _reviveWorkspaceSymbolDto(data: WorkspaceSymbolDto[]): search.IWorkspaceSymbol[];
|
||||
private static _reviveWorkspaceSymbolDto(data: IWorkspaceSymbolDto): search.IWorkspaceSymbol;
|
||||
private static _reviveWorkspaceSymbolDto(data: IWorkspaceSymbolDto[]): search.IWorkspaceSymbol[];
|
||||
private static _reviveWorkspaceSymbolDto(data: undefined): undefined;
|
||||
private static _reviveWorkspaceSymbolDto(data: WorkspaceSymbolDto | WorkspaceSymbolDto[] | undefined): search.IWorkspaceSymbol | search.IWorkspaceSymbol[] | undefined {
|
||||
private static _reviveWorkspaceSymbolDto(data: IWorkspaceSymbolDto | IWorkspaceSymbolDto[] | undefined): search.IWorkspaceSymbol | search.IWorkspaceSymbol[] | undefined {
|
||||
if (!data) {
|
||||
return <undefined>data;
|
||||
} else if (Array.isArray(data)) {
|
||||
@@ -97,21 +97,21 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
}
|
||||
}
|
||||
|
||||
private static _reviveCodeActionDto(data: ReadonlyArray<CodeActionDto>): modes.CodeAction[] {
|
||||
private static _reviveCodeActionDto(data: ReadonlyArray<ICodeActionDto>): modes.CodeAction[] {
|
||||
if (data) {
|
||||
data.forEach(code => reviveWorkspaceEditDto(code.edit));
|
||||
}
|
||||
return <modes.CodeAction[]>data;
|
||||
}
|
||||
|
||||
private static _reviveLinkDTO(data: LinkDto): modes.ILink {
|
||||
private static _reviveLinkDTO(data: ILinkDto): modes.ILink {
|
||||
if (data.url && typeof data.url !== 'string') {
|
||||
data.url = URI.revive(data.url);
|
||||
}
|
||||
return <modes.ILink>data;
|
||||
}
|
||||
|
||||
private static _reviveCallHierarchyItemDto(data: CallHierarchyDto | undefined): callh.CallHierarchyItem {
|
||||
private static _reviveCallHierarchyItemDto(data: ICallHierarchyDto | undefined): callh.CallHierarchyItem {
|
||||
if (data) {
|
||||
data.uri = URI.revive(data.uri);
|
||||
}
|
||||
@@ -122,7 +122,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- outline
|
||||
|
||||
$registerDocumentSymbolProvider(handle: number, selector: ISerializedDocumentFilter[], displayName: string): void {
|
||||
$registerDocumentSymbolProvider(handle: number, selector: IDocumentFilterDto[], displayName: string): void {
|
||||
this._registrations.set(handle, modes.DocumentSymbolProviderRegistry.register(selector, <modes.DocumentSymbolProvider>{
|
||||
displayName,
|
||||
provideDocumentSymbols: (model: ITextModel, token: CancellationToken): Promise<modes.DocumentSymbol[] | undefined> => {
|
||||
@@ -133,7 +133,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- code lens
|
||||
|
||||
$registerCodeLensSupport(handle: number, selector: ISerializedDocumentFilter[], eventHandle: number | undefined): void {
|
||||
$registerCodeLensSupport(handle: number, selector: IDocumentFilterDto[], eventHandle: number | undefined): void {
|
||||
|
||||
const provider = <modes.CodeLensProvider>{
|
||||
provideCodeLenses: (model: ITextModel, token: CancellationToken): Promise<modes.CodeLensList | undefined> => {
|
||||
@@ -170,7 +170,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- declaration
|
||||
|
||||
$registerDefinitionSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
|
||||
$registerDefinitionSupport(handle: number, selector: IDocumentFilterDto[]): void {
|
||||
this._registrations.set(handle, modes.DefinitionProviderRegistry.register(selector, <modes.DefinitionProvider>{
|
||||
provideDefinition: (model, position, token): Promise<modes.LocationLink[]> => {
|
||||
return this._proxy.$provideDefinition(handle, model.uri, position, token).then(MainThreadLanguageFeatures._reviveLocationLinkDto);
|
||||
@@ -178,7 +178,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
}));
|
||||
}
|
||||
|
||||
$registerDeclarationSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
|
||||
$registerDeclarationSupport(handle: number, selector: IDocumentFilterDto[]): void {
|
||||
this._registrations.set(handle, modes.DeclarationProviderRegistry.register(selector, <modes.DeclarationProvider>{
|
||||
provideDeclaration: (model, position, token) => {
|
||||
return this._proxy.$provideDeclaration(handle, model.uri, position, token).then(MainThreadLanguageFeatures._reviveLocationLinkDto);
|
||||
@@ -186,7 +186,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
}));
|
||||
}
|
||||
|
||||
$registerImplementationSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
|
||||
$registerImplementationSupport(handle: number, selector: IDocumentFilterDto[]): void {
|
||||
this._registrations.set(handle, modes.ImplementationProviderRegistry.register(selector, <modes.ImplementationProvider>{
|
||||
provideImplementation: (model, position, token): Promise<modes.LocationLink[]> => {
|
||||
return this._proxy.$provideImplementation(handle, model.uri, position, token).then(MainThreadLanguageFeatures._reviveLocationLinkDto);
|
||||
@@ -194,7 +194,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
}));
|
||||
}
|
||||
|
||||
$registerTypeDefinitionSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
|
||||
$registerTypeDefinitionSupport(handle: number, selector: IDocumentFilterDto[]): void {
|
||||
this._registrations.set(handle, modes.TypeDefinitionProviderRegistry.register(selector, <modes.TypeDefinitionProvider>{
|
||||
provideTypeDefinition: (model, position, token): Promise<modes.LocationLink[]> => {
|
||||
return this._proxy.$provideTypeDefinition(handle, model.uri, position, token).then(MainThreadLanguageFeatures._reviveLocationLinkDto);
|
||||
@@ -204,7 +204,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- extra info
|
||||
|
||||
$registerHoverProvider(handle: number, selector: ISerializedDocumentFilter[]): void {
|
||||
$registerHoverProvider(handle: number, selector: IDocumentFilterDto[]): void {
|
||||
this._registrations.set(handle, modes.HoverProviderRegistry.register(selector, <modes.HoverProvider>{
|
||||
provideHover: (model: ITextModel, position: EditorPosition, token: CancellationToken): Promise<modes.Hover | undefined> => {
|
||||
return this._proxy.$provideHover(handle, model.uri, position, token);
|
||||
@@ -214,7 +214,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- occurrences
|
||||
|
||||
$registerDocumentHighlightProvider(handle: number, selector: ISerializedDocumentFilter[]): void {
|
||||
$registerDocumentHighlightProvider(handle: number, selector: IDocumentFilterDto[]): void {
|
||||
this._registrations.set(handle, modes.DocumentHighlightProviderRegistry.register(selector, <modes.DocumentHighlightProvider>{
|
||||
provideDocumentHighlights: (model: ITextModel, position: EditorPosition, token: CancellationToken): Promise<modes.DocumentHighlight[] | undefined> => {
|
||||
return this._proxy.$provideDocumentHighlights(handle, model.uri, position, token);
|
||||
@@ -224,7 +224,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- references
|
||||
|
||||
$registerReferenceSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
|
||||
$registerReferenceSupport(handle: number, selector: IDocumentFilterDto[]): void {
|
||||
this._registrations.set(handle, modes.ReferenceProviderRegistry.register(selector, <modes.ReferenceProvider>{
|
||||
provideReferences: (model: ITextModel, position: EditorPosition, context: modes.ReferenceContext, token: CancellationToken): Promise<modes.Location[]> => {
|
||||
return this._proxy.$provideReferences(handle, model.uri, position, context, token).then(MainThreadLanguageFeatures._reviveLocationDto);
|
||||
@@ -234,7 +234,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- quick fix
|
||||
|
||||
$registerQuickFixSupport(handle: number, selector: ISerializedDocumentFilter[], providedCodeActionKinds?: string[]): void {
|
||||
$registerQuickFixSupport(handle: number, selector: IDocumentFilterDto[], providedCodeActionKinds?: string[]): void {
|
||||
this._registrations.set(handle, modes.CodeActionProviderRegistry.register(selector, <modes.CodeActionProvider>{
|
||||
provideCodeActions: async (model: ITextModel, rangeOrSelection: EditorRange | Selection, context: modes.CodeActionContext, token: CancellationToken): Promise<modes.CodeActionList | undefined> => {
|
||||
const listDto = await this._proxy.$provideCodeActions(handle, model.uri, rangeOrSelection, context, token);
|
||||
@@ -256,7 +256,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- formatting
|
||||
|
||||
$registerDocumentFormattingSupport(handle: number, selector: ISerializedDocumentFilter[], extensionId: ExtensionIdentifier, displayName: string): void {
|
||||
$registerDocumentFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void {
|
||||
this._registrations.set(handle, modes.DocumentFormattingEditProviderRegistry.register(selector, <modes.DocumentFormattingEditProvider>{
|
||||
extensionId,
|
||||
displayName,
|
||||
@@ -266,7 +266,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
}));
|
||||
}
|
||||
|
||||
$registerRangeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[], extensionId: ExtensionIdentifier, displayName: string): void {
|
||||
$registerRangeFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void {
|
||||
this._registrations.set(handle, modes.DocumentRangeFormattingEditProviderRegistry.register(selector, <modes.DocumentRangeFormattingEditProvider>{
|
||||
extensionId,
|
||||
displayName,
|
||||
@@ -276,7 +276,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
}));
|
||||
}
|
||||
|
||||
$registerOnTypeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[], autoFormatTriggerCharacters: string[], extensionId: ExtensionIdentifier): void {
|
||||
$registerOnTypeFormattingSupport(handle: number, selector: IDocumentFilterDto[], autoFormatTriggerCharacters: string[], extensionId: ExtensionIdentifier): void {
|
||||
this._registrations.set(handle, modes.OnTypeFormattingEditProviderRegistry.register(selector, <modes.OnTypeFormattingEditProvider>{
|
||||
extensionId,
|
||||
autoFormatTriggerCharacters,
|
||||
@@ -313,7 +313,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- rename
|
||||
|
||||
$registerRenameSupport(handle: number, selector: ISerializedDocumentFilter[], supportResolveLocation: boolean): void {
|
||||
$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> => {
|
||||
return this._proxy.$provideRenameEdits(handle, model.uri, position, newName, token).then(reviveWorkspaceEditDto);
|
||||
@@ -326,7 +326,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- suggest
|
||||
|
||||
private static _inflateSuggestDto(defaultRange: IRange, data: SuggestDataDto): modes.CompletionItem {
|
||||
private static _inflateSuggestDto(defaultRange: IRange, data: ISuggestDataDto): modes.CompletionItem {
|
||||
return {
|
||||
label: data.a,
|
||||
kind: data.b,
|
||||
@@ -346,7 +346,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
};
|
||||
}
|
||||
|
||||
$registerSuggestSupport(handle: number, selector: ISerializedDocumentFilter[], triggerCharacters: string[], supportsResolveDetails: boolean, extensionId: ExtensionIdentifier): void {
|
||||
$registerSuggestSupport(handle: number, selector: IDocumentFilterDto[], triggerCharacters: string[], supportsResolveDetails: boolean, extensionId: ExtensionIdentifier): void {
|
||||
const provider: modes.CompletionItemProvider = {
|
||||
triggerCharacters,
|
||||
_debugDisplayName: extensionId.value,
|
||||
@@ -380,7 +380,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- parameter hints
|
||||
|
||||
$registerSignatureHelpProvider(handle: number, selector: ISerializedDocumentFilter[], metadata: ISerializedSignatureHelpProviderMetadata): void {
|
||||
$registerSignatureHelpProvider(handle: number, selector: IDocumentFilterDto[], metadata: ISignatureHelpProviderMetadataDto): void {
|
||||
this._registrations.set(handle, modes.SignatureHelpProviderRegistry.register(selector, <modes.SignatureHelpProvider>{
|
||||
|
||||
signatureHelpTriggerCharacters: metadata.triggerCharacters,
|
||||
@@ -403,7 +403,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- links
|
||||
|
||||
$registerDocumentLinkProvider(handle: number, selector: ISerializedDocumentFilter[], supportsResolve: boolean): void {
|
||||
$registerDocumentLinkProvider(handle: number, selector: IDocumentFilterDto[], supportsResolve: boolean): void {
|
||||
const provider: modes.LinkProvider = {
|
||||
provideLinks: (model, token) => {
|
||||
return this._proxy.$provideDocumentLinks(handle, model.uri, token).then(dto => {
|
||||
@@ -423,7 +423,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
};
|
||||
if (supportsResolve) {
|
||||
provider.resolveLink = (link, token) => {
|
||||
const dto: LinkDto = link;
|
||||
const dto: ILinkDto = link;
|
||||
if (!dto.cacheId) {
|
||||
return link;
|
||||
}
|
||||
@@ -437,7 +437,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- colors
|
||||
|
||||
$registerDocumentColorProvider(handle: number, selector: ISerializedDocumentFilter[]): void {
|
||||
$registerDocumentColorProvider(handle: number, selector: IDocumentFilterDto[]): void {
|
||||
const proxy = this._proxy;
|
||||
this._registrations.set(handle, modes.ColorProviderRegistry.register(selector, <modes.DocumentColorProvider>{
|
||||
provideDocumentColors: (model, token) => {
|
||||
@@ -471,7 +471,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- folding
|
||||
|
||||
$registerFoldingRangeProvider(handle: number, selector: ISerializedDocumentFilter[]): void {
|
||||
$registerFoldingRangeProvider(handle: number, selector: IDocumentFilterDto[]): void {
|
||||
const proxy = this._proxy;
|
||||
this._registrations.set(handle, modes.FoldingRangeProviderRegistry.register(selector, <modes.FoldingRangeProvider>{
|
||||
provideFoldingRanges: (model, context, token) => {
|
||||
@@ -482,7 +482,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// -- smart select
|
||||
|
||||
$registerSelectionRangeProvider(handle: number, selector: ISerializedDocumentFilter[]): void {
|
||||
$registerSelectionRangeProvider(handle: number, selector: IDocumentFilterDto[]): void {
|
||||
this._registrations.set(handle, modes.SelectionRangeRegistry.register(selector, {
|
||||
provideSelectionRanges: (model, positions, token) => {
|
||||
return this._proxy.$provideSelectionRanges(handle, model.uri, positions, token);
|
||||
@@ -492,7 +492,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- call hierarchy
|
||||
|
||||
$registerCallHierarchyProvider(handle: number, selector: ISerializedDocumentFilter[]): void {
|
||||
$registerCallHierarchyProvider(handle: number, selector: IDocumentFilterDto[]): void {
|
||||
this._registrations.set(handle, callh.CallHierarchyProviderRegistry.register(selector, {
|
||||
provideCallHierarchyItem: (document, position, token) => {
|
||||
return this._proxy.$provideCallHierarchyItem(handle, document.uri, position, token).then(MainThreadLanguageFeatures._reviveCallHierarchyItemDto);
|
||||
@@ -516,11 +516,11 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- configuration
|
||||
|
||||
private static _reviveRegExp(regExp: ISerializedRegExp): RegExp {
|
||||
private static _reviveRegExp(regExp: IRegExpDto): RegExp {
|
||||
return new RegExp(regExp.pattern, regExp.flags);
|
||||
}
|
||||
|
||||
private static _reviveIndentationRule(indentationRule: ISerializedIndentationRule): IndentationRule {
|
||||
private static _reviveIndentationRule(indentationRule: IIndentationRuleDto): IndentationRule {
|
||||
return {
|
||||
decreaseIndentPattern: MainThreadLanguageFeatures._reviveRegExp(indentationRule.decreaseIndentPattern),
|
||||
increaseIndentPattern: MainThreadLanguageFeatures._reviveRegExp(indentationRule.increaseIndentPattern),
|
||||
@@ -529,7 +529,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
};
|
||||
}
|
||||
|
||||
private static _reviveOnEnterRule(onEnterRule: ISerializedOnEnterRule): OnEnterRule {
|
||||
private static _reviveOnEnterRule(onEnterRule: IOnEnterRuleDto): OnEnterRule {
|
||||
return {
|
||||
beforeText: MainThreadLanguageFeatures._reviveRegExp(onEnterRule.beforeText),
|
||||
afterText: onEnterRule.afterText ? MainThreadLanguageFeatures._reviveRegExp(onEnterRule.afterText) : undefined,
|
||||
@@ -538,11 +538,11 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
};
|
||||
}
|
||||
|
||||
private static _reviveOnEnterRules(onEnterRules: ISerializedOnEnterRule[]): OnEnterRule[] {
|
||||
private static _reviveOnEnterRules(onEnterRules: IOnEnterRuleDto[]): OnEnterRule[] {
|
||||
return onEnterRules.map(MainThreadLanguageFeatures._reviveOnEnterRule);
|
||||
}
|
||||
|
||||
$setLanguageConfiguration(handle: number, languageId: string, _configuration: ISerializedLanguageConfiguration): void {
|
||||
$setLanguageConfiguration(handle: number, languageId: string, _configuration: ILanguageConfigurationDto): void {
|
||||
|
||||
const configuration: LanguageConfiguration = {
|
||||
comments: _configuration.comments,
|
||||
|
||||
@@ -29,7 +29,7 @@ import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { ExtHostContext, MainThreadTaskShape, ExtHostTaskShape, MainContext, IExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import {
|
||||
TaskDefinitionDTO, TaskExecutionDTO, ProcessExecutionOptionsDTO, TaskPresentationOptionsDTO,
|
||||
ProcessExecutionDTO, ShellExecutionDTO, ShellExecutionOptionsDTO, CustomExecutionDTO, CustomExecution2DTO, TaskDTO, TaskSourceDTO, TaskHandleDTO, TaskFilterDTO, TaskProcessStartedDTO, TaskProcessEndedDTO, TaskSystemInfoDTO,
|
||||
ProcessExecutionDTO, ShellExecutionDTO, ShellExecutionOptionsDTO, CustomExecution2DTO, TaskDTO, TaskSourceDTO, TaskHandleDTO, TaskFilterDTO, TaskProcessStartedDTO, TaskProcessEndedDTO, TaskSystemInfoDTO,
|
||||
RunOptionsDTO
|
||||
} from 'vs/workbench/api/common/shared/tasks';
|
||||
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
|
||||
@@ -131,7 +131,7 @@ namespace ProcessExecutionOptionsDTO {
|
||||
}
|
||||
|
||||
namespace ProcessExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecutionDTO | CustomExecution2DTO): value is ProcessExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecution2DTO): value is ProcessExecutionDTO {
|
||||
const candidate = value as ProcessExecutionDTO;
|
||||
return candidate && !!candidate.process;
|
||||
}
|
||||
@@ -199,7 +199,7 @@ namespace ShellExecutionOptionsDTO {
|
||||
}
|
||||
|
||||
namespace ShellExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecutionDTO | CustomExecution2DTO): value is ShellExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecution2DTO): value is ShellExecutionDTO {
|
||||
const candidate = value as ShellExecutionDTO;
|
||||
return candidate && (!!candidate.commandLine || !!candidate.command);
|
||||
}
|
||||
@@ -230,28 +230,8 @@ namespace ShellExecutionDTO {
|
||||
}
|
||||
}
|
||||
|
||||
namespace CustomExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecutionDTO | CustomExecution2DTO): value is CustomExecutionDTO {
|
||||
const candidate = value as CustomExecutionDTO;
|
||||
return candidate && candidate.customExecution === 'customExecution';
|
||||
}
|
||||
|
||||
export function from(value: CommandConfiguration): CustomExecutionDTO {
|
||||
return {
|
||||
customExecution: 'customExecution'
|
||||
};
|
||||
}
|
||||
|
||||
export function to(value: CustomExecutionDTO): CommandConfiguration {
|
||||
return {
|
||||
runtime: RuntimeType.CustomExecution,
|
||||
presentation: undefined
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace CustomExecution2DTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecutionDTO | CustomExecution2DTO): value is CustomExecution2DTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecution2DTO): value is CustomExecution2DTO {
|
||||
const candidate = value as CustomExecution2DTO;
|
||||
return candidate && candidate.customExecution === 'customExecution2';
|
||||
}
|
||||
@@ -371,8 +351,6 @@ namespace TaskDTO {
|
||||
command = ShellExecutionDTO.to(task.execution);
|
||||
} else if (ProcessExecutionDTO.is(task.execution)) {
|
||||
command = ProcessExecutionDTO.to(task.execution);
|
||||
} else if (CustomExecutionDTO.is(task.execution)) {
|
||||
command = CustomExecutionDTO.to(task.execution);
|
||||
} else if (CustomExecution2DTO.is(task.execution)) {
|
||||
command = CustomExecution2DTO.to(task.execution);
|
||||
}
|
||||
@@ -420,7 +398,7 @@ namespace TaskFilterDTO {
|
||||
@extHostNamedCustomer(MainContext.MainThreadTask)
|
||||
export class MainThreadTask implements MainThreadTaskShape {
|
||||
|
||||
private readonly _extHostContext: IExtHostContext;
|
||||
private readonly _extHostContext: IExtHostContext | undefined;
|
||||
private readonly _proxy: ExtHostTaskShape;
|
||||
private readonly _providers: Map<number, { disposable: IDisposable, provider: ITaskProvider }>;
|
||||
|
||||
|
||||
@@ -3,14 +3,15 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ITerminalService, ITerminalInstance, IShellLaunchConfig, ITerminalProcessExtHostProxy, ISpawnExtHostProcessRequest, ITerminalDimensions, EXT_HOST_CREATION_DELAY, IAvailableShellsRequest, IDefaultShellAndArgsRequest, IStartExtensionTerminalRequest } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceShape, MainContext, IExtHostContext, ShellLaunchConfigDto, TerminalLaunchConfig, ITerminalDimensionsDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceShape, MainContext, IExtHostContext, IShellLaunchConfigDto, TerminalLaunchConfig, ITerminalDimensionsDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { StopWatch } from 'vs/base/common/stopwatch';
|
||||
import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadTerminalService)
|
||||
export class MainThreadTerminalService implements MainThreadTerminalServiceShape {
|
||||
@@ -21,13 +22,14 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
private readonly _terminalProcesses = new Map<number, Promise<ITerminalProcessExtHostProxy>>();
|
||||
private readonly _terminalProcessesReady = new Map<number, (proxy: ITerminalProcessExtHostProxy) => void>();
|
||||
private readonly _terminalOnDidWriteDataListeners = new Map<number, IDisposable>();
|
||||
private readonly _terminalOnDidAcceptInputListeners = new Map<number, IDisposable>();
|
||||
private _dataEventTracker: TerminalDataEventTracker | undefined;
|
||||
|
||||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
@ITerminalService private readonly _terminalService: ITerminalService,
|
||||
@ITerminalInstanceService readonly terminalInstanceService: ITerminalInstanceService,
|
||||
@IRemoteAgentService readonly _remoteAgentService: IRemoteAgentService
|
||||
@IRemoteAgentService readonly _remoteAgentService: IRemoteAgentService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
) {
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTerminalService);
|
||||
this._remoteAuthority = extHostContext.remoteAuthority;
|
||||
@@ -100,11 +102,6 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
});
|
||||
}
|
||||
|
||||
public $createTerminalRenderer(name: string): Promise<number> {
|
||||
const instance = this._terminalService.createTerminalRenderer(name);
|
||||
return Promise.resolve(instance.id);
|
||||
}
|
||||
|
||||
public $show(terminalId: number, preserveFocus: boolean): void {
|
||||
const terminalInstance = this._terminalService.getInstanceFromId(terminalId);
|
||||
if (terminalInstance) {
|
||||
@@ -127,44 +124,6 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
}
|
||||
}
|
||||
|
||||
public $terminalRendererWrite(terminalId: number, text: string): void {
|
||||
const terminalInstance = this._terminalService.getInstanceFromId(terminalId);
|
||||
if (terminalInstance && terminalInstance.shellLaunchConfig.isRendererOnly) {
|
||||
terminalInstance.write(text);
|
||||
}
|
||||
}
|
||||
|
||||
public $terminalRendererSetName(terminalId: number, name: string): void {
|
||||
const terminalInstance = this._terminalService.getInstanceFromId(terminalId);
|
||||
if (terminalInstance && terminalInstance.shellLaunchConfig.isRendererOnly) {
|
||||
terminalInstance.setTitle(name, false);
|
||||
}
|
||||
}
|
||||
|
||||
public $terminalRendererSetDimensions(terminalId: number, dimensions: ITerminalDimensions): void {
|
||||
const terminalInstance = this._terminalService.getInstanceFromId(terminalId);
|
||||
if (terminalInstance && terminalInstance.shellLaunchConfig.isRendererOnly) {
|
||||
terminalInstance.setDimensions(dimensions);
|
||||
}
|
||||
}
|
||||
|
||||
public $terminalRendererRegisterOnInputListener(terminalId: number): void {
|
||||
const terminalInstance = this._terminalService.getInstanceFromId(terminalId);
|
||||
if (!terminalInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Listener already registered
|
||||
if (this._terminalOnDidAcceptInputListeners.has(terminalId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Register
|
||||
const listener = terminalInstance.onRendererInput(data => this._onTerminalRendererInput(terminalId, data));
|
||||
this._terminalOnDidAcceptInputListeners.set(terminalId, listener);
|
||||
terminalInstance.addDisposable(listener);
|
||||
}
|
||||
|
||||
public $sendText(terminalId: number, text: string, addNewLine: boolean): void {
|
||||
const terminalInstance = this._terminalService.getInstanceFromId(terminalId);
|
||||
if (terminalInstance) {
|
||||
@@ -172,6 +131,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
public $registerOnDataListener(terminalId: number): void {
|
||||
const terminalInstance = this._terminalService.getInstanceFromId(terminalId);
|
||||
if (!terminalInstance) {
|
||||
@@ -191,14 +151,34 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
terminalInstance.addDisposable(listener);
|
||||
}
|
||||
|
||||
public $startSendingDataEvents(): void {
|
||||
if (!this._dataEventTracker) {
|
||||
this._dataEventTracker = this._instantiationService.createInstance(TerminalDataEventTracker, (id, data) => {
|
||||
this._onTerminalData2(id, data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public $stopSendingDataEvents(): void {
|
||||
if (this._dataEventTracker) {
|
||||
this._dataEventTracker.dispose();
|
||||
this._dataEventTracker = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
private _onActiveTerminalChanged(terminalId: number | null): void {
|
||||
this._proxy.$acceptActiveTerminalChanged(terminalId);
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
private _onTerminalData(terminalId: number, data: string): void {
|
||||
this._proxy.$acceptTerminalProcessData(terminalId, data);
|
||||
}
|
||||
|
||||
private _onTerminalData2(terminalId: number, data: string): void {
|
||||
this._proxy.$acceptTerminalProcessData2(terminalId, data);
|
||||
}
|
||||
|
||||
private _onTitleChanged(terminalId: number, name: string): void {
|
||||
this._proxy.$acceptTerminalTitleChange(terminalId, name);
|
||||
}
|
||||
@@ -207,10 +187,6 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
this._proxy.$acceptWorkspacePermissionsChanged(isAllowed);
|
||||
}
|
||||
|
||||
private _onTerminalRendererInput(terminalId: number, data: string): void {
|
||||
this._proxy.$acceptTerminalRendererInput(terminalId, data);
|
||||
}
|
||||
|
||||
private _onTerminalDisposed(terminalInstance: ITerminalInstance): void {
|
||||
this._proxy.$acceptTerminalClosed(terminalInstance.id);
|
||||
}
|
||||
@@ -254,7 +230,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
} else {
|
||||
this._terminalProcesses.set(proxy.terminalId, Promise.resolve(proxy));
|
||||
}
|
||||
const shellLaunchConfigDto: ShellLaunchConfigDto = {
|
||||
const shellLaunchConfigDto: IShellLaunchConfigDto = {
|
||||
name: request.shellLaunchConfig.name,
|
||||
executable: request.shellLaunchConfig.executable,
|
||||
args: request.shellLaunchConfig.args,
|
||||
@@ -359,7 +335,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
|
||||
private _onRequestDefaultShellAndArgs(request: IDefaultShellAndArgsRequest): void {
|
||||
if (this._isPrimaryExtHost()) {
|
||||
this._proxy.$requestDefaultShellAndArgs().then(e => request(e.shell, e.args));
|
||||
this._proxy.$requestDefaultShellAndArgs(request.useAutomationShell).then(e => request.callback(e.shell, e.args));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,3 +347,22 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
return terminal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encapsulates temporary tracking of data events from terminal instances, once disposed all
|
||||
* listeners are removed.
|
||||
*/
|
||||
class TerminalDataEventTracker extends Disposable {
|
||||
constructor(
|
||||
private readonly _callback: (id: number, data: string) => void,
|
||||
@ITerminalService private readonly _terminalService: ITerminalService
|
||||
) {
|
||||
super();
|
||||
this._terminalService.terminalInstances.forEach(instance => this._registerInstance(instance));
|
||||
this._register(this._terminalService.onInstanceCreated(instance => this._registerInstance(instance)));
|
||||
}
|
||||
|
||||
private _registerInstance(instance: ITerminalInstance): void {
|
||||
this._register(instance.onData(e => this._callback(instance.id, e)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { distinct } from 'vs/base/common/arrays';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { isUndefinedOrNull, isNumber } from 'vs/base/common/types';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadTreeViews)
|
||||
@@ -63,7 +62,7 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
$setMessage(treeViewId: string, message: string | IMarkdownString): void {
|
||||
$setMessage(treeViewId: string, message: string): void {
|
||||
const viewer = this.getTreeView(treeViewId);
|
||||
if (viewer) {
|
||||
viewer.message = message;
|
||||
|
||||
@@ -15,66 +15,60 @@ import { OverviewRulerLane } from 'vs/editor/common/model';
|
||||
import * as languageConfiguration from 'vs/editor/common/modes/languageConfiguration';
|
||||
import { score } from 'vs/editor/common/modes/languageSelector';
|
||||
import * as files from 'vs/platform/files/common/files';
|
||||
import { ExtHostContext, IInitData, IMainContext, MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostContext, MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostApiCommands } from 'vs/workbench/api/common/extHostApiCommands';
|
||||
import { ExtHostClipboard } from 'vs/workbench/api/common/extHostClipboard';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { IExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { ExtHostComments } from 'vs/workbench/api/common/extHostComments';
|
||||
import { ExtHostConfiguration, ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
// {{SQL CARBON EDIT}} - Remove ExtHostDebugService
|
||||
// import { ExtHostDebugService } from 'vs/workbench/api/node/extHostDebugService';
|
||||
// {{SQL CARBON EDIT}} - Import product
|
||||
import product from 'vs/platform/product/node/product';
|
||||
import { ExtHostDecorations } from 'vs/workbench/api/common/extHostDecorations';
|
||||
import { ExtHostConfigProvider, IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { ExtHostDiagnostics } from 'vs/workbench/api/common/extHostDiagnostics';
|
||||
import { ExtHostDialogs } from 'vs/workbench/api/common/extHostDialogs';
|
||||
import { ExtHostDocumentContentProvider } from 'vs/workbench/api/common/extHostDocumentContentProviders';
|
||||
import { ExtHostDocumentSaveParticipant } from 'vs/workbench/api/common/extHostDocumentSaveParticipant';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { IExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { ExtensionActivatedByAPI } from 'vs/workbench/api/common/extHostExtensionActivator';
|
||||
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
|
||||
import { IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService';
|
||||
import { ExtHostFileSystem } from 'vs/workbench/api/common/extHostFileSystem';
|
||||
import { ExtHostFileSystemEventService } from 'vs/workbench/api/common/extHostFileSystemEventService';
|
||||
import { ExtHostLanguageFeatures } from 'vs/workbench/api/common/extHostLanguageFeatures';
|
||||
import { ExtHostLanguages } from 'vs/workbench/api/common/extHostLanguages';
|
||||
import { ExtHostLogService } from 'vs/workbench/api/common/extHostLogService';
|
||||
import { ExtHostMessageService } from 'vs/workbench/api/common/extHostMessageService';
|
||||
import { ExtHostOutputService } from 'vs/workbench/api/common/extHostOutput';
|
||||
import { LogOutputChannelFactory } from 'vs/workbench/api/node/extHostOutputService';
|
||||
import { IExtHostOutputService } from 'vs/workbench/api/common/extHostOutput';
|
||||
import { ExtHostProgress } from 'vs/workbench/api/common/extHostProgress';
|
||||
import { ExtHostQuickOpen } from 'vs/workbench/api/common/extHostQuickOpen';
|
||||
import { ExtHostSCM } from 'vs/workbench/api/common/extHostSCM';
|
||||
import { ExtHostSearch, registerEHSearchProviders } from 'vs/workbench/api/node/extHostSearch';
|
||||
import { ExtHostStatusBar } from 'vs/workbench/api/common/extHostStatusBar';
|
||||
import { ExtHostStorage } from 'vs/workbench/api/common/extHostStorage';
|
||||
import { ExtHostTask } from 'vs/workbench/api/node/extHostTask';
|
||||
import { ExtHostTerminalService } from 'vs/workbench/api/node/extHostTerminalService';
|
||||
import { IExtHostStorage } from 'vs/workbench/api/common/extHostStorage';
|
||||
import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService';
|
||||
import { ExtHostEditors } from 'vs/workbench/api/common/extHostTextEditors';
|
||||
import { ExtHostTreeViews } from 'vs/workbench/api/common/extHostTreeViews';
|
||||
import { ExtHostDownloadService } from 'vs/workbench/api/node/extHostDownloadService';
|
||||
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
|
||||
import { ExtHostUrls } from 'vs/workbench/api/common/extHostUrls';
|
||||
import { ExtHostWebviews } from 'vs/workbench/api/common/extHostWebview';
|
||||
import { ExtHostWindow } from 'vs/workbench/api/common/extHostWindow';
|
||||
import { ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { throwProposedApiError, checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ProxyIdentifier } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { originalFSPath } from 'vs/base/common/resources';
|
||||
import { CLIServer } from 'vs/workbench/api/node/extHostCLIServer';
|
||||
import { values } from 'vs/base/common/collections';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IURITransformer } from 'vs/base/common/uriIpc';
|
||||
import { ExtHostEditorInsets } from 'vs/workbench/api/common/extHostCodeInsets';
|
||||
import { ExtHostLabelService } from 'vs/workbench/api/common/extHostLabelService';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
|
||||
import { getSingletonServiceDescriptors } from 'vs/platform/instantiation/common/extensions';
|
||||
import { getRemoteName } from 'vs/platform/remote/common/remoteHosts';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostDecorations } from 'vs/workbench/api/common/extHostDecorations';
|
||||
import { IExtHostTask } from 'vs/workbench/api/common/extHostTask';
|
||||
import { IExtHostDebugService } from 'vs/workbench/api/common/extHostDebugService';
|
||||
import { IExtHostSearch } from 'vs/workbench/api/common/extHostSearch';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IURITransformerService } from 'vs/workbench/api/common/extHostUriTransformerService';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
|
||||
export interface IExtensionApiFactory {
|
||||
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
|
||||
@@ -91,68 +85,55 @@ function proposedApiFunction<T>(extension: IExtensionDescription, fn: T): T {
|
||||
/**
|
||||
* This method instantiates and returns the extension API surface
|
||||
*/
|
||||
export function createApiFactory(
|
||||
initData: IInitData,
|
||||
rpcProtocol: IMainContext,
|
||||
extHostWorkspace: ExtHostWorkspace,
|
||||
extHostConfiguration: ExtHostConfiguration,
|
||||
extensionService: ExtHostExtensionService,
|
||||
extHostLogService: ExtHostLogService,
|
||||
extHostStorage: ExtHostStorage,
|
||||
uriTransformer: IURITransformer | null
|
||||
): IExtensionApiFactory {
|
||||
export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): IExtensionApiFactory {
|
||||
|
||||
// bootstrap services
|
||||
const services = new ServiceCollection(...getSingletonServiceDescriptors());
|
||||
const instaService = new InstantiationService(services);
|
||||
// services
|
||||
const initData = accessor.get(IExtHostInitDataService);
|
||||
const extensionService = accessor.get(IExtHostExtensionService);
|
||||
const extHostWorkspace = accessor.get(IExtHostWorkspace);
|
||||
const extHostConfiguration = accessor.get(IExtHostConfiguration);
|
||||
const uriTransformer = accessor.get(IURITransformerService);
|
||||
const rpcProtocol = accessor.get(IExtHostRpcService);
|
||||
const extHostStorage = accessor.get(IExtHostStorage);
|
||||
const extHostLogService = <ExtHostLogService>accessor.get(ILogService);
|
||||
|
||||
// Addressable instances
|
||||
// register addressable instances
|
||||
rpcProtocol.set(ExtHostContext.ExtHostLogService, extHostLogService);
|
||||
const extHostDecorations = rpcProtocol.set(ExtHostContext.ExtHostDecorations, new ExtHostDecorations(rpcProtocol));
|
||||
rpcProtocol.set(ExtHostContext.ExtHostWorkspace, extHostWorkspace);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostConfiguration, extHostConfiguration);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostStorage, extHostStorage);
|
||||
|
||||
// automatically create and register addressable instances
|
||||
const extHostDecorations = rpcProtocol.set(ExtHostContext.ExtHostDecorations, accessor.get(IExtHostDecorations));
|
||||
const extHostDocumentsAndEditors = rpcProtocol.set(ExtHostContext.ExtHostDocumentsAndEditors, accessor.get(IExtHostDocumentsAndEditors));
|
||||
const extHostCommands = rpcProtocol.set(ExtHostContext.ExtHostCommands, accessor.get(IExtHostCommands));
|
||||
const extHostTerminalService = rpcProtocol.set(ExtHostContext.ExtHostTerminalService, accessor.get(IExtHostTerminalService));
|
||||
// const extHostDebugService = rpcProtocol.set(ExtHostContext.ExtHostDebugService, accessor.get(IExtHostDebugService)); {{SQL CARBON EDIT}} remove debug service
|
||||
const extHostSearch = rpcProtocol.set(ExtHostContext.ExtHostSearch, accessor.get(IExtHostSearch));
|
||||
const extHostTask = rpcProtocol.set(ExtHostContext.ExtHostTask, accessor.get(IExtHostTask));
|
||||
const extHostOutputService = rpcProtocol.set(ExtHostContext.ExtHostOutputService, accessor.get(IExtHostOutputService));
|
||||
|
||||
// manually create and register addressable instances
|
||||
const extHostWebviews = rpcProtocol.set(ExtHostContext.ExtHostWebviews, new ExtHostWebviews(rpcProtocol, initData.environment));
|
||||
const extHostUrls = rpcProtocol.set(ExtHostContext.ExtHostUrls, new ExtHostUrls(rpcProtocol));
|
||||
const extHostDocumentsAndEditors = rpcProtocol.set(ExtHostContext.ExtHostDocumentsAndEditors, new ExtHostDocumentsAndEditors(rpcProtocol));
|
||||
const extHostDocuments = rpcProtocol.set(ExtHostContext.ExtHostDocuments, new ExtHostDocuments(rpcProtocol, extHostDocumentsAndEditors));
|
||||
const extHostDocumentContentProviders = rpcProtocol.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(rpcProtocol, extHostDocumentsAndEditors, extHostLogService));
|
||||
const extHostDocumentSaveParticipant = rpcProtocol.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(extHostLogService, extHostDocuments, rpcProtocol.getProxy(MainContext.MainThreadTextEditors)));
|
||||
const extHostEditors = rpcProtocol.set(ExtHostContext.ExtHostEditors, new ExtHostEditors(rpcProtocol, extHostDocumentsAndEditors));
|
||||
const extHostCommands = rpcProtocol.set(ExtHostContext.ExtHostCommands, new ExtHostCommands(rpcProtocol, extHostLogService));
|
||||
const extHostTreeViews = rpcProtocol.set(ExtHostContext.ExtHostTreeViews, new ExtHostTreeViews(rpcProtocol.getProxy(MainContext.MainThreadTreeViews), extHostCommands, extHostLogService));
|
||||
rpcProtocol.set(ExtHostContext.ExtHostDownloadService, new ExtHostDownloadService(rpcProtocol.getProxy(MainContext.MainThreadDownloadService), extHostCommands));
|
||||
rpcProtocol.set(ExtHostContext.ExtHostWorkspace, extHostWorkspace);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostConfiguration, extHostConfiguration);
|
||||
const extHostEditorInsets = rpcProtocol.set(ExtHostContext.ExtHostEditorInsets, new ExtHostEditorInsets(rpcProtocol.getProxy(MainContext.MainThreadEditorInsets), extHostEditors, initData.environment));
|
||||
const extHostDiagnostics = rpcProtocol.set(ExtHostContext.ExtHostDiagnostics, new ExtHostDiagnostics(rpcProtocol));
|
||||
const extHostLanguageFeatures = rpcProtocol.set(ExtHostContext.ExtHostLanguageFeatures, new ExtHostLanguageFeatures(rpcProtocol, uriTransformer, extHostDocuments, extHostCommands, extHostDiagnostics, extHostLogService));
|
||||
const extHostFileSystem = rpcProtocol.set(ExtHostContext.ExtHostFileSystem, new ExtHostFileSystem(rpcProtocol, extHostLanguageFeatures));
|
||||
const extHostFileSystemEvent = rpcProtocol.set(ExtHostContext.ExtHostFileSystemEventService, new ExtHostFileSystemEventService(rpcProtocol, extHostDocumentsAndEditors));
|
||||
const extHostQuickOpen = rpcProtocol.set(ExtHostContext.ExtHostQuickOpen, new ExtHostQuickOpen(rpcProtocol, extHostWorkspace, extHostCommands));
|
||||
const extHostTerminalService = rpcProtocol.set(ExtHostContext.ExtHostTerminalService, new ExtHostTerminalService(rpcProtocol, extHostConfiguration, extHostWorkspace, extHostDocumentsAndEditors, extHostLogService));
|
||||
// const extHostDebugService = rpcProtocol.set(ExtHostContext.ExtHostDebugService, instaService.createInstance(ExtHostDebugService, rpcProtocol, extHostWorkspace, extensionService, extHostDocumentsAndEditors, extHostConfiguration, extHostTerminalService, extHostCommands)); {{SQL CARBON EDIT}} remove debug service
|
||||
const extHostSCM = rpcProtocol.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(rpcProtocol, extHostCommands, extHostLogService));
|
||||
const extHostComment = rpcProtocol.set(ExtHostContext.ExtHostComments, new ExtHostComments(rpcProtocol, extHostCommands, extHostDocuments));
|
||||
const extHostSearch = rpcProtocol.set(ExtHostContext.ExtHostSearch, new ExtHostSearch(rpcProtocol, uriTransformer, extHostLogService));
|
||||
const extHostTask = rpcProtocol.set(ExtHostContext.ExtHostTask, new ExtHostTask(rpcProtocol, extHostWorkspace, extHostDocumentsAndEditors, extHostConfiguration, extHostTerminalService));
|
||||
const extHostWindow = rpcProtocol.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(rpcProtocol));
|
||||
rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService);
|
||||
const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress)));
|
||||
const extHostOutputService = rpcProtocol.set(ExtHostContext.ExtHostOutputService, new ExtHostOutputService(LogOutputChannelFactory, initData.logsLocation, rpcProtocol));
|
||||
rpcProtocol.set(ExtHostContext.ExtHostStorage, extHostStorage);
|
||||
const extHostLabelService = rpcProtocol.set(ExtHostContext.ExtHosLabelService, new ExtHostLabelService(rpcProtocol));
|
||||
|
||||
if (initData.remote.isRemote && initData.remote.authority) {
|
||||
extHostTask.registerTaskSystem(Schemas.vscodeRemote, {
|
||||
scheme: Schemas.vscodeRemote,
|
||||
authority: initData.remote.authority,
|
||||
platform: process.platform
|
||||
});
|
||||
|
||||
registerEHSearchProviders(extHostSearch, extHostLogService);
|
||||
|
||||
const cliServer = new CLIServer(extHostCommands);
|
||||
process.env['VSCODE_IPC_HOOK_CLI'] = cliServer.ipcHandlePath;
|
||||
}
|
||||
|
||||
// Check that no named customers are missing
|
||||
// {{SQL CARBON EDIT}} filter out the services we don't expose
|
||||
const filtered: ProxyIdentifier<any>[] = [ExtHostContext.ExtHostDebugService, ExtHostContext.ExtHostTask];
|
||||
@@ -276,7 +257,7 @@ export function createApiFactory(
|
||||
return extHostClipboard;
|
||||
},
|
||||
get shell() {
|
||||
return extHostTerminalService.getDefaultShell(configProvider);
|
||||
return extHostTerminalService.getDefaultShell(false, configProvider);
|
||||
},
|
||||
openExternal(uri: URI) {
|
||||
return extHostWindow.openUri(uri, { allowTunneling: !!initData.remote.isRemote });
|
||||
@@ -462,8 +443,13 @@ export function createApiFactory(
|
||||
return extHostTerminalService.onDidChangeActiveTerminal(listener, thisArg, disposables);
|
||||
},
|
||||
onDidChangeTerminalDimensions(listener, thisArg?, disposables?) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTerminalService.onDidChangeTerminalDimensions(listener, thisArg, disposables);
|
||||
},
|
||||
onDidWriteTerminalData(listener, thisArg?, disposables?) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTerminalService.onDidWriteTerminalData(listener, thisArg, disposables);
|
||||
},
|
||||
get state() {
|
||||
return extHostWindow.state;
|
||||
},
|
||||
@@ -540,16 +526,11 @@ export function createApiFactory(
|
||||
if (typeof nameOrOptions === 'object') {
|
||||
if ('pty' in nameOrOptions) {
|
||||
return extHostTerminalService.createExtensionTerminal(nameOrOptions);
|
||||
} else {
|
||||
nameOrOptions.hideFromUser = nameOrOptions.hideFromUser || (nameOrOptions.runInBackground && extension.enableProposedApi);
|
||||
return extHostTerminalService.createTerminalFromOptions(nameOrOptions);
|
||||
}
|
||||
return extHostTerminalService.createTerminalFromOptions(nameOrOptions);
|
||||
}
|
||||
return extHostTerminalService.createTerminal(<string>nameOrOptions, shellPath, shellArgs);
|
||||
},
|
||||
createTerminalRenderer(name: string): vscode.TerminalRenderer {
|
||||
return extHostTerminalService.createTerminalRenderer(name);
|
||||
},
|
||||
registerTreeDataProvider(viewId: string, treeDataProvider: vscode.TreeDataProvider<any>): vscode.Disposable {
|
||||
return extHostTreeViews.registerTreeDataProvider(viewId, treeDataProvider, extension);
|
||||
},
|
||||
@@ -810,7 +791,7 @@ export function createApiFactory(
|
||||
|
||||
return <typeof vscode>{
|
||||
// {{SQL CARBON EDIT}} - Expose the VS Code version here for extensions that rely on it
|
||||
version: product.vscodeVersion,
|
||||
version: initData.vscodeVersion,
|
||||
// namespaces
|
||||
commands,
|
||||
debug,
|
||||
@@ -857,7 +838,6 @@ export function createApiFactory(
|
||||
EventEmitter: Emitter,
|
||||
ExtensionExecutionContext: extHostTypes.ExtensionExecutionContext,
|
||||
ExtensionKind: extHostTypes.ExtensionKind,
|
||||
CustomExecution: extHostTypes.CustomExecution,
|
||||
CustomExecution2: extHostTypes.CustomExecution2,
|
||||
FileChangeType: extHostTypes.FileChangeType,
|
||||
FileSystemError: extHostTypes.FileSystemError,
|
||||
@@ -922,7 +902,7 @@ export function createApiFactory(
|
||||
|
||||
class Extension<T> implements vscode.Extension<T> {
|
||||
|
||||
private _extensionService: ExtHostExtensionService;
|
||||
private _extensionService: IExtHostExtensionService;
|
||||
private _identifier: ExtensionIdentifier;
|
||||
|
||||
readonly id: string;
|
||||
@@ -930,7 +910,7 @@ class Extension<T> implements vscode.Extension<T> {
|
||||
readonly packageJSON: IExtensionDescription;
|
||||
readonly extensionKind: vscode.ExtensionKind;
|
||||
|
||||
constructor(extensionService: ExtHostExtensionService, description: IExtensionDescription, kind: extHostTypes.ExtensionKind) {
|
||||
constructor(extensionService: IExtHostExtensionService, description: IExtensionDescription, kind: extHostTypes.ExtensionKind) {
|
||||
this._extensionService = extensionService;
|
||||
this._identifier = description.identifier;
|
||||
this.id = description.identifier.value;
|
||||
@@ -79,6 +79,7 @@ export interface IWorkspaceData extends IStaticWorkspaceData {
|
||||
|
||||
export interface IInitData {
|
||||
version: string;
|
||||
vscodeVersion: string; // {{SQL CARBON EDIT}} add vscodeVersion
|
||||
commit?: string;
|
||||
parentPid: number;
|
||||
environment: IEnvironment;
|
||||
@@ -135,7 +136,7 @@ export interface MainThreadCommentsShape extends IDisposable {
|
||||
$unregisterCommentController(handle: number): void;
|
||||
$updateCommentControllerFeatures(handle: number, features: CommentProviderFeatures): void;
|
||||
$createCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, range: IRange, extensionId: ExtensionIdentifier): modes.CommentThread | undefined;
|
||||
$updateCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, range: IRange, label: string, contextValue: string | undefined, comments: modes.Comment[], collapseState: modes.CommentThreadCollapsibleState): void;
|
||||
$updateCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, range: IRange, label: string | undefined, contextValue: string | undefined, comments: modes.Comment[], collapseState: modes.CommentThreadCollapsibleState): void;
|
||||
$deleteCommentThread(handle: number, commentThreadHandle: number): void;
|
||||
$onDidCommentThreadsChange(handle: number, event: modes.CommentThreadChangedEvent): void;
|
||||
}
|
||||
@@ -239,7 +240,7 @@ export interface MainThreadTextEditorsShape extends IDisposable {
|
||||
$tryRevealRange(id: string, range: IRange, revealType: TextEditorRevealType): Promise<void>;
|
||||
$trySetSelections(id: string, selections: ISelection[]): Promise<void>;
|
||||
$tryApplyEdits(id: string, modelVersionId: number, edits: ISingleEditOperation[], opts: IApplyEditsOptions): Promise<boolean>;
|
||||
$tryApplyWorkspaceEdit(workspaceEditDto: WorkspaceEditDto): Promise<boolean>;
|
||||
$tryApplyWorkspaceEdit(workspaceEditDto: IWorkspaceEditDto): Promise<boolean>;
|
||||
$tryInsertSnippet(id: string, template: string, selections: readonly IRange[], opts: IUndoStopOptions): Promise<boolean>;
|
||||
$getDiffInformation(id: string): Promise<editorCommon.ILineChange[]>;
|
||||
}
|
||||
@@ -248,7 +249,7 @@ export interface MainThreadTreeViewsShape extends IDisposable {
|
||||
$registerTreeViewDataProvider(treeViewId: string, options: { showCollapseAll: boolean }): void;
|
||||
$refresh(treeViewId: string, itemsToRefresh?: { [treeItemHandle: string]: ITreeItem }): Promise<void>;
|
||||
$reveal(treeViewId: string, treeItem: ITreeItem, parentChain: ITreeItem[], options: IRevealOptions): Promise<void>;
|
||||
$setMessage(treeViewId: string, message: string | IMarkdownString): void;
|
||||
$setMessage(treeViewId: string, message: string): void;
|
||||
}
|
||||
|
||||
export interface MainThreadDownloadServiceShape extends IDisposable {
|
||||
@@ -270,28 +271,28 @@ export interface MainThreadKeytarShape extends IDisposable {
|
||||
$findPassword(service: string): Promise<string | null>;
|
||||
}
|
||||
|
||||
export interface ISerializedRegExp {
|
||||
export interface IRegExpDto {
|
||||
pattern: string;
|
||||
flags?: string;
|
||||
}
|
||||
export interface ISerializedIndentationRule {
|
||||
decreaseIndentPattern: ISerializedRegExp;
|
||||
increaseIndentPattern: ISerializedRegExp;
|
||||
indentNextLinePattern?: ISerializedRegExp;
|
||||
unIndentedLinePattern?: ISerializedRegExp;
|
||||
export interface IIndentationRuleDto {
|
||||
decreaseIndentPattern: IRegExpDto;
|
||||
increaseIndentPattern: IRegExpDto;
|
||||
indentNextLinePattern?: IRegExpDto;
|
||||
unIndentedLinePattern?: IRegExpDto;
|
||||
}
|
||||
export interface ISerializedOnEnterRule {
|
||||
beforeText: ISerializedRegExp;
|
||||
afterText?: ISerializedRegExp;
|
||||
oneLineAboveText?: ISerializedRegExp;
|
||||
export interface IOnEnterRuleDto {
|
||||
beforeText: IRegExpDto;
|
||||
afterText?: IRegExpDto;
|
||||
oneLineAboveText?: IRegExpDto;
|
||||
action: EnterAction;
|
||||
}
|
||||
export interface ISerializedLanguageConfiguration {
|
||||
export interface ILanguageConfigurationDto {
|
||||
comments?: CommentRule;
|
||||
brackets?: CharacterPair[];
|
||||
wordPattern?: ISerializedRegExp;
|
||||
indentationRules?: ISerializedIndentationRule;
|
||||
onEnterRules?: ISerializedOnEnterRule[];
|
||||
wordPattern?: IRegExpDto;
|
||||
indentationRules?: IIndentationRuleDto;
|
||||
onEnterRules?: IOnEnterRuleDto[];
|
||||
__electricCharacterSupport?: {
|
||||
brackets?: any;
|
||||
docComment?: {
|
||||
@@ -312,7 +313,7 @@ export interface ISerializedLanguageConfiguration {
|
||||
|
||||
export type GlobPattern = string | { base: string; pattern: string };
|
||||
|
||||
export interface ISerializedDocumentFilter {
|
||||
export interface IDocumentFilterDto {
|
||||
$serialized: true;
|
||||
language?: string;
|
||||
scheme?: string;
|
||||
@@ -320,37 +321,37 @@ export interface ISerializedDocumentFilter {
|
||||
exclusive?: boolean;
|
||||
}
|
||||
|
||||
export interface ISerializedSignatureHelpProviderMetadata {
|
||||
export interface ISignatureHelpProviderMetadataDto {
|
||||
readonly triggerCharacters: readonly string[];
|
||||
readonly retriggerCharacters: readonly string[];
|
||||
}
|
||||
|
||||
export interface MainThreadLanguageFeaturesShape extends IDisposable {
|
||||
$unregister(handle: number): void;
|
||||
$registerDocumentSymbolProvider(handle: number, selector: ISerializedDocumentFilter[], label: string): void;
|
||||
$registerCodeLensSupport(handle: number, selector: ISerializedDocumentFilter[], eventHandle: number | undefined): void;
|
||||
$registerDocumentSymbolProvider(handle: number, selector: IDocumentFilterDto[], label: string): void;
|
||||
$registerCodeLensSupport(handle: number, selector: IDocumentFilterDto[], eventHandle: number | undefined): void;
|
||||
$emitCodeLensEvent(eventHandle: number, event?: any): void;
|
||||
$registerDefinitionSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerDeclarationSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerImplementationSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerTypeDefinitionSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerHoverProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerDocumentHighlightProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerReferenceSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerQuickFixSupport(handle: number, selector: ISerializedDocumentFilter[], supportedKinds?: string[]): void;
|
||||
$registerDocumentFormattingSupport(handle: number, selector: ISerializedDocumentFilter[], extensionId: ExtensionIdentifier, displayName: string): void;
|
||||
$registerRangeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[], extensionId: ExtensionIdentifier, displayName: string): void;
|
||||
$registerOnTypeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[], autoFormatTriggerCharacters: string[], extensionId: ExtensionIdentifier): void;
|
||||
$registerDefinitionSupport(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$registerDeclarationSupport(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$registerImplementationSupport(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$registerTypeDefinitionSupport(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$registerHoverProvider(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$registerDocumentHighlightProvider(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$registerReferenceSupport(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$registerQuickFixSupport(handle: number, selector: IDocumentFilterDto[], supportedKinds?: string[]): void;
|
||||
$registerDocumentFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void;
|
||||
$registerRangeFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void;
|
||||
$registerOnTypeFormattingSupport(handle: number, selector: IDocumentFilterDto[], autoFormatTriggerCharacters: string[], extensionId: ExtensionIdentifier): void;
|
||||
$registerNavigateTypeSupport(handle: number): void;
|
||||
$registerRenameSupport(handle: number, selector: ISerializedDocumentFilter[], supportsResolveInitialValues: boolean): void;
|
||||
$registerSuggestSupport(handle: number, selector: ISerializedDocumentFilter[], triggerCharacters: string[], supportsResolveDetails: boolean, extensionId: ExtensionIdentifier): void;
|
||||
$registerSignatureHelpProvider(handle: number, selector: ISerializedDocumentFilter[], metadata: ISerializedSignatureHelpProviderMetadata): void;
|
||||
$registerDocumentLinkProvider(handle: number, selector: ISerializedDocumentFilter[], supportsResolve: boolean): void;
|
||||
$registerDocumentColorProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerFoldingRangeProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerSelectionRangeProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerCallHierarchyProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$setLanguageConfiguration(handle: number, languageId: string, configuration: ISerializedLanguageConfiguration): void;
|
||||
$registerRenameSupport(handle: number, selector: IDocumentFilterDto[], supportsResolveInitialValues: boolean): void;
|
||||
$registerSuggestSupport(handle: number, selector: IDocumentFilterDto[], triggerCharacters: string[], supportsResolveDetails: boolean, extensionId: ExtensionIdentifier): void;
|
||||
$registerSignatureHelpProvider(handle: number, selector: IDocumentFilterDto[], metadata: ISignatureHelpProviderMetadataDto): void;
|
||||
$registerDocumentLinkProvider(handle: number, selector: IDocumentFilterDto[], supportsResolve: boolean): void;
|
||||
$registerDocumentColorProvider(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$registerFoldingRangeProvider(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$registerSelectionRangeProvider(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$registerCallHierarchyProvider(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$setLanguageConfiguration(handle: number, languageId: string, configuration: ILanguageConfigurationDto): void;
|
||||
}
|
||||
|
||||
export interface MainThreadLanguagesShape extends IDisposable {
|
||||
@@ -398,12 +399,14 @@ export interface TerminalLaunchConfig {
|
||||
|
||||
export interface MainThreadTerminalServiceShape extends IDisposable {
|
||||
$createTerminal(config: TerminalLaunchConfig): Promise<{ id: number, name: string }>;
|
||||
$createTerminalRenderer(name: string): Promise<number>;
|
||||
$dispose(terminalId: number): void;
|
||||
$hide(terminalId: number): void;
|
||||
$sendText(terminalId: number, text: string, addNewLine: boolean): void;
|
||||
$show(terminalId: number, preserveFocus: boolean): void;
|
||||
/** @deprecated */
|
||||
$registerOnDataListener(terminalId: number): void;
|
||||
$startSendingDataEvents(): void;
|
||||
$stopSendingDataEvents(): void;
|
||||
|
||||
// Process
|
||||
$sendProcessTitle(terminalId: number, title: string): void;
|
||||
@@ -414,12 +417,6 @@ export interface MainThreadTerminalServiceShape extends IDisposable {
|
||||
$sendProcessCwd(terminalId: number, initialCwd: string): void;
|
||||
$sendOverrideDimensions(terminalId: number, dimensions: ITerminalDimensions | undefined): void;
|
||||
$sendResolvedLaunchConfig(terminalId: number, shellLaunchConfig: IShellLaunchConfig): void;
|
||||
|
||||
// Renderer
|
||||
$terminalRendererSetName(terminalId: number, name: string): void;
|
||||
$terminalRendererSetDimensions(terminalId: number, dimensions: ITerminalDimensions): void;
|
||||
$terminalRendererWrite(terminalId: number, text: string): void;
|
||||
$terminalRendererRegisterOnInputListener(terminalId: number): void;
|
||||
}
|
||||
|
||||
export interface TransferQuickPickItems extends quickInput.IQuickPickItem {
|
||||
@@ -652,7 +649,7 @@ export interface SCMProviderFeatures {
|
||||
count?: number;
|
||||
commitTemplate?: string;
|
||||
acceptInputCommand?: modes.Command;
|
||||
statusBarCommands?: CommandDto[];
|
||||
statusBarCommands?: ICommandDto[];
|
||||
}
|
||||
|
||||
export interface SCMGroupFeatures {
|
||||
@@ -823,9 +820,6 @@ export interface ExtHostTreeViewsShape {
|
||||
$setVisible(treeViewId: string, visible: boolean): void;
|
||||
}
|
||||
|
||||
export interface ExtHostDownloadServiceShape {
|
||||
}
|
||||
|
||||
export interface ExtHostWorkspaceShape {
|
||||
$initializeWorkspace(workspace: IWorkspaceData | null): void;
|
||||
$acceptWorkspaceData(workspace: IWorkspaceData | null): void;
|
||||
@@ -932,7 +926,7 @@ export class IdObject {
|
||||
}
|
||||
}
|
||||
|
||||
export interface SuggestDataDto {
|
||||
export interface ISuggestDataDto {
|
||||
a/* label */: string;
|
||||
b/* kind */: modes.CompletionItemKind;
|
||||
c/* detail */?: string;
|
||||
@@ -950,51 +944,51 @@ export interface SuggestDataDto {
|
||||
x?: ChainedCacheId;
|
||||
}
|
||||
|
||||
export interface SuggestResultDto {
|
||||
export interface ISuggestResultDto {
|
||||
x?: number;
|
||||
a: IRange;
|
||||
b: SuggestDataDto[];
|
||||
b: ISuggestDataDto[];
|
||||
c?: boolean;
|
||||
}
|
||||
|
||||
export interface SignatureHelpDto {
|
||||
export interface ISignatureHelpDto {
|
||||
id: CacheId;
|
||||
signatures: modes.SignatureInformation[];
|
||||
activeSignature: number;
|
||||
activeParameter: number;
|
||||
}
|
||||
|
||||
export interface SignatureHelpContextDto {
|
||||
export interface ISignatureHelpContextDto {
|
||||
readonly triggerKind: modes.SignatureHelpTriggerKind;
|
||||
readonly triggerCharacter?: string;
|
||||
readonly isRetrigger: boolean;
|
||||
readonly activeSignatureHelp?: SignatureHelpDto;
|
||||
readonly activeSignatureHelp?: ISignatureHelpDto;
|
||||
}
|
||||
|
||||
export interface LocationDto {
|
||||
export interface ILocationDto {
|
||||
uri: UriComponents;
|
||||
range: IRange;
|
||||
}
|
||||
|
||||
export interface DefinitionLinkDto {
|
||||
export interface IDefinitionLinkDto {
|
||||
originSelectionRange?: IRange;
|
||||
uri: UriComponents;
|
||||
range: IRange;
|
||||
targetSelectionRange?: IRange;
|
||||
}
|
||||
|
||||
export interface WorkspaceSymbolDto extends IdObject {
|
||||
export interface IWorkspaceSymbolDto extends IdObject {
|
||||
name: string;
|
||||
containerName?: string;
|
||||
kind: modes.SymbolKind;
|
||||
location: LocationDto;
|
||||
location: ILocationDto;
|
||||
}
|
||||
|
||||
export interface WorkspaceSymbolsDto extends IdObject {
|
||||
symbols: WorkspaceSymbolDto[];
|
||||
export interface IWorkspaceSymbolsDto extends IdObject {
|
||||
symbols: IWorkspaceSymbolDto[];
|
||||
}
|
||||
|
||||
export interface ResourceFileEditDto {
|
||||
export interface IResourceFileEditDto {
|
||||
oldUri?: UriComponents;
|
||||
newUri?: UriComponents;
|
||||
options?: {
|
||||
@@ -1005,76 +999,76 @@ export interface ResourceFileEditDto {
|
||||
};
|
||||
}
|
||||
|
||||
export interface ResourceTextEditDto {
|
||||
export interface IResourceTextEditDto {
|
||||
resource: UriComponents;
|
||||
modelVersionId?: number;
|
||||
edits: modes.TextEdit[];
|
||||
}
|
||||
|
||||
export interface WorkspaceEditDto {
|
||||
edits: Array<ResourceFileEditDto | ResourceTextEditDto>;
|
||||
export interface IWorkspaceEditDto {
|
||||
edits: Array<IResourceFileEditDto | IResourceTextEditDto>;
|
||||
|
||||
// todo@joh reject should go into rename
|
||||
rejectReason?: string;
|
||||
}
|
||||
|
||||
export function reviveWorkspaceEditDto(data: WorkspaceEditDto | undefined): modes.WorkspaceEdit {
|
||||
export function reviveWorkspaceEditDto(data: IWorkspaceEditDto | undefined): modes.WorkspaceEdit {
|
||||
if (data && data.edits) {
|
||||
for (const edit of data.edits) {
|
||||
if (typeof (<ResourceTextEditDto>edit).resource === 'object') {
|
||||
(<ResourceTextEditDto>edit).resource = URI.revive((<ResourceTextEditDto>edit).resource);
|
||||
if (typeof (<IResourceTextEditDto>edit).resource === 'object') {
|
||||
(<IResourceTextEditDto>edit).resource = URI.revive((<IResourceTextEditDto>edit).resource);
|
||||
} else {
|
||||
(<ResourceFileEditDto>edit).newUri = URI.revive((<ResourceFileEditDto>edit).newUri);
|
||||
(<ResourceFileEditDto>edit).oldUri = URI.revive((<ResourceFileEditDto>edit).oldUri);
|
||||
(<IResourceFileEditDto>edit).newUri = URI.revive((<IResourceFileEditDto>edit).newUri);
|
||||
(<IResourceFileEditDto>edit).oldUri = URI.revive((<IResourceFileEditDto>edit).oldUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
return <modes.WorkspaceEdit>data;
|
||||
}
|
||||
|
||||
export type CommandDto = ObjectIdentifier & modes.Command;
|
||||
export type ICommandDto = ObjectIdentifier & modes.Command;
|
||||
|
||||
export interface CodeActionDto {
|
||||
export interface ICodeActionDto {
|
||||
title: string;
|
||||
edit?: WorkspaceEditDto;
|
||||
edit?: IWorkspaceEditDto;
|
||||
diagnostics?: IMarkerData[];
|
||||
command?: CommandDto;
|
||||
command?: ICommandDto;
|
||||
kind?: string;
|
||||
isPreferred?: boolean;
|
||||
}
|
||||
|
||||
export interface CodeActionListDto {
|
||||
export interface ICodeActionListDto {
|
||||
cacheId: number;
|
||||
actions: ReadonlyArray<CodeActionDto>;
|
||||
actions: ReadonlyArray<ICodeActionDto>;
|
||||
}
|
||||
|
||||
export type CacheId = number;
|
||||
export type ChainedCacheId = [CacheId, CacheId];
|
||||
|
||||
export interface LinksListDto {
|
||||
export interface ILinksListDto {
|
||||
id?: CacheId;
|
||||
links: LinkDto[];
|
||||
links: ILinkDto[];
|
||||
}
|
||||
|
||||
export interface LinkDto {
|
||||
export interface ILinkDto {
|
||||
cacheId?: ChainedCacheId;
|
||||
range: IRange;
|
||||
url?: string | UriComponents;
|
||||
tooltip?: string;
|
||||
}
|
||||
|
||||
export interface CodeLensListDto {
|
||||
export interface ICodeLensListDto {
|
||||
cacheId?: number;
|
||||
lenses: CodeLensDto[];
|
||||
lenses: ICodeLensDto[];
|
||||
}
|
||||
|
||||
export interface CodeLensDto {
|
||||
export interface ICodeLensDto {
|
||||
cacheId?: ChainedCacheId;
|
||||
range: IRange;
|
||||
command?: CommandDto;
|
||||
command?: ICommandDto;
|
||||
}
|
||||
|
||||
export interface CallHierarchyDto {
|
||||
export interface ICallHierarchyDto {
|
||||
_id: number;
|
||||
kind: modes.SymbolKind;
|
||||
name: string;
|
||||
@@ -1086,40 +1080,40 @@ export interface CallHierarchyDto {
|
||||
|
||||
export interface ExtHostLanguageFeaturesShape {
|
||||
$provideDocumentSymbols(handle: number, resource: UriComponents, token: CancellationToken): Promise<modes.DocumentSymbol[] | undefined>;
|
||||
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<CodeLensListDto | undefined>;
|
||||
$resolveCodeLens(handle: number, symbol: CodeLensDto, token: CancellationToken): Promise<CodeLensDto | undefined>;
|
||||
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<ICodeLensListDto | undefined>;
|
||||
$resolveCodeLens(handle: number, symbol: ICodeLensDto, token: CancellationToken): Promise<ICodeLensDto | undefined>;
|
||||
$releaseCodeLenses(handle: number, id: number): void;
|
||||
$provideDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<DefinitionLinkDto[]>;
|
||||
$provideDeclaration(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<DefinitionLinkDto[]>;
|
||||
$provideImplementation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<DefinitionLinkDto[]>;
|
||||
$provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<DefinitionLinkDto[]>;
|
||||
$provideDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<IDefinitionLinkDto[]>;
|
||||
$provideDeclaration(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<IDefinitionLinkDto[]>;
|
||||
$provideImplementation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<IDefinitionLinkDto[]>;
|
||||
$provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<IDefinitionLinkDto[]>;
|
||||
$provideHover(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.Hover | undefined>;
|
||||
$provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.DocumentHighlight[] | undefined>;
|
||||
$provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext, token: CancellationToken): Promise<LocationDto[] | undefined>;
|
||||
$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<CodeActionListDto | undefined>;
|
||||
$provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext, token: CancellationToken): Promise<ILocationDto[] | undefined>;
|
||||
$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<ICodeActionListDto | undefined>;
|
||||
$releaseCodeActions(handle: number, cacheId: number): void;
|
||||
$provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined>;
|
||||
$provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined>;
|
||||
$provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined>;
|
||||
$provideWorkspaceSymbols(handle: number, search: string, token: CancellationToken): Promise<WorkspaceSymbolsDto>;
|
||||
$resolveWorkspaceSymbol(handle: number, symbol: WorkspaceSymbolDto, token: CancellationToken): Promise<WorkspaceSymbolDto | undefined>;
|
||||
$provideWorkspaceSymbols(handle: number, search: string, token: CancellationToken): Promise<IWorkspaceSymbolsDto>;
|
||||
$resolveWorkspaceSymbol(handle: number, symbol: IWorkspaceSymbolDto, token: CancellationToken): Promise<IWorkspaceSymbolDto | undefined>;
|
||||
$releaseWorkspaceSymbols(handle: number, id: number): void;
|
||||
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Promise<WorkspaceEditDto | undefined>;
|
||||
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Promise<IWorkspaceEditDto | undefined>;
|
||||
$resolveRenameLocation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.RenameLocation | undefined>;
|
||||
$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<SuggestResultDto | undefined>;
|
||||
$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, id: ChainedCacheId, token: CancellationToken): Promise<SuggestDataDto | undefined>;
|
||||
$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<ISuggestResultDto | undefined>;
|
||||
$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, id: ChainedCacheId, token: CancellationToken): Promise<ISuggestDataDto | undefined>;
|
||||
$releaseCompletionItems(handle: number, id: number): void;
|
||||
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<SignatureHelpDto | undefined>;
|
||||
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<ISignatureHelpDto | undefined>;
|
||||
$releaseSignatureHelp(handle: number, id: number): void;
|
||||
$provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Promise<LinksListDto | undefined>;
|
||||
$resolveDocumentLink(handle: number, id: ChainedCacheId, token: CancellationToken): Promise<LinkDto | undefined>;
|
||||
$provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Promise<ILinksListDto | undefined>;
|
||||
$resolveDocumentLink(handle: number, id: ChainedCacheId, token: CancellationToken): Promise<ILinkDto | undefined>;
|
||||
$releaseDocumentLinks(handle: number, id: number): void;
|
||||
$provideDocumentColors(handle: number, resource: UriComponents, token: CancellationToken): Promise<IRawColorInfo[]>;
|
||||
$provideColorPresentations(handle: number, resource: UriComponents, colorInfo: IRawColorInfo, token: CancellationToken): Promise<modes.IColorPresentation[] | undefined>;
|
||||
$provideFoldingRanges(handle: number, resource: UriComponents, context: modes.FoldingContext, token: CancellationToken): Promise<modes.FoldingRange[] | undefined>;
|
||||
$provideSelectionRanges(handle: number, resource: UriComponents, positions: IPosition[], token: CancellationToken): Promise<modes.SelectionRange[][]>;
|
||||
$provideCallHierarchyItem(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<CallHierarchyDto | undefined>;
|
||||
$resolveCallHierarchyItem(handle: number, item: callHierarchy.CallHierarchyItem, direction: callHierarchy.CallHierarchyDirection, token: CancellationToken): Promise<[CallHierarchyDto, modes.Location[]][]>;
|
||||
$provideCallHierarchyItem(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<ICallHierarchyDto | undefined>;
|
||||
$resolveCallHierarchyItem(handle: number, item: callHierarchy.CallHierarchyItem, direction: callHierarchy.CallHierarchyDirection, token: CancellationToken): Promise<[ICallHierarchyDto, modes.Location[]][]>;
|
||||
}
|
||||
|
||||
export interface ExtHostQuickOpenShape {
|
||||
@@ -1133,7 +1127,7 @@ export interface ExtHostQuickOpenShape {
|
||||
$onDidHide(sessionId: number): void;
|
||||
}
|
||||
|
||||
export interface ShellLaunchConfigDto {
|
||||
export interface IShellLaunchConfigDto {
|
||||
name?: string;
|
||||
executable?: string;
|
||||
args?: string[] | string;
|
||||
@@ -1161,12 +1155,13 @@ export interface ExtHostTerminalServiceShape {
|
||||
$acceptTerminalOpened(id: number, name: string): void;
|
||||
$acceptActiveTerminalChanged(id: number | null): void;
|
||||
$acceptTerminalProcessId(id: number, processId: number): void;
|
||||
/** @deprecated */
|
||||
$acceptTerminalProcessData(id: number, data: string): void;
|
||||
$acceptTerminalRendererInput(id: number, data: string): void;
|
||||
$acceptTerminalProcessData2(id: number, data: string): void;
|
||||
$acceptTerminalTitleChange(id: number, name: string): void;
|
||||
$acceptTerminalDimensions(id: number, cols: number, rows: number): void;
|
||||
$acceptTerminalMaximumDimensions(id: number, cols: number, rows: number): void;
|
||||
$spawnExtHostProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, activeWorkspaceRootUri: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void;
|
||||
$spawnExtHostProcess(id: number, shellLaunchConfig: IShellLaunchConfigDto, activeWorkspaceRootUri: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void;
|
||||
$startExtensionTerminal(id: number, initialDimensions: ITerminalDimensionsDto | undefined): void;
|
||||
$acceptProcessInput(id: number, data: string): void;
|
||||
$acceptProcessResize(id: number, cols: number, rows: number): void;
|
||||
@@ -1176,7 +1171,7 @@ export interface ExtHostTerminalServiceShape {
|
||||
$acceptProcessRequestLatency(id: number): number;
|
||||
$acceptWorkspacePermissionsChanged(isAllowed: boolean): void;
|
||||
$requestAvailableShells(): Promise<IShellDefinitionDto[]>;
|
||||
$requestDefaultShellAndArgs(): Promise<IShellAndArgsDto>;
|
||||
$requestDefaultShellAndArgs(useAutomationShell: boolean): Promise<IShellAndArgsDto>;
|
||||
}
|
||||
|
||||
export interface ExtHostSCMShape {
|
||||
@@ -1254,8 +1249,8 @@ export interface ExtHostDebugServiceShape {
|
||||
$startDASession(handle: number, session: IDebugSessionDto): Promise<void>;
|
||||
$stopDASession(handle: number): Promise<void>;
|
||||
$sendDAMessage(handle: number, message: DebugProtocol.ProtocolMessage): void;
|
||||
$resolveDebugConfiguration(handle: number, folder: UriComponents | undefined, debugConfiguration: IConfig): Promise<IConfig | null | undefined>;
|
||||
$provideDebugConfigurations(handle: number, folder: UriComponents | undefined): Promise<IConfig[]>;
|
||||
$resolveDebugConfiguration(handle: number, folder: UriComponents | undefined, debugConfiguration: IConfig, token: CancellationToken): Promise<IConfig | null | undefined>;
|
||||
$provideDebugConfigurations(handle: number, folder: UriComponents | undefined, token: CancellationToken): Promise<IConfig[]>;
|
||||
$legacyDebugAdapterExecutable(handle: number, folderUri: UriComponents | undefined): Promise<IAdapterDescriptor>; // TODO@AW legacy
|
||||
$provideDebugAdapter(handle: number, session: IDebugSessionDto): Promise<IAdapterDescriptor>;
|
||||
$acceptDebugSessionStarted(session: IDebugSessionDto): void;
|
||||
@@ -1360,7 +1355,6 @@ export const ExtHostContext = {
|
||||
ExtHostDocumentSaveParticipant: createExtId<ExtHostDocumentSaveParticipantShape>('ExtHostDocumentSaveParticipant'),
|
||||
ExtHostEditors: createExtId<ExtHostEditorsShape>('ExtHostEditors'),
|
||||
ExtHostTreeViews: createExtId<ExtHostTreeViewsShape>('ExtHostTreeViews'),
|
||||
ExtHostDownloadService: createExtId<ExtHostDownloadServiceShape>('ExtHostDownloadService'),
|
||||
ExtHostFileSystem: createExtId<ExtHostFileSystemShape>('ExtHostFileSystem'),
|
||||
ExtHostFileSystemEventService: createExtId<ExtHostFileSystemEventServiceShape>('ExtHostFileSystemEventService'),
|
||||
ExtHostLanguageFeatures: createExtId<ExtHostLanguageFeaturesShape>('ExtHostLanguageFeatures'),
|
||||
|
||||
@@ -8,7 +8,7 @@ import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import * as vscode from 'vscode';
|
||||
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import * as types from 'vs/workbench/api/common/extHostTypes';
|
||||
import { IRawColorInfo, WorkspaceEditDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { IRawColorInfo, IWorkspaceEditDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ISingleEditOperation } from 'vs/editor/common/model';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import * as search from 'vs/workbench/contrib/search/common/search';
|
||||
@@ -135,7 +135,7 @@ export class ExtHostApiCommands {
|
||||
description: 'Execute code action provider.',
|
||||
args: [
|
||||
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
|
||||
{ name: 'range', description: 'Range in a text document', constraint: types.Range },
|
||||
{ name: 'rangeOrSelection', description: 'Range in a text document. Some refactoring provider requires Selection object.', constraint: types.Range },
|
||||
{ name: 'kind', description: '(optional) Code action kind to return code actions for', constraint: (value: any) => !value || typeof value.value === 'string' },
|
||||
],
|
||||
returns: 'A promise that resolves to an array of Command-instances.'
|
||||
@@ -362,7 +362,7 @@ export class ExtHostApiCommands {
|
||||
position: position && typeConverters.Position.from(position),
|
||||
newName
|
||||
};
|
||||
return this._commands.executeCommand<WorkspaceEditDto>('_executeDocumentRenameProvider', args).then(value => {
|
||||
return this._commands.executeCommand<IWorkspaceEditDto>('_executeDocumentRenameProvider', args).then(value => {
|
||||
if (!value) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -470,20 +470,22 @@ export class ExtHostApiCommands {
|
||||
return res;
|
||||
}
|
||||
|
||||
detail: string;
|
||||
range: vscode.Range;
|
||||
selectionRange: vscode.Range;
|
||||
children: vscode.DocumentSymbol[];
|
||||
containerName: string;
|
||||
detail!: string;
|
||||
range!: vscode.Range;
|
||||
selectionRange!: vscode.Range;
|
||||
children!: vscode.DocumentSymbol[];
|
||||
containerName!: string;
|
||||
}
|
||||
return value.map(MergedInfo.to);
|
||||
});
|
||||
}
|
||||
|
||||
private _executeCodeActionProvider(resource: URI, range: types.Range, kind?: string): Promise<(vscode.CodeAction | vscode.Command | undefined)[] | undefined> {
|
||||
private _executeCodeActionProvider(resource: URI, rangeOrSelection: types.Range | types.Selection, kind?: string): Promise<(vscode.CodeAction | vscode.Command | undefined)[] | undefined> {
|
||||
const args = {
|
||||
resource,
|
||||
range: typeConverters.Range.from(range),
|
||||
rangeOrSelection: types.Selection.isSelection(rangeOrSelection)
|
||||
? typeConverters.Selection.from(rangeOrSelection)
|
||||
: typeConverters.Range.from(rangeOrSelection),
|
||||
kind
|
||||
};
|
||||
return this._commands.executeCommand<CustomCodeAction[]>('_executeCodeActionProvider', args)
|
||||
@@ -504,6 +506,7 @@ export class ExtHostApiCommands {
|
||||
if (codeAction.command) {
|
||||
ret.command = this._commands.converter.fromInternal(codeAction.command);
|
||||
}
|
||||
ret.isPreferred = codeAction.isPreferred;
|
||||
return ret;
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -63,7 +63,7 @@ export class ExtHostEditorInsets implements ExtHostEditorInsetsShape {
|
||||
|
||||
private readonly _uuid = generateUuid();
|
||||
private _html: string = '';
|
||||
private _options: vscode.WebviewOptions;
|
||||
private _options: vscode.WebviewOptions = Object.create(null);
|
||||
|
||||
toWebviewResource(resource: vscode.Uri): vscode.Uri {
|
||||
return toWebviewResource(that._initData, this._uuid, resource);
|
||||
|
||||
@@ -8,7 +8,7 @@ import { ICommandHandlerDescription, ICommandEvent } from 'vs/platform/commands/
|
||||
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
|
||||
import * as extHostTypeConverter from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { cloneAndChange } from 'vs/base/common/objects';
|
||||
import { MainContext, MainThreadCommandsShape, ExtHostCommandsShape, ObjectIdentifier, IMainContext, CommandDto } from './extHost.protocol';
|
||||
import { MainContext, MainThreadCommandsShape, ExtHostCommandsShape, ObjectIdentifier, ICommandDto } from './extHost.protocol';
|
||||
import { isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import * as vscode from 'vscode';
|
||||
@@ -19,6 +19,8 @@ import { Position } from 'vs/editor/common/core/position';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
|
||||
interface CommandHandler {
|
||||
callback: Function;
|
||||
@@ -32,6 +34,8 @@ export interface ArgumentProcessor {
|
||||
|
||||
export class ExtHostCommands implements ExtHostCommandsShape {
|
||||
|
||||
readonly _serviceBrand: any;
|
||||
|
||||
private readonly _onDidExecuteCommand: Emitter<vscode.CommandExecutionEvent>;
|
||||
readonly onDidExecuteCommand: Event<vscode.CommandExecutionEvent>;
|
||||
|
||||
@@ -42,10 +46,10 @@ export class ExtHostCommands implements ExtHostCommandsShape {
|
||||
private readonly _argumentProcessors: ArgumentProcessor[];
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
logService: ILogService
|
||||
@IExtHostRpcService extHostRpc: IExtHostRpcService,
|
||||
@ILogService logService: ILogService
|
||||
) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadCommands);
|
||||
this._proxy = extHostRpc.getProxy(MainContext.MainThreadCommands);
|
||||
this._onDidExecuteCommand = new Emitter<vscode.CommandExecutionEvent>({
|
||||
onFirstListenerDidAdd: () => this._proxy.$registerCommandListener(),
|
||||
onLastListenerRemove: () => this._proxy.$unregisterCommandListener(),
|
||||
@@ -228,13 +232,13 @@ export class CommandsConverter {
|
||||
this._commands.registerCommand(true, this._delegatingCommandId, this._executeConvertedCommand, this);
|
||||
}
|
||||
|
||||
toInternal(command: vscode.Command | undefined, disposables: DisposableStore): CommandDto | undefined {
|
||||
toInternal(command: vscode.Command | undefined, disposables: DisposableStore): ICommandDto | undefined {
|
||||
|
||||
if (!command) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const result: CommandDto = {
|
||||
const result: ICommandDto = {
|
||||
$ident: undefined,
|
||||
id: command.command,
|
||||
title: command.title,
|
||||
@@ -282,3 +286,6 @@ export class CommandsConverter {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export interface IExtHostCommands extends ExtHostCommands { }
|
||||
export const IExtHostCommands = createDecorator<IExtHostCommands>('IExtHostCommands');
|
||||
|
||||
@@ -253,13 +253,13 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
||||
return this._range;
|
||||
}
|
||||
|
||||
private _label: string;
|
||||
private _label: string | undefined;
|
||||
|
||||
get label(): string {
|
||||
get label(): string | undefined {
|
||||
return this._label;
|
||||
}
|
||||
|
||||
set label(label: string) {
|
||||
set label(label: string | undefined) {
|
||||
this._label = label;
|
||||
this._onDidUpdateCommentThread.fire();
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import { mixin, deepClone } from 'vs/base/common/objects';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { ExtHostConfigurationShape, MainThreadConfigurationShape, IWorkspaceConfigurationChangeEventData, IConfigurationInitData } from './extHost.protocol';
|
||||
import { ExtHostWorkspace, IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { ExtHostConfigurationShape, MainThreadConfigurationShape, IWorkspaceConfigurationChangeEventData, IConfigurationInitData, MainContext } from './extHost.protocol';
|
||||
import { ConfigurationTarget as ExtHostConfigurationTarget } from './extHostTypes';
|
||||
import { IConfigurationData, ConfigurationTarget, IConfigurationModel } from 'vs/platform/configuration/common/configuration';
|
||||
import { Configuration, ConfigurationChangeEvent, ConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
|
||||
@@ -18,6 +18,8 @@ import { ConfigurationScope, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/confi
|
||||
import { isObject } from 'vs/base/common/types';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { Barrier } from 'vs/base/common/async';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
|
||||
function lookUp(tree: any, key: string) {
|
||||
if (key) {
|
||||
@@ -40,13 +42,18 @@ type ConfigurationInspect<T> = {
|
||||
|
||||
export class ExtHostConfiguration implements ExtHostConfigurationShape {
|
||||
|
||||
readonly _serviceBrand: any;
|
||||
|
||||
private readonly _proxy: MainThreadConfigurationShape;
|
||||
private readonly _extHostWorkspace: ExtHostWorkspace;
|
||||
private readonly _barrier: Barrier;
|
||||
private _actual: ExtHostConfigProvider | null;
|
||||
|
||||
constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace) {
|
||||
this._proxy = proxy;
|
||||
constructor(
|
||||
@IExtHostRpcService extHostRpc: IExtHostRpcService,
|
||||
@IExtHostWorkspace extHostWorkspace: IExtHostWorkspace
|
||||
) {
|
||||
this._proxy = extHostRpc.getProxy(MainContext.MainThreadConfiguration);
|
||||
this._extHostWorkspace = extHostWorkspace;
|
||||
this._barrier = new Barrier();
|
||||
this._actual = null;
|
||||
@@ -274,3 +281,6 @@ export class ExtHostConfigProvider {
|
||||
return new ConfigurationModel(model.contents, model.keys, model.overrides).freeze();
|
||||
}
|
||||
}
|
||||
|
||||
export const IExtHostConfiguration = createDecorator<IExtHostConfiguration>('IExtHostConfiguration');
|
||||
export interface IExtHostConfiguration extends ExtHostConfiguration { }
|
||||
|
||||
34
src/vs/workbench/api/common/extHostDebugService.ts
Normal file
34
src/vs/workbench/api/common/extHostDebugService.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { ExtHostDebugServiceShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import * as vscode from 'vscode';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export const IExtHostDebugService = createDecorator<IExtHostDebugService>('IExtHostDebugService');
|
||||
|
||||
export interface IExtHostDebugService extends ExtHostDebugServiceShape {
|
||||
|
||||
readonly _serviceBrand: any;
|
||||
|
||||
onDidStartDebugSession: Event<vscode.DebugSession>;
|
||||
onDidTerminateDebugSession: Event<vscode.DebugSession>;
|
||||
onDidChangeActiveDebugSession: Event<vscode.DebugSession | undefined>;
|
||||
activeDebugSession: vscode.DebugSession | undefined;
|
||||
activeDebugConsole: vscode.DebugConsole;
|
||||
onDidReceiveDebugSessionCustomEvent: Event<vscode.DebugSessionCustomEvent>;
|
||||
onDidChangeBreakpoints: Event<vscode.BreakpointsChangeEvent>;
|
||||
breakpoints: vscode.Breakpoint[];
|
||||
|
||||
addBreakpoints(breakpoints0: vscode.Breakpoint[]): Promise<void>;
|
||||
removeBreakpoints(breakpoints0: vscode.Breakpoint[]): Promise<void>;
|
||||
startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration, parentSession?: vscode.DebugSession): Promise<boolean>;
|
||||
registerDebugConfigurationProvider(type: string, provider: vscode.DebugConfigurationProvider): vscode.Disposable;
|
||||
registerDebugAdapterDescriptorFactory(extension: IExtensionDescription, type: string, factory: vscode.DebugAdapterDescriptorFactory): vscode.Disposable;
|
||||
registerDebugAdapterTrackerFactory(type: string, factory: vscode.DebugAdapterTrackerFactory): vscode.Disposable;
|
||||
}
|
||||
|
||||
@@ -5,26 +5,31 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { MainContext, IMainContext, ExtHostDecorationsShape, MainThreadDecorationsShape, DecorationData, DecorationRequest, DecorationReply } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { MainContext, ExtHostDecorationsShape, MainThreadDecorationsShape, DecorationData, DecorationRequest, DecorationReply } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { Disposable } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { asArray } from 'vs/base/common/arrays';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
|
||||
interface ProviderData {
|
||||
provider: vscode.DecorationProvider;
|
||||
extensionId: ExtensionIdentifier;
|
||||
}
|
||||
|
||||
export class ExtHostDecorations implements ExtHostDecorationsShape {
|
||||
export class ExtHostDecorations implements IExtHostDecorations {
|
||||
|
||||
private static _handlePool = 0;
|
||||
|
||||
readonly _serviceBrand: undefined;
|
||||
private readonly _provider = new Map<number, ProviderData>();
|
||||
private readonly _proxy: MainThreadDecorationsShape;
|
||||
|
||||
constructor(mainContext: IMainContext) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadDecorations);
|
||||
constructor(
|
||||
@IExtHostRpcService extHostRpc: IExtHostRpcService,
|
||||
) {
|
||||
this._proxy = extHostRpc.getProxy(MainContext.MainThreadDecorations);
|
||||
}
|
||||
|
||||
registerDecorationProvider(provider: vscode.DecorationProvider, extensionId: ExtensionIdentifier): vscode.Disposable {
|
||||
@@ -70,3 +75,6 @@ export class ExtHostDecorations implements ExtHostDecorationsShape {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const IExtHostDecorations = createDecorator<IExtHostDecorations>('IExtHostDecorations');
|
||||
export interface IExtHostDecorations extends ExtHostDecorations, ExtHostDecorationsShape { }
|
||||
|
||||
@@ -50,7 +50,7 @@ export class ExtHostDocumentContentProvider implements ExtHostDocumentContentPro
|
||||
}
|
||||
if (this._documentsAndEditors.getDocument(uri)) {
|
||||
this.$provideTextDocumentContent(handle, uri).then(value => {
|
||||
if (!value) {
|
||||
if (!value && typeof value !== 'string') {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ export class ExtHostDocumentData extends MirrorTextModel {
|
||||
private _proxy: MainThreadDocumentsShape;
|
||||
private _languageId: string;
|
||||
private _isDirty: boolean;
|
||||
private _document: vscode.TextDocument;
|
||||
private _document?: vscode.TextDocument;
|
||||
private _textLines: vscode.TextLine[] = [];
|
||||
private _isDisposed: boolean = false;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Event } from 'vs/base/common/event';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { sequence } from 'vs/base/common/async';
|
||||
import { illegalState } from 'vs/base/common/errors';
|
||||
import { ExtHostDocumentSaveParticipantShape, MainThreadTextEditorsShape, ResourceTextEditDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostDocumentSaveParticipantShape, MainThreadTextEditorsShape, IResourceTextEditDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { TextEdit } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { Range, TextDocumentSaveReason, EndOfLine } from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
@@ -142,7 +142,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
|
||||
|
||||
}).then(values => {
|
||||
|
||||
const resourceEdit: ResourceTextEditDto = {
|
||||
const resourceEdit: IResourceTextEditDto = {
|
||||
resource: document.uri,
|
||||
edits: []
|
||||
};
|
||||
@@ -153,7 +153,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
|
||||
resourceEdit.edits.push({
|
||||
range: range && Range.from(range),
|
||||
text: newText,
|
||||
eol: EndOfLine.from(newEol)
|
||||
eol: newEol && EndOfLine.from(newEol)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,17 +7,21 @@ import * as assert from 'vs/base/common/assert';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { dispose } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ExtHostDocumentsAndEditorsShape, IDocumentsAndEditorsDelta, IMainContext, MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostDocumentsAndEditorsShape, IDocumentsAndEditorsDelta, MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData';
|
||||
import { ExtHostTextEditor } from 'vs/workbench/api/common/extHostTextEditor';
|
||||
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { Disposable } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
|
||||
export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsShape {
|
||||
|
||||
readonly _serviceBrand: any;
|
||||
|
||||
private _disposables: Disposable[] = [];
|
||||
|
||||
private _activeEditorId: string | null;
|
||||
private _activeEditorId: string | null = null;
|
||||
|
||||
private readonly _editors = new Map<string, ExtHostTextEditor>();
|
||||
private readonly _documents = new Map<string, ExtHostDocumentData>();
|
||||
@@ -33,7 +37,7 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
|
||||
readonly onDidChangeActiveTextEditor: Event<ExtHostTextEditor | undefined> = this._onDidChangeActiveTextEditor.event;
|
||||
|
||||
constructor(
|
||||
private readonly _mainContext: IMainContext,
|
||||
@IExtHostRpcService private readonly _extHostRpc: IExtHostRpcService,
|
||||
) { }
|
||||
|
||||
dispose() {
|
||||
@@ -64,7 +68,7 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
|
||||
assert.ok(!this._documents.has(resource.toString()), `document '${resource} already exists!'`);
|
||||
|
||||
const documentData = new ExtHostDocumentData(
|
||||
this._mainContext.getProxy(MainContext.MainThreadDocuments),
|
||||
this._extHostRpc.getProxy(MainContext.MainThreadDocuments),
|
||||
resource,
|
||||
data.lines,
|
||||
data.EOL,
|
||||
@@ -95,7 +99,7 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
|
||||
|
||||
const documentData = this._documents.get(resource.toString())!;
|
||||
const editor = new ExtHostTextEditor(
|
||||
this._mainContext.getProxy(MainContext.MainThreadTextEditors),
|
||||
this._extHostRpc.getProxy(MainContext.MainThreadTextEditors),
|
||||
data.id,
|
||||
documentData,
|
||||
data.selections.map(typeConverters.Selection.to),
|
||||
@@ -159,3 +163,6 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IExtHostDocumentsAndEditors extends ExtHostDocumentsAndEditors { }
|
||||
export const IExtHostDocumentsAndEditors = createDecorator<IExtHostDocumentsAndEditors>('IExtHostDocumentsAndEditors');
|
||||
|
||||
779
src/vs/workbench/api/common/extHostExtensionService.ts
Normal file
779
src/vs/workbench/api/common/extHostExtensionService.ts
Normal file
@@ -0,0 +1,779 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import { originalFSPath } from 'vs/base/common/resources';
|
||||
import { Barrier } from 'vs/base/common/async';
|
||||
import { dispose, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { TernarySearchTree } from 'vs/base/common/map';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ExtHostExtensionServiceShape, IInitData, MainContext, MainThreadExtensionServiceShape, MainThreadTelemetryShape, MainThreadWorkspaceShape, IResolveAuthorityResult } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostConfiguration, IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { ActivatedExtension, EmptyExtension, ExtensionActivatedByAPI, ExtensionActivatedByEvent, ExtensionActivationReason, ExtensionActivationTimes, ExtensionActivationTimesBuilder, ExtensionsActivator, IExtensionAPI, IExtensionContext, IExtensionModule, HostExtension, ExtensionActivationTimesFragment } from 'vs/workbench/api/common/extHostExtensionActivator';
|
||||
import { ExtHostLogService } from 'vs/workbench/api/common/extHostLogService';
|
||||
import { ExtHostStorage, IExtHostStorage } from 'vs/workbench/api/common/extHostStorage';
|
||||
import { ExtHostWorkspace, IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { ExtensionActivationError } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { ExtensionMemento } from 'vs/workbench/api/common/extHostMemento';
|
||||
import { RemoteAuthorityResolverError, ExtensionExecutionContext } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { ResolvedAuthority, ResolvedOptions } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { IInstantiationService, createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
|
||||
interface ITestRunner {
|
||||
/** Old test runner API, as exported from `vscode/lib/testrunner` */
|
||||
run(testsRoot: string, clb: (error: Error, failures?: number) => void): void;
|
||||
}
|
||||
|
||||
interface INewTestRunner {
|
||||
/** New test runner API, as explained in the extension test doc */
|
||||
run(): Promise<void>;
|
||||
}
|
||||
|
||||
export const IHostUtils = createDecorator<IHostUtils>('IHostUtils');
|
||||
|
||||
export interface IHostUtils {
|
||||
_serviceBrand: undefined;
|
||||
exit(code?: number): void;
|
||||
exists(path: string): Promise<boolean>;
|
||||
realpath(path: string): Promise<string>;
|
||||
}
|
||||
|
||||
type TelemetryActivationEventFragment = {
|
||||
id: { classification: 'PublicNonPersonalData', purpose: 'FeatureInsight' };
|
||||
name: { classification: 'PublicNonPersonalData', purpose: 'FeatureInsight' };
|
||||
extensionVersion: { classification: 'PublicNonPersonalData', purpose: 'FeatureInsight' };
|
||||
publisherDisplayName: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
activationEvents: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
isBuiltin: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true };
|
||||
reason: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
};
|
||||
|
||||
export abstract class AbstractExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
|
||||
readonly _serviceBrand: any;
|
||||
|
||||
private static readonly WORKSPACE_CONTAINS_TIMEOUT = 7000;
|
||||
|
||||
protected readonly _hostUtils: IHostUtils;
|
||||
protected readonly _initData: IInitData;
|
||||
protected readonly _extHostContext: IExtHostRpcService;
|
||||
protected readonly _instaService: IInstantiationService;
|
||||
protected readonly _extHostWorkspace: ExtHostWorkspace;
|
||||
protected readonly _extHostConfiguration: ExtHostConfiguration;
|
||||
protected readonly _extHostLogService: ExtHostLogService;
|
||||
|
||||
protected readonly _mainThreadWorkspaceProxy: MainThreadWorkspaceShape;
|
||||
protected readonly _mainThreadTelemetryProxy: MainThreadTelemetryShape;
|
||||
protected readonly _mainThreadExtensionsProxy: MainThreadExtensionServiceShape;
|
||||
|
||||
private readonly _almostReadyToRunExtensions: Barrier;
|
||||
private readonly _readyToStartExtensionHost: Barrier;
|
||||
private readonly _readyToRunExtensions: Barrier;
|
||||
protected readonly _registry: ExtensionDescriptionRegistry;
|
||||
private readonly _storage: ExtHostStorage;
|
||||
private readonly _storagePath: IExtensionStoragePaths;
|
||||
private readonly _activator: ExtensionsActivator;
|
||||
private _extensionPathIndex: Promise<TernarySearchTree<IExtensionDescription>> | null;
|
||||
|
||||
private readonly _resolvers: { [authorityPrefix: string]: vscode.RemoteAuthorityResolver; };
|
||||
|
||||
private _started: boolean;
|
||||
|
||||
private readonly _disposables: DisposableStore;
|
||||
|
||||
constructor(
|
||||
@IInstantiationService instaService: IInstantiationService,
|
||||
@IHostUtils hostUtils: IHostUtils,
|
||||
@IExtHostRpcService extHostContext: IExtHostRpcService,
|
||||
@IExtHostWorkspace extHostWorkspace: IExtHostWorkspace,
|
||||
@IExtHostConfiguration extHostConfiguration: IExtHostConfiguration,
|
||||
@ILogService extHostLogService: ExtHostLogService,
|
||||
@IExtHostInitDataService initData: IExtHostInitDataService,
|
||||
@IExtensionStoragePaths storagePath: IExtensionStoragePaths
|
||||
) {
|
||||
this._hostUtils = hostUtils;
|
||||
this._extHostContext = extHostContext;
|
||||
this._initData = initData;
|
||||
|
||||
this._extHostWorkspace = extHostWorkspace;
|
||||
this._extHostConfiguration = extHostConfiguration;
|
||||
this._extHostLogService = extHostLogService;
|
||||
this._disposables = new DisposableStore();
|
||||
|
||||
this._mainThreadWorkspaceProxy = this._extHostContext.getProxy(MainContext.MainThreadWorkspace);
|
||||
this._mainThreadTelemetryProxy = this._extHostContext.getProxy(MainContext.MainThreadTelemetry);
|
||||
this._mainThreadExtensionsProxy = this._extHostContext.getProxy(MainContext.MainThreadExtensionService);
|
||||
|
||||
this._almostReadyToRunExtensions = new Barrier();
|
||||
this._readyToStartExtensionHost = new Barrier();
|
||||
this._readyToRunExtensions = new Barrier();
|
||||
this._registry = new ExtensionDescriptionRegistry(this._initData.extensions);
|
||||
this._storage = new ExtHostStorage(this._extHostContext);
|
||||
this._storagePath = storagePath;
|
||||
|
||||
this._instaService = instaService.createChild(new ServiceCollection(
|
||||
[IExtHostStorage, this._storage]
|
||||
));
|
||||
|
||||
const hostExtensions = new Set<string>();
|
||||
this._initData.hostExtensions.forEach((extensionId) => hostExtensions.add(ExtensionIdentifier.toKey(extensionId)));
|
||||
|
||||
this._activator = new ExtensionsActivator(this._registry, this._initData.resolvedExtensions, this._initData.hostExtensions, {
|
||||
onExtensionActivationError: (extensionId: ExtensionIdentifier, error: ExtensionActivationError): void => {
|
||||
this._mainThreadExtensionsProxy.$onExtensionActivationError(extensionId, error);
|
||||
},
|
||||
|
||||
actualActivateExtension: async (extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<ActivatedExtension> => {
|
||||
if (hostExtensions.has(ExtensionIdentifier.toKey(extensionId))) {
|
||||
const activationEvent = (reason instanceof ExtensionActivatedByEvent ? reason.activationEvent : null);
|
||||
await this._mainThreadExtensionsProxy.$activateExtension(extensionId, activationEvent);
|
||||
return new HostExtension();
|
||||
}
|
||||
const extensionDescription = this._registry.getExtensionDescription(extensionId)!;
|
||||
return this._activateExtension(extensionDescription, reason);
|
||||
}
|
||||
});
|
||||
this._extensionPathIndex = null;
|
||||
this._resolvers = Object.create(null);
|
||||
this._started = false;
|
||||
}
|
||||
|
||||
public async initialize(): Promise<void> {
|
||||
try {
|
||||
|
||||
await this._beforeAlmostReadyToRunExtensions();
|
||||
this._almostReadyToRunExtensions.open();
|
||||
|
||||
await this._extHostWorkspace.waitForInitializeCall();
|
||||
this._readyToStartExtensionHost.open();
|
||||
|
||||
if (this._initData.autoStart) {
|
||||
this._startExtensionHost();
|
||||
}
|
||||
} catch (err) {
|
||||
errors.onUnexpectedError(err);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract _beforeAlmostReadyToRunExtensions(): Promise<void>;
|
||||
|
||||
public async deactivateAll(): Promise<void> {
|
||||
let allPromises: Promise<void>[] = [];
|
||||
try {
|
||||
const allExtensions = this._registry.getAllExtensionDescriptions();
|
||||
const allExtensionsIds = allExtensions.map(ext => ext.identifier);
|
||||
const activatedExtensions = allExtensionsIds.filter(id => this.isActivated(id));
|
||||
|
||||
allPromises = activatedExtensions.map((extensionId) => {
|
||||
return this._deactivate(extensionId);
|
||||
});
|
||||
} catch (err) {
|
||||
// TODO: write to log once we have one
|
||||
}
|
||||
await allPromises;
|
||||
}
|
||||
|
||||
public isActivated(extensionId: ExtensionIdentifier): boolean {
|
||||
if (this._readyToRunExtensions.isOpen()) {
|
||||
return this._activator.isActivated(extensionId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private _activateByEvent(activationEvent: string, startup: boolean): Promise<void> {
|
||||
const reason = new ExtensionActivatedByEvent(startup, activationEvent);
|
||||
return this._activator.activateByEvent(activationEvent, reason);
|
||||
}
|
||||
|
||||
private _activateById(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void> {
|
||||
return this._activator.activateById(extensionId, reason);
|
||||
}
|
||||
|
||||
public activateByIdWithErrors(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void> {
|
||||
return this._activateById(extensionId, reason).then(() => {
|
||||
const extension = this._activator.getActivatedExtension(extensionId);
|
||||
if (extension.activationFailed) {
|
||||
// activation failed => bubble up the error as the promise result
|
||||
return Promise.reject(extension.activationFailedError);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
public getExtensionRegistry(): Promise<ExtensionDescriptionRegistry> {
|
||||
return this._readyToRunExtensions.wait().then(_ => this._registry);
|
||||
}
|
||||
|
||||
public getExtensionExports(extensionId: ExtensionIdentifier): IExtensionAPI | null | undefined {
|
||||
if (this._readyToRunExtensions.isOpen()) {
|
||||
return this._activator.getActivatedExtension(extensionId).exports;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// create trie to enable fast 'filename -> extension id' look up
|
||||
public getExtensionPathIndex(): Promise<TernarySearchTree<IExtensionDescription>> {
|
||||
if (!this._extensionPathIndex) {
|
||||
const tree = TernarySearchTree.forPaths<IExtensionDescription>();
|
||||
const extensions = this._registry.getAllExtensionDescriptions().map(ext => {
|
||||
if (!ext.main) {
|
||||
return undefined;
|
||||
}
|
||||
return this._hostUtils.realpath(ext.extensionLocation.fsPath).then(value => tree.set(URI.file(value).fsPath, ext));
|
||||
});
|
||||
this._extensionPathIndex = Promise.all(extensions).then(() => tree);
|
||||
}
|
||||
return this._extensionPathIndex;
|
||||
}
|
||||
|
||||
private _deactivate(extensionId: ExtensionIdentifier): Promise<void> {
|
||||
let result = Promise.resolve(undefined);
|
||||
|
||||
if (!this._readyToRunExtensions.isOpen()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!this._activator.isActivated(extensionId)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
const extension = this._activator.getActivatedExtension(extensionId);
|
||||
if (!extension) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// call deactivate if available
|
||||
try {
|
||||
if (typeof extension.module.deactivate === 'function') {
|
||||
result = Promise.resolve(extension.module.deactivate()).then(undefined, (err) => {
|
||||
// TODO: Do something with err if this is not the shutdown case
|
||||
return Promise.resolve(undefined);
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
// TODO: Do something with err if this is not the shutdown case
|
||||
}
|
||||
|
||||
// clean up subscriptions
|
||||
try {
|
||||
dispose(extension.subscriptions);
|
||||
} catch (err) {
|
||||
// TODO: Do something with err if this is not the shutdown case
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// --- impl
|
||||
|
||||
private _activateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise<ActivatedExtension> {
|
||||
this._mainThreadExtensionsProxy.$onWillActivateExtension(extensionDescription.identifier);
|
||||
return this._doActivateExtension(extensionDescription, reason).then((activatedExtension) => {
|
||||
const activationTimes = activatedExtension.activationTimes;
|
||||
const activationEvent = (reason instanceof ExtensionActivatedByEvent ? reason.activationEvent : null);
|
||||
this._mainThreadExtensionsProxy.$onDidActivateExtension(extensionDescription.identifier, activationTimes.startup, activationTimes.codeLoadingTime, activationTimes.activateCallTime, activationTimes.activateResolvedTime, activationEvent);
|
||||
this._logExtensionActivationTimes(extensionDescription, reason, 'success', activationTimes);
|
||||
return activatedExtension;
|
||||
}, (err) => {
|
||||
this._logExtensionActivationTimes(extensionDescription, reason, 'failure');
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
private _logExtensionActivationTimes(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason, outcome: string, activationTimes?: ExtensionActivationTimes) {
|
||||
const event = getTelemetryActivationEvent(extensionDescription, reason);
|
||||
type ExtensionActivationTimesClassification = {
|
||||
outcome: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
} & TelemetryActivationEventFragment & ExtensionActivationTimesFragment;
|
||||
|
||||
type ExtensionActivationTimesEvent = {
|
||||
outcome: string
|
||||
} & ActivationTimesEvent & TelemetryActivationEvent;
|
||||
|
||||
type ActivationTimesEvent = {
|
||||
startup?: boolean;
|
||||
codeLoadingTime?: number;
|
||||
activateCallTime?: number;
|
||||
activateResolvedTime?: number;
|
||||
};
|
||||
|
||||
this._mainThreadTelemetryProxy.$publicLog2<ExtensionActivationTimesEvent, ExtensionActivationTimesClassification>('extensionActivationTimes', {
|
||||
...event,
|
||||
...(activationTimes || {}),
|
||||
outcome
|
||||
});
|
||||
}
|
||||
|
||||
private _doActivateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise<ActivatedExtension> {
|
||||
const event = getTelemetryActivationEvent(extensionDescription, reason);
|
||||
type ActivatePluginClassification = {} & TelemetryActivationEventFragment;
|
||||
this._mainThreadTelemetryProxy.$publicLog2<TelemetryActivationEvent, ActivatePluginClassification>('activatePlugin', event);
|
||||
if (!extensionDescription.main) {
|
||||
// Treat the extension as being empty => NOT AN ERROR CASE
|
||||
return Promise.resolve(new EmptyExtension(ExtensionActivationTimes.NONE));
|
||||
}
|
||||
|
||||
this._extHostLogService.info(`ExtensionService#_doActivateExtension ${extensionDescription.identifier.value} ${JSON.stringify(reason)}`);
|
||||
|
||||
const activationTimesBuilder = new ExtensionActivationTimesBuilder(reason.startup);
|
||||
return Promise.all<any>([
|
||||
this._loadCommonJSModule(extensionDescription.main, activationTimesBuilder),
|
||||
this._loadExtensionContext(extensionDescription)
|
||||
]).then(values => {
|
||||
return AbstractExtHostExtensionService._callActivate(this._extHostLogService, extensionDescription.identifier, <IExtensionModule>values[0], <IExtensionContext>values[1], activationTimesBuilder);
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract _loadCommonJSModule<T>(modulePath: string, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<T>;
|
||||
|
||||
private _loadExtensionContext(extensionDescription: IExtensionDescription): Promise<vscode.ExtensionContext> {
|
||||
|
||||
const globalState = new ExtensionMemento(extensionDescription.identifier.value, true, this._storage);
|
||||
const workspaceState = new ExtensionMemento(extensionDescription.identifier.value, false, this._storage);
|
||||
|
||||
this._extHostLogService.trace(`ExtensionService#loadExtensionContext ${extensionDescription.identifier.value}`);
|
||||
return Promise.all([
|
||||
globalState.whenReady,
|
||||
workspaceState.whenReady,
|
||||
this._storagePath.whenReady
|
||||
]).then(() => {
|
||||
const that = this;
|
||||
return Object.freeze(<IExtensionContext>{
|
||||
globalState,
|
||||
workspaceState,
|
||||
subscriptions: [],
|
||||
get extensionPath() { return extensionDescription.extensionLocation.fsPath; },
|
||||
storagePath: this._storagePath.workspaceValue(extensionDescription),
|
||||
globalStoragePath: this._storagePath.globalValue(extensionDescription),
|
||||
asAbsolutePath: (relativePath: string) => { return path.join(extensionDescription.extensionLocation.fsPath, relativePath); },
|
||||
logPath: that._extHostLogService.getLogDirectory(extensionDescription.identifier),
|
||||
executionContext: this._initData.remote.isRemote ? ExtensionExecutionContext.Remote : ExtensionExecutionContext.Local,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private static _callActivate(logService: ILogService, extensionId: ExtensionIdentifier, extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<ActivatedExtension> {
|
||||
// Make sure the extension's surface is not undefined
|
||||
extensionModule = extensionModule || {
|
||||
activate: undefined,
|
||||
deactivate: undefined
|
||||
};
|
||||
|
||||
return this._callActivateOptional(logService, extensionId, extensionModule, context, activationTimesBuilder).then((extensionExports) => {
|
||||
return new ActivatedExtension(false, null, activationTimesBuilder.build(), extensionModule, extensionExports, context.subscriptions);
|
||||
});
|
||||
}
|
||||
|
||||
private static _callActivateOptional(logService: ILogService, extensionId: ExtensionIdentifier, extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<IExtensionAPI> {
|
||||
if (typeof extensionModule.activate === 'function') {
|
||||
try {
|
||||
activationTimesBuilder.activateCallStart();
|
||||
logService.trace(`ExtensionService#_callActivateOptional ${extensionId.value}`);
|
||||
const activateResult: Promise<IExtensionAPI> = extensionModule.activate.apply(global, [context]);
|
||||
activationTimesBuilder.activateCallStop();
|
||||
|
||||
activationTimesBuilder.activateResolveStart();
|
||||
return Promise.resolve(activateResult).then((value) => {
|
||||
activationTimesBuilder.activateResolveStop();
|
||||
return value;
|
||||
});
|
||||
} catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
} else {
|
||||
// No activate found => the module is the extension's exports
|
||||
return Promise.resolve<IExtensionAPI>(extensionModule);
|
||||
}
|
||||
}
|
||||
|
||||
// -- eager activation
|
||||
|
||||
// Handle "eager" activation extensions
|
||||
private _handleEagerExtensions(): Promise<void> {
|
||||
this._activateByEvent('*', true).then(undefined, (err) => {
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
this._disposables.add(this._extHostWorkspace.onDidChangeWorkspace((e) => this._handleWorkspaceContainsEagerExtensions(e.added)));
|
||||
const folders = this._extHostWorkspace.workspace ? this._extHostWorkspace.workspace.folders : [];
|
||||
return this._handleWorkspaceContainsEagerExtensions(folders);
|
||||
}
|
||||
|
||||
private _handleWorkspaceContainsEagerExtensions(folders: ReadonlyArray<vscode.WorkspaceFolder>): Promise<void> {
|
||||
if (folders.length === 0) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
return Promise.all(
|
||||
this._registry.getAllExtensionDescriptions().map((desc) => {
|
||||
return this._handleWorkspaceContainsEagerExtension(folders, desc);
|
||||
})
|
||||
).then(() => { });
|
||||
}
|
||||
|
||||
private _handleWorkspaceContainsEagerExtension(folders: ReadonlyArray<vscode.WorkspaceFolder>, desc: IExtensionDescription): Promise<void> {
|
||||
const activationEvents = desc.activationEvents;
|
||||
if (!activationEvents) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
if (this.isActivated(desc.identifier)) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const fileNames: string[] = [];
|
||||
const globPatterns: string[] = [];
|
||||
|
||||
for (const activationEvent of activationEvents) {
|
||||
if (/^workspaceContains:/.test(activationEvent)) {
|
||||
const fileNameOrGlob = activationEvent.substr('workspaceContains:'.length);
|
||||
if (fileNameOrGlob.indexOf('*') >= 0 || fileNameOrGlob.indexOf('?') >= 0) {
|
||||
globPatterns.push(fileNameOrGlob);
|
||||
} else {
|
||||
fileNames.push(fileNameOrGlob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fileNames.length === 0 && globPatterns.length === 0) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const fileNamePromise = Promise.all(fileNames.map((fileName) => this._activateIfFileName(folders, desc.identifier, fileName))).then(() => { });
|
||||
const globPatternPromise = this._activateIfGlobPatterns(folders, desc.identifier, globPatterns);
|
||||
|
||||
return Promise.all([fileNamePromise, globPatternPromise]).then(() => { });
|
||||
}
|
||||
|
||||
private async _activateIfFileName(folders: ReadonlyArray<vscode.WorkspaceFolder>, extensionId: ExtensionIdentifier, fileName: string): Promise<void> {
|
||||
|
||||
// find exact path
|
||||
for (const { uri } of folders) {
|
||||
if (await this._hostUtils.exists(path.join(URI.revive(uri).fsPath, fileName))) {
|
||||
// the file was found
|
||||
return (
|
||||
this._activateById(extensionId, new ExtensionActivatedByEvent(true, `workspaceContains:${fileName}`))
|
||||
.then(undefined, err => console.error(err))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private async _activateIfGlobPatterns(folders: ReadonlyArray<vscode.WorkspaceFolder>, extensionId: ExtensionIdentifier, globPatterns: string[]): Promise<void> {
|
||||
this._extHostLogService.trace(`extensionHostMain#activateIfGlobPatterns: fileSearch, extension: ${extensionId.value}, entryPoint: workspaceContains`);
|
||||
|
||||
if (globPatterns.length === 0) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const tokenSource = new CancellationTokenSource();
|
||||
const searchP = this._mainThreadWorkspaceProxy.$checkExists(folders.map(folder => folder.uri), globPatterns, tokenSource.token);
|
||||
|
||||
const timer = setTimeout(async () => {
|
||||
tokenSource.cancel();
|
||||
this._activateById(extensionId, new ExtensionActivatedByEvent(true, `workspaceContainsTimeout:${globPatterns.join(',')}`))
|
||||
.then(undefined, err => console.error(err));
|
||||
}, AbstractExtHostExtensionService.WORKSPACE_CONTAINS_TIMEOUT);
|
||||
|
||||
let exists: boolean = false;
|
||||
try {
|
||||
exists = await searchP;
|
||||
} catch (err) {
|
||||
if (!errors.isPromiseCanceledError(err)) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
tokenSource.dispose();
|
||||
clearTimeout(timer);
|
||||
|
||||
if (exists) {
|
||||
// a file was found matching one of the glob patterns
|
||||
return (
|
||||
this._activateById(extensionId, new ExtensionActivatedByEvent(true, `workspaceContains:${globPatterns.join(',')}`))
|
||||
.then(undefined, err => console.error(err))
|
||||
);
|
||||
}
|
||||
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
private _handleExtensionTests(): Promise<void> {
|
||||
return this._doHandleExtensionTests().then(undefined, error => {
|
||||
console.error(error); // ensure any error message makes it onto the console
|
||||
|
||||
return Promise.reject(error);
|
||||
});
|
||||
}
|
||||
|
||||
private async _doHandleExtensionTests(): Promise<void> {
|
||||
const { extensionDevelopmentLocationURI: extensionDevelopmentLocationURI, extensionTestsLocationURI } = this._initData.environment;
|
||||
if (!(extensionDevelopmentLocationURI && extensionTestsLocationURI && extensionTestsLocationURI.scheme === Schemas.file)) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const extensionTestsPath = originalFSPath(extensionTestsLocationURI);
|
||||
|
||||
// Require the test runner via node require from the provided path
|
||||
let testRunner: ITestRunner | INewTestRunner | undefined;
|
||||
let requireError: Error | undefined;
|
||||
try {
|
||||
testRunner = await this._loadCommonJSModule(extensionTestsPath, new ExtensionActivationTimesBuilder(false));
|
||||
} catch (error) {
|
||||
requireError = error;
|
||||
}
|
||||
|
||||
// Execute the runner if it follows the old `run` spec
|
||||
if (testRunner && typeof testRunner.run === 'function') {
|
||||
return new Promise<void>((c, e) => {
|
||||
const oldTestRunnerCallback = (error: Error, failures: number | undefined) => {
|
||||
if (error) {
|
||||
e(error.toString());
|
||||
} else {
|
||||
c(undefined);
|
||||
}
|
||||
|
||||
// after tests have run, we shutdown the host
|
||||
this._gracefulExit(error || (typeof failures === 'number' && failures > 0) ? 1 /* ERROR */ : 0 /* OK */);
|
||||
};
|
||||
|
||||
const runResult = testRunner!.run(extensionTestsPath, oldTestRunnerCallback);
|
||||
|
||||
// Using the new API `run(): Promise<void>`
|
||||
if (runResult && runResult.then) {
|
||||
runResult
|
||||
.then(() => {
|
||||
c();
|
||||
this._gracefulExit(0);
|
||||
})
|
||||
.catch((err: Error) => {
|
||||
e(err.toString());
|
||||
this._gracefulExit(1);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Otherwise make sure to shutdown anyway even in case of an error
|
||||
else {
|
||||
this._gracefulExit(1 /* ERROR */);
|
||||
}
|
||||
|
||||
return Promise.reject(new Error(requireError ? requireError.toString() : nls.localize('extensionTestError', "Path {0} does not point to a valid extension test runner.", extensionTestsPath)));
|
||||
}
|
||||
|
||||
private _gracefulExit(code: number): void {
|
||||
// to give the PH process a chance to flush any outstanding console
|
||||
// messages to the main process, we delay the exit() by some time
|
||||
setTimeout(() => {
|
||||
// If extension tests are running, give the exit code to the renderer
|
||||
if (this._initData.remote.isRemote && !!this._initData.environment.extensionTestsLocationURI) {
|
||||
this._mainThreadExtensionsProxy.$onExtensionHostExit(code);
|
||||
return;
|
||||
}
|
||||
|
||||
this._hostUtils.exit(code);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
private _startExtensionHost(): Promise<void> {
|
||||
if (this._started) {
|
||||
throw new Error(`Extension host is already started!`);
|
||||
}
|
||||
this._started = true;
|
||||
|
||||
return this._readyToStartExtensionHost.wait()
|
||||
.then(() => this._readyToRunExtensions.open())
|
||||
.then(() => this._handleEagerExtensions())
|
||||
.then(() => this._handleExtensionTests())
|
||||
.then(() => {
|
||||
this._extHostLogService.info(`eager extensions activated`);
|
||||
});
|
||||
}
|
||||
|
||||
// -- called by extensions
|
||||
|
||||
public registerRemoteAuthorityResolver(authorityPrefix: string, resolver: vscode.RemoteAuthorityResolver): vscode.Disposable {
|
||||
this._resolvers[authorityPrefix] = resolver;
|
||||
return toDisposable(() => {
|
||||
delete this._resolvers[authorityPrefix];
|
||||
});
|
||||
}
|
||||
|
||||
// -- called by main thread
|
||||
|
||||
public async $resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise<IResolveAuthorityResult> {
|
||||
const authorityPlusIndex = remoteAuthority.indexOf('+');
|
||||
if (authorityPlusIndex === -1) {
|
||||
throw new Error(`Not an authority that can be resolved!`);
|
||||
}
|
||||
const authorityPrefix = remoteAuthority.substr(0, authorityPlusIndex);
|
||||
|
||||
await this._almostReadyToRunExtensions.wait();
|
||||
await this._activateByEvent(`onResolveRemoteAuthority:${authorityPrefix}`, false);
|
||||
|
||||
const resolver = this._resolvers[authorityPrefix];
|
||||
if (!resolver) {
|
||||
throw new Error(`No remote extension installed to resolve ${authorityPrefix}.`);
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await resolver.resolve(remoteAuthority, { resolveAttempt });
|
||||
|
||||
// Split merged API result into separate authority/options
|
||||
const authority: ResolvedAuthority = {
|
||||
authority: remoteAuthority,
|
||||
host: result.host,
|
||||
port: result.port
|
||||
};
|
||||
const options: ResolvedOptions = {
|
||||
extensionHostEnv: result.extensionHostEnv
|
||||
};
|
||||
|
||||
return {
|
||||
type: 'ok',
|
||||
value: {
|
||||
authority,
|
||||
options
|
||||
}
|
||||
};
|
||||
} catch (err) {
|
||||
if (err instanceof RemoteAuthorityResolverError) {
|
||||
return {
|
||||
type: 'error',
|
||||
error: {
|
||||
code: err._code,
|
||||
message: err._message,
|
||||
detail: err._detail
|
||||
}
|
||||
};
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
public $startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise<void> {
|
||||
this._registry.keepOnly(enabledExtensionIds);
|
||||
return this._startExtensionHost();
|
||||
}
|
||||
|
||||
public $activateByEvent(activationEvent: string): Promise<void> {
|
||||
return (
|
||||
this._readyToRunExtensions.wait()
|
||||
.then(_ => this._activateByEvent(activationEvent, false))
|
||||
);
|
||||
}
|
||||
|
||||
public async $activate(extensionId: ExtensionIdentifier, activationEvent: string): Promise<boolean> {
|
||||
await this._readyToRunExtensions.wait();
|
||||
if (!this._registry.getExtensionDescription(extensionId)) {
|
||||
// unknown extension => ignore
|
||||
return false;
|
||||
}
|
||||
await this._activateById(extensionId, new ExtensionActivatedByEvent(false, activationEvent));
|
||||
return true;
|
||||
}
|
||||
|
||||
public async $deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void> {
|
||||
toAdd.forEach((extension) => (<any>extension).extensionLocation = URI.revive(extension.extensionLocation));
|
||||
|
||||
const trie = await this.getExtensionPathIndex();
|
||||
|
||||
await Promise.all(toRemove.map(async (extensionId) => {
|
||||
const extensionDescription = this._registry.getExtensionDescription(extensionId);
|
||||
if (!extensionDescription) {
|
||||
return;
|
||||
}
|
||||
const realpathValue = await this._hostUtils.realpath(extensionDescription.extensionLocation.fsPath);
|
||||
trie.delete(URI.file(realpathValue).fsPath);
|
||||
}));
|
||||
|
||||
await Promise.all(toAdd.map(async (extensionDescription) => {
|
||||
const realpathValue = await this._hostUtils.realpath(extensionDescription.extensionLocation.fsPath);
|
||||
trie.set(URI.file(realpathValue).fsPath, extensionDescription);
|
||||
}));
|
||||
|
||||
this._registry.deltaExtensions(toAdd, toRemove);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
public async $test_latency(n: number): Promise<number> {
|
||||
return n;
|
||||
}
|
||||
|
||||
public async $test_up(b: VSBuffer): Promise<number> {
|
||||
return b.byteLength;
|
||||
}
|
||||
|
||||
public async $test_down(size: number): Promise<VSBuffer> {
|
||||
let buff = VSBuffer.alloc(size);
|
||||
let value = Math.random() % 256;
|
||||
for (let i = 0; i < size; i++) {
|
||||
buff.writeUInt8(value, i);
|
||||
}
|
||||
return buff;
|
||||
}
|
||||
|
||||
public abstract async $setRemoteEnvironment(env: { [key: string]: string | null }): Promise<void>;
|
||||
}
|
||||
|
||||
|
||||
type TelemetryActivationEvent = {
|
||||
id: string;
|
||||
name: string;
|
||||
extensionVersion: string;
|
||||
publisherDisplayName: string;
|
||||
activationEvents: string | null;
|
||||
isBuiltin: boolean;
|
||||
reason: string;
|
||||
};
|
||||
|
||||
function getTelemetryActivationEvent(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): TelemetryActivationEvent {
|
||||
const reasonStr = reason instanceof ExtensionActivatedByEvent ? reason.activationEvent :
|
||||
reason instanceof ExtensionActivatedByAPI ? 'api' :
|
||||
'';
|
||||
const event = {
|
||||
id: extensionDescription.identifier.value,
|
||||
name: extensionDescription.name,
|
||||
extensionVersion: extensionDescription.version,
|
||||
publisherDisplayName: extensionDescription.publisher,
|
||||
activationEvents: extensionDescription.activationEvents ? extensionDescription.activationEvents.join(',') : null,
|
||||
isBuiltin: extensionDescription.isBuiltin,
|
||||
reason: reasonStr
|
||||
};
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
export const IExtHostExtensionService = createDecorator<IExtHostExtensionService>('IExtHostExtensionService');
|
||||
|
||||
export interface IExtHostExtensionService extends AbstractExtHostExtensionService {
|
||||
_serviceBrand: any;
|
||||
initialize(): Promise<void>;
|
||||
isActivated(extensionId: ExtensionIdentifier): boolean;
|
||||
activateByIdWithErrors(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void>;
|
||||
deactivateAll(): Promise<void>;
|
||||
getExtensionExports(extensionId: ExtensionIdentifier): IExtensionAPI | null | undefined;
|
||||
getExtensionRegistry(): Promise<ExtensionDescriptionRegistry>;
|
||||
getExtensionPathIndex(): Promise<TernarySearchTree<IExtensionDescription>>;
|
||||
registerRemoteAuthorityResolver(authorityPrefix: string, resolver: vscode.RemoteAuthorityResolver): vscode.Disposable;
|
||||
}
|
||||
@@ -155,7 +155,7 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
private readonly _usedSchemes = new Set<string>();
|
||||
private readonly _watches = new Map<number, IDisposable>();
|
||||
|
||||
private _linkProviderRegistration: IDisposable;
|
||||
private _linkProviderRegistration?: IDisposable;
|
||||
private _handlePool: number = 0;
|
||||
|
||||
readonly fileSystem: vscode.FileSystem;
|
||||
|
||||
@@ -9,7 +9,7 @@ import { IRelativePattern, parse } from 'vs/base/common/glob';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostFileSystemEventServiceShape, FileSystemEvents, IMainContext, MainContext, ResourceFileEditDto, ResourceTextEditDto, MainThreadTextEditorsShape } from './extHost.protocol';
|
||||
import { ExtHostFileSystemEventServiceShape, FileSystemEvents, IMainContext, MainContext, IResourceFileEditDto, IResourceTextEditDto, MainThreadTextEditorsShape } from './extHost.protocol';
|
||||
import * as typeConverter from './extHostTypeConverters';
|
||||
import { Disposable, WorkspaceEdit } from './extHostTypes';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
@@ -169,7 +169,7 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ
|
||||
}
|
||||
// flatten all WorkspaceEdits collected via waitUntil-call
|
||||
// and apply them in one go.
|
||||
const allEdits = new Array<Array<ResourceFileEditDto | ResourceTextEditDto>>();
|
||||
const allEdits = new Array<Array<IResourceFileEditDto | IResourceTextEditDto>>();
|
||||
for (let edit of edits) {
|
||||
if (edit) { // sparse array
|
||||
let { edits } = typeConverter.WorkspaceEdit.from(edit, this._extHostDocumentsAndEditors);
|
||||
|
||||
14
src/vs/workbench/api/common/extHostInitDataService.ts
Normal file
14
src/vs/workbench/api/common/extHostInitDataService.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IInitData } from './extHost.protocol';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export const IExtHostInitDataService = createDecorator<IExtHostInitDataService>('IExtHostInitDataService');
|
||||
|
||||
export interface IExtHostInitDataService extends Readonly<IInitData> {
|
||||
_serviceBrand: undefined;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { ExtHostDiagnostics } from 'vs/workbench/api/common/extHostDiagnostics';
|
||||
import { asPromise } from 'vs/base/common/async';
|
||||
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, WorkspaceSymbolDto, SuggestResultDto, WorkspaceSymbolsDto, CodeActionDto, ISerializedDocumentFilter, WorkspaceEditDto, ISerializedSignatureHelpProviderMetadata, LinkDto, CodeLensDto, SuggestDataDto, LinksListDto, ChainedCacheId, CodeLensListDto, CodeActionListDto, SignatureHelpDto, SignatureHelpContextDto } from './extHost.protocol';
|
||||
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, IRawColorInfo, IMainContext, IdObject, IRegExpDto, IIndentationRuleDto, IOnEnterRuleDto, ILanguageConfigurationDto, IWorkspaceSymbolDto, ISuggestResultDto, IWorkspaceSymbolsDto, ICodeActionDto, IDocumentFilterDto, IWorkspaceEditDto, ISignatureHelpProviderMetadataDto, ILinkDto, ICodeLensDto, ISuggestDataDto, ILinksListDto, ChainedCacheId, ICodeLensListDto, ICodeActionListDto, ISignatureHelpDto, ISignatureHelpContextDto } from './extHost.protocol';
|
||||
import { regExpLeadsToEndlessLoop, regExpFlags } from 'vs/base/common/strings';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
import { IRange, Range as EditorRange } from 'vs/editor/common/core/range';
|
||||
@@ -111,7 +111,7 @@ class CodeLensAdapter {
|
||||
private readonly _provider: vscode.CodeLensProvider
|
||||
) { }
|
||||
|
||||
provideCodeLenses(resource: URI, token: CancellationToken): Promise<CodeLensListDto | undefined> {
|
||||
provideCodeLenses(resource: URI, token: CancellationToken): Promise<ICodeLensListDto | undefined> {
|
||||
const doc = this._documents.getDocument(resource);
|
||||
|
||||
return asPromise(() => this._provider.provideCodeLenses(doc, token)).then(lenses => {
|
||||
@@ -124,7 +124,7 @@ class CodeLensAdapter {
|
||||
const disposables = new DisposableStore();
|
||||
this._disposables.set(cacheId, disposables);
|
||||
|
||||
const result: CodeLensListDto = {
|
||||
const result: ICodeLensListDto = {
|
||||
cacheId,
|
||||
lenses: [],
|
||||
};
|
||||
@@ -141,7 +141,7 @@ class CodeLensAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
resolveCodeLens(symbol: CodeLensDto, token: CancellationToken): Promise<CodeLensDto | undefined> {
|
||||
resolveCodeLens(symbol: ICodeLensDto, token: CancellationToken): Promise<ICodeLensDto | undefined> {
|
||||
|
||||
const lens = symbol.cacheId && this._cache.get(...symbol.cacheId);
|
||||
if (!lens) {
|
||||
@@ -308,7 +308,7 @@ class ReferenceAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
export interface CustomCodeAction extends CodeActionDto {
|
||||
export interface CustomCodeAction extends ICodeActionDto {
|
||||
_isSynthetic?: boolean;
|
||||
}
|
||||
|
||||
@@ -327,7 +327,7 @@ class CodeActionAdapter {
|
||||
private readonly _extensionId: ExtensionIdentifier
|
||||
) { }
|
||||
|
||||
provideCodeActions(resource: URI, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<CodeActionListDto | undefined> {
|
||||
provideCodeActions(resource: URI, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<ICodeActionListDto | undefined> {
|
||||
|
||||
const doc = this._documents.getDocument(resource);
|
||||
const ran = Selection.isISelection(rangeOrSelection)
|
||||
@@ -391,7 +391,7 @@ class CodeActionAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
return <CodeActionListDto>{ cacheId, actions };
|
||||
return <ICodeActionListDto>{ cacheId, actions };
|
||||
});
|
||||
}
|
||||
|
||||
@@ -480,8 +480,8 @@ class NavigateTypeAdapter {
|
||||
this._provider = provider;
|
||||
}
|
||||
|
||||
provideWorkspaceSymbols(search: string, token: CancellationToken): Promise<WorkspaceSymbolsDto> {
|
||||
const result: WorkspaceSymbolsDto = IdObject.mixin({ symbols: [] });
|
||||
provideWorkspaceSymbols(search: string, token: CancellationToken): Promise<IWorkspaceSymbolsDto> {
|
||||
const result: IWorkspaceSymbolsDto = IdObject.mixin({ symbols: [] });
|
||||
return asPromise(() => this._provider.provideWorkspaceSymbols(search, token)).then(value => {
|
||||
if (isNonEmptyArray(value)) {
|
||||
for (const item of value) {
|
||||
@@ -506,7 +506,7 @@ class NavigateTypeAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
resolveWorkspaceSymbol(symbol: WorkspaceSymbolDto, token: CancellationToken): Promise<WorkspaceSymbolDto | undefined> {
|
||||
resolveWorkspaceSymbol(symbol: IWorkspaceSymbolDto, token: CancellationToken): Promise<IWorkspaceSymbolDto | undefined> {
|
||||
|
||||
if (typeof this._provider.resolveWorkspaceSymbol !== 'function') {
|
||||
return Promise.resolve(symbol);
|
||||
@@ -543,7 +543,7 @@ class RenameAdapter {
|
||||
private readonly _provider: vscode.RenameProvider
|
||||
) { }
|
||||
|
||||
provideRenameEdits(resource: URI, position: IPosition, newName: string, token: CancellationToken): Promise<WorkspaceEditDto | undefined> {
|
||||
provideRenameEdits(resource: URI, position: IPosition, newName: string, token: CancellationToken): Promise<IWorkspaceEditDto | undefined> {
|
||||
|
||||
const doc = this._documents.getDocument(resource);
|
||||
const pos = typeConvert.Position.to(position);
|
||||
@@ -556,10 +556,10 @@ class RenameAdapter {
|
||||
}, err => {
|
||||
const rejectReason = RenameAdapter._asMessage(err);
|
||||
if (rejectReason) {
|
||||
return <WorkspaceEditDto>{ rejectReason, edits: undefined! };
|
||||
return <IWorkspaceEditDto>{ rejectReason, edits: undefined! };
|
||||
} else {
|
||||
// generic error
|
||||
return Promise.reject<WorkspaceEditDto>(err);
|
||||
return Promise.reject<IWorkspaceEditDto>(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -633,7 +633,7 @@ class SuggestAdapter {
|
||||
this._provider = provider;
|
||||
}
|
||||
|
||||
provideCompletionItems(resource: URI, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<SuggestResultDto | undefined> {
|
||||
provideCompletionItems(resource: URI, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<ISuggestResultDto | undefined> {
|
||||
|
||||
const doc = this._documents.getDocument(resource);
|
||||
const pos = typeConvert.Position.to(position);
|
||||
@@ -662,7 +662,7 @@ class SuggestAdapter {
|
||||
const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) as Range || new Range(pos, pos))
|
||||
.with({ end: pos });
|
||||
|
||||
const result: SuggestResultDto = {
|
||||
const result: ISuggestResultDto = {
|
||||
x: pid,
|
||||
b: [],
|
||||
a: typeConvert.Range.from(wordRangeBeforePos),
|
||||
@@ -682,7 +682,7 @@ class SuggestAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
resolveCompletionItem(_resource: URI, position: IPosition, id: ChainedCacheId, token: CancellationToken): Promise<SuggestDataDto | undefined> {
|
||||
resolveCompletionItem(_resource: URI, position: IPosition, id: ChainedCacheId, token: CancellationToken): Promise<ISuggestDataDto | undefined> {
|
||||
|
||||
if (typeof this._provider.resolveCompletionItem !== 'function') {
|
||||
return Promise.resolve(undefined);
|
||||
@@ -710,7 +710,7 @@ class SuggestAdapter {
|
||||
this._cache.delete(id);
|
||||
}
|
||||
|
||||
private _convertCompletionItem(item: vscode.CompletionItem, position: vscode.Position, id: ChainedCacheId): SuggestDataDto | undefined {
|
||||
private _convertCompletionItem(item: vscode.CompletionItem, position: vscode.Position, id: ChainedCacheId): ISuggestDataDto | undefined {
|
||||
if (typeof item.label !== 'string' || item.label.length === 0) {
|
||||
console.warn('INVALID text edit -> must have at least a label');
|
||||
return undefined;
|
||||
@@ -721,7 +721,7 @@ class SuggestAdapter {
|
||||
throw Error('DisposableStore is missing...');
|
||||
}
|
||||
|
||||
const result: SuggestDataDto = {
|
||||
const result: ISuggestDataDto = {
|
||||
//
|
||||
x: id,
|
||||
//
|
||||
@@ -777,7 +777,7 @@ class SignatureHelpAdapter {
|
||||
private readonly _provider: vscode.SignatureHelpProvider,
|
||||
) { }
|
||||
|
||||
provideSignatureHelp(resource: URI, position: IPosition, context: SignatureHelpContextDto, token: CancellationToken): Promise<SignatureHelpDto | undefined> {
|
||||
provideSignatureHelp(resource: URI, position: IPosition, context: ISignatureHelpContextDto, token: CancellationToken): Promise<ISignatureHelpDto | undefined> {
|
||||
const doc = this._documents.getDocument(resource);
|
||||
const pos = typeConvert.Position.to(position);
|
||||
const vscodeContext = this.reviveContext(context);
|
||||
@@ -791,7 +791,7 @@ class SignatureHelpAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
private reviveContext(context: SignatureHelpContextDto): vscode.SignatureHelpContext {
|
||||
private reviveContext(context: ISignatureHelpContextDto): vscode.SignatureHelpContext {
|
||||
let activeSignatureHelp: vscode.SignatureHelp | undefined = undefined;
|
||||
if (context.activeSignatureHelp) {
|
||||
const revivedSignatureHelp = typeConvert.SignatureHelp.to(context.activeSignatureHelp);
|
||||
@@ -855,7 +855,7 @@ class LinkProviderAdapter {
|
||||
private readonly _provider: vscode.DocumentLinkProvider
|
||||
) { }
|
||||
|
||||
provideLinks(resource: URI, token: CancellationToken): Promise<LinksListDto | undefined> {
|
||||
provideLinks(resource: URI, token: CancellationToken): Promise<ILinksListDto | undefined> {
|
||||
const doc = this._documents.getDocument(resource);
|
||||
|
||||
return asPromise(() => this._provider.provideDocumentLinks(doc, token)).then(links => {
|
||||
@@ -877,9 +877,9 @@ class LinkProviderAdapter {
|
||||
} else {
|
||||
// cache links for future resolving
|
||||
const pid = this._cache.add(links);
|
||||
const result: LinksListDto = { links: [], id: pid };
|
||||
const result: ILinksListDto = { links: [], id: pid };
|
||||
for (let i = 0; i < links.length; i++) {
|
||||
const dto: LinkDto = typeConvert.DocumentLink.from(links[i]);
|
||||
const dto: ILinkDto = typeConvert.DocumentLink.from(links[i]);
|
||||
dto.cacheId = [pid, i];
|
||||
result.links.push(dto);
|
||||
}
|
||||
@@ -888,7 +888,7 @@ class LinkProviderAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
resolveLink(id: ChainedCacheId, token: CancellationToken): Promise<LinkDto | undefined> {
|
||||
resolveLink(id: ChainedCacheId, token: CancellationToken): Promise<ILinkDto | undefined> {
|
||||
if (typeof this._provider.resolveDocumentLink !== 'function') {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
@@ -1103,11 +1103,11 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
this._logService = logService;
|
||||
}
|
||||
|
||||
private _transformDocumentSelector(selector: vscode.DocumentSelector): Array<ISerializedDocumentFilter> {
|
||||
private _transformDocumentSelector(selector: vscode.DocumentSelector): Array<IDocumentFilterDto> {
|
||||
return coalesce(asArray(selector).map(sel => this._doTransformDocumentSelector(sel)));
|
||||
}
|
||||
|
||||
private _doTransformDocumentSelector(selector: string | vscode.DocumentFilter): ISerializedDocumentFilter | undefined {
|
||||
private _doTransformDocumentSelector(selector: string | vscode.DocumentFilter): IDocumentFilterDto | undefined {
|
||||
if (typeof selector === 'string') {
|
||||
return {
|
||||
$serialized: true,
|
||||
@@ -1215,11 +1215,11 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
return result;
|
||||
}
|
||||
|
||||
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<CodeLensListDto | undefined> {
|
||||
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<ICodeLensListDto | undefined> {
|
||||
return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.provideCodeLenses(URI.revive(resource), token), undefined);
|
||||
}
|
||||
|
||||
$resolveCodeLens(handle: number, symbol: CodeLensDto, token: CancellationToken): Promise<CodeLensDto | undefined> {
|
||||
$resolveCodeLens(handle: number, symbol: ICodeLensDto, token: CancellationToken): Promise<ICodeLensDto | undefined> {
|
||||
return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.resolveCodeLens(symbol, token), undefined);
|
||||
}
|
||||
|
||||
@@ -1314,7 +1314,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
}
|
||||
|
||||
|
||||
$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<CodeActionListDto | undefined> {
|
||||
$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<ICodeActionListDto | undefined> {
|
||||
return this._withAdapter(handle, CodeActionAdapter, adapter => adapter.provideCodeActions(URI.revive(resource), rangeOrSelection, context, token), undefined);
|
||||
}
|
||||
|
||||
@@ -1362,11 +1362,11 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideWorkspaceSymbols(handle: number, search: string, token: CancellationToken): Promise<WorkspaceSymbolsDto> {
|
||||
$provideWorkspaceSymbols(handle: number, search: string, token: CancellationToken): Promise<IWorkspaceSymbolsDto> {
|
||||
return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.provideWorkspaceSymbols(search, token), { symbols: [] });
|
||||
}
|
||||
|
||||
$resolveWorkspaceSymbol(handle: number, symbol: WorkspaceSymbolDto, token: CancellationToken): Promise<WorkspaceSymbolDto | undefined> {
|
||||
$resolveWorkspaceSymbol(handle: number, symbol: IWorkspaceSymbolDto, token: CancellationToken): Promise<IWorkspaceSymbolDto | undefined> {
|
||||
return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.resolveWorkspaceSymbol(symbol, token), undefined);
|
||||
}
|
||||
|
||||
@@ -1382,7 +1382,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Promise<WorkspaceEditDto | undefined> {
|
||||
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Promise<IWorkspaceEditDto | undefined> {
|
||||
return this._withAdapter(handle, RenameAdapter, adapter => adapter.provideRenameEdits(URI.revive(resource), position, newName, token), undefined);
|
||||
}
|
||||
|
||||
@@ -1398,11 +1398,11 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<SuggestResultDto | undefined> {
|
||||
$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<ISuggestResultDto | undefined> {
|
||||
return this._withAdapter(handle, SuggestAdapter, adapter => adapter.provideCompletionItems(URI.revive(resource), position, context, token), undefined);
|
||||
}
|
||||
|
||||
$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, id: ChainedCacheId, token: CancellationToken): Promise<SuggestDataDto | undefined> {
|
||||
$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, id: ChainedCacheId, token: CancellationToken): Promise<ISuggestDataDto | undefined> {
|
||||
return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(URI.revive(resource), position, id, token), undefined);
|
||||
}
|
||||
|
||||
@@ -1413,7 +1413,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
// --- parameter hints
|
||||
|
||||
registerSignatureHelpProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, metadataOrTriggerChars: string[] | vscode.SignatureHelpProviderMetadata): vscode.Disposable {
|
||||
const metadata: ISerializedSignatureHelpProviderMetadata | undefined = Array.isArray(metadataOrTriggerChars)
|
||||
const metadata: ISignatureHelpProviderMetadataDto | undefined = Array.isArray(metadataOrTriggerChars)
|
||||
? { triggerCharacters: metadataOrTriggerChars, retriggerCharacters: [] }
|
||||
: metadataOrTriggerChars;
|
||||
|
||||
@@ -1422,7 +1422,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: SignatureHelpContextDto, token: CancellationToken): Promise<SignatureHelpDto | undefined> {
|
||||
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: ISignatureHelpContextDto, token: CancellationToken): Promise<ISignatureHelpDto | undefined> {
|
||||
return this._withAdapter(handle, SignatureHelpAdapter, adapter => adapter.provideSignatureHelp(URI.revive(resource), position, context, token), undefined);
|
||||
}
|
||||
|
||||
@@ -1438,11 +1438,11 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Promise<LinksListDto | undefined> {
|
||||
$provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Promise<ILinksListDto | undefined> {
|
||||
return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.provideLinks(URI.revive(resource), token), undefined);
|
||||
}
|
||||
|
||||
$resolveDocumentLink(handle: number, id: ChainedCacheId, token: CancellationToken): Promise<LinkDto | undefined> {
|
||||
$resolveDocumentLink(handle: number, id: ChainedCacheId, token: CancellationToken): Promise<ILinkDto | undefined> {
|
||||
return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.resolveLink(id, token), undefined);
|
||||
}
|
||||
|
||||
@@ -1504,14 +1504,14 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
// --- configuration
|
||||
|
||||
private static _serializeRegExp(regExp: RegExp): ISerializedRegExp {
|
||||
private static _serializeRegExp(regExp: RegExp): IRegExpDto {
|
||||
return {
|
||||
pattern: regExp.source,
|
||||
flags: regExpFlags(regExp),
|
||||
};
|
||||
}
|
||||
|
||||
private static _serializeIndentationRule(indentationRule: vscode.IndentationRule): ISerializedIndentationRule {
|
||||
private static _serializeIndentationRule(indentationRule: vscode.IndentationRule): IIndentationRuleDto {
|
||||
return {
|
||||
decreaseIndentPattern: ExtHostLanguageFeatures._serializeRegExp(indentationRule.decreaseIndentPattern),
|
||||
increaseIndentPattern: ExtHostLanguageFeatures._serializeRegExp(indentationRule.increaseIndentPattern),
|
||||
@@ -1520,7 +1520,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
};
|
||||
}
|
||||
|
||||
private static _serializeOnEnterRule(onEnterRule: vscode.OnEnterRule): ISerializedOnEnterRule {
|
||||
private static _serializeOnEnterRule(onEnterRule: vscode.OnEnterRule): IOnEnterRuleDto {
|
||||
return {
|
||||
beforeText: ExtHostLanguageFeatures._serializeRegExp(onEnterRule.beforeText),
|
||||
afterText: onEnterRule.afterText ? ExtHostLanguageFeatures._serializeRegExp(onEnterRule.afterText) : undefined,
|
||||
@@ -1529,7 +1529,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
};
|
||||
}
|
||||
|
||||
private static _serializeOnEnterRules(onEnterRules: vscode.OnEnterRule[]): ISerializedOnEnterRule[] {
|
||||
private static _serializeOnEnterRules(onEnterRules: vscode.OnEnterRule[]): IOnEnterRuleDto[] {
|
||||
return onEnterRules.map(ExtHostLanguageFeatures._serializeOnEnterRule);
|
||||
}
|
||||
|
||||
@@ -1549,7 +1549,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
}
|
||||
|
||||
const handle = this._nextHandle();
|
||||
const serializedConfiguration: ISerializedLanguageConfiguration = {
|
||||
const serializedConfiguration: ILanguageConfigurationDto = {
|
||||
comments: configuration.comments,
|
||||
brackets: configuration.brackets,
|
||||
wordPattern: configuration.wordPattern ? ExtHostLanguageFeatures._serializeRegExp(configuration.wordPattern) : undefined,
|
||||
|
||||
@@ -14,7 +14,7 @@ export class ExtensionMemento implements IExtensionMemento {
|
||||
private readonly _storage: ExtHostStorage;
|
||||
|
||||
private readonly _init: Promise<ExtensionMemento>;
|
||||
private _value: { [n: string]: any; };
|
||||
private _value?: { [n: string]: any; };
|
||||
private readonly _storageListener: IDisposable;
|
||||
|
||||
constructor(id: string, global: boolean, storage: ExtHostStorage) {
|
||||
@@ -41,7 +41,7 @@ export class ExtensionMemento implements IExtensionMemento {
|
||||
get<T>(key: string): T | undefined;
|
||||
get<T>(key: string, defaultValue: T): T;
|
||||
get<T>(key: string, defaultValue?: T): T {
|
||||
let value = this._value[key];
|
||||
let value = this._value![key];
|
||||
if (typeof value === 'undefined') {
|
||||
value = defaultValue;
|
||||
}
|
||||
@@ -49,8 +49,8 @@ export class ExtensionMemento implements IExtensionMemento {
|
||||
}
|
||||
|
||||
update(key: string, value: any): Promise<void> {
|
||||
this._value[key] = value;
|
||||
return this._storage.setValue(this._shared, this._id, this._value);
|
||||
this._value![key] = value;
|
||||
return this._storage.setValue(this._shared, this._id, this._value!);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { MainContext, MainThreadOutputServiceShape, IMainContext, ExtHostOutputServiceShape } from './extHost.protocol';
|
||||
import { MainContext, MainThreadOutputServiceShape, ExtHostOutputServiceShape } from './extHost.protocol';
|
||||
import * as vscode from 'vscode';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
|
||||
export abstract class AbstractExtHostOutputChannel extends Disposable implements vscode.OutputChannel {
|
||||
|
||||
@@ -27,6 +29,7 @@ export abstract class AbstractExtHostOutputChannel extends Disposable implements
|
||||
this._name = name;
|
||||
this._proxy = proxy;
|
||||
this._id = proxy.$register(this.name, log, file);
|
||||
this._disposed = false;
|
||||
this._offset = 0;
|
||||
}
|
||||
|
||||
@@ -105,38 +108,50 @@ class ExtHostLogFileOutputChannel extends AbstractExtHostOutputChannel {
|
||||
}
|
||||
}
|
||||
|
||||
export interface IOutputChannelFactory {
|
||||
createOutputChannel(name: string, logsLocation: URI, proxy: MainThreadOutputServiceShape): Promise<AbstractExtHostOutputChannel>;
|
||||
}
|
||||
export class LazyOutputChannel implements vscode.OutputChannel {
|
||||
|
||||
export const PushOutputChannelFactory = new class implements IOutputChannelFactory {
|
||||
async createOutputChannel(name: string, _logsLocation: URI, proxy: MainThreadOutputServiceShape): Promise<AbstractExtHostOutputChannel> {
|
||||
return new ExtHostPushOutputChannel(name, proxy);
|
||||
constructor(
|
||||
readonly name: string,
|
||||
private readonly _channel: Promise<AbstractExtHostOutputChannel>
|
||||
) { }
|
||||
|
||||
append(value: string): void {
|
||||
this._channel.then(channel => channel.append(value));
|
||||
}
|
||||
};
|
||||
appendLine(value: string): void {
|
||||
this._channel.then(channel => channel.appendLine(value));
|
||||
}
|
||||
clear(): void {
|
||||
this._channel.then(channel => channel.clear());
|
||||
}
|
||||
show(columnOrPreserveFocus?: vscode.ViewColumn | boolean, preserveFocus?: boolean): void {
|
||||
this._channel.then(channel => channel.show(columnOrPreserveFocus, preserveFocus));
|
||||
}
|
||||
hide(): void {
|
||||
this._channel.then(channel => channel.hide());
|
||||
}
|
||||
dispose(): void {
|
||||
this._channel.then(channel => channel.dispose());
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostOutputService implements ExtHostOutputServiceShape {
|
||||
|
||||
private readonly _factory: IOutputChannelFactory;
|
||||
private readonly _logsLocation: URI;
|
||||
private readonly _proxy: MainThreadOutputServiceShape;
|
||||
private readonly _channels: Map<string, AbstractExtHostOutputChannel> = new Map<string, AbstractExtHostOutputChannel>();
|
||||
private _visibleChannelDisposable: IDisposable;
|
||||
readonly _serviceBrand: any;
|
||||
|
||||
constructor(factory: IOutputChannelFactory, logsLocation: URI, mainContext: IMainContext) {
|
||||
this._factory = factory;
|
||||
this._logsLocation = logsLocation;
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadOutputService);
|
||||
protected readonly _proxy: MainThreadOutputServiceShape;
|
||||
protected readonly _channels: Map<string, AbstractExtHostOutputChannel> = new Map<string, AbstractExtHostOutputChannel>();
|
||||
protected readonly _visibleChannelDisposable = new MutableDisposable();
|
||||
|
||||
constructor(@IExtHostRpcService extHostRpc: IExtHostRpcService) {
|
||||
this._proxy = extHostRpc.getProxy(MainContext.MainThreadOutputService);
|
||||
}
|
||||
|
||||
$setVisibleChannel(channelId: string): void {
|
||||
if (this._visibleChannelDisposable) {
|
||||
this._visibleChannelDisposable = dispose(this._visibleChannelDisposable);
|
||||
}
|
||||
if (channelId) {
|
||||
const channel = this._channels.get(channelId);
|
||||
if (channel) {
|
||||
this._visibleChannelDisposable = channel.onDidAppend(() => channel.update());
|
||||
this._visibleChannelDisposable.value = channel.onDidAppend(() => channel.update());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,33 +160,8 @@ export class ExtHostOutputService implements ExtHostOutputServiceShape {
|
||||
name = name.trim();
|
||||
if (!name) {
|
||||
throw new Error('illegal argument `name`. must not be falsy');
|
||||
} else {
|
||||
const extHostOutputChannel = this._factory.createOutputChannel(name, this._logsLocation, this._proxy);
|
||||
extHostOutputChannel.then(channel => channel._id.then(id => this._channels.set(id, channel)));
|
||||
return {
|
||||
get name(): string {
|
||||
return name;
|
||||
},
|
||||
append(value: string): void {
|
||||
extHostOutputChannel.then(channel => channel.append(value));
|
||||
},
|
||||
appendLine(value: string): void {
|
||||
extHostOutputChannel.then(channel => channel.appendLine(value));
|
||||
},
|
||||
clear(): void {
|
||||
extHostOutputChannel.then(channel => channel.clear());
|
||||
},
|
||||
show(columnOrPreserveFocus?: vscode.ViewColumn | boolean, preserveFocus?: boolean): void {
|
||||
extHostOutputChannel.then(channel => channel.show(columnOrPreserveFocus, preserveFocus));
|
||||
},
|
||||
hide(): void {
|
||||
extHostOutputChannel.then(channel => channel.hide());
|
||||
},
|
||||
dispose(): void {
|
||||
extHostOutputChannel.then(channel => channel.dispose());
|
||||
}
|
||||
};
|
||||
}
|
||||
return new ExtHostPushOutputChannel(name, this._proxy);
|
||||
}
|
||||
|
||||
createOutputChannelFromLogFile(name: string, file: URI): vscode.OutputChannel {
|
||||
@@ -185,3 +175,6 @@ export class ExtHostOutputService implements ExtHostOutputServiceShape {
|
||||
return new ExtHostLogFileOutputChannel(name, file, this._proxy);
|
||||
}
|
||||
}
|
||||
|
||||
export interface IExtHostOutputService extends ExtHostOutputService { }
|
||||
export const IExtHostOutputService = createDecorator<IExtHostOutputService>('IExtHostOutputService');
|
||||
|
||||
29
src/vs/workbench/api/common/extHostRpcService.ts
Normal file
29
src/vs/workbench/api/common/extHostRpcService.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ProxyIdentifier, IRPCProtocol } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export const IExtHostRpcService = createDecorator<IExtHostRpcService>('IExtHostRpcService');
|
||||
|
||||
export interface IExtHostRpcService extends IRPCProtocol {
|
||||
_serviceBrand: any;
|
||||
}
|
||||
|
||||
export class ExtHostRpcService implements IExtHostRpcService {
|
||||
readonly _serviceBrand: any;
|
||||
|
||||
readonly getProxy: <T>(identifier: ProxyIdentifier<T>) => T;
|
||||
readonly set: <T, R extends T> (identifier: ProxyIdentifier<T>, instance: R) => R;
|
||||
readonly assertRegistered: (identifiers: ProxyIdentifier<any>[]) => void;
|
||||
|
||||
constructor(rpcProtocol: IRPCProtocol) {
|
||||
this.getProxy = rpcProtocol.getProxy.bind(rpcProtocol);
|
||||
this.set = rpcProtocol.set.bind(rpcProtocol);
|
||||
this.assertRegistered = rpcProtocol.assertRegistered.bind(rpcProtocol);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import { debounce } from 'vs/base/common/decorators';
|
||||
import { DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { asPromise } from 'vs/base/common/async';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { MainContext, MainThreadSCMShape, SCMRawResource, SCMRawResourceSplice, SCMRawResourceSplices, IMainContext, ExtHostSCMShape, CommandDto } from './extHost.protocol';
|
||||
import { MainContext, MainThreadSCMShape, SCMRawResource, SCMRawResourceSplice, SCMRawResourceSplices, IMainContext, ExtHostSCMShape, ICommandDto } from './extHost.protocol';
|
||||
import { sortedDiff } from 'vs/base/common/arrays';
|
||||
import { comparePaths } from 'vs/base/common/comparers';
|
||||
import * as vscode from 'vscode';
|
||||
@@ -445,7 +445,7 @@ class ExtHostSourceControl implements vscode.SourceControl {
|
||||
|
||||
this._statusBarCommands = statusBarCommands;
|
||||
|
||||
const internal = (statusBarCommands || []).map(c => this._commands.converter.toInternal(c, this._statusBarDisposables.value!)) as CommandDto[];
|
||||
const internal = (statusBarCommands || []).map(c => this._commands.converter.toInternal(c, this._statusBarDisposables.value!)) as ICommandDto[];
|
||||
this._proxy.$updateSourceControl(this.handle, { statusBarCommands: internal });
|
||||
}
|
||||
|
||||
|
||||
16
src/vs/workbench/api/common/extHostSearch.ts
Normal file
16
src/vs/workbench/api/common/extHostSearch.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostSearchShape } from '../common/extHost.protocol';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export interface IExtHostSearch extends ExtHostSearchShape {
|
||||
registerTextSearchProvider(scheme: string, provider: vscode.TextSearchProvider): IDisposable;
|
||||
registerFileSearchProvider(scheme: string, provider: vscode.FileSearchProvider): IDisposable;
|
||||
}
|
||||
|
||||
export const IExtHostSearch = createDecorator<IExtHostSearch>('IExtHostSearch');
|
||||
@@ -3,8 +3,10 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { MainContext, MainThreadStorageShape, IMainContext, ExtHostStorageShape } from './extHost.protocol';
|
||||
import { MainContext, MainThreadStorageShape, ExtHostStorageShape } from './extHost.protocol';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export interface IStorageChangeEvent {
|
||||
shared: boolean;
|
||||
@@ -14,12 +16,14 @@ export interface IStorageChangeEvent {
|
||||
|
||||
export class ExtHostStorage implements ExtHostStorageShape {
|
||||
|
||||
readonly _serviceBrand: any;
|
||||
|
||||
private _proxy: MainThreadStorageShape;
|
||||
|
||||
private _onDidChangeStorage = new Emitter<IStorageChangeEvent>();
|
||||
readonly onDidChangeStorage = this._onDidChangeStorage.event;
|
||||
|
||||
constructor(mainContext: IMainContext) {
|
||||
constructor(mainContext: IExtHostRpcService) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadStorage);
|
||||
}
|
||||
|
||||
@@ -35,3 +39,6 @@ export class ExtHostStorage implements ExtHostStorageShape {
|
||||
this._onDidChangeStorage.fire({ shared, key, value });
|
||||
}
|
||||
}
|
||||
|
||||
export interface IExtHostStorage extends ExtHostStorage { }
|
||||
export const IExtHostStorage = createDecorator<IExtHostStorage>('IExtHostStorage');
|
||||
|
||||
16
src/vs/workbench/api/common/extHostStoragePaths.ts
Normal file
16
src/vs/workbench/api/common/extHostStoragePaths.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export const IExtensionStoragePaths = createDecorator<IExtensionStoragePaths>('IExtensionStoragePaths');
|
||||
|
||||
export interface IExtensionStoragePaths {
|
||||
_serviceBrand: any;
|
||||
whenReady: Promise<any>;
|
||||
workspaceValue(extension: IExtensionDescription): string | undefined;
|
||||
globalValue(extension: IExtensionDescription): string;
|
||||
}
|
||||
30
src/vs/workbench/api/common/extHostTask.ts
Normal file
30
src/vs/workbench/api/common/extHostTask.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { ExtHostTaskShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import * as vscode from 'vscode';
|
||||
import { TaskSystemInfoDTO } from '../common/shared/tasks';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export interface IExtHostTask extends ExtHostTaskShape {
|
||||
|
||||
readonly _serviceBrand: any;
|
||||
|
||||
taskExecutions: vscode.TaskExecution[];
|
||||
onDidStartTask: Event<vscode.TaskStartEvent>;
|
||||
onDidEndTask: Event<vscode.TaskEndEvent>;
|
||||
onDidStartTaskProcess: Event<vscode.TaskProcessStartEvent>;
|
||||
onDidEndTaskProcess: Event<vscode.TaskProcessEndEvent>;
|
||||
|
||||
registerTaskProvider(extension: IExtensionDescription, type: string, provider: vscode.TaskProvider): vscode.Disposable;
|
||||
registerTaskSystem(scheme: string, info: TaskSystemInfoDTO): void;
|
||||
fetchTasks(filter?: vscode.TaskFilter): Promise<vscode.Task[]>;
|
||||
executeTask(extension: IExtensionDescription, task: vscode.Task): Promise<vscode.TaskExecution>;
|
||||
terminateTask(execution: vscode.TaskExecution): Promise<void>;
|
||||
}
|
||||
|
||||
export const IExtHostTask = createDecorator<IExtHostTask>('IExtHostTask');
|
||||
32
src/vs/workbench/api/common/extHostTerminalService.ts
Normal file
32
src/vs/workbench/api/common/extHostTerminalService.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { ExtHostTerminalServiceShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export interface IExtHostTerminalService extends ExtHostTerminalServiceShape {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
activeTerminal: vscode.Terminal | undefined;
|
||||
terminals: vscode.Terminal[];
|
||||
|
||||
onDidCloseTerminal: Event<vscode.Terminal>;
|
||||
onDidOpenTerminal: Event<vscode.Terminal>;
|
||||
onDidChangeActiveTerminal: Event<vscode.Terminal | undefined>;
|
||||
onDidChangeTerminalDimensions: Event<vscode.TerminalDimensionsChangeEvent>;
|
||||
onDidWriteTerminalData: Event<vscode.TerminalDataWriteEvent>;
|
||||
|
||||
createTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal;
|
||||
createTerminalFromOptions(options: vscode.TerminalOptions): vscode.Terminal;
|
||||
createExtensionTerminal(options: vscode.ExtensionTerminalOptions): vscode.Terminal;
|
||||
attachPtyToTerminal(id: number, pty: vscode.Pseudoterminal): void;
|
||||
getDefaultShell(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string;
|
||||
}
|
||||
|
||||
export const IExtHostTerminalService = createDecorator<IExtHostTerminalService>('IExtHostTerminalService');
|
||||
@@ -151,11 +151,11 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
|
||||
private _proxy: MainThreadTextEditorsShape;
|
||||
private _id: string;
|
||||
|
||||
private _tabSize: number;
|
||||
private _indentSize: number;
|
||||
private _insertSpaces: boolean;
|
||||
private _cursorStyle: TextEditorCursorStyle;
|
||||
private _lineNumbers: TextEditorLineNumbersStyle;
|
||||
private _tabSize!: number;
|
||||
private _indentSize!: number;
|
||||
private _insertSpaces!: boolean;
|
||||
private _cursorStyle!: TextEditorCursorStyle;
|
||||
private _lineNumbers!: TextEditorLineNumbersStyle;
|
||||
|
||||
constructor(proxy: MainThreadTextEditorsShape, id: string, source: IResolvedTextEditorConfiguration) {
|
||||
this._proxy = proxy;
|
||||
|
||||
@@ -13,7 +13,7 @@ import { ExtHostTreeViewsShape, MainThreadTreeViewsShape } from './extHost.proto
|
||||
import { ITreeItem, TreeViewItemHandleArg, ITreeItemLabel, IRevealOptions } from 'vs/workbench/common/views';
|
||||
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { asPromise } from 'vs/base/common/async';
|
||||
import { TreeItemCollapsibleState, ThemeIcon, MarkdownString } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { TreeItemCollapsibleState, ThemeIcon } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { isUndefinedOrNull, isString } from 'vs/base/common/types';
|
||||
import { equals, coalesce } from 'vs/base/common/arrays';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
@@ -84,7 +84,10 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
|
||||
get visible() { return treeView.visible; },
|
||||
get onDidChangeVisibility() { return treeView.onDidChangeVisibility; },
|
||||
get message() { return treeView.message; },
|
||||
set message(message: string | MarkdownString) { checkProposedApiEnabled(extension); treeView.message = message; },
|
||||
set message(message: string) {
|
||||
checkProposedApiEnabled(extension);
|
||||
treeView.message = message;
|
||||
},
|
||||
reveal: (element: T, options?: IRevealOptions): Promise<void> => {
|
||||
return treeView.reveal(element, options);
|
||||
},
|
||||
@@ -182,6 +185,7 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
private _onDidChangeData: Emitter<TreeData<T>> = this._register(new Emitter<TreeData<T>>());
|
||||
|
||||
private refreshPromise: Promise<void> = Promise.resolve();
|
||||
private refreshQueue: Promise<void> = Promise.resolve();
|
||||
|
||||
constructor(private viewId: string, options: vscode.TreeViewOptions<T>, private proxy: MainThreadTreeViewsShape, private commands: CommandsConverter, private logService: ILogService, private extension: IExtensionDescription) {
|
||||
super();
|
||||
@@ -214,9 +218,11 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
return result;
|
||||
}, 200)(({ message, elements }) => {
|
||||
if (elements.length) {
|
||||
const _promiseCallback = promiseCallback;
|
||||
refreshingPromise = null;
|
||||
this.refresh(elements).then(() => _promiseCallback());
|
||||
this.refreshQueue = this.refreshQueue.then(() => {
|
||||
const _promiseCallback = promiseCallback;
|
||||
refreshingPromise = null;
|
||||
return this.refresh(elements).then(() => _promiseCallback());
|
||||
});
|
||||
}
|
||||
if (message) {
|
||||
this.proxy.$setMessage(this.viewId, this._message);
|
||||
@@ -255,12 +261,12 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
.then(treeNode => this.proxy.$reveal(this.viewId, treeNode.item, parentChain.map(p => p.item), { select, focus, expand })), error => this.logService.error(error));
|
||||
}
|
||||
|
||||
private _message: string | MarkdownString;
|
||||
get message(): string | MarkdownString {
|
||||
private _message: string = '';
|
||||
get message(): string {
|
||||
return this._message;
|
||||
}
|
||||
|
||||
set message(message: string | MarkdownString) {
|
||||
set message(message: string) {
|
||||
this._message = message;
|
||||
this._onDidChangeData.fire({ message: true, element: false });
|
||||
}
|
||||
@@ -583,9 +589,9 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
if (node) {
|
||||
if (node.children) {
|
||||
for (const child of node.children) {
|
||||
const childEleement = this.elements.get(child.item.handle);
|
||||
if (childEleement) {
|
||||
this.clear(childEleement);
|
||||
const childElement = this.elements.get(child.item.handle);
|
||||
if (childElement) {
|
||||
this.clear(childElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -601,9 +607,9 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
if (node) {
|
||||
if (node.children) {
|
||||
for (const child of node.children) {
|
||||
const childEleement = this.elements.get(child.item.handle);
|
||||
if (childEleement) {
|
||||
this.clear(childEleement);
|
||||
const childElement = this.elements.get(child.item.handle);
|
||||
if (childElement) {
|
||||
this.clear(childElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import { IRange } from 'vs/editor/common/core/range';
|
||||
import { ISelection } from 'vs/editor/common/core/selection';
|
||||
import * as htmlContent from 'vs/base/common/htmlContent';
|
||||
import * as languageSelector from 'vs/editor/common/modes/languageSelector';
|
||||
import { WorkspaceEditDto, ResourceTextEditDto, ResourceFileEditDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { IWorkspaceEditDto, IResourceTextEditDto, IResourceFileEditDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { MarkerSeverity, IRelatedInformation, IMarkerData, MarkerTag } from 'vs/platform/markers/common/markers';
|
||||
import { ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
@@ -442,7 +442,7 @@ export namespace TextEdit {
|
||||
export function from(edit: vscode.TextEdit): modes.TextEdit {
|
||||
return <modes.TextEdit>{
|
||||
text: edit.newText,
|
||||
eol: EndOfLine.from(edit.newEol),
|
||||
eol: edit.newEol && EndOfLine.from(edit.newEol),
|
||||
range: Range.from(edit.range)
|
||||
};
|
||||
}
|
||||
@@ -455,8 +455,8 @@ export namespace TextEdit {
|
||||
}
|
||||
|
||||
export namespace WorkspaceEdit {
|
||||
export function from(value: vscode.WorkspaceEdit, documents?: ExtHostDocumentsAndEditors): WorkspaceEditDto {
|
||||
const result: WorkspaceEditDto = {
|
||||
export function from(value: vscode.WorkspaceEdit, documents?: ExtHostDocumentsAndEditors): IWorkspaceEditDto {
|
||||
const result: IWorkspaceEditDto = {
|
||||
edits: []
|
||||
};
|
||||
for (const entry of (value as types.WorkspaceEdit)._allEntries()) {
|
||||
@@ -464,28 +464,28 @@ export namespace WorkspaceEdit {
|
||||
if (Array.isArray(uriOrEdits)) {
|
||||
// text edits
|
||||
const doc = documents && uri ? documents.getDocument(uri) : undefined;
|
||||
result.edits.push(<ResourceTextEditDto>{ resource: uri, modelVersionId: doc && doc.version, edits: uriOrEdits.map(TextEdit.from) });
|
||||
result.edits.push(<IResourceTextEditDto>{ resource: uri, modelVersionId: doc && doc.version, edits: uriOrEdits.map(TextEdit.from) });
|
||||
} else {
|
||||
// resource edits
|
||||
result.edits.push(<ResourceFileEditDto>{ oldUri: uri, newUri: uriOrEdits, options: entry[2] });
|
||||
result.edits.push(<IResourceFileEditDto>{ oldUri: uri, newUri: uriOrEdits, options: entry[2] });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function to(value: WorkspaceEditDto) {
|
||||
export function to(value: IWorkspaceEditDto) {
|
||||
const result = new types.WorkspaceEdit();
|
||||
for (const edit of value.edits) {
|
||||
if (Array.isArray((<ResourceTextEditDto>edit).edits)) {
|
||||
if (Array.isArray((<IResourceTextEditDto>edit).edits)) {
|
||||
result.set(
|
||||
URI.revive((<ResourceTextEditDto>edit).resource),
|
||||
<types.TextEdit[]>(<ResourceTextEditDto>edit).edits.map(TextEdit.to)
|
||||
URI.revive((<IResourceTextEditDto>edit).resource),
|
||||
<types.TextEdit[]>(<IResourceTextEditDto>edit).edits.map(TextEdit.to)
|
||||
);
|
||||
} else {
|
||||
result.renameFile(
|
||||
URI.revive((<ResourceFileEditDto>edit).oldUri!),
|
||||
URI.revive((<ResourceFileEditDto>edit).newUri!),
|
||||
(<ResourceFileEditDto>edit).options
|
||||
URI.revive((<IResourceFileEditDto>edit).oldUri!),
|
||||
URI.revive((<IResourceFileEditDto>edit).newUri!),
|
||||
(<IResourceFileEditDto>edit).options
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -514,7 +514,7 @@ export class TextEdit {
|
||||
|
||||
protected _range: Range;
|
||||
protected _newText: string | null;
|
||||
protected _newEol: EndOfLine;
|
||||
protected _newEol?: EndOfLine;
|
||||
|
||||
get range(): Range {
|
||||
return this._range;
|
||||
@@ -538,11 +538,11 @@ export class TextEdit {
|
||||
this._newText = value;
|
||||
}
|
||||
|
||||
get newEol(): EndOfLine {
|
||||
get newEol(): EndOfLine | undefined {
|
||||
return this._newEol;
|
||||
}
|
||||
|
||||
set newEol(value: EndOfLine) {
|
||||
set newEol(value: EndOfLine | undefined) {
|
||||
if (value && typeof value !== 'number') {
|
||||
throw illegalArgument('newEol');
|
||||
}
|
||||
@@ -550,7 +550,7 @@ export class TextEdit {
|
||||
}
|
||||
|
||||
constructor(range: Range, newText: string | null) {
|
||||
this.range = range;
|
||||
this._range = range;
|
||||
this._newText = newText;
|
||||
}
|
||||
|
||||
@@ -798,7 +798,7 @@ export class Location {
|
||||
}
|
||||
|
||||
uri: URI;
|
||||
range: Range;
|
||||
range!: Range;
|
||||
|
||||
constructor(uri: URI, rangeOrPosition: Range | Position) {
|
||||
this.uri = uri;
|
||||
@@ -861,10 +861,10 @@ export class Diagnostic {
|
||||
|
||||
range: Range;
|
||||
message: string;
|
||||
source: string;
|
||||
code: string | number;
|
||||
severity: DiagnosticSeverity;
|
||||
relatedInformation: DiagnosticRelatedInformation[];
|
||||
source?: string;
|
||||
code?: string | number;
|
||||
relatedInformation?: DiagnosticRelatedInformation[];
|
||||
tags?: DiagnosticTag[];
|
||||
|
||||
constructor(range: Range, message: string, severity: DiagnosticSeverity = DiagnosticSeverity.Error) {
|
||||
@@ -989,7 +989,7 @@ export class SymbolInformation {
|
||||
}
|
||||
|
||||
name: string;
|
||||
location: Location;
|
||||
location!: Location;
|
||||
kind: SymbolKind;
|
||||
containerName: string | undefined;
|
||||
|
||||
@@ -1075,6 +1075,8 @@ export class CodeAction {
|
||||
|
||||
kind?: CodeActionKind;
|
||||
|
||||
isPreferred?: boolean;
|
||||
|
||||
constructor(title: string, kind?: CodeActionKind) {
|
||||
this.title = title;
|
||||
this.kind = kind;
|
||||
@@ -1253,8 +1255,8 @@ export class SignatureInformation {
|
||||
export class SignatureHelp {
|
||||
|
||||
signatures: SignatureInformation[];
|
||||
activeSignature: number;
|
||||
activeParameter: number;
|
||||
activeSignature: number = 0;
|
||||
activeParameter: number = 0;
|
||||
|
||||
constructor() {
|
||||
this.signatures = [];
|
||||
@@ -1310,19 +1312,19 @@ export enum CompletionItemKind {
|
||||
export class CompletionItem implements vscode.CompletionItem {
|
||||
|
||||
label: string;
|
||||
kind: CompletionItemKind | undefined;
|
||||
kind?: CompletionItemKind;
|
||||
detail?: string;
|
||||
documentation?: string | MarkdownString;
|
||||
sortText?: string;
|
||||
filterText?: string;
|
||||
preselect?: boolean;
|
||||
insertText: string | SnippetString;
|
||||
insertText?: string | SnippetString;
|
||||
keepWhitespace?: boolean;
|
||||
range: Range;
|
||||
range?: Range;
|
||||
commitCharacters?: string[];
|
||||
textEdit: TextEdit;
|
||||
additionalTextEdits: TextEdit[];
|
||||
command: vscode.Command;
|
||||
textEdit?: TextEdit;
|
||||
additionalTextEdits?: TextEdit[];
|
||||
command?: vscode.Command;
|
||||
|
||||
constructor(label: string, kind?: CompletionItemKind) {
|
||||
this.label = label;
|
||||
@@ -1753,26 +1755,6 @@ export enum TaskScope {
|
||||
Workspace = 2
|
||||
}
|
||||
|
||||
export class CustomExecution implements vscode.CustomExecution {
|
||||
private _callback: (args: vscode.TerminalRenderer, cancellationToken: vscode.CancellationToken) => Thenable<number>;
|
||||
|
||||
constructor(callback: (args: vscode.TerminalRenderer, cancellationToken: vscode.CancellationToken) => Thenable<number>) {
|
||||
this._callback = callback;
|
||||
}
|
||||
|
||||
public computeId(): string {
|
||||
return 'customExecution' + generateUuid();
|
||||
}
|
||||
|
||||
public set callback(value: (args: vscode.TerminalRenderer, cancellationToken: vscode.CancellationToken) => Thenable<number>) {
|
||||
this._callback = value;
|
||||
}
|
||||
|
||||
public get callback(): (args: vscode.TerminalRenderer, cancellationToken: vscode.CancellationToken) => Thenable<number> {
|
||||
return this._callback;
|
||||
}
|
||||
}
|
||||
|
||||
export class CustomExecution2 implements vscode.CustomExecution2 {
|
||||
private _callback: () => Thenable<vscode.Pseudoterminal>;
|
||||
constructor(callback: () => Thenable<vscode.Pseudoterminal>) {
|
||||
@@ -1804,7 +1786,7 @@ export class Task implements vscode.Task2 {
|
||||
private _definition: vscode.TaskDefinition;
|
||||
private _scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder | undefined;
|
||||
private _name: string;
|
||||
private _execution: ProcessExecution | ShellExecution | CustomExecution | CustomExecution2 | undefined;
|
||||
private _execution: ProcessExecution | ShellExecution | CustomExecution2 | undefined;
|
||||
private _problemMatchers: string[];
|
||||
private _hasDefinedMatchers: boolean;
|
||||
private _isBackground: boolean;
|
||||
@@ -1813,8 +1795,8 @@ export class Task implements vscode.Task2 {
|
||||
private _presentationOptions: vscode.TaskPresentationOptions;
|
||||
private _runOptions: vscode.RunOptions;
|
||||
|
||||
constructor(definition: vscode.TaskDefinition, name: string, source: string, execution?: ProcessExecution | ShellExecution | CustomExecution | CustomExecution2, problemMatchers?: string | string[]);
|
||||
constructor(definition: vscode.TaskDefinition, scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder, name: string, source: string, execution?: ProcessExecution | ShellExecution | CustomExecution | CustomExecution2, problemMatchers?: string | string[]);
|
||||
constructor(definition: vscode.TaskDefinition, name: string, source: string, execution?: ProcessExecution | ShellExecution | CustomExecution2, problemMatchers?: string | string[]);
|
||||
constructor(definition: vscode.TaskDefinition, scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder, name: string, source: string, execution?: ProcessExecution | ShellExecution | CustomExecution2, problemMatchers?: string | string[]);
|
||||
constructor(definition: vscode.TaskDefinition, arg2: string | (vscode.TaskScope.Global | vscode.TaskScope.Workspace) | vscode.WorkspaceFolder, arg3: any, arg4?: any, arg5?: any, arg6?: any) {
|
||||
this.definition = definition;
|
||||
let problemMatchers: string | string[];
|
||||
@@ -1879,7 +1861,7 @@ export class Task implements vscode.Task2 {
|
||||
type: Task.ShellType,
|
||||
id: this._execution.computeId()
|
||||
};
|
||||
} else if (this._execution instanceof CustomExecution) {
|
||||
} else if (this._execution instanceof CustomExecution2) {
|
||||
this._definition = {
|
||||
type: Task.ExtensionCallbackType,
|
||||
id: this._execution.computeId()
|
||||
@@ -1926,18 +1908,18 @@ export class Task implements vscode.Task2 {
|
||||
}
|
||||
|
||||
get execution(): ProcessExecution | ShellExecution | undefined {
|
||||
return ((this._execution instanceof CustomExecution) || (this._execution instanceof CustomExecution2)) ? undefined : this._execution;
|
||||
return (this._execution instanceof CustomExecution2) ? undefined : this._execution;
|
||||
}
|
||||
|
||||
set execution(value: ProcessExecution | ShellExecution | undefined) {
|
||||
this.execution2 = value;
|
||||
}
|
||||
|
||||
get execution2(): ProcessExecution | ShellExecution | CustomExecution | CustomExecution2 | undefined {
|
||||
get execution2(): ProcessExecution | ShellExecution | CustomExecution2 | undefined {
|
||||
return this._execution;
|
||||
}
|
||||
|
||||
set execution2(value: ProcessExecution | ShellExecution | CustomExecution | CustomExecution2 | undefined) {
|
||||
set execution2(value: ProcessExecution | ShellExecution | CustomExecution2 | undefined) {
|
||||
if (value === null) {
|
||||
value = undefined;
|
||||
}
|
||||
|
||||
37
src/vs/workbench/api/common/extHostUriTransformerService.ts
Normal file
37
src/vs/workbench/api/common/extHostUriTransformerService.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IURITransformer } from 'vs/base/common/uriIpc';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
|
||||
export interface IURITransformerService extends IURITransformer {
|
||||
_serviceBrand: any;
|
||||
}
|
||||
|
||||
export const IURITransformerService = createDecorator<IURITransformerService>('IURITransformerService');
|
||||
|
||||
export class URITransformerService implements IURITransformerService {
|
||||
_serviceBrand: any;
|
||||
|
||||
transformIncoming: (uri: UriComponents) => UriComponents;
|
||||
transformOutgoing: (uri: UriComponents) => UriComponents;
|
||||
transformOutgoingURI: (uri: URI) => URI;
|
||||
transformOutgoingScheme: (scheme: string) => string;
|
||||
|
||||
constructor(delegate: IURITransformer | null) {
|
||||
if (!delegate) {
|
||||
this.transformIncoming = arg => arg;
|
||||
this.transformOutgoing = arg => arg;
|
||||
this.transformOutgoingURI = arg => arg;
|
||||
this.transformOutgoingScheme = arg => arg;
|
||||
} else {
|
||||
this.transformIncoming = delegate.transformIncoming.bind(delegate);
|
||||
this.transformOutgoing = delegate.transformOutgoing.bind(delegate);
|
||||
this.transformOutgoingURI = delegate.transformOutgoingURI.bind(delegate);
|
||||
this.transformOutgoingScheme = delegate.transformOutgoingScheme.bind(delegate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,11 +20,14 @@ import { Workspace, WorkspaceFolder } from 'vs/platform/workspace/common/workspa
|
||||
import { Range, RelativePattern } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/queryBuilder';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostWorkspaceShape, IWorkspaceData, MainThreadMessageServiceShape, MainThreadWorkspaceShape, IMainContext, MainContext, IStaticWorkspaceData } from './extHost.protocol';
|
||||
import { ExtHostWorkspaceShape, IWorkspaceData, MainThreadMessageServiceShape, MainThreadWorkspaceShape, MainContext } from './extHost.protocol';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { Barrier } from 'vs/base/common/async';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { withUndefinedAsNull } from 'vs/base/common/types';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
|
||||
export interface IExtHostWorkspaceProvider {
|
||||
getWorkspaceFolder2(uri: vscode.Uri, resolveParent?: boolean): Promise<vscode.WorkspaceFolder | undefined>;
|
||||
@@ -153,6 +156,8 @@ class ExtHostWorkspaceImpl extends Workspace {
|
||||
|
||||
export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspaceProvider {
|
||||
|
||||
readonly _serviceBrand: any;
|
||||
|
||||
private readonly _onDidChangeWorkspace = new Emitter<vscode.WorkspaceFoldersChangeEvent>();
|
||||
readonly onDidChangeWorkspace: Event<vscode.WorkspaceFoldersChangeEvent> = this._onDidChangeWorkspace.event;
|
||||
|
||||
@@ -169,21 +174,21 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac
|
||||
private readonly _activeSearchCallbacks: ((match: IRawFileMatch2) => any)[] = [];
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
logService: ILogService,
|
||||
requestIdProvider: Counter,
|
||||
data?: IStaticWorkspaceData
|
||||
@IExtHostRpcService extHostRpc: IExtHostRpcService,
|
||||
@IExtHostInitDataService initData: IExtHostInitDataService,
|
||||
@ILogService logService: ILogService,
|
||||
) {
|
||||
this._logService = logService;
|
||||
this._requestIdProvider = requestIdProvider;
|
||||
this._requestIdProvider = new Counter();
|
||||
this._barrier = new Barrier();
|
||||
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadWorkspace);
|
||||
this._messageService = mainContext.getProxy(MainContext.MainThreadMessageService);
|
||||
this._proxy = extHostRpc.getProxy(MainContext.MainThreadWorkspace);
|
||||
this._messageService = extHostRpc.getProxy(MainContext.MainThreadMessageService);
|
||||
const data = initData.workspace;
|
||||
this._confirmedWorkspace = data ? new ExtHostWorkspaceImpl(data.id, data.name, [], data.configuration ? URI.revive(data.configuration) : null, !!data.isUntitled) : undefined;
|
||||
}
|
||||
|
||||
$initializeWorkspace(data: IWorkspaceData): void {
|
||||
$initializeWorkspace(data: IWorkspaceData | null): void {
|
||||
this.$acceptWorkspaceData(data);
|
||||
this._barrier.open();
|
||||
}
|
||||
@@ -289,7 +294,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac
|
||||
this._unconfirmedWorkspace = undefined;
|
||||
|
||||
// show error to user
|
||||
this._messageService.$showMessage(Severity.Error, localize('updateerror', "Extension '{0}' failed to update workspace folders: {1}", extName, error), { extension }, []);
|
||||
this._messageService.$showMessage(Severity.Error, localize('updateerror', "Extension '{0}' failed to update workspace folders: {1}", extName, error.toString()), { extension }, []);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -390,7 +395,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac
|
||||
}
|
||||
}
|
||||
|
||||
$acceptWorkspaceData(data: IWorkspaceData): void {
|
||||
$acceptWorkspaceData(data: IWorkspaceData | null): void {
|
||||
|
||||
const { workspace, added, removed } = ExtHostWorkspaceImpl.toExtHostWorkspace(data, this._confirmedWorkspace, this._unconfirmedWorkspace);
|
||||
|
||||
@@ -546,3 +551,6 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac
|
||||
return this._proxy.$resolveProxy(url);
|
||||
}
|
||||
}
|
||||
|
||||
export const IExtHostWorkspace = createDecorator<IExtHostWorkspace>('IExtHostWorkspace');
|
||||
export interface IExtHostWorkspace extends ExtHostWorkspace, ExtHostWorkspaceShape, IExtHostWorkspaceProvider { }
|
||||
|
||||
@@ -66,10 +66,6 @@ export interface ShellExecutionDTO {
|
||||
options?: ShellExecutionOptionsDTO;
|
||||
}
|
||||
|
||||
export interface CustomExecutionDTO {
|
||||
customExecution: 'customExecution';
|
||||
}
|
||||
|
||||
export interface CustomExecution2DTO {
|
||||
customExecution: 'customExecution2';
|
||||
}
|
||||
@@ -88,7 +84,7 @@ export interface TaskHandleDTO {
|
||||
export interface TaskDTO {
|
||||
_id: string;
|
||||
name?: string;
|
||||
execution: ProcessExecutionDTO | ShellExecutionDTO | CustomExecutionDTO | CustomExecution2DTO | undefined;
|
||||
execution: ProcessExecutionDTO | ShellExecutionDTO | CustomExecution2DTO | undefined;
|
||||
definition: TaskDefinitionDTO;
|
||||
isBackground?: boolean;
|
||||
source: TaskSourceDTO;
|
||||
@@ -129,4 +125,4 @@ export interface TaskSystemInfoDTO {
|
||||
scheme: string;
|
||||
authority: string;
|
||||
platform: string;
|
||||
}
|
||||
}
|
||||
|
||||
41
src/vs/workbench/api/node/extHost.services.ts
Normal file
41
src/vs/workbench/api/node/extHost.services.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IExtHostOutputService } from 'vs/workbench/api/common/extHostOutput';
|
||||
import { ExtHostOutputService2 } from 'vs/workbench/api/node/extHostOutputService';
|
||||
import { IExtHostWorkspace, ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { IExtHostDecorations, ExtHostDecorations } from 'vs/workbench/api/common/extHostDecorations';
|
||||
import { IExtHostConfiguration, ExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { IExtHostCommands, ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { IExtHostDocumentsAndEditors, ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { ExtHostTerminalService } from 'vs/workbench/api/node/extHostTerminalService';
|
||||
import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService';
|
||||
import { IExtHostTask } from 'vs/workbench/api/common/extHostTask';
|
||||
import { ExtHostTask } from 'vs/workbench/api/node/extHostTask';
|
||||
import { ExtHostDebugService } from 'vs/workbench/api/node/extHostDebugService';
|
||||
import { IExtHostDebugService } from 'vs/workbench/api/common/extHostDebugService';
|
||||
import { IExtHostSearch } from 'vs/workbench/api/common/extHostSearch';
|
||||
import { ExtHostSearch } from 'vs/workbench/api/node/extHostSearch';
|
||||
import { ExtensionStoragePaths } from 'vs/workbench/api/node/extHostStoragePaths';
|
||||
import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
|
||||
import { IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService';
|
||||
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
|
||||
import { IExtHostStorage, ExtHostStorage } from 'vs/workbench/api/common/extHostStorage';
|
||||
|
||||
// register singleton services
|
||||
registerSingleton(IExtHostOutputService, ExtHostOutputService2);
|
||||
registerSingleton(IExtHostWorkspace, ExtHostWorkspace);
|
||||
registerSingleton(IExtHostDecorations, ExtHostDecorations);
|
||||
registerSingleton(IExtHostConfiguration, ExtHostConfiguration);
|
||||
registerSingleton(IExtHostCommands, ExtHostCommands);
|
||||
registerSingleton(IExtHostDocumentsAndEditors, ExtHostDocumentsAndEditors);
|
||||
registerSingleton(IExtHostTerminalService, ExtHostTerminalService);
|
||||
registerSingleton(IExtHostTask, ExtHostTask);
|
||||
registerSingleton(IExtHostDebugService, ExtHostDebugService);
|
||||
registerSingleton(IExtHostSearch, ExtHostSearch);
|
||||
registerSingleton(IExtensionStoragePaths, ExtensionStoragePaths);
|
||||
registerSingleton(IExtHostExtensionService, ExtHostExtensionService);
|
||||
registerSingleton(IExtHostStorage, ExtHostStorage);
|
||||
@@ -6,7 +6,7 @@
|
||||
import { generateRandomPipeName } from 'vs/base/parts/ipc/node/ipc.net';
|
||||
import * as http from 'http';
|
||||
import * as fs from 'fs';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { IExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { IURIToOpen, IOpenSettings } from 'vs/platform/windows/common/windows';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces';
|
||||
@@ -38,7 +38,7 @@ export class CLIServer {
|
||||
private _server: http.Server;
|
||||
private _ipcHandlePath: string | undefined;
|
||||
|
||||
constructor(private _commands: ExtHostCommands) {
|
||||
constructor(@IExtHostCommands private _commands: IExtHostCommands) {
|
||||
this._server = http.createServer((req, res) => this.onRequest(req, res));
|
||||
this.setup().catch(err => {
|
||||
console.error(err);
|
||||
@@ -179,4 +179,4 @@ export class CLIServer {
|
||||
fs.unlinkSync(this._ipcHandlePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,33 +11,37 @@ import { asPromise } from 'vs/base/common/async';
|
||||
import * as nls from 'vs/nls';
|
||||
import {
|
||||
MainContext, MainThreadDebugServiceShape, ExtHostDebugServiceShape, DebugSessionUUID,
|
||||
IMainContext, IBreakpointsDeltaDto, ISourceMultiBreakpointDto, IFunctionBreakpointDto, IDebugSessionDto
|
||||
IBreakpointsDeltaDto, ISourceMultiBreakpointDto, IFunctionBreakpointDto, IDebugSessionDto
|
||||
} from 'vs/workbench/api/common/extHost.protocol';
|
||||
import * as vscode from 'vscode';
|
||||
import { Disposable, Position, Location, SourceBreakpoint, FunctionBreakpoint, DebugAdapterServer, DebugAdapterExecutable } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { ExecutableDebugAdapter, SocketDebugAdapter } from 'vs/workbench/contrib/debug/node/debugAdapter';
|
||||
import { AbstractDebugAdapter } from 'vs/workbench/contrib/debug/common/abstractDebugAdapter';
|
||||
import { IExtHostWorkspaceProvider } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService';
|
||||
import { ExtHostDocumentsAndEditors, IExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { IDebuggerContribution, IConfig, IDebugAdapter, IDebugAdapterServer, IDebugAdapterExecutable, IAdapterDescriptor } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { hasChildProcesses, prepareCommand, runInExternalTerminal } from 'vs/workbench/contrib/debug/node/terminals';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { AbstractVariableResolverService } from 'vs/workbench/services/configurationResolver/common/variableResolver';
|
||||
import { ExtHostConfiguration, ExtHostConfigProvider } from '../common/extHostConfiguration';
|
||||
import { ExtHostConfigProvider, IExtHostConfiguration } from '../common/extHostConfiguration';
|
||||
import { convertToVSCPaths, convertToDAPaths, isDebuggerMainContribution } from 'vs/workbench/contrib/debug/common/debugUtils';
|
||||
import { ExtHostTerminalService } from 'vs/workbench/api/node/extHostTerminalService';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { IExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
|
||||
import { IProcessEnvironment } from 'vs/base/common/platform';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { SignService } from 'vs/platform/sign/node/signService';
|
||||
import { ISignService } from 'vs/platform/sign/common/sign';
|
||||
import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { IExtHostDebugService } from 'vs/workbench/api/common/extHostDebugService';
|
||||
|
||||
export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
export class ExtHostDebugService implements IExtHostDebugService, ExtHostDebugServiceShape {
|
||||
|
||||
readonly _serviceBrand: any;
|
||||
|
||||
private _configProviderHandleCounter: number;
|
||||
private _configProviders: ConfigProviderTuple[];
|
||||
@@ -86,13 +90,14 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
private _signService: ISignService;
|
||||
|
||||
|
||||
constructor(mainContext: IMainContext,
|
||||
private _workspaceService: IExtHostWorkspaceProvider,
|
||||
private _extensionService: ExtHostExtensionService,
|
||||
private _editorsService: ExtHostDocumentsAndEditors,
|
||||
private _configurationService: ExtHostConfiguration,
|
||||
private _terminalService: ExtHostTerminalService,
|
||||
private _commandService: ExtHostCommands
|
||||
constructor(
|
||||
@IExtHostRpcService extHostRpcService: IExtHostRpcService,
|
||||
@IExtHostWorkspace private _workspaceService: IExtHostWorkspace,
|
||||
@IExtHostExtensionService private _extensionService: IExtHostExtensionService,
|
||||
@IExtHostDocumentsAndEditors private _editorsService: IExtHostDocumentsAndEditors,
|
||||
@IExtHostConfiguration private _configurationService: IExtHostConfiguration,
|
||||
@IExtHostTerminalService private _terminalService: IExtHostTerminalService,
|
||||
@IExtHostCommands private _commandService: IExtHostCommands
|
||||
) {
|
||||
this._configProviderHandleCounter = 0;
|
||||
this._configProviders = [];
|
||||
@@ -112,7 +117,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
this._onDidChangeActiveDebugSession = new Emitter<vscode.DebugSession>();
|
||||
this._onDidReceiveDebugSessionCustomEvent = new Emitter<vscode.DebugSessionCustomEvent>();
|
||||
|
||||
this._debugServiceProxy = mainContext.getProxy(MainContext.MainThreadDebugService);
|
||||
this._debugServiceProxy = extHostRpcService.getProxy(MainContext.MainThreadDebugService);
|
||||
|
||||
this._onDidChangeBreakpoints = new Emitter<vscode.BreakpointsChangeEvent>({
|
||||
onFirstListenerAdd: () => {
|
||||
@@ -344,7 +349,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
}).then(async needNewTerminal => {
|
||||
|
||||
const configProvider = await this._configurationService.getConfigProvider();
|
||||
const shell = this._terminalService.getDefaultShell(configProvider);
|
||||
const shell = this._terminalService.getDefaultShell(true, configProvider);
|
||||
|
||||
if (needNewTerminal || !this._integratedTerminalInstance) {
|
||||
const options: vscode.TerminalOptions = {
|
||||
@@ -599,7 +604,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
this.fireBreakpointChanges(a, r, c);
|
||||
}
|
||||
|
||||
public $provideDebugConfigurations(configProviderHandle: number, folderUri: UriComponents | undefined): Promise<vscode.DebugConfiguration[]> {
|
||||
public $provideDebugConfigurations(configProviderHandle: number, folderUri: UriComponents | undefined, token: CancellationToken): Promise<vscode.DebugConfiguration[]> {
|
||||
return asPromise(async () => {
|
||||
const provider = this.getConfigProviderByHandle(configProviderHandle);
|
||||
if (!provider) {
|
||||
@@ -609,7 +614,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
throw new Error('DebugConfigurationProvider has no method provideDebugConfigurations');
|
||||
}
|
||||
const folder = await this.getFolder(folderUri);
|
||||
return provider.provideDebugConfigurations(folder, CancellationToken.None);
|
||||
return provider.provideDebugConfigurations(folder, token);
|
||||
}).then(debugConfigurations => {
|
||||
if (!debugConfigurations) {
|
||||
throw new Error('nothing returned from DebugConfigurationProvider.provideDebugConfigurations');
|
||||
@@ -618,7 +623,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
});
|
||||
}
|
||||
|
||||
public $resolveDebugConfiguration(configProviderHandle: number, folderUri: UriComponents | undefined, debugConfiguration: vscode.DebugConfiguration): Promise<vscode.DebugConfiguration | null | undefined> {
|
||||
public $resolveDebugConfiguration(configProviderHandle: number, folderUri: UriComponents | undefined, debugConfiguration: vscode.DebugConfiguration, token: CancellationToken): Promise<vscode.DebugConfiguration | null | undefined> {
|
||||
return asPromise(async () => {
|
||||
const provider = this.getConfigProviderByHandle(configProviderHandle);
|
||||
if (!provider) {
|
||||
@@ -628,7 +633,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
throw new Error('DebugConfigurationProvider has no method resolveDebugConfiguration');
|
||||
}
|
||||
const folder = await this.getFolder(folderUri);
|
||||
return provider.resolveDebugConfiguration(folder, debugConfiguration, CancellationToken.None);
|
||||
return provider.resolveDebugConfiguration(folder, debugConfiguration, token);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -6,23 +6,26 @@
|
||||
import { join } from 'vs/base/common/path';
|
||||
import { tmpdir } from 'os';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { IExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { MainThreadDownloadServiceShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
|
||||
export class ExtHostDownloadService extends Disposable {
|
||||
|
||||
constructor(
|
||||
proxy: MainThreadDownloadServiceShape,
|
||||
commands: ExtHostCommands
|
||||
@IExtHostRpcService extHostRpc: IExtHostRpcService,
|
||||
@IExtHostCommands commands: IExtHostCommands
|
||||
) {
|
||||
super();
|
||||
|
||||
const proxy = extHostRpc.getProxy(MainContext.MainThreadDownloadService);
|
||||
|
||||
commands.registerCommand(false, '_workbench.downloadResource', async (resource: URI): Promise<any> => {
|
||||
const location = URI.file(join(tmpdir(), generateUuid()));
|
||||
await proxy.$download(resource, location);
|
||||
return location;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,768 +3,63 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import * as path from 'vs/base/common/path';
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { createApiFactory, initializeExtensionApi, ISqlExtensionApiFactory } from 'sql/workbench/api/node/sqlExtHost.api.impl';
|
||||
import { originalFSPath } from 'vs/base/common/resources';
|
||||
import { Barrier } from 'vs/base/common/async';
|
||||
import { dispose, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { TernarySearchTree } from 'vs/base/common/map';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
// {{SQL CARBON EDIT}} - Remove createApiFactory initializeExtensionApi, and IExtensionApiFactory imports
|
||||
// import { createApiFactory, IExtensionApiFactory } from 'vs/workbench/api/node/extHost.api.impl';
|
||||
import { createApiFactoryAndRegisterActors } from 'vs/workbench/api/common/extHost.api.impl';
|
||||
import { NodeModuleRequireInterceptor, VSCodeNodeModuleFactory, KeytarNodeModuleFactory, OpenNodeModuleFactory } from 'vs/workbench/api/node/extHostRequireInterceptor';
|
||||
import { ExtHostExtensionServiceShape, IEnvironment, IInitData, IMainContext, MainContext, MainThreadExtensionServiceShape, MainThreadTelemetryShape, MainThreadWorkspaceShape, IResolveAuthorityResult } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { ActivatedExtension, EmptyExtension, ExtensionActivatedByAPI, ExtensionActivatedByEvent, ExtensionActivationReason, ExtensionActivationTimes, ExtensionActivationTimesBuilder, ExtensionsActivator, IExtensionAPI, IExtensionContext, IExtensionModule, HostExtension, ExtensionActivationTimesFragment } from 'vs/workbench/api/common/extHostExtensionActivator';
|
||||
import { ExtHostLogService } from 'vs/workbench/api/common/extHostLogService';
|
||||
import { ExtHostStorage } from 'vs/workbench/api/common/extHostStorage';
|
||||
import { ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { ExtensionActivationError } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
|
||||
import { MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtensionActivationTimesBuilder } from 'vs/workbench/api/common/extHostExtensionActivator';
|
||||
import { connectProxyResolver } from 'vs/workbench/services/extensions/node/proxyResolver';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { ExtensionMemento } from 'vs/workbench/api/common/extHostMemento';
|
||||
import { ExtensionStoragePaths } from 'vs/workbench/api/node/extHostStoragePaths';
|
||||
import { RemoteAuthorityResolverError, ExtensionExecutionContext } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { IURITransformer } from 'vs/base/common/uriIpc';
|
||||
import { ResolvedAuthority, ResolvedOptions } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { AbstractExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService';
|
||||
import { ExtHostDownloadService } from 'vs/workbench/api/node/extHostDownloadService';
|
||||
import { CLIServer } from 'vs/workbench/api/node/extHostCLIServer';
|
||||
import { initializeExtensionApi, createApiFactory } from 'sql/workbench/api/common/sqlExtHost.api.impl'; // {{SQL CARBON EDIT}} use our extension initalizer
|
||||
|
||||
interface ITestRunner {
|
||||
/** Old test runner API, as exported from `vscode/lib/testrunner` */
|
||||
run(testsRoot: string, clb: (error: Error, failures?: number) => void): void;
|
||||
}
|
||||
export class ExtHostExtensionService extends AbstractExtHostExtensionService {
|
||||
|
||||
interface INewTestRunner {
|
||||
/** New test runner API, as explained in the extension test doc */
|
||||
run(): Promise<void>;
|
||||
}
|
||||
protected async _beforeAlmostReadyToRunExtensions(): Promise<void> {
|
||||
// initialize API and register actors
|
||||
const extensionApiFactory = this._instaService.invokeFunction(createApiFactory);
|
||||
|
||||
export interface IHostUtils {
|
||||
exit(code?: number): void;
|
||||
exists(path: string): Promise<boolean>;
|
||||
realpath(path: string): Promise<string>;
|
||||
}
|
||||
// Register Download command
|
||||
this._instaService.createInstance(ExtHostDownloadService);
|
||||
|
||||
type TelemetryActivationEventFragment = {
|
||||
id: { classification: 'PublicNonPersonalData', purpose: 'FeatureInsight' };
|
||||
name: { classification: 'PublicNonPersonalData', purpose: 'FeatureInsight' };
|
||||
extensionVersion: { classification: 'PublicNonPersonalData', purpose: 'FeatureInsight' };
|
||||
publisherDisplayName: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
activationEvents: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
isBuiltin: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true };
|
||||
reason: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
};
|
||||
|
||||
export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
|
||||
private static readonly WORKSPACE_CONTAINS_TIMEOUT = 7000;
|
||||
|
||||
private readonly _hostUtils: IHostUtils;
|
||||
private readonly _initData: IInitData;
|
||||
private readonly _extHostContext: IMainContext;
|
||||
private readonly _extHostWorkspace: ExtHostWorkspace;
|
||||
private readonly _extHostConfiguration: ExtHostConfiguration;
|
||||
private readonly _environment: IEnvironment;
|
||||
private readonly _extHostLogService: ExtHostLogService;
|
||||
|
||||
private readonly _mainThreadWorkspaceProxy: MainThreadWorkspaceShape;
|
||||
private readonly _mainThreadTelemetryProxy: MainThreadTelemetryShape;
|
||||
private readonly _mainThreadExtensionsProxy: MainThreadExtensionServiceShape;
|
||||
|
||||
private readonly _almostReadyToRunExtensions: Barrier;
|
||||
private readonly _readyToStartExtensionHost: Barrier;
|
||||
private readonly _readyToRunExtensions: Barrier;
|
||||
private readonly _registry: ExtensionDescriptionRegistry;
|
||||
private readonly _storage: ExtHostStorage;
|
||||
private readonly _storagePath: ExtensionStoragePaths;
|
||||
private readonly _activator: ExtensionsActivator;
|
||||
private _extensionPathIndex: Promise<TernarySearchTree<IExtensionDescription>> | null;
|
||||
private readonly _extensionApiFactory: ISqlExtensionApiFactory;
|
||||
|
||||
private readonly _resolvers: { [authorityPrefix: string]: vscode.RemoteAuthorityResolver; };
|
||||
|
||||
private _started: boolean;
|
||||
|
||||
private readonly _disposables: DisposableStore;
|
||||
|
||||
constructor(
|
||||
hostUtils: IHostUtils,
|
||||
initData: IInitData,
|
||||
extHostContext: IMainContext,
|
||||
extHostWorkspace: ExtHostWorkspace,
|
||||
extHostConfiguration: ExtHostConfiguration,
|
||||
environment: IEnvironment,
|
||||
extHostLogService: ExtHostLogService,
|
||||
uriTransformer: IURITransformer | null
|
||||
) {
|
||||
this._hostUtils = hostUtils;
|
||||
this._initData = initData;
|
||||
this._extHostContext = extHostContext;
|
||||
this._extHostWorkspace = extHostWorkspace;
|
||||
this._extHostConfiguration = extHostConfiguration;
|
||||
this._environment = environment;
|
||||
this._extHostLogService = extHostLogService;
|
||||
this._disposables = new DisposableStore();
|
||||
|
||||
this._mainThreadWorkspaceProxy = this._extHostContext.getProxy(MainContext.MainThreadWorkspace);
|
||||
this._mainThreadTelemetryProxy = this._extHostContext.getProxy(MainContext.MainThreadTelemetry);
|
||||
this._mainThreadExtensionsProxy = this._extHostContext.getProxy(MainContext.MainThreadExtensionService);
|
||||
|
||||
this._almostReadyToRunExtensions = new Barrier();
|
||||
this._readyToStartExtensionHost = new Barrier();
|
||||
this._readyToRunExtensions = new Barrier();
|
||||
this._registry = new ExtensionDescriptionRegistry(initData.extensions);
|
||||
this._storage = new ExtHostStorage(this._extHostContext);
|
||||
this._storagePath = new ExtensionStoragePaths(withNullAsUndefined(initData.workspace), initData.environment);
|
||||
|
||||
const hostExtensions = new Set<string>();
|
||||
initData.hostExtensions.forEach((extensionId) => hostExtensions.add(ExtensionIdentifier.toKey(extensionId)));
|
||||
|
||||
this._activator = new ExtensionsActivator(this._registry, initData.resolvedExtensions, initData.hostExtensions, {
|
||||
onExtensionActivationError: (extensionId: ExtensionIdentifier, error: ExtensionActivationError): void => {
|
||||
this._mainThreadExtensionsProxy.$onExtensionActivationError(extensionId, error);
|
||||
},
|
||||
|
||||
actualActivateExtension: async (extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<ActivatedExtension> => {
|
||||
if (hostExtensions.has(ExtensionIdentifier.toKey(extensionId))) {
|
||||
const activationEvent = (reason instanceof ExtensionActivatedByEvent ? reason.activationEvent : null);
|
||||
await this._mainThreadExtensionsProxy.$activateExtension(extensionId, activationEvent);
|
||||
return new HostExtension();
|
||||
}
|
||||
const extensionDescription = this._registry.getExtensionDescription(extensionId)!;
|
||||
return this._activateExtension(extensionDescription, reason);
|
||||
}
|
||||
});
|
||||
this._extensionPathIndex = null;
|
||||
|
||||
// initialize API first (i.e. do not release barrier until the API is initialized)
|
||||
this._extensionApiFactory = createApiFactory(
|
||||
this._initData,
|
||||
this._extHostContext,
|
||||
this._extHostWorkspace,
|
||||
this._extHostConfiguration,
|
||||
this,
|
||||
this._extHostLogService,
|
||||
this._storage,
|
||||
uriTransformer
|
||||
);
|
||||
|
||||
this._resolvers = Object.create(null);
|
||||
|
||||
this._started = false;
|
||||
|
||||
this._initialize();
|
||||
|
||||
if (this._initData.autoStart) {
|
||||
this._startExtensionHost();
|
||||
// Register CLI Server for ipc
|
||||
if (this._initData.remote.isRemote && this._initData.remote.authority) {
|
||||
const cliServer = this._instaService.createInstance(CLIServer);
|
||||
process.env['VSCODE_IPC_HOOK_CLI'] = cliServer.ipcHandlePath;
|
||||
}
|
||||
|
||||
// Module loading tricks
|
||||
const configProvider = await this._extHostConfiguration.getConfigProvider();
|
||||
const extensionPaths = await this.getExtensionPathIndex();
|
||||
// {{SQL CARBON EDIT}} - disable VSCodeNodeModuleFactory and use older initializeExtensionApi
|
||||
// NodeModuleRequireInterceptor.INSTANCE.register(new VSCodeNodeModuleFactory(this._extensionApiFactory, extensionPaths, this._registry, configProvider));
|
||||
await initializeExtensionApi(this, extensionApiFactory, this._registry, configProvider);
|
||||
NodeModuleRequireInterceptor.INSTANCE.register(new KeytarNodeModuleFactory(this._extHostContext.getProxy(MainContext.MainThreadKeytar), this._initData.environment));
|
||||
if (this._initData.remote.isRemote) {
|
||||
NodeModuleRequireInterceptor.INSTANCE.register(new OpenNodeModuleFactory(
|
||||
this._extHostContext.getProxy(MainContext.MainThreadWindow),
|
||||
this._extHostContext.getProxy(MainContext.MainThreadTelemetry),
|
||||
extensionPaths
|
||||
));
|
||||
}
|
||||
|
||||
// Do this when extension service exists, but extensions are not being activated yet.
|
||||
await connectProxyResolver(this._extHostWorkspace, configProvider, this, this._extHostLogService, this._mainThreadTelemetryProxy);
|
||||
|
||||
}
|
||||
|
||||
private async _initialize(): Promise<void> {
|
||||
protected _loadCommonJSModule<T>(modulePath: string, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<T> {
|
||||
let r: T | null = null;
|
||||
activationTimesBuilder.codeLoadingStart();
|
||||
this._extHostLogService.info(`ExtensionService#loadCommonJSModule ${modulePath}`);
|
||||
try {
|
||||
const configProvider = await this._extHostConfiguration.getConfigProvider();
|
||||
const extensionPaths = await this.getExtensionPathIndex();
|
||||
// {{SQL CARBON EDIT}} - disable VSCodeNodeModuleFactory and use older initializeExtensionApi
|
||||
// NodeModuleRequireInterceptor.INSTANCE.register(new VSCodeNodeModuleFactory(this._extensionApiFactory, extensionPaths, this._registry, configProvider));
|
||||
await initializeExtensionApi(this, this._extensionApiFactory, this._registry, configProvider);
|
||||
NodeModuleRequireInterceptor.INSTANCE.register(new KeytarNodeModuleFactory(this._extHostContext.getProxy(MainContext.MainThreadKeytar), this._environment));
|
||||
if (this._initData.remote.isRemote) {
|
||||
NodeModuleRequireInterceptor.INSTANCE.register(new OpenNodeModuleFactory(
|
||||
this._extHostContext.getProxy(MainContext.MainThreadWindow),
|
||||
this._extHostContext.getProxy(MainContext.MainThreadTelemetry),
|
||||
extensionPaths
|
||||
));
|
||||
}
|
||||
|
||||
// Do this when extension service exists, but extensions are not being activated yet.
|
||||
await connectProxyResolver(this._extHostWorkspace, configProvider, this, this._extHostLogService, this._mainThreadTelemetryProxy);
|
||||
this._almostReadyToRunExtensions.open();
|
||||
|
||||
await this._extHostWorkspace.waitForInitializeCall();
|
||||
this._readyToStartExtensionHost.open();
|
||||
} catch (err) {
|
||||
errors.onUnexpectedError(err);
|
||||
r = require.__$__nodeRequire<T>(modulePath);
|
||||
} catch (e) {
|
||||
return Promise.reject(e);
|
||||
} finally {
|
||||
activationTimesBuilder.codeLoadingStop();
|
||||
}
|
||||
}
|
||||
|
||||
public async deactivateAll(): Promise<void> {
|
||||
let allPromises: Promise<void>[] = [];
|
||||
try {
|
||||
const allExtensions = this._registry.getAllExtensionDescriptions();
|
||||
const allExtensionsIds = allExtensions.map(ext => ext.identifier);
|
||||
const activatedExtensions = allExtensionsIds.filter(id => this.isActivated(id));
|
||||
|
||||
allPromises = activatedExtensions.map((extensionId) => {
|
||||
return this._deactivate(extensionId);
|
||||
});
|
||||
} catch (err) {
|
||||
// TODO: write to log once we have one
|
||||
}
|
||||
await allPromises;
|
||||
}
|
||||
|
||||
public isActivated(extensionId: ExtensionIdentifier): boolean {
|
||||
if (this._readyToRunExtensions.isOpen()) {
|
||||
return this._activator.isActivated(extensionId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private _activateByEvent(activationEvent: string, startup: boolean): Promise<void> {
|
||||
const reason = new ExtensionActivatedByEvent(startup, activationEvent);
|
||||
return this._activator.activateByEvent(activationEvent, reason);
|
||||
}
|
||||
|
||||
private _activateById(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void> {
|
||||
return this._activator.activateById(extensionId, reason);
|
||||
}
|
||||
|
||||
public activateByIdWithErrors(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void> {
|
||||
return this._activateById(extensionId, reason).then(() => {
|
||||
const extension = this._activator.getActivatedExtension(extensionId);
|
||||
if (extension.activationFailed) {
|
||||
// activation failed => bubble up the error as the promise result
|
||||
return Promise.reject(extension.activationFailedError);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
public getExtensionRegistry(): Promise<ExtensionDescriptionRegistry> {
|
||||
return this._readyToRunExtensions.wait().then(_ => this._registry);
|
||||
}
|
||||
|
||||
public getExtensionExports(extensionId: ExtensionIdentifier): IExtensionAPI | null | undefined {
|
||||
if (this._readyToRunExtensions.isOpen()) {
|
||||
return this._activator.getActivatedExtension(extensionId).exports;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// create trie to enable fast 'filename -> extension id' look up
|
||||
public getExtensionPathIndex(): Promise<TernarySearchTree<IExtensionDescription>> {
|
||||
if (!this._extensionPathIndex) {
|
||||
const tree = TernarySearchTree.forPaths<IExtensionDescription>();
|
||||
const extensions = this._registry.getAllExtensionDescriptions().map(ext => {
|
||||
if (!ext.main) {
|
||||
return undefined;
|
||||
}
|
||||
return this._hostUtils.realpath(ext.extensionLocation.fsPath).then(value => tree.set(URI.file(value).fsPath, ext));
|
||||
});
|
||||
this._extensionPathIndex = Promise.all(extensions).then(() => tree);
|
||||
}
|
||||
return this._extensionPathIndex;
|
||||
}
|
||||
|
||||
private _deactivate(extensionId: ExtensionIdentifier): Promise<void> {
|
||||
let result = Promise.resolve(undefined);
|
||||
|
||||
if (!this._readyToRunExtensions.isOpen()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!this._activator.isActivated(extensionId)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
const extension = this._activator.getActivatedExtension(extensionId);
|
||||
if (!extension) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// call deactivate if available
|
||||
try {
|
||||
if (typeof extension.module.deactivate === 'function') {
|
||||
result = Promise.resolve(extension.module.deactivate()).then(undefined, (err) => {
|
||||
// TODO: Do something with err if this is not the shutdown case
|
||||
return Promise.resolve(undefined);
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
// TODO: Do something with err if this is not the shutdown case
|
||||
}
|
||||
|
||||
// clean up subscriptions
|
||||
try {
|
||||
dispose(extension.subscriptions);
|
||||
} catch (err) {
|
||||
// TODO: Do something with err if this is not the shutdown case
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// --- impl
|
||||
|
||||
private _activateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise<ActivatedExtension> {
|
||||
this._mainThreadExtensionsProxy.$onWillActivateExtension(extensionDescription.identifier);
|
||||
return this._doActivateExtension(extensionDescription, reason).then((activatedExtension) => {
|
||||
const activationTimes = activatedExtension.activationTimes;
|
||||
const activationEvent = (reason instanceof ExtensionActivatedByEvent ? reason.activationEvent : null);
|
||||
this._mainThreadExtensionsProxy.$onDidActivateExtension(extensionDescription.identifier, activationTimes.startup, activationTimes.codeLoadingTime, activationTimes.activateCallTime, activationTimes.activateResolvedTime, activationEvent);
|
||||
this._logExtensionActivationTimes(extensionDescription, reason, 'success', activationTimes);
|
||||
return activatedExtension;
|
||||
}, (err) => {
|
||||
this._logExtensionActivationTimes(extensionDescription, reason, 'failure');
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
private _logExtensionActivationTimes(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason, outcome: string, activationTimes?: ExtensionActivationTimes) {
|
||||
const event = getTelemetryActivationEvent(extensionDescription, reason);
|
||||
type ExtensionActivationTimesClassification = {
|
||||
outcome: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
} & TelemetryActivationEventFragment & ExtensionActivationTimesFragment;
|
||||
|
||||
type ExtensionActivationTimesEvent = {
|
||||
outcome: string
|
||||
} & ActivationTimesEvent & TelemetryActivationEvent;
|
||||
|
||||
type ActivationTimesEvent = {
|
||||
startup?: boolean;
|
||||
codeLoadingTime?: number;
|
||||
activateCallTime?: number;
|
||||
activateResolvedTime?: number;
|
||||
};
|
||||
|
||||
this._mainThreadTelemetryProxy.$publicLog2<ExtensionActivationTimesEvent, ExtensionActivationTimesClassification>('extensionActivationTimes', {
|
||||
...event,
|
||||
...(activationTimes || {}),
|
||||
outcome
|
||||
});
|
||||
}
|
||||
|
||||
private _doActivateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise<ActivatedExtension> {
|
||||
const event = getTelemetryActivationEvent(extensionDescription, reason);
|
||||
type ActivatePluginClassification = {} & TelemetryActivationEventFragment;
|
||||
this._mainThreadTelemetryProxy.$publicLog2<TelemetryActivationEvent, ActivatePluginClassification>('activatePlugin', event);
|
||||
if (!extensionDescription.main) {
|
||||
// Treat the extension as being empty => NOT AN ERROR CASE
|
||||
return Promise.resolve(new EmptyExtension(ExtensionActivationTimes.NONE));
|
||||
}
|
||||
|
||||
this._extHostLogService.info(`ExtensionService#_doActivateExtension ${extensionDescription.identifier.value} ${JSON.stringify(reason)}`);
|
||||
|
||||
const activationTimesBuilder = new ExtensionActivationTimesBuilder(reason.startup);
|
||||
return Promise.all<any>([
|
||||
loadCommonJSModule(this._extHostLogService, extensionDescription.main, activationTimesBuilder),
|
||||
this._loadExtensionContext(extensionDescription)
|
||||
]).then(values => {
|
||||
return ExtHostExtensionService._callActivate(this._extHostLogService, extensionDescription.identifier, <IExtensionModule>values[0], <IExtensionContext>values[1], activationTimesBuilder);
|
||||
});
|
||||
}
|
||||
|
||||
private _loadExtensionContext(extensionDescription: IExtensionDescription): Promise<vscode.ExtensionContext> {
|
||||
|
||||
const globalState = new ExtensionMemento(extensionDescription.identifier.value, true, this._storage);
|
||||
const workspaceState = new ExtensionMemento(extensionDescription.identifier.value, false, this._storage);
|
||||
|
||||
this._extHostLogService.trace(`ExtensionService#loadExtensionContext ${extensionDescription.identifier.value}`);
|
||||
return Promise.all([
|
||||
globalState.whenReady,
|
||||
workspaceState.whenReady,
|
||||
this._storagePath.whenReady
|
||||
]).then(() => {
|
||||
const that = this;
|
||||
return Object.freeze(<IExtensionContext>{
|
||||
globalState,
|
||||
workspaceState,
|
||||
subscriptions: [],
|
||||
get extensionPath() { return extensionDescription.extensionLocation.fsPath; },
|
||||
storagePath: this._storagePath.workspaceValue(extensionDescription),
|
||||
globalStoragePath: this._storagePath.globalValue(extensionDescription),
|
||||
asAbsolutePath: (relativePath: string) => { return path.join(extensionDescription.extensionLocation.fsPath, relativePath); },
|
||||
logPath: that._extHostLogService.getLogDirectory(extensionDescription.identifier),
|
||||
executionContext: this._initData.remote.isRemote ? ExtensionExecutionContext.Remote : ExtensionExecutionContext.Local,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private static _callActivate(logService: ILogService, extensionId: ExtensionIdentifier, extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<ActivatedExtension> {
|
||||
// Make sure the extension's surface is not undefined
|
||||
extensionModule = extensionModule || {
|
||||
activate: undefined,
|
||||
deactivate: undefined
|
||||
};
|
||||
|
||||
return this._callActivateOptional(logService, extensionId, extensionModule, context, activationTimesBuilder).then((extensionExports) => {
|
||||
return new ActivatedExtension(false, null, activationTimesBuilder.build(), extensionModule, extensionExports, context.subscriptions);
|
||||
});
|
||||
}
|
||||
|
||||
private static _callActivateOptional(logService: ILogService, extensionId: ExtensionIdentifier, extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<IExtensionAPI> {
|
||||
if (typeof extensionModule.activate === 'function') {
|
||||
try {
|
||||
activationTimesBuilder.activateCallStart();
|
||||
logService.trace(`ExtensionService#_callActivateOptional ${extensionId.value}`);
|
||||
const activateResult: Promise<IExtensionAPI> = extensionModule.activate.apply(global, [context]);
|
||||
activationTimesBuilder.activateCallStop();
|
||||
|
||||
activationTimesBuilder.activateResolveStart();
|
||||
return Promise.resolve(activateResult).then((value) => {
|
||||
activationTimesBuilder.activateResolveStop();
|
||||
return value;
|
||||
});
|
||||
} catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
} else {
|
||||
// No activate found => the module is the extension's exports
|
||||
return Promise.resolve<IExtensionAPI>(extensionModule);
|
||||
}
|
||||
}
|
||||
|
||||
// -- eager activation
|
||||
|
||||
// Handle "eager" activation extensions
|
||||
private async _handleEagerExtensions(): Promise<void> {
|
||||
// {{SQL CARBON EDIT}} - load MSSQL extension first so it doesn't get delayed by other extensions
|
||||
try {
|
||||
await this._activateById(new ExtensionIdentifier('microsoft.mssql'), new ExtensionActivatedByEvent(true, `Load MSSQL extension first on startup`));
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
return this._defaultHandleEagerExtensions();
|
||||
}
|
||||
|
||||
|
||||
// Handle "eager" activation extensions
|
||||
private _defaultHandleEagerExtensions(): Promise<void> {
|
||||
this._activateByEvent('*', true).then(undefined, (err) => {
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
this._disposables.add(this._extHostWorkspace.onDidChangeWorkspace((e) => this._handleWorkspaceContainsEagerExtensions(e.added)));
|
||||
const folders = this._extHostWorkspace.workspace ? this._extHostWorkspace.workspace.folders : [];
|
||||
return this._handleWorkspaceContainsEagerExtensions(folders);
|
||||
}
|
||||
|
||||
private _handleWorkspaceContainsEagerExtensions(folders: ReadonlyArray<vscode.WorkspaceFolder>): Promise<void> {
|
||||
if (folders.length === 0) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
return Promise.all(
|
||||
this._registry.getAllExtensionDescriptions().map((desc) => {
|
||||
return this._handleWorkspaceContainsEagerExtension(folders, desc);
|
||||
})
|
||||
).then(() => { });
|
||||
}
|
||||
|
||||
private _handleWorkspaceContainsEagerExtension(folders: ReadonlyArray<vscode.WorkspaceFolder>, desc: IExtensionDescription): Promise<void> {
|
||||
const activationEvents = desc.activationEvents;
|
||||
if (!activationEvents) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
if (this.isActivated(desc.identifier)) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const fileNames: string[] = [];
|
||||
const globPatterns: string[] = [];
|
||||
|
||||
for (const activationEvent of activationEvents) {
|
||||
if (/^workspaceContains:/.test(activationEvent)) {
|
||||
const fileNameOrGlob = activationEvent.substr('workspaceContains:'.length);
|
||||
if (fileNameOrGlob.indexOf('*') >= 0 || fileNameOrGlob.indexOf('?') >= 0) {
|
||||
globPatterns.push(fileNameOrGlob);
|
||||
} else {
|
||||
fileNames.push(fileNameOrGlob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fileNames.length === 0 && globPatterns.length === 0) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const fileNamePromise = Promise.all(fileNames.map((fileName) => this._activateIfFileName(folders, desc.identifier, fileName))).then(() => { });
|
||||
const globPatternPromise = this._activateIfGlobPatterns(folders, desc.identifier, globPatterns);
|
||||
|
||||
return Promise.all([fileNamePromise, globPatternPromise]).then(() => { });
|
||||
}
|
||||
|
||||
private async _activateIfFileName(folders: ReadonlyArray<vscode.WorkspaceFolder>, extensionId: ExtensionIdentifier, fileName: string): Promise<void> {
|
||||
|
||||
// find exact path
|
||||
for (const { uri } of folders) {
|
||||
if (await this._hostUtils.exists(path.join(URI.revive(uri).fsPath, fileName))) {
|
||||
// the file was found
|
||||
return (
|
||||
this._activateById(extensionId, new ExtensionActivatedByEvent(true, `workspaceContains:${fileName}`))
|
||||
.then(undefined, err => console.error(err))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private async _activateIfGlobPatterns(folders: ReadonlyArray<vscode.WorkspaceFolder>, extensionId: ExtensionIdentifier, globPatterns: string[]): Promise<void> {
|
||||
this._extHostLogService.trace(`extensionHostMain#activateIfGlobPatterns: fileSearch, extension: ${extensionId.value}, entryPoint: workspaceContains`);
|
||||
|
||||
if (globPatterns.length === 0) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const tokenSource = new CancellationTokenSource();
|
||||
const searchP = this._mainThreadWorkspaceProxy.$checkExists(folders.map(folder => folder.uri), globPatterns, tokenSource.token);
|
||||
|
||||
const timer = setTimeout(async () => {
|
||||
tokenSource.cancel();
|
||||
this._activateById(extensionId, new ExtensionActivatedByEvent(true, `workspaceContainsTimeout:${globPatterns.join(',')}`))
|
||||
.then(undefined, err => console.error(err));
|
||||
}, ExtHostExtensionService.WORKSPACE_CONTAINS_TIMEOUT);
|
||||
|
||||
let exists: boolean = false;
|
||||
try {
|
||||
exists = await searchP;
|
||||
} catch (err) {
|
||||
if (!errors.isPromiseCanceledError(err)) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
tokenSource.dispose();
|
||||
clearTimeout(timer);
|
||||
|
||||
if (exists) {
|
||||
// a file was found matching one of the glob patterns
|
||||
return (
|
||||
this._activateById(extensionId, new ExtensionActivatedByEvent(true, `workspaceContains:${globPatterns.join(',')}`))
|
||||
.then(undefined, err => console.error(err))
|
||||
);
|
||||
}
|
||||
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
private _handleExtensionTests(): Promise<void> {
|
||||
return this._doHandleExtensionTests().then(undefined, error => {
|
||||
console.error(error); // ensure any error message makes it onto the console
|
||||
|
||||
return Promise.reject(error);
|
||||
});
|
||||
}
|
||||
|
||||
private _doHandleExtensionTests(): Promise<void> {
|
||||
const { extensionDevelopmentLocationURI: extensionDevelopmentLocationURI, extensionTestsLocationURI } = this._initData.environment;
|
||||
if (!(extensionDevelopmentLocationURI && extensionTestsLocationURI && extensionTestsLocationURI.scheme === Schemas.file)) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const extensionTestsPath = originalFSPath(extensionTestsLocationURI);
|
||||
|
||||
// Require the test runner via node require from the provided path
|
||||
let testRunner: ITestRunner | INewTestRunner | undefined;
|
||||
let requireError: Error | undefined;
|
||||
try {
|
||||
testRunner = <any>require.__$__nodeRequire(extensionTestsPath);
|
||||
} catch (error) {
|
||||
requireError = error;
|
||||
}
|
||||
|
||||
// Execute the runner if it follows the old `run` spec
|
||||
if (testRunner && typeof testRunner.run === 'function') {
|
||||
return new Promise<void>((c, e) => {
|
||||
const oldTestRunnerCallback = (error: Error, failures: number | undefined) => {
|
||||
if (error) {
|
||||
e(error.toString());
|
||||
} else {
|
||||
c(undefined);
|
||||
}
|
||||
|
||||
// after tests have run, we shutdown the host
|
||||
this._gracefulExit(error || (typeof failures === 'number' && failures > 0) ? 1 /* ERROR */ : 0 /* OK */);
|
||||
};
|
||||
|
||||
const runResult = testRunner!.run(extensionTestsPath, oldTestRunnerCallback);
|
||||
|
||||
// Using the new API `run(): Promise<void>`
|
||||
if (runResult && runResult.then) {
|
||||
runResult
|
||||
.then(() => {
|
||||
c();
|
||||
this._gracefulExit(0);
|
||||
})
|
||||
.catch((err: Error) => {
|
||||
e(err.toString());
|
||||
this._gracefulExit(1);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Otherwise make sure to shutdown anyway even in case of an error
|
||||
else {
|
||||
this._gracefulExit(1 /* ERROR */);
|
||||
}
|
||||
|
||||
return Promise.reject(new Error(requireError ? requireError.toString() : nls.localize('extensionTestError', "Path {0} does not point to a valid extension test runner.", extensionTestsPath)));
|
||||
}
|
||||
|
||||
private _gracefulExit(code: number): void {
|
||||
// to give the PH process a chance to flush any outstanding console
|
||||
// messages to the main process, we delay the exit() by some time
|
||||
setTimeout(() => {
|
||||
// If extension tests are running, give the exit code to the renderer
|
||||
if (this._initData.remote.isRemote && !!this._initData.environment.extensionTestsLocationURI) {
|
||||
this._mainThreadExtensionsProxy.$onExtensionHostExit(code);
|
||||
return;
|
||||
}
|
||||
|
||||
this._hostUtils.exit(code);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
private _startExtensionHost(): Promise<void> {
|
||||
if (this._started) {
|
||||
throw new Error(`Extension host is already started!`);
|
||||
}
|
||||
this._started = true;
|
||||
|
||||
return this._readyToStartExtensionHost.wait()
|
||||
.then(() => this._readyToRunExtensions.open())
|
||||
.then(() => this._handleEagerExtensions())
|
||||
.then(() => this._handleExtensionTests())
|
||||
.then(() => {
|
||||
this._extHostLogService.info(`eager extensions activated`);
|
||||
});
|
||||
}
|
||||
|
||||
// -- called by extensions
|
||||
|
||||
public registerRemoteAuthorityResolver(authorityPrefix: string, resolver: vscode.RemoteAuthorityResolver): vscode.Disposable {
|
||||
this._resolvers[authorityPrefix] = resolver;
|
||||
return toDisposable(() => {
|
||||
delete this._resolvers[authorityPrefix];
|
||||
});
|
||||
}
|
||||
|
||||
// -- called by main thread
|
||||
|
||||
public async $resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise<IResolveAuthorityResult> {
|
||||
const authorityPlusIndex = remoteAuthority.indexOf('+');
|
||||
if (authorityPlusIndex === -1) {
|
||||
throw new Error(`Not an authority that can be resolved!`);
|
||||
}
|
||||
const authorityPrefix = remoteAuthority.substr(0, authorityPlusIndex);
|
||||
|
||||
await this._almostReadyToRunExtensions.wait();
|
||||
await this._activateByEvent(`onResolveRemoteAuthority:${authorityPrefix}`, false);
|
||||
|
||||
const resolver = this._resolvers[authorityPrefix];
|
||||
if (!resolver) {
|
||||
throw new Error(`No remote extension installed to resolve ${authorityPrefix}.`);
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await resolver.resolve(remoteAuthority, { resolveAttempt });
|
||||
|
||||
// Split merged API result into separate authority/options
|
||||
const authority: ResolvedAuthority = {
|
||||
authority: remoteAuthority,
|
||||
host: result.host,
|
||||
port: result.port
|
||||
};
|
||||
const options: ResolvedOptions = {
|
||||
extensionHostEnv: result.extensionHostEnv
|
||||
};
|
||||
|
||||
return {
|
||||
type: 'ok',
|
||||
value: {
|
||||
authority,
|
||||
options
|
||||
}
|
||||
};
|
||||
} catch (err) {
|
||||
if (err instanceof RemoteAuthorityResolverError) {
|
||||
return {
|
||||
type: 'error',
|
||||
error: {
|
||||
code: err._code,
|
||||
message: err._message,
|
||||
detail: err._detail
|
||||
}
|
||||
};
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
public $startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise<void> {
|
||||
this._registry.keepOnly(enabledExtensionIds);
|
||||
return this._startExtensionHost();
|
||||
}
|
||||
|
||||
public $activateByEvent(activationEvent: string): Promise<void> {
|
||||
return (
|
||||
this._readyToRunExtensions.wait()
|
||||
.then(_ => this._activateByEvent(activationEvent, false))
|
||||
);
|
||||
}
|
||||
|
||||
public async $activate(extensionId: ExtensionIdentifier, activationEvent: string): Promise<boolean> {
|
||||
await this._readyToRunExtensions.wait();
|
||||
if (!this._registry.getExtensionDescription(extensionId)) {
|
||||
// unknown extension => ignore
|
||||
return false;
|
||||
}
|
||||
await this._activateById(extensionId, new ExtensionActivatedByEvent(false, activationEvent));
|
||||
return true;
|
||||
}
|
||||
|
||||
public async $deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void> {
|
||||
toAdd.forEach((extension) => (<any>extension).extensionLocation = URI.revive(extension.extensionLocation));
|
||||
|
||||
const trie = await this.getExtensionPathIndex();
|
||||
|
||||
await Promise.all(toRemove.map(async (extensionId) => {
|
||||
const extensionDescription = this._registry.getExtensionDescription(extensionId);
|
||||
if (!extensionDescription) {
|
||||
return;
|
||||
}
|
||||
const realpathValue = await this._hostUtils.realpath(extensionDescription.extensionLocation.fsPath);
|
||||
trie.delete(URI.file(realpathValue).fsPath);
|
||||
}));
|
||||
|
||||
await Promise.all(toAdd.map(async (extensionDescription) => {
|
||||
const realpathValue = await this._hostUtils.realpath(extensionDescription.extensionLocation.fsPath);
|
||||
trie.set(URI.file(realpathValue).fsPath, extensionDescription);
|
||||
}));
|
||||
|
||||
this._registry.deltaExtensions(toAdd, toRemove);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
public async $test_latency(n: number): Promise<number> {
|
||||
return n;
|
||||
}
|
||||
|
||||
public async $test_up(b: VSBuffer): Promise<number> {
|
||||
return b.byteLength;
|
||||
}
|
||||
|
||||
public async $test_down(size: number): Promise<VSBuffer> {
|
||||
let buff = VSBuffer.alloc(size);
|
||||
let value = Math.random() % 256;
|
||||
for (let i = 0; i < size; i++) {
|
||||
buff.writeUInt8(value, i);
|
||||
}
|
||||
return buff;
|
||||
return Promise.resolve(r);
|
||||
}
|
||||
|
||||
public async $setRemoteEnvironment(env: { [key: string]: string | null }): Promise<void> {
|
||||
@@ -782,44 +77,3 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loadCommonJSModule<T>(logService: ILogService, modulePath: string, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<T> {
|
||||
let r: T | null = null;
|
||||
activationTimesBuilder.codeLoadingStart();
|
||||
logService.info(`ExtensionService#loadCommonJSModule ${modulePath}`);
|
||||
try {
|
||||
r = require.__$__nodeRequire<T>(modulePath);
|
||||
} catch (e) {
|
||||
return Promise.reject(e);
|
||||
} finally {
|
||||
activationTimesBuilder.codeLoadingStop();
|
||||
}
|
||||
return Promise.resolve(r);
|
||||
}
|
||||
|
||||
type TelemetryActivationEvent = {
|
||||
id: string;
|
||||
name: string;
|
||||
extensionVersion: string;
|
||||
publisherDisplayName: string;
|
||||
activationEvents: string | null;
|
||||
isBuiltin: boolean;
|
||||
reason: string;
|
||||
};
|
||||
|
||||
function getTelemetryActivationEvent(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): TelemetryActivationEvent {
|
||||
const reasonStr = reason instanceof ExtensionActivatedByEvent ? reason.activationEvent :
|
||||
reason instanceof ExtensionActivatedByAPI ? 'api' :
|
||||
'';
|
||||
const event = {
|
||||
id: extensionDescription.identifier.value,
|
||||
name: extensionDescription.name,
|
||||
extensionVersion: extensionDescription.version,
|
||||
publisherDisplayName: extensionDescription.publisher,
|
||||
activationEvents: extensionDescription.activationEvents ? extensionDescription.activationEvents.join(',') : null,
|
||||
isBuiltin: extensionDescription.isBuiltin,
|
||||
reason: reasonStr
|
||||
};
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,9 @@ import { join } from 'vs/base/common/path';
|
||||
import { OutputAppender } from 'vs/workbench/services/output/node/outputAppender';
|
||||
import { toLocalISOString } from 'vs/base/common/date';
|
||||
import { dirExists, mkdirp } from 'vs/base/node/pfs';
|
||||
import { AbstractExtHostOutputChannel, IOutputChannelFactory, ExtHostPushOutputChannel } from 'vs/workbench/api/common/extHostOutput';
|
||||
import { AbstractExtHostOutputChannel, ExtHostPushOutputChannel, ExtHostOutputService, LazyOutputChannel } from 'vs/workbench/api/common/extHostOutput';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
|
||||
export class ExtHostOutputChannelBackedByFile extends AbstractExtHostOutputChannel {
|
||||
|
||||
@@ -43,23 +45,39 @@ export class ExtHostOutputChannelBackedByFile extends AbstractExtHostOutputChann
|
||||
}
|
||||
}
|
||||
|
||||
export const LogOutputChannelFactory = new class implements IOutputChannelFactory {
|
||||
export class ExtHostOutputService2 extends ExtHostOutputService {
|
||||
|
||||
_namePool = 1;
|
||||
private _logsLocation: URI;
|
||||
private _namePool: number = 1;
|
||||
|
||||
async createOutputChannel(name: string, logsLocation: URI, proxy: MainThreadOutputServiceShape): Promise<AbstractExtHostOutputChannel> {
|
||||
constructor(
|
||||
@IExtHostRpcService extHostRpc: IExtHostRpcService,
|
||||
@IExtHostInitDataService initData: IExtHostInitDataService,
|
||||
) {
|
||||
super(extHostRpc);
|
||||
this._logsLocation = initData.logsLocation;
|
||||
}
|
||||
|
||||
createOutputChannel(name: string): vscode.OutputChannel {
|
||||
name = name.trim();
|
||||
if (!name) {
|
||||
throw new Error('illegal argument `name`. must not be falsy');
|
||||
}
|
||||
return new LazyOutputChannel(name, this._doCreateOutChannel(name));
|
||||
}
|
||||
|
||||
private async _doCreateOutChannel(name: string): Promise<AbstractExtHostOutputChannel> {
|
||||
try {
|
||||
const outputDirPath = join(logsLocation.fsPath, `output_logging_${toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '')}`);
|
||||
const outputDir = await dirExists(outputDirPath).then(exists => exists ? exists : mkdirp(outputDirPath).then(() => true)).then(() => outputDirPath);
|
||||
const outputDirPath = join(this._logsLocation.fsPath, `output_logging_${toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '')}`);
|
||||
const outputDir = await dirExists(outputDirPath).then(exists => exists || mkdirp(outputDirPath).then(() => true)).then(() => outputDirPath);
|
||||
const fileName = `${this._namePool++}-${name.replace(/[\\/:\*\?"<>\|]/g, '')}`;
|
||||
const file = URI.file(join(outputDir, `${fileName}.log`));
|
||||
const appender = new OutputAppender(fileName, file.fsPath);
|
||||
return new ExtHostOutputChannelBackedByFile(name, appender, proxy);
|
||||
return new ExtHostOutputChannelBackedByFile(name, appender, this._proxy);
|
||||
} catch (error) {
|
||||
// Do not crash if logger cannot be created
|
||||
console.log(error);
|
||||
return new ExtHostPushOutputChannel(name, proxy);
|
||||
return new ExtHostPushOutputChannel(name, this._proxy);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/c
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { endsWith } from 'vs/base/common/strings';
|
||||
import { IExtensionApiFactory } from 'vs/workbench/api/node/extHost.api.impl';
|
||||
import { IExtensionApiFactory } from 'vs/workbench/api/common/extHost.api.impl';
|
||||
|
||||
|
||||
interface LoadFunction {
|
||||
@@ -75,7 +75,7 @@ export class VSCodeNodeModuleFactory implements INodeModuleFactory {
|
||||
public readonly nodeModuleName = 'vscode';
|
||||
|
||||
private readonly _extApiImpl = new Map<string, typeof vscode>();
|
||||
private _defaultApiImpl: typeof vscode;
|
||||
private _defaultApiImpl?: typeof vscode;
|
||||
|
||||
constructor(
|
||||
private readonly _apiFactory: IExtensionApiFactory,
|
||||
@@ -191,7 +191,7 @@ export class OpenNodeModuleFactory implements INodeModuleFactory {
|
||||
public readonly nodeModuleName: string[] = ['open', 'opn'];
|
||||
|
||||
private _extensionId: string | undefined;
|
||||
private _original: IOriginalOpen;
|
||||
private _original?: IOriginalOpen;
|
||||
private _impl: IOpenModule;
|
||||
|
||||
constructor(mainThreadWindow: MainThreadWindowShape, private _mainThreadTelemerty: MainThreadTelemetryShape, private readonly _extensionPaths: TernarySearchTree<IExtensionDescription>) {
|
||||
@@ -224,7 +224,7 @@ export class OpenNodeModuleFactory implements INodeModuleFactory {
|
||||
|
||||
private callOriginal(target: string, options: OpenOptions | undefined): Thenable<any> {
|
||||
this.sendNoForwardTelemetry();
|
||||
return this._original(target, options);
|
||||
return this._original!(target, options);
|
||||
}
|
||||
|
||||
private sendShimmingTelemetry(): void {
|
||||
|
||||
@@ -15,8 +15,10 @@ import { RipgrepSearchProvider } from 'vs/workbench/services/search/node/ripgrep
|
||||
import { OutputChannel } from 'vs/workbench/services/search/node/ripgrepSearchUtils';
|
||||
import { TextSearchManager } from 'vs/workbench/services/search/node/textSearchManager';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostSearchShape, IMainContext, MainContext, MainThreadSearchShape } from '../common/extHost.protocol';
|
||||
import { IURITransformer } from 'vs/base/common/uriIpc';
|
||||
import { ExtHostSearchShape, MainContext, MainThreadSearchShape } from '../common/extHost.protocol';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { IURITransformerService } from 'vs/workbench/api/common/extHostUriTransformerService';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
|
||||
export class ExtHostSearch implements ExtHostSearchShape {
|
||||
|
||||
@@ -32,16 +34,30 @@ export class ExtHostSearch implements ExtHostSearchShape {
|
||||
|
||||
private _fileSearchManager: FileSearchManager;
|
||||
|
||||
constructor(mainContext: IMainContext, private _uriTransformer: IURITransformer | null, private _logService: ILogService, private _pfs = pfs) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadSearch);
|
||||
protected _pfs: typeof pfs = pfs; // allow extending for tests
|
||||
|
||||
constructor(
|
||||
@IExtHostRpcService extHostRpc: IExtHostRpcService,
|
||||
@IExtHostInitDataService initData: IExtHostInitDataService,
|
||||
@IURITransformerService private _uriTransformer: IURITransformerService,
|
||||
@ILogService private _logService: ILogService,
|
||||
) {
|
||||
this._proxy = extHostRpc.getProxy(MainContext.MainThreadSearch);
|
||||
this._fileSearchManager = new FileSearchManager();
|
||||
|
||||
if (initData.remote.isRemote && initData.remote.authority) {
|
||||
this._registerEHSearchProviders();
|
||||
}
|
||||
}
|
||||
|
||||
private _registerEHSearchProviders(): void {
|
||||
const outputChannel = new OutputChannel(this._logService);
|
||||
this.registerTextSearchProvider('file', new RipgrepSearchProvider(outputChannel));
|
||||
this.registerInternalFileSearchProvider('file', new SearchService());
|
||||
}
|
||||
|
||||
private _transformScheme(scheme: string): string {
|
||||
if (this._uriTransformer) {
|
||||
return this._uriTransformer.transformOutgoingScheme(scheme);
|
||||
}
|
||||
return scheme;
|
||||
return this._uriTransformer.transformOutgoingScheme(scheme);
|
||||
}
|
||||
|
||||
registerTextSearchProvider(scheme: string, provider: vscode.TextSearchProvider): IDisposable {
|
||||
@@ -148,12 +164,6 @@ export class ExtHostSearch implements ExtHostSearchShape {
|
||||
}
|
||||
}
|
||||
|
||||
export function registerEHSearchProviders(extHostSearch: ExtHostSearch, logService: ILogService): void {
|
||||
const outputChannel = new OutputChannel(logService);
|
||||
extHostSearch.registerTextSearchProvider('file', new RipgrepSearchProvider(outputChannel));
|
||||
extHostSearch.registerInternalFileSearchProvider('file', new SearchService());
|
||||
}
|
||||
|
||||
function reviveQuery<U extends IRawQuery>(rawQuery: U): U extends IRawTextQuery ? ITextQuery : IFileQuery {
|
||||
return {
|
||||
...<any>rawQuery, // TODO
|
||||
|
||||
@@ -8,23 +8,24 @@ import { URI } from 'vs/base/common/uri';
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
import { IEnvironment, IStaticWorkspaceData } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
|
||||
export class ExtensionStoragePaths {
|
||||
export class ExtensionStoragePaths implements IExtensionStoragePaths {
|
||||
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
private readonly _workspace?: IStaticWorkspaceData;
|
||||
private readonly _environment: IEnvironment;
|
||||
|
||||
private readonly _ready: Promise<string | undefined>;
|
||||
readonly whenReady: Promise<string | undefined>;
|
||||
private _value?: string;
|
||||
|
||||
constructor(workspace: IStaticWorkspaceData | undefined, environment: IEnvironment) {
|
||||
this._workspace = workspace;
|
||||
this._environment = environment;
|
||||
this._ready = this._getOrCreateWorkspaceStoragePath().then(value => this._value = value);
|
||||
}
|
||||
|
||||
get whenReady(): Promise<any> {
|
||||
return this._ready;
|
||||
constructor(@IExtHostInitDataService initData: IExtHostInitDataService) {
|
||||
this._workspace = withNullAsUndefined(initData.workspace);
|
||||
this._environment = initData.environment;
|
||||
this.whenReady = this._getOrCreateWorkspaceStoragePath().then(value => this._value = value);
|
||||
}
|
||||
|
||||
workspaceValue(extension: IExtensionDescription): string | undefined {
|
||||
|
||||
@@ -12,28 +12,28 @@ import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { win32 } from 'vs/base/node/processes';
|
||||
|
||||
|
||||
import { MainContext, MainThreadTaskShape, ExtHostTaskShape, IMainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { MainContext, MainThreadTaskShape, ExtHostTaskShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
|
||||
import * as types from 'vs/workbench/api/common/extHostTypes';
|
||||
import { ExtHostWorkspace, IExtHostWorkspaceProvider } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { IExtHostWorkspaceProvider, IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import * as vscode from 'vscode';
|
||||
import {
|
||||
TaskDefinitionDTO, TaskExecutionDTO, TaskPresentationOptionsDTO,
|
||||
ProcessExecutionOptionsDTO, ProcessExecutionDTO,
|
||||
ShellExecutionOptionsDTO, ShellExecutionDTO,
|
||||
CustomExecutionDTO,
|
||||
CustomExecution2DTO,
|
||||
TaskDTO, TaskHandleDTO, TaskFilterDTO, TaskProcessStartedDTO, TaskProcessEndedDTO, TaskSystemInfoDTO, TaskSetDTO
|
||||
} from '../common/shared/tasks';
|
||||
// {{SQL CARBON EDIT}}
|
||||
// import { ExtHostVariableResolverService } from 'vs/workbench/api/node/extHostDebugService';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { ExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { ExtHostTerminalService, ExtHostTerminal } from 'vs/workbench/api/node/extHostTerminalService';
|
||||
import { ExtHostVariableResolverService } from 'vs/workbench/api/node/extHostDebugService';
|
||||
import { IExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
|
||||
namespace TaskDefinitionDTO {
|
||||
export function from(value: vscode.TaskDefinition): TaskDefinitionDTO | undefined {
|
||||
@@ -81,7 +81,7 @@ namespace ProcessExecutionOptionsDTO {
|
||||
}
|
||||
|
||||
namespace ProcessExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecutionDTO | CustomExecution2DTO | undefined): value is ProcessExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecution2DTO | undefined): value is ProcessExecutionDTO {
|
||||
if (value) {
|
||||
const candidate = value as ProcessExecutionDTO;
|
||||
return candidate && !!candidate.process;
|
||||
@@ -126,7 +126,7 @@ namespace ShellExecutionOptionsDTO {
|
||||
}
|
||||
|
||||
namespace ShellExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecutionDTO | CustomExecution2DTO | undefined): value is ShellExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecution2DTO | undefined): value is ShellExecutionDTO {
|
||||
if (value) {
|
||||
const candidate = value as ShellExecutionDTO;
|
||||
return candidate && (!!candidate.commandLine || !!candidate.command);
|
||||
@@ -163,25 +163,8 @@ namespace ShellExecutionDTO {
|
||||
}
|
||||
}
|
||||
|
||||
namespace CustomExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecutionDTO | CustomExecution2DTO | undefined): value is CustomExecutionDTO {
|
||||
if (value) {
|
||||
let candidate = value as CustomExecutionDTO;
|
||||
return candidate && candidate.customExecution === 'customExecution';
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function from(value: vscode.CustomExecution): CustomExecutionDTO {
|
||||
return {
|
||||
customExecution: 'customExecution'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace CustomExecution2DTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecutionDTO | CustomExecution2DTO | undefined): value is CustomExecution2DTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecution2DTO | undefined): value is CustomExecution2DTO {
|
||||
if (value) {
|
||||
let candidate = value as CustomExecution2DTO;
|
||||
return candidate && candidate.customExecution === 'customExecution2';
|
||||
@@ -230,13 +213,11 @@ namespace TaskDTO {
|
||||
if (value === undefined || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
let execution: ShellExecutionDTO | ProcessExecutionDTO | CustomExecutionDTO | CustomExecution2DTO | undefined;
|
||||
let execution: ShellExecutionDTO | ProcessExecutionDTO | CustomExecution2DTO | undefined;
|
||||
if (value.execution instanceof types.ProcessExecution) {
|
||||
execution = ProcessExecutionDTO.from(value.execution);
|
||||
} else if (value.execution instanceof types.ShellExecution) {
|
||||
execution = ShellExecutionDTO.from(value.execution);
|
||||
} else if ((<vscode.Task2>value).execution2 && (<vscode.Task2>value).execution2 instanceof types.CustomExecution) {
|
||||
execution = CustomExecutionDTO.from(<types.CustomExecution>(<vscode.Task2>value).execution2);
|
||||
} else if ((<vscode.Task2>value).execution2 && (<vscode.Task2>value).execution2 instanceof types.CustomExecution2) {
|
||||
execution = CustomExecution2DTO.from(<types.CustomExecution2>(<vscode.Task2>value).execution2);
|
||||
}
|
||||
@@ -374,122 +355,18 @@ interface HandlerData {
|
||||
extension: IExtensionDescription;
|
||||
}
|
||||
|
||||
class CustomExecutionData implements IDisposable {
|
||||
private static waitForDimensionsTimeoutInMs: number = 5000;
|
||||
private _cancellationSource?: CancellationTokenSource;
|
||||
private readonly _onTaskExecutionComplete: Emitter<CustomExecutionData> = new Emitter<CustomExecutionData>();
|
||||
private readonly _disposables = new DisposableStore();
|
||||
private terminal?: vscode.Terminal;
|
||||
private terminalId?: number;
|
||||
public result: number | undefined;
|
||||
|
||||
constructor(
|
||||
private readonly customExecution: vscode.CustomExecution,
|
||||
private readonly terminalService: ExtHostTerminalService) {
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this._cancellationSource = undefined;
|
||||
this._disposables.dispose();
|
||||
}
|
||||
|
||||
public get onTaskExecutionComplete(): Event<CustomExecutionData> {
|
||||
return this._onTaskExecutionComplete.event;
|
||||
}
|
||||
|
||||
private onDidCloseTerminal(terminal: vscode.Terminal): void {
|
||||
if ((this.terminal === terminal) && this._cancellationSource) {
|
||||
this._cancellationSource.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private onDidOpenTerminal(terminal: vscode.Terminal): void {
|
||||
if (!(terminal instanceof ExtHostTerminal)) {
|
||||
throw new Error('How could this not be a extension host terminal?');
|
||||
}
|
||||
|
||||
if (this.terminalId && terminal._id === this.terminalId) {
|
||||
this.startCallback(this.terminalId);
|
||||
}
|
||||
}
|
||||
|
||||
public async startCallback(terminalId: number): Promise<void> {
|
||||
this.terminalId = terminalId;
|
||||
|
||||
// If we have already started the extension task callback, then
|
||||
// do not start it again.
|
||||
// It is completely valid for multiple terminals to be opened
|
||||
// before the one for our task.
|
||||
if (this._cancellationSource) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const callbackTerminals: vscode.Terminal[] = this.terminalService.terminals.filter((terminal) => terminal._id === terminalId);
|
||||
|
||||
if (!callbackTerminals || callbackTerminals.length === 0) {
|
||||
this._disposables.add(this.terminalService.onDidOpenTerminal(this.onDidOpenTerminal.bind(this)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (callbackTerminals.length !== 1) {
|
||||
throw new Error(`Expected to only have one terminal at this point`);
|
||||
}
|
||||
|
||||
this.terminal = callbackTerminals[0];
|
||||
const terminalRenderer: vscode.TerminalRenderer = await this.terminalService.resolveTerminalRenderer(terminalId);
|
||||
|
||||
// If we don't have the maximum dimensions yet, then we need to wait for them (but not indefinitely).
|
||||
// Custom executions will expect the dimensions to be set properly before they are launched.
|
||||
// BUT, due to the API contract VSCode has for terminals and dimensions, they are still responsible for
|
||||
// handling cases where they are not set.
|
||||
if (!terminalRenderer.maximumDimensions) {
|
||||
const dimensionTimeout: Promise<void> = new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, CustomExecutionData.waitForDimensionsTimeoutInMs);
|
||||
});
|
||||
|
||||
let dimensionsRegistration: IDisposable | undefined;
|
||||
const dimensionsPromise: Promise<void> = new Promise((resolve) => {
|
||||
dimensionsRegistration = terminalRenderer.onDidChangeMaximumDimensions((newDimensions) => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
await Promise.race([dimensionTimeout, dimensionsPromise]);
|
||||
if (dimensionsRegistration) {
|
||||
dimensionsRegistration.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
this._cancellationSource = new CancellationTokenSource();
|
||||
this._disposables.add(this._cancellationSource);
|
||||
|
||||
this._disposables.add(this.terminalService.onDidCloseTerminal(this.onDidCloseTerminal.bind(this)));
|
||||
|
||||
// Regardless of how the task completes, we are done with this custom execution task.
|
||||
this.customExecution.callback(terminalRenderer, this._cancellationSource.token).then(
|
||||
(success) => {
|
||||
this.result = success;
|
||||
this._onTaskExecutionComplete.fire(this);
|
||||
}, (rejected) => {
|
||||
this._onTaskExecutionComplete.fire(this);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostTask implements ExtHostTaskShape {
|
||||
|
||||
private _proxy: MainThreadTaskShape;
|
||||
private _workspaceProvider: IExtHostWorkspaceProvider;
|
||||
private _editorService: ExtHostDocumentsAndEditors;
|
||||
private _configurationService: ExtHostConfiguration;
|
||||
private _terminalService: ExtHostTerminalService;
|
||||
readonly _serviceBrand: any;
|
||||
|
||||
private readonly _proxy: MainThreadTaskShape;
|
||||
private readonly _workspaceProvider: IExtHostWorkspaceProvider;
|
||||
private readonly _editorService: IExtHostDocumentsAndEditors;
|
||||
private readonly _configurationService: IExtHostConfiguration;
|
||||
private readonly _terminalService: IExtHostTerminalService;
|
||||
private _handleCounter: number;
|
||||
private _handlers: Map<number, HandlerData>;
|
||||
private _taskExecutions: Map<string, TaskExecutionImpl>;
|
||||
private _providedCustomExecutions: Map<string, CustomExecutionData>;
|
||||
private _activeCustomExecutions: Map<string, CustomExecutionData>;
|
||||
private _providedCustomExecutions2: Map<string, vscode.CustomExecution2>;
|
||||
private _activeCustomExecutions2: Map<string, vscode.CustomExecution2>;
|
||||
|
||||
@@ -500,12 +377,14 @@ export class ExtHostTask implements ExtHostTaskShape {
|
||||
private readonly _onDidTaskProcessEnded: Emitter<vscode.TaskProcessEndEvent> = new Emitter<vscode.TaskProcessEndEvent>();
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
workspaceService: ExtHostWorkspace,
|
||||
editorService: ExtHostDocumentsAndEditors,
|
||||
configurationService: ExtHostConfiguration,
|
||||
extHostTerminalService: ExtHostTerminalService) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadTask);
|
||||
@IExtHostRpcService extHostRpc: IExtHostRpcService,
|
||||
@IExtHostInitDataService initData: IExtHostInitDataService,
|
||||
@IExtHostWorkspace workspaceService: IExtHostWorkspace,
|
||||
@IExtHostDocumentsAndEditors editorService: IExtHostDocumentsAndEditors,
|
||||
@IExtHostConfiguration configurationService: IExtHostConfiguration,
|
||||
@IExtHostTerminalService extHostTerminalService: IExtHostTerminalService
|
||||
) {
|
||||
this._proxy = extHostRpc.getProxy(MainContext.MainThreadTask);
|
||||
this._workspaceProvider = workspaceService;
|
||||
this._editorService = editorService;
|
||||
this._configurationService = configurationService;
|
||||
@@ -513,10 +392,16 @@ export class ExtHostTask implements ExtHostTaskShape {
|
||||
this._handleCounter = 0;
|
||||
this._handlers = new Map<number, HandlerData>();
|
||||
this._taskExecutions = new Map<string, TaskExecutionImpl>();
|
||||
this._providedCustomExecutions = new Map<string, CustomExecutionData>();
|
||||
this._activeCustomExecutions = new Map<string, CustomExecutionData>();
|
||||
this._providedCustomExecutions2 = new Map<string, vscode.CustomExecution2>();
|
||||
this._activeCustomExecutions2 = new Map<string, vscode.CustomExecution2>();
|
||||
|
||||
if (initData.remote.isRemote && initData.remote.authority) {
|
||||
this.registerTaskSystem(Schemas.vscodeRemote, {
|
||||
scheme: Schemas.vscodeRemote,
|
||||
authority: initData.remote.authority,
|
||||
platform: process.platform
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public registerTaskProvider(extension: IExtensionDescription, type: string, provider: vscode.TaskProvider): vscode.Disposable {
|
||||
@@ -589,26 +474,7 @@ export class ExtHostTask implements ExtHostTaskShape {
|
||||
|
||||
// Clone the custom execution to keep the original untouched. This is important for multiple runs of the same task.
|
||||
this._activeCustomExecutions2.set(execution.id, execution2);
|
||||
await this._terminalService.attachPtyToTerminal(terminalId, await execution2.callback());
|
||||
}
|
||||
|
||||
// Once a terminal is spun up for the custom execution task this event will be fired.
|
||||
// At that point, we need to actually start the callback, but
|
||||
// only if it hasn't already begun.
|
||||
const extensionCallback: CustomExecutionData | undefined = this._providedCustomExecutions.get(execution.id);
|
||||
if (extensionCallback) {
|
||||
if (this._activeCustomExecutions.get(execution.id) !== undefined) {
|
||||
throw new Error('We should not be trying to start the same custom task executions twice.');
|
||||
}
|
||||
|
||||
this._activeCustomExecutions.set(execution.id, extensionCallback);
|
||||
|
||||
const taskExecutionComplete: IDisposable = extensionCallback.onTaskExecutionComplete(() => {
|
||||
this.customExecutionComplete(execution);
|
||||
taskExecutionComplete.dispose();
|
||||
});
|
||||
|
||||
extensionCallback.startCallback(terminalId);
|
||||
this._terminalService.attachPtyToTerminal(terminalId, await execution2.callback());
|
||||
}
|
||||
|
||||
this._onDidExecuteTask.fire({
|
||||
@@ -666,7 +532,6 @@ export class ExtHostTask implements ExtHostTaskShape {
|
||||
// For custom execution tasks, we need to store the execution objects locally
|
||||
// since we obviously cannot send callback functions through the proxy.
|
||||
// So, clear out any existing ones.
|
||||
this._providedCustomExecutions.clear();
|
||||
this._providedCustomExecutions2.clear();
|
||||
|
||||
// Set up a list of task ID promises that we can wait on
|
||||
@@ -690,14 +555,11 @@ export class ExtHostTask implements ExtHostTaskShape {
|
||||
if (taskDTO) {
|
||||
taskDTOs.push(taskDTO);
|
||||
|
||||
if (CustomExecutionDTO.is(taskDTO.execution)) {
|
||||
if (CustomExecution2DTO.is(taskDTO.execution)) {
|
||||
// The ID is calculated on the main thread task side, so, let's call into it here.
|
||||
// We need the task id's pre-computed for custom task executions because when OnDidStartTask
|
||||
// is invoked, we have to be able to map it back to our data.
|
||||
taskIdPromises.push(this.addCustomExecution(taskDTO, <vscode.Task2>task));
|
||||
} else if (CustomExecution2DTO.is(taskDTO.execution)) {
|
||||
taskIdPromises.push(this.addCustomExecution2(taskDTO, <vscode.Task2>task));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -747,10 +609,6 @@ export class ExtHostTask implements ExtHostTaskShape {
|
||||
throw new Error('Unexpected: The resolved task definition must be the same object as the original task definition. The task definition cannot be changed.');
|
||||
}
|
||||
|
||||
if (CustomExecutionDTO.is(resolvedTaskDTO.execution)) {
|
||||
await this.addCustomExecution(resolvedTaskDTO, <vscode.Task2>resolvedTask);
|
||||
}
|
||||
|
||||
if (CustomExecution2DTO.is(resolvedTaskDTO.execution)) {
|
||||
await this.addCustomExecution2(resolvedTaskDTO, <vscode.Task2>resolvedTask);
|
||||
}
|
||||
@@ -805,11 +663,6 @@ export class ExtHostTask implements ExtHostTaskShape {
|
||||
return this._handleCounter++;
|
||||
}
|
||||
|
||||
private async addCustomExecution(taskDTO: TaskDTO, task: vscode.Task2): Promise<void> {
|
||||
const taskId = await this._proxy.$createTaskId(taskDTO);
|
||||
this._providedCustomExecutions.set(taskId, new CustomExecutionData(<vscode.CustomExecution>(<vscode.Task2>task).execution2, this._terminalService));
|
||||
}
|
||||
|
||||
private async addCustomExecution2(taskDTO: TaskDTO, task: vscode.Task2): Promise<void> {
|
||||
const taskId = await this._proxy.$createTaskId(taskDTO);
|
||||
this._providedCustomExecutions2.set(taskId, <vscode.CustomExecution2>(<vscode.Task2>task).execution2);
|
||||
@@ -838,12 +691,6 @@ export class ExtHostTask implements ExtHostTaskShape {
|
||||
}
|
||||
|
||||
private customExecutionComplete(execution: TaskExecutionDTO): void {
|
||||
const extensionCallback: CustomExecutionData | undefined = this._activeCustomExecutions.get(execution.id);
|
||||
if (extensionCallback) {
|
||||
this._activeCustomExecutions.delete(execution.id);
|
||||
this._proxy.$customExecutionComplete(execution.id, extensionCallback.result);
|
||||
extensionCallback.dispose();
|
||||
}
|
||||
const extensionCallback2: vscode.CustomExecution2 | undefined = this._activeCustomExecutions2.get(execution.id);
|
||||
if (extensionCallback2) {
|
||||
this._activeCustomExecutions2.delete(execution.id);
|
||||
|
||||
@@ -10,26 +10,25 @@ import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IMainContext, ShellLaunchConfigDto, IShellDefinitionDto, IShellAndArgsDto, ITerminalDimensionsDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostConfiguration, ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IShellLaunchConfigDto, IShellDefinitionDto, IShellAndArgsDto, ITerminalDimensionsDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostConfiguration, ExtHostConfigProvider, IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { EXT_HOST_CREATION_DELAY, IShellLaunchConfig, ITerminalEnvironment, ITerminalChildProcess, ITerminalDimensions } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { TerminalProcess } from 'vs/workbench/contrib/terminal/node/terminalProcess';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { ExtHostWorkspace, IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { ExtHostVariableResolverService } from 'vs/workbench/api/node/extHostDebugService';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { ExtHostDocumentsAndEditors, IExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { getSystemShell, detectAvailableShells } from 'vs/workbench/contrib/terminal/node/terminal';
|
||||
import { getMainProcessParentEnv } from 'vs/workbench/contrib/terminal/node/terminalEnvironment';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
const RENDERER_NO_PROCESS_ID = -1;
|
||||
import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
|
||||
export class BaseExtHostTerminal {
|
||||
public _id: number;
|
||||
public _id: number | undefined;
|
||||
protected _idPromise: Promise<number>;
|
||||
private _idPromiseComplete: (value: number) => any;
|
||||
private _idPromiseComplete: ((value: number) => any) | undefined;
|
||||
private _disposed: boolean = false;
|
||||
private _queuedRequests: ApiRequest[] = [];
|
||||
|
||||
@@ -71,9 +70,12 @@ export class BaseExtHostTerminal {
|
||||
|
||||
public _runQueuedRequests(id: number): void {
|
||||
this._id = id;
|
||||
this._idPromiseComplete(id);
|
||||
if (this._idPromiseComplete) {
|
||||
this._idPromiseComplete(id);
|
||||
this._idPromiseComplete = undefined;
|
||||
}
|
||||
this._queuedRequests.forEach((r) => {
|
||||
r.run(this._proxy, this._id);
|
||||
r.run(this._proxy, id);
|
||||
});
|
||||
this._queuedRequests.length = 0;
|
||||
}
|
||||
@@ -82,32 +84,29 @@ export class BaseExtHostTerminal {
|
||||
export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Terminal {
|
||||
private _pidPromise: Promise<number | undefined>;
|
||||
private _cols: number | undefined;
|
||||
private _pidPromiseComplete: ((value: number | undefined) => any) | null;
|
||||
private _pidPromiseComplete: ((value: number | undefined) => any) | undefined;
|
||||
private _rows: number | undefined;
|
||||
|
||||
/** @deprecated */
|
||||
private readonly _onData = new Emitter<string>();
|
||||
/** @deprecated */
|
||||
public get onDidWriteData(): Event<string> {
|
||||
// Tell the main side to start sending data if it's not already
|
||||
this._idPromise.then(c => {
|
||||
this._proxy.$registerOnDataListener(this._id);
|
||||
this._idPromise.then(id => {
|
||||
this._proxy.$registerOnDataListener(id);
|
||||
});
|
||||
return this._onData.event;
|
||||
}
|
||||
|
||||
public isOpen: boolean = false;
|
||||
|
||||
constructor(
|
||||
proxy: MainThreadTerminalServiceShape,
|
||||
private _name?: string,
|
||||
id?: number,
|
||||
pid?: number
|
||||
id?: number
|
||||
) {
|
||||
super(proxy, id);
|
||||
this._pidPromise = new Promise<number>(c => {
|
||||
if (pid === RENDERER_NO_PROCESS_ID) {
|
||||
c(undefined);
|
||||
} else {
|
||||
this._pidPromiseComplete = c;
|
||||
}
|
||||
});
|
||||
this._pidPromise = new Promise<number>(c => this._pidPromiseComplete = c);
|
||||
}
|
||||
|
||||
public async create(
|
||||
@@ -124,10 +123,11 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
|
||||
this._runQueuedRequests(terminal.id);
|
||||
}
|
||||
|
||||
public async createExtensionTerminal(): Promise<void> {
|
||||
public async createExtensionTerminal(): Promise<number> {
|
||||
const terminal = await this._proxy.$createTerminal({ name: this._name, isExtensionTerminal: true });
|
||||
this._name = terminal.name;
|
||||
this._runQueuedRequests(terminal.id);
|
||||
return terminal.id;
|
||||
}
|
||||
|
||||
public get name(): string {
|
||||
@@ -181,7 +181,7 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
|
||||
// The event may fire 2 times when the panel is restored
|
||||
if (this._pidPromiseComplete) {
|
||||
this._pidPromiseComplete(processId);
|
||||
this._pidPromiseComplete = null;
|
||||
this._pidPromiseComplete = undefined;
|
||||
} else {
|
||||
// Recreate the promise if this is the nth processId set (e.g. reused task terminals)
|
||||
this._pidPromise.then(pid => {
|
||||
@@ -197,92 +197,14 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostTerminalRenderer extends BaseExtHostTerminal implements vscode.TerminalRenderer {
|
||||
public get name(): string { return this._name; }
|
||||
public set name(newName: string) {
|
||||
this._name = newName;
|
||||
this._checkDisposed();
|
||||
this._queueApiRequest(this._proxy.$terminalRendererSetName, [this._name]);
|
||||
}
|
||||
export class ExtHostTerminalService implements IExtHostTerminalService, ExtHostTerminalServiceShape {
|
||||
|
||||
private readonly _onInput = new Emitter<string>();
|
||||
public get onDidAcceptInput(): Event<string> {
|
||||
this._checkDisposed();
|
||||
this._queueApiRequest(this._proxy.$terminalRendererRegisterOnInputListener, [this._id]);
|
||||
// Tell the main side to start sending data if it's not already
|
||||
// this._proxy.$terminalRendererRegisterOnDataListener(this._id);
|
||||
return this._onInput && this._onInput.event;
|
||||
}
|
||||
readonly _serviceBrand: any;
|
||||
|
||||
private _dimensions: vscode.TerminalDimensions | undefined;
|
||||
public get dimensions(): vscode.TerminalDimensions | undefined { return this._dimensions; }
|
||||
public set dimensions(dimensions: vscode.TerminalDimensions | undefined) {
|
||||
this._checkDisposed();
|
||||
this._dimensions = dimensions;
|
||||
this._queueApiRequest(this._proxy.$terminalRendererSetDimensions, [dimensions]);
|
||||
}
|
||||
|
||||
private _maximumDimensions: vscode.TerminalDimensions | undefined;
|
||||
public get maximumDimensions(): vscode.TerminalDimensions | undefined {
|
||||
if (!this._maximumDimensions) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
rows: this._maximumDimensions.rows,
|
||||
columns: this._maximumDimensions.columns
|
||||
};
|
||||
}
|
||||
|
||||
private readonly _onDidChangeMaximumDimensions: Emitter<vscode.TerminalDimensions> = new Emitter<vscode.TerminalDimensions>();
|
||||
public get onDidChangeMaximumDimensions(): Event<vscode.TerminalDimensions> {
|
||||
return this._onDidChangeMaximumDimensions && this._onDidChangeMaximumDimensions.event;
|
||||
}
|
||||
|
||||
public get terminal(): ExtHostTerminal {
|
||||
return this._terminal;
|
||||
}
|
||||
|
||||
constructor(
|
||||
proxy: MainThreadTerminalServiceShape,
|
||||
private _name: string,
|
||||
private _terminal: ExtHostTerminal,
|
||||
id?: number
|
||||
) {
|
||||
super(proxy, id);
|
||||
|
||||
if (!id) {
|
||||
this._proxy.$createTerminalRenderer(this._name).then(id => {
|
||||
this._runQueuedRequests(id);
|
||||
(<any>this._terminal)._runQueuedRequests(id);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public write(data: string): void {
|
||||
this._checkDisposed();
|
||||
this._queueApiRequest(this._proxy.$terminalRendererWrite, [data]);
|
||||
}
|
||||
|
||||
public _fireOnInput(data: string): void {
|
||||
this._onInput.fire(data);
|
||||
}
|
||||
|
||||
public _setMaximumDimensions(columns: number, rows: number): void {
|
||||
if (this._maximumDimensions && this._maximumDimensions.columns === columns && this._maximumDimensions.rows === rows) {
|
||||
return;
|
||||
}
|
||||
const newValue = { columns, rows };
|
||||
this._maximumDimensions = newValue;
|
||||
this._onDidChangeMaximumDimensions.fire(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
private _proxy: MainThreadTerminalServiceShape;
|
||||
private _activeTerminal: ExtHostTerminal | undefined;
|
||||
private _terminals: ExtHostTerminal[] = [];
|
||||
private _terminalProcesses: { [id: number]: ITerminalChildProcess } = {};
|
||||
private _terminalRenderers: ExtHostTerminalRenderer[] = [];
|
||||
private _getTerminalPromises: { [id: number]: Promise<ExtHostTerminal> } = {};
|
||||
private _variableResolver: ExtHostVariableResolverService | undefined;
|
||||
private _lastActiveWorkspace: IWorkspaceFolder | undefined;
|
||||
@@ -301,15 +223,21 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
public get onDidChangeActiveTerminal(): Event<vscode.Terminal | undefined> { return this._onDidChangeActiveTerminal && this._onDidChangeActiveTerminal.event; }
|
||||
private readonly _onDidChangeTerminalDimensions: Emitter<vscode.TerminalDimensionsChangeEvent> = new Emitter<vscode.TerminalDimensionsChangeEvent>();
|
||||
public get onDidChangeTerminalDimensions(): Event<vscode.TerminalDimensionsChangeEvent> { return this._onDidChangeTerminalDimensions && this._onDidChangeTerminalDimensions.event; }
|
||||
private readonly _onDidWriteTerminalData: Emitter<vscode.TerminalDataWriteEvent>;
|
||||
public get onDidWriteTerminalData(): Event<vscode.TerminalDataWriteEvent> { return this._onDidWriteTerminalData && this._onDidWriteTerminalData.event; }
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
private _extHostConfiguration: ExtHostConfiguration,
|
||||
private _extHostWorkspace: ExtHostWorkspace,
|
||||
private _extHostDocumentsAndEditors: ExtHostDocumentsAndEditors,
|
||||
private _logService: ILogService
|
||||
@IExtHostRpcService extHostRpc: IExtHostRpcService,
|
||||
@IExtHostConfiguration private _extHostConfiguration: ExtHostConfiguration,
|
||||
@IExtHostWorkspace private _extHostWorkspace: ExtHostWorkspace,
|
||||
@IExtHostDocumentsAndEditors private _extHostDocumentsAndEditors: ExtHostDocumentsAndEditors,
|
||||
@ILogService private _logService: ILogService
|
||||
) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadTerminalService);
|
||||
this._proxy = extHostRpc.getProxy(MainContext.MainThreadTerminalService);
|
||||
this._onDidWriteTerminalData = new Emitter<vscode.TerminalDataWriteEvent>({
|
||||
onFirstListenerAdd: () => this._proxy.$startSendingDataEvents(),
|
||||
onLastListenerRemove: () => this._proxy.$stopSendingDataEvents()
|
||||
});
|
||||
this._updateLastActiveWorkspace();
|
||||
this._updateVariableResolver();
|
||||
this._registerListeners();
|
||||
@@ -332,12 +260,12 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
public createExtensionTerminal(options: vscode.ExtensionTerminalOptions): vscode.Terminal {
|
||||
const terminal = new ExtHostTerminal(this._proxy, options.name);
|
||||
const p = new ExtHostPseudoterminal(options.pty);
|
||||
terminal.createExtensionTerminal().then(() => this._setupExtHostProcessListeners(terminal._id, p));
|
||||
terminal.createExtensionTerminal().then(id => this._setupExtHostProcessListeners(id, p));
|
||||
this._terminals.push(terminal);
|
||||
return terminal;
|
||||
}
|
||||
|
||||
public async attachPtyToTerminal(id: number, pty: vscode.Pseudoterminal): Promise<void> {
|
||||
public attachPtyToTerminal(id: number, pty: vscode.Pseudoterminal): void {
|
||||
const terminal = this._getTerminalByIdEventually(id);
|
||||
if (!terminal) {
|
||||
throw new Error(`Cannot resolve terminal with id ${id} for virtual process`);
|
||||
@@ -346,18 +274,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
this._setupExtHostProcessListeners(id, p);
|
||||
}
|
||||
|
||||
public createTerminalRenderer(name: string): vscode.TerminalRenderer {
|
||||
const terminal = new ExtHostTerminal(this._proxy, name);
|
||||
terminal._setProcessId(undefined);
|
||||
this._terminals.push(terminal);
|
||||
|
||||
const renderer = new ExtHostTerminalRenderer(this._proxy, name, terminal);
|
||||
this._terminalRenderers.push(renderer);
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
public getDefaultShell(configProvider: ExtHostConfigProvider): string {
|
||||
public getDefaultShell(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string {
|
||||
const fetchSetting = (key: string) => {
|
||||
const setting = configProvider
|
||||
.getConfiguration(key.substr(0, key.lastIndexOf('.')))
|
||||
@@ -372,11 +289,12 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
process.env.windir,
|
||||
this._lastActiveWorkspace,
|
||||
this._variableResolver,
|
||||
this._logService
|
||||
this._logService,
|
||||
useAutomationShell
|
||||
);
|
||||
}
|
||||
|
||||
private _getDefaultShellArgs(configProvider: ExtHostConfigProvider): string[] | string {
|
||||
private _getDefaultShellArgs(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string[] | string {
|
||||
const fetchSetting = (key: string) => {
|
||||
const setting = configProvider
|
||||
.getConfiguration(key.substr(0, key.lastIndexOf('.')))
|
||||
@@ -384,28 +302,10 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
return this._apiInspectConfigToPlain<string | string[]>(setting);
|
||||
};
|
||||
|
||||
return terminalEnvironment.getDefaultShellArgs(fetchSetting, this._isWorkspaceShellAllowed, this._lastActiveWorkspace, this._variableResolver, this._logService);
|
||||
return terminalEnvironment.getDefaultShellArgs(fetchSetting, this._isWorkspaceShellAllowed, useAutomationShell, this._lastActiveWorkspace, this._variableResolver, this._logService);
|
||||
}
|
||||
|
||||
public async resolveTerminalRenderer(id: number): Promise<vscode.TerminalRenderer> {
|
||||
// Check to see if the extension host already knows about this terminal.
|
||||
for (const terminalRenderer of this._terminalRenderers) {
|
||||
if (terminalRenderer._id === id) {
|
||||
return terminalRenderer;
|
||||
}
|
||||
}
|
||||
|
||||
const terminal = this._getTerminalById(id);
|
||||
if (!terminal) {
|
||||
throw new Error(`Cannot resolve terminal renderer for terminal id ${id}`);
|
||||
}
|
||||
const renderer = new ExtHostTerminalRenderer(this._proxy, terminal.name, terminal, terminal._id);
|
||||
this._terminalRenderers.push(renderer);
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
public $acceptActiveTerminalChanged(id: number | null): void {
|
||||
public async $acceptActiveTerminalChanged(id: number | null): Promise<void> {
|
||||
const original = this._activeTerminal;
|
||||
if (id === null) {
|
||||
this._activeTerminal = undefined;
|
||||
@@ -414,69 +314,62 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.performTerminalIdAction(id, terminal => {
|
||||
if (terminal) {
|
||||
this._activeTerminal = terminal;
|
||||
if (original !== this._activeTerminal) {
|
||||
this._onDidChangeActiveTerminal.fire(this._activeTerminal);
|
||||
}
|
||||
const terminal = await this._getTerminalByIdEventually(id);
|
||||
if (terminal) {
|
||||
this._activeTerminal = terminal;
|
||||
if (original !== this._activeTerminal) {
|
||||
this._onDidChangeActiveTerminal.fire(this._activeTerminal);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public $acceptTerminalProcessData(id: number, data: string): void {
|
||||
this._getTerminalByIdEventually(id).then(terminal => {
|
||||
if (terminal) {
|
||||
terminal._fireOnData(data);
|
||||
}
|
||||
});
|
||||
/** @deprecated */
|
||||
public async $acceptTerminalProcessData(id: number, data: string): Promise<void> {
|
||||
const terminal = await this._getTerminalByIdEventually(id);
|
||||
if (terminal) {
|
||||
terminal._fireOnData(data);
|
||||
}
|
||||
}
|
||||
|
||||
public $acceptTerminalDimensions(id: number, cols: number, rows: number): void {
|
||||
this._getTerminalByIdEventually(id).then(terminal => {
|
||||
if (terminal) {
|
||||
if (terminal.setDimensions(cols, rows)) {
|
||||
this._onDidChangeTerminalDimensions.fire({
|
||||
terminal: terminal,
|
||||
dimensions: terminal.dimensions as vscode.TerminalDimensions
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
public async $acceptTerminalProcessData2(id: number, data: string): Promise<void> {
|
||||
const terminal = await this._getTerminalByIdEventually(id);
|
||||
if (terminal) {
|
||||
this._onDidWriteTerminalData.fire({ terminal, data });
|
||||
}
|
||||
}
|
||||
|
||||
public $acceptTerminalMaximumDimensions(id: number, cols: number, rows: number): void {
|
||||
public async $acceptTerminalDimensions(id: number, cols: number, rows: number): Promise<void> {
|
||||
const terminal = await this._getTerminalByIdEventually(id);
|
||||
if (terminal) {
|
||||
if (terminal.setDimensions(cols, rows)) {
|
||||
this._onDidChangeTerminalDimensions.fire({
|
||||
terminal: terminal,
|
||||
dimensions: terminal.dimensions as vscode.TerminalDimensions
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async $acceptTerminalMaximumDimensions(id: number, cols: number, rows: number): Promise<void> {
|
||||
await this._getTerminalByIdEventually(id);
|
||||
|
||||
if (this._terminalProcesses[id]) {
|
||||
// Virtual processes only - when virtual process resize fires it means that the
|
||||
// Extension pty terminal only - when virtual process resize fires it means that the
|
||||
// terminal's maximum dimensions changed
|
||||
this._terminalProcesses[id].resize(cols, rows);
|
||||
} else {
|
||||
// Terminal renderer
|
||||
this._getTerminalByIdEventually(id).then(() => {
|
||||
// When a terminal's dimensions change, a renderer's _maximum_ dimensions change
|
||||
const renderer = this._getTerminalRendererById(id);
|
||||
if (renderer) {
|
||||
renderer._setMaximumDimensions(cols, rows);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public $acceptTerminalRendererInput(id: number, data: string): void {
|
||||
const renderer = this._getTerminalRendererById(id);
|
||||
if (renderer) {
|
||||
renderer._fireOnInput(data);
|
||||
}
|
||||
}
|
||||
|
||||
public $acceptTerminalTitleChange(id: number, name: string): void {
|
||||
public async $acceptTerminalTitleChange(id: number, name: string): Promise<void> {
|
||||
await this._getTerminalByIdEventually(id);
|
||||
const extHostTerminal = this._getTerminalObjectById(this.terminals, id);
|
||||
if (extHostTerminal) {
|
||||
extHostTerminal.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
public $acceptTerminalClosed(id: number): void {
|
||||
public async $acceptTerminalClosed(id: number): Promise<void> {
|
||||
await this._getTerminalByIdEventually(id);
|
||||
const index = this._getTerminalObjectIndexById(this.terminals, id);
|
||||
if (index !== null) {
|
||||
const terminal = this._terminals.splice(index, 1)[0];
|
||||
@@ -489,20 +382,25 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
if (index !== null) {
|
||||
// The terminal has already been created (via createTerminal*), only fire the event
|
||||
this._onDidOpenTerminal.fire(this.terminals[index]);
|
||||
this.terminals[index].isOpen = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const renderer = this._getTerminalRendererById(id);
|
||||
const terminal = new ExtHostTerminal(this._proxy, name, id, renderer ? RENDERER_NO_PROCESS_ID : undefined);
|
||||
const terminal = new ExtHostTerminal(this._proxy, name, id);
|
||||
this._terminals.push(terminal);
|
||||
this._onDidOpenTerminal.fire(terminal);
|
||||
terminal.isOpen = true;
|
||||
}
|
||||
|
||||
public $acceptTerminalProcessId(id: number, processId: number): void {
|
||||
this.performTerminalIdAction(id, terminal => terminal._setProcessId(processId));
|
||||
public async $acceptTerminalProcessId(id: number, processId: number): Promise<void> {
|
||||
const terminal = await this._getTerminalByIdEventually(id);
|
||||
if (terminal) {
|
||||
terminal._setProcessId(processId);
|
||||
}
|
||||
}
|
||||
|
||||
public performTerminalIdAction(id: number, callback: (terminal: ExtHostTerminal) => void): void {
|
||||
// TODO: Use await this._getTerminalByIdEventually(id);
|
||||
let terminal = this._getTerminalById(id);
|
||||
if (terminal) {
|
||||
callback(terminal);
|
||||
@@ -551,7 +449,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
this._variableResolver = new ExtHostVariableResolverService(workspaceFolders || [], this._extHostDocumentsAndEditors, configProvider);
|
||||
}
|
||||
|
||||
public async $spawnExtHostProcess(id: number, shellLaunchConfigDto: ShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise<void> {
|
||||
public async $spawnExtHostProcess(id: number, shellLaunchConfigDto: IShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise<void> {
|
||||
const shellLaunchConfig: IShellLaunchConfig = {
|
||||
name: shellLaunchConfigDto.name,
|
||||
executable: shellLaunchConfigDto.executable,
|
||||
@@ -564,8 +462,8 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
const platformKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux');
|
||||
const configProvider = await this._extHostConfiguration.getConfigProvider();
|
||||
if (!shellLaunchConfig.executable) {
|
||||
shellLaunchConfig.executable = this.getDefaultShell(configProvider);
|
||||
shellLaunchConfig.args = this._getDefaultShellArgs(configProvider);
|
||||
shellLaunchConfig.executable = this.getDefaultShell(false, configProvider);
|
||||
shellLaunchConfig.args = this._getDefaultShellArgs(false, configProvider);
|
||||
} else {
|
||||
if (this._variableResolver) {
|
||||
shellLaunchConfig.executable = this._variableResolver.resolve(this._lastActiveWorkspace, shellLaunchConfig.executable);
|
||||
@@ -625,7 +523,27 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
public async $startExtensionTerminal(id: number, initialDimensions: ITerminalDimensionsDto | undefined): Promise<void> {
|
||||
// Make sure the ExtHostTerminal exists so onDidOpenTerminal has fired before we call
|
||||
// Pseudoterminal.start
|
||||
await this._getTerminalByIdEventually(id);
|
||||
const terminal = await this._getTerminalByIdEventually(id);
|
||||
if (!terminal) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait for onDidOpenTerminal to fire
|
||||
let openPromise: Promise<void>;
|
||||
if (terminal.isOpen) {
|
||||
openPromise = Promise.resolve();
|
||||
} else {
|
||||
openPromise = new Promise<void>(r => {
|
||||
// Ensure open is called after onDidOpenTerminal
|
||||
const listener = this.onDidOpenTerminal(async e => {
|
||||
if (e === terminal) {
|
||||
listener.dispose();
|
||||
r();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
await openPromise;
|
||||
|
||||
// Processes should be initialized here for normal virtual process terminals, however for
|
||||
// tasks they are responsible for attaching the virtual process to a terminal so this
|
||||
@@ -686,11 +604,11 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
return detectAvailableShells();
|
||||
}
|
||||
|
||||
public async $requestDefaultShellAndArgs(): Promise<IShellAndArgsDto> {
|
||||
public async $requestDefaultShellAndArgs(useAutomationShell: boolean): Promise<IShellAndArgsDto> {
|
||||
const configProvider = await this._extHostConfiguration.getConfigProvider();
|
||||
return Promise.resolve({
|
||||
shell: this.getDefaultShell(configProvider),
|
||||
args: this._getDefaultShellArgs(configProvider)
|
||||
shell: this.getDefaultShell(useAutomationShell, configProvider),
|
||||
args: this._getDefaultShellArgs(useAutomationShell, configProvider)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -702,7 +620,8 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
this._proxy.$sendProcessExit(id, exitCode);
|
||||
}
|
||||
|
||||
private _getTerminalByIdEventually(id: number, retries: number = 5): Promise<ExtHostTerminal> {
|
||||
// TODO: This could be improved by using a single promise and resolve it when the terminal is ready
|
||||
private _getTerminalByIdEventually(id: number, retries: number = 5): Promise<ExtHostTerminal | undefined> {
|
||||
if (!this._getTerminalPromises[id]) {
|
||||
this._getTerminalPromises[id] = this._createGetTerminalPromise(id, retries);
|
||||
} else {
|
||||
@@ -735,16 +654,12 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
return this._getTerminalObjectById(this._terminals, id);
|
||||
}
|
||||
|
||||
private _getTerminalRendererById(id: number): ExtHostTerminalRenderer | null {
|
||||
return this._getTerminalObjectById(this._terminalRenderers, id);
|
||||
}
|
||||
|
||||
private _getTerminalObjectById<T extends ExtHostTerminal | ExtHostTerminalRenderer>(array: T[], id: number): T | null {
|
||||
private _getTerminalObjectById<T extends ExtHostTerminal>(array: T[], id: number): T | null {
|
||||
const index = this._getTerminalObjectIndexById(array, id);
|
||||
return index !== null ? array[index] : null;
|
||||
}
|
||||
|
||||
private _getTerminalObjectIndexById<T extends ExtHostTerminal | ExtHostTerminalRenderer>(array: T[], id: number): number | null {
|
||||
private _getTerminalObjectIndexById<T extends ExtHostTerminal>(array: T[], id: number): number | null {
|
||||
let index: number | null = null;
|
||||
array.some((item, i) => {
|
||||
const thisId = item._id;
|
||||
@@ -777,9 +692,6 @@ class ApiRequest {
|
||||
}
|
||||
|
||||
class ExtHostPseudoterminal implements ITerminalChildProcess {
|
||||
private _queuedEvents: (IQueuedEvent<string> | IQueuedEvent<number> | IQueuedEvent<{ pid: number, cwd: string }> | IQueuedEvent<ITerminalDimensions | undefined>)[] = [];
|
||||
private _queueDisposables: IDisposable[] | undefined;
|
||||
|
||||
private readonly _onProcessData = new Emitter<string>();
|
||||
public readonly onProcessData: Event<string> = this._onProcessData.event;
|
||||
private readonly _onProcessExit = new Emitter<number>();
|
||||
@@ -791,23 +703,10 @@ class ExtHostPseudoterminal implements ITerminalChildProcess {
|
||||
private readonly _onProcessOverrideDimensions = new Emitter<ITerminalDimensions | undefined>();
|
||||
public get onProcessOverrideDimensions(): Event<ITerminalDimensions | undefined> { return this._onProcessOverrideDimensions.event; }
|
||||
|
||||
constructor(
|
||||
private readonly _pty: vscode.Pseudoterminal
|
||||
) {
|
||||
this._queueDisposables = [];
|
||||
this._queueDisposables.push(this._pty.onDidWrite(e => this._queuedEvents.push({ emitter: this._onProcessData, data: e })));
|
||||
if (this._pty.onDidClose) {
|
||||
this._queueDisposables.push(this._pty.onDidClose(e => this._queuedEvents.push({ emitter: this._onProcessExit, data: 0 })));
|
||||
}
|
||||
if (this._pty.onDidOverrideDimensions) {
|
||||
this._queueDisposables.push(this._pty.onDidOverrideDimensions(e => this._queuedEvents.push({ emitter: this._onProcessOverrideDimensions, data: e ? { cols: e.columns, rows: e.rows } : undefined })));
|
||||
}
|
||||
}
|
||||
constructor(private readonly _pty: vscode.Pseudoterminal) { }
|
||||
|
||||
shutdown(): void {
|
||||
if (this._pty.close) {
|
||||
this._pty.close();
|
||||
}
|
||||
this._pty.close();
|
||||
}
|
||||
|
||||
input(data: string): void {
|
||||
@@ -835,12 +734,7 @@ class ExtHostPseudoterminal implements ITerminalChildProcess {
|
||||
}
|
||||
|
||||
startSendingEvents(initialDimensions: ITerminalDimensionsDto | undefined): void {
|
||||
// Flush all buffered events
|
||||
this._queuedEvents.forEach(e => (<any>e.emitter.fire)(e.data));
|
||||
this._queuedEvents = [];
|
||||
this._queueDisposables = undefined;
|
||||
|
||||
// Attach the real listeners
|
||||
// Attach the listeners
|
||||
this._pty.onDidWrite(e => this._onProcessData.fire(e));
|
||||
if (this._pty.onDidClose) {
|
||||
this._pty.onDidClose(e => this._onProcessExit.fire(0));
|
||||
@@ -849,13 +743,7 @@ class ExtHostPseudoterminal implements ITerminalChildProcess {
|
||||
this._pty.onDidOverrideDimensions(e => this._onProcessOverrideDimensions.fire(e ? { cols: e.columns, rows: e.rows } : undefined)); // {{SQL CARBON EDIT}} strict-null-checks
|
||||
}
|
||||
|
||||
if (this._pty.open) {
|
||||
this._pty.open(initialDimensions);
|
||||
}
|
||||
this._pty.open(initialDimensions ? initialDimensions : undefined);
|
||||
}
|
||||
}
|
||||
|
||||
interface IQueuedEvent<T> {
|
||||
emitter: Emitter<T>;
|
||||
data: T;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user