mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-06-22 03:15:09 -04:00
Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 (#6381)
* Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 * disable strict null check
This commit is contained in:
@@ -11,7 +11,7 @@ import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor';
|
||||
import { EditorGroupLayout } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IWindowsService, IOpenSettings, IURIToOpen } from 'vs/platform/windows/common/windows';
|
||||
import { IOpenSettings, IURIToOpen, IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { IDownloadService } from 'vs/platform/download/common/download';
|
||||
import { IWorkspacesService, hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IRecent } from 'vs/platform/history/common/history';
|
||||
@@ -129,8 +129,8 @@ export class OpenAPICommand {
|
||||
CommandsRegistry.registerCommand(OpenAPICommand.ID, adjustHandler(OpenAPICommand.execute));
|
||||
|
||||
CommandsRegistry.registerCommand('_workbench.removeFromRecentlyOpened', function (accessor: ServicesAccessor, uri: URI) {
|
||||
const windowsService = accessor.get(IWindowsService);
|
||||
return windowsService.removeFromRecentlyOpened([uri]).then(() => undefined);
|
||||
const windowService = accessor.get(IWindowService);
|
||||
return windowService.removeFromRecentlyOpened([uri]);
|
||||
});
|
||||
|
||||
export class RemoveFromRecentlyOpenedAPICommand {
|
||||
@@ -160,7 +160,7 @@ interface RecentEntry {
|
||||
}
|
||||
|
||||
CommandsRegistry.registerCommand('_workbench.addToRecentlyOpened', async function (accessor: ServicesAccessor, recentEntry: RecentEntry) {
|
||||
const windowsService = accessor.get(IWindowsService);
|
||||
const windowService = accessor.get(IWindowService);
|
||||
const workspacesService = accessor.get(IWorkspacesService);
|
||||
let recent: IRecent | undefined = undefined;
|
||||
const uri = recentEntry.uri;
|
||||
@@ -173,7 +173,7 @@ CommandsRegistry.registerCommand('_workbench.addToRecentlyOpened', async functio
|
||||
} else {
|
||||
recent = { fileUri: uri, label };
|
||||
}
|
||||
return windowsService.addRecentlyOpened([recent]);
|
||||
return windowService.addRecentlyOpened([recent]);
|
||||
});
|
||||
|
||||
export class SetEditorLayoutAPICommand {
|
||||
|
||||
@@ -42,12 +42,12 @@ const configurationEntrySchema: IJSONSchema = {
|
||||
enum: ['application', 'machine', 'window', 'resource'],
|
||||
default: 'window',
|
||||
enumDescriptions: [
|
||||
nls.localize('scope.application.description', "Application specific configuration, which can be configured only in local user settings."),
|
||||
nls.localize('scope.machine.description', "Machine specific configuration, which can be configured only in local and remote user settings."),
|
||||
nls.localize('scope.window.description', "Window specific configuration, which can be configured in the user or workspace settings."),
|
||||
nls.localize('scope.resource.description', "Resource specific configuration, which can be configured in the user, workspace or folder settings.")
|
||||
nls.localize('scope.application.description', "Application specific configuration, which can be configured only in the user settings."),
|
||||
nls.localize('scope.machine.description', "Machine specific configuration, which can be configured only in the user settings when the extension is running locally, or only in the remote settings when the extension is running remotely."),
|
||||
nls.localize('scope.window.description', "Window specific configuration, which can be configured in the user, remote or workspace settings."),
|
||||
nls.localize('scope.resource.description', "Resource specific configuration, which can be configured in the user, remote, workspace or folder settings.")
|
||||
],
|
||||
description: nls.localize('scope.description', "Scope in which the configuration is applicable. Available scopes are `window` and `resource`.")
|
||||
description: nls.localize('scope.description', "Scope in which the configuration is applicable. Available scopes are `application`, `machine`, `window` and `resource`.")
|
||||
},
|
||||
enumDescriptions: {
|
||||
type: 'array',
|
||||
|
||||
@@ -3,50 +3,50 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IRemoteConsoleLog } from 'vs/base/common/console';
|
||||
import { SerializedError } from 'vs/base/common/errors';
|
||||
import { IRelativePattern } from 'vs/base/common/glob';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { TextEditorCursorStyle, RenderLineNumbersType } from 'vs/editor/common/config/editorOptions';
|
||||
import { RenderLineNumbersType, TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import { ISelection, Selection } from 'vs/editor/common/core/selection';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import { ISingleEditOperation, EndOfLineSequence } from 'vs/editor/common/model';
|
||||
import { EndOfLineSequence, ISingleEditOperation } from 'vs/editor/common/model';
|
||||
import { IModelChangedEvent } from 'vs/editor/common/model/mirrorTextModel';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { CharacterPair, CommentRule, EnterAction } from 'vs/editor/common/modes/languageConfiguration';
|
||||
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
|
||||
import { ConfigurationTarget, IConfigurationData, IConfigurationModel } from 'vs/platform/configuration/common/configuration';
|
||||
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import * as files from 'vs/platform/files/common/files';
|
||||
import { ResourceLabelFormatter } from 'vs/platform/label/common/label';
|
||||
import { LogLevel } from 'vs/platform/log/common/log';
|
||||
import { IMarkerData } from 'vs/platform/markers/common/markers';
|
||||
import { IProgressOptions, IProgressStep } from 'vs/platform/progress/common/progress';
|
||||
import * as quickInput from 'vs/platform/quickinput/common/quickInput';
|
||||
import * as search from 'vs/workbench/services/search/common/search';
|
||||
import { RemoteAuthorityResolverErrorCode, ResolvedAuthority } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import * as statusbar from 'vs/platform/statusbar/common/statusbar';
|
||||
import { ClassifiedEvent, GDPRClassification, StrictPropertyCheck } from 'vs/platform/telemetry/common/gdprTypings';
|
||||
import { ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ThemeColor } from 'vs/platform/theme/common/themeService';
|
||||
import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor';
|
||||
import * as tasks from 'vs/workbench/api/common/shared/tasks';
|
||||
import { ITreeItem, IRevealOptions } from 'vs/workbench/common/views';
|
||||
import { IRevealOptions, ITreeItem } from 'vs/workbench/common/views';
|
||||
import * as callHierarchy from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
|
||||
import { IAdapterDescriptor, IConfig, ITerminalSettings } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/queryBuilder';
|
||||
import { ITerminalDimensions } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { ExtensionActivationError } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IRPCProtocol, createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
import { IProgressOptions, IProgressStep } from 'vs/platform/progress/common/progress';
|
||||
import { createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId, IRPCProtocol } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
import * as search from 'vs/workbench/services/search/common/search';
|
||||
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { ResolvedAuthority, RemoteAuthorityResolverErrorCode } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import * as codeInset from 'vs/workbench/contrib/codeinset/common/codeInset';
|
||||
import * as callHierarchy from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
|
||||
import { IRelativePattern } from 'vs/base/common/glob';
|
||||
import { IRemoteConsoleLog } from 'vs/base/common/console';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { ITreeItem as sqlITreeItem } from 'sql/workbench/common/views';
|
||||
@@ -62,6 +62,8 @@ export interface IEnvironment {
|
||||
extensionTestsLocationURI?: URI;
|
||||
globalStorageHome: URI;
|
||||
userHome: URI;
|
||||
webviewResourceRoot: string;
|
||||
webviewCspSource: string;
|
||||
}
|
||||
|
||||
export interface IStaticWorkspaceData {
|
||||
@@ -88,11 +90,11 @@ export interface IInitData {
|
||||
logLevel: LogLevel;
|
||||
logsLocation: URI;
|
||||
autoStart: boolean;
|
||||
remoteAuthority?: string | null;
|
||||
remote: { isRemote: boolean; authority: string | undefined; };
|
||||
}
|
||||
|
||||
export interface IConfigurationInitData extends IConfigurationData {
|
||||
configurationScopes: { [key: string]: ConfigurationScope };
|
||||
configurationScopes: [string, ConfigurationScope | undefined][];
|
||||
}
|
||||
|
||||
export interface IWorkspaceConfigurationChangeEventData {
|
||||
@@ -121,33 +123,18 @@ export interface MainThreadCommandsShape extends IDisposable {
|
||||
$getCommands(): Promise<string[]>;
|
||||
}
|
||||
|
||||
export interface CommentThreadTemplate {
|
||||
label: string;
|
||||
acceptInputCommand?: modes.Command;
|
||||
additionalCommands?: modes.Command[];
|
||||
deleteCommand?: modes.Command;
|
||||
}
|
||||
|
||||
export interface CommentProviderFeatures {
|
||||
startDraftLabel?: string;
|
||||
deleteDraftLabel?: string;
|
||||
finishDraftLabel?: string;
|
||||
reactionGroup?: modes.CommentReaction[];
|
||||
commentThreadTemplate?: CommentThreadTemplate;
|
||||
reactionHandler?: boolean;
|
||||
}
|
||||
|
||||
export interface MainThreadCommentsShape extends IDisposable {
|
||||
$registerCommentController(handle: number, id: string, label: string): void;
|
||||
$unregisterCommentController(handle: number): void;
|
||||
$updateCommentControllerFeatures(handle: number, features: CommentProviderFeatures): void;
|
||||
$createCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, range: IRange): modes.CommentThread2 | undefined;
|
||||
$updateCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, range: IRange, label: string, contextValue: string | undefined, comments: modes.Comment[], acceptInputCommand: modes.Command | undefined, additionalCommands: modes.Command[], deleteCommand: modes.Command | undefined, collapseState: modes.CommentThreadCollapsibleState): 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;
|
||||
$deleteCommentThread(handle: number, commentThreadHandle: number): void;
|
||||
$setInputValue(handle: number, input: string): void;
|
||||
$registerDocumentCommentProvider(handle: number, features: CommentProviderFeatures): void;
|
||||
$unregisterDocumentCommentProvider(handle: number): void;
|
||||
$registerWorkspaceCommentProvider(handle: number, extensionId: ExtensionIdentifier): void;
|
||||
$unregisterWorkspaceCommentProvider(handle: number): void;
|
||||
$onDidCommentThreadsChange(handle: number, event: modes.CommentThreadChangedEvent): void;
|
||||
}
|
||||
|
||||
@@ -251,7 +238,7 @@ export interface MainThreadTextEditorsShape extends IDisposable {
|
||||
$trySetSelections(id: string, selections: ISelection[]): Promise<void>;
|
||||
$tryApplyEdits(id: string, modelVersionId: number, edits: ISingleEditOperation[], opts: IApplyEditsOptions): Promise<boolean>;
|
||||
$tryApplyWorkspaceEdit(workspaceEditDto: WorkspaceEditDto): Promise<boolean>;
|
||||
$tryInsertSnippet(id: string, template: string, selections: IRange[], opts: IUndoStopOptions): Promise<boolean>;
|
||||
$tryInsertSnippet(id: string, template: string, selections: readonly IRange[], opts: IUndoStopOptions): Promise<boolean>;
|
||||
$getDiffInformation(id: string): Promise<editorCommon.ILineChange[]>;
|
||||
}
|
||||
|
||||
@@ -336,7 +323,6 @@ 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;
|
||||
$registerCodeInsetSupport(handle: number, selector: ISerializedDocumentFilter[], eventHandle: number | undefined): void;
|
||||
$emitCodeLensEvent(eventHandle: number, event?: any): void;
|
||||
$registerDefinitionSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerDeclarationSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
@@ -351,7 +337,7 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
|
||||
$registerOnTypeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[], 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): 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;
|
||||
@@ -392,8 +378,20 @@ export interface MainThreadProgressShape extends IDisposable {
|
||||
$progressEnd(handle: number): void;
|
||||
}
|
||||
|
||||
export interface TerminalLaunchConfig {
|
||||
name?: string;
|
||||
shellPath?: string;
|
||||
shellArgs?: string[] | string;
|
||||
cwd?: string | UriComponents;
|
||||
env?: { [key: string]: string | null };
|
||||
waitOnExit?: boolean;
|
||||
strictEnv?: boolean;
|
||||
hideFromUser?: boolean;
|
||||
isVirtualProcess?: boolean;
|
||||
}
|
||||
|
||||
export interface MainThreadTerminalServiceShape extends IDisposable {
|
||||
$createTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string, cwd?: string | UriComponents, env?: { [key: string]: string | null }, waitOnExit?: boolean, strictEnv?: boolean): Promise<{ id: number, name: string }>;
|
||||
$createTerminal(config: TerminalLaunchConfig): Promise<{ id: number, name: string }>;
|
||||
$createTerminalRenderer(name: string): Promise<number>;
|
||||
$dispose(terminalId: number): void;
|
||||
$hide(terminalId: number): void;
|
||||
@@ -404,8 +402,9 @@ export interface MainThreadTerminalServiceShape extends IDisposable {
|
||||
// Process
|
||||
$sendProcessTitle(terminalId: number, title: string): void;
|
||||
$sendProcessData(terminalId: number, data: string): void;
|
||||
$sendProcessPid(terminalId: number, pid: number): void;
|
||||
$sendProcessReady(terminalId: number, pid: number, cwd: string): void;
|
||||
$sendProcessExit(terminalId: number, exitCode: number): void;
|
||||
$sendOverrideDimensions(terminalId: number, dimensions: ITerminalDimensions | undefined): void;
|
||||
$sendProcessInitialCwd(terminalId: number, cwd: string): void;
|
||||
$sendProcessCwd(terminalId: number, initialCwd: string): void;
|
||||
|
||||
@@ -428,6 +427,8 @@ export type TransferQuickInput = TransferQuickPick | TransferInputBox;
|
||||
|
||||
export interface BaseTransferQuickInput {
|
||||
|
||||
[key: string]: any;
|
||||
|
||||
id: number;
|
||||
|
||||
type?: 'quickPick' | 'inputBox';
|
||||
@@ -500,7 +501,7 @@ export interface MainThreadQuickOpenShape extends IDisposable {
|
||||
}
|
||||
|
||||
export interface MainThreadStatusBarShape extends IDisposable {
|
||||
$setEntry(id: number, extensionId: ExtensionIdentifier | undefined, text: string, tooltip: string, command: string, color: string | ThemeColor, alignment: statusbar.StatusbarAlignment, priority: number | undefined): void;
|
||||
$setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string, command: string, color: string | ThemeColor, alignment: statusbar.StatusbarAlignment, priority: number | undefined): void;
|
||||
$dispose(id: number): void;
|
||||
}
|
||||
|
||||
@@ -511,12 +512,25 @@ export interface MainThreadStorageShape extends IDisposable {
|
||||
|
||||
export interface MainThreadTelemetryShape extends IDisposable {
|
||||
$publicLog(eventName: string, data?: any): void;
|
||||
$publicLog2<E extends ClassifiedEvent<T> = never, T extends GDPRClassification<T> = never>(eventName: string, data?: StrictPropertyCheck<T, E>): void;
|
||||
}
|
||||
|
||||
export interface MainThreadEditorInsetsShape extends IDisposable {
|
||||
$createEditorInset(handle: number, id: string, uri: UriComponents, line: number, height: number, options: modes.IWebviewOptions, extensionId: ExtensionIdentifier, extensionLocation: UriComponents): Promise<void>;
|
||||
$disposeEditorInset(handle: number): void;
|
||||
|
||||
$setHtml(handle: number, value: string): void;
|
||||
$setOptions(handle: number, options: modes.IWebviewOptions): void;
|
||||
$postMessage(handle: number, value: any): Promise<boolean>;
|
||||
}
|
||||
|
||||
export interface ExtHostEditorInsetsShape {
|
||||
$onDidDispose(handle: number): void;
|
||||
$onDidReceiveMessage(handle: number, message: any): void;
|
||||
}
|
||||
|
||||
export type WebviewPanelHandle = string;
|
||||
|
||||
export type WebviewInsetHandle = number;
|
||||
|
||||
export interface WebviewPanelShowOptions {
|
||||
readonly viewColumn?: EditorViewColumn;
|
||||
readonly preserveFocus?: boolean;
|
||||
@@ -524,15 +538,14 @@ export interface WebviewPanelShowOptions {
|
||||
|
||||
export interface MainThreadWebviewsShape extends IDisposable {
|
||||
$createWebviewPanel(handle: WebviewPanelHandle, viewType: string, title: string, showOptions: WebviewPanelShowOptions, options: modes.IWebviewPanelOptions & modes.IWebviewOptions, extensionId: ExtensionIdentifier, extensionLocation: UriComponents): void;
|
||||
$createWebviewCodeInset(handle: WebviewInsetHandle, symbolId: string, options: modes.IWebviewOptions, extensionId: ExtensionIdentifier | undefined, extensionLocation: UriComponents | undefined): void;
|
||||
$disposeWebview(handle: WebviewPanelHandle): void;
|
||||
$reveal(handle: WebviewPanelHandle, showOptions: WebviewPanelShowOptions): void;
|
||||
$setTitle(handle: WebviewPanelHandle, value: string): void;
|
||||
$setIconPath(handle: WebviewPanelHandle, value: { light: UriComponents, dark: UriComponents } | undefined): void;
|
||||
|
||||
$setHtml(handle: WebviewPanelHandle | WebviewInsetHandle, value: string): void;
|
||||
$setOptions(handle: WebviewPanelHandle | WebviewInsetHandle, options: modes.IWebviewOptions): void;
|
||||
$postMessage(handle: WebviewPanelHandle | WebviewInsetHandle, value: any): Promise<boolean>;
|
||||
$setHtml(handle: WebviewPanelHandle, value: string): void;
|
||||
$setOptions(handle: WebviewPanelHandle, options: modes.IWebviewOptions): void;
|
||||
$postMessage(handle: WebviewPanelHandle, value: any): Promise<boolean>;
|
||||
|
||||
$registerSerializer(viewType: string): void;
|
||||
$unregisterSerializer(viewType: string): void;
|
||||
@@ -567,7 +580,7 @@ export interface ITextSearchComplete {
|
||||
export interface MainThreadWorkspaceShape extends IDisposable {
|
||||
$startFileSearch(includePattern: string | undefined, includeFolder: UriComponents | undefined, excludePatternOrDisregardExcludes: string | false | undefined, maxResults: number | undefined, token: CancellationToken): Promise<UriComponents[] | undefined>;
|
||||
$startTextSearch(query: search.IPatternInfo, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Promise<ITextSearchComplete>;
|
||||
$checkExists(includes: string[], token: CancellationToken): Promise<boolean>;
|
||||
$checkExists(folders: UriComponents[], includes: string[], token: CancellationToken): Promise<boolean>;
|
||||
$saveAll(includeUntitled?: boolean): Promise<boolean>;
|
||||
$updateWorkspaceFolders(extensionName: string, index: number, deleteCount: number, workspaceFoldersToAdd: { uri: UriComponents, name?: string }[]): Promise<void>;
|
||||
$resolveProxy(url: string): Promise<string | undefined>;
|
||||
@@ -581,9 +594,21 @@ export interface IFileChangeDto {
|
||||
export interface MainThreadFileSystemShape extends IDisposable {
|
||||
$registerFileSystemProvider(handle: number, scheme: string, capabilities: files.FileSystemProviderCapabilities): void;
|
||||
$unregisterProvider(handle: number): void;
|
||||
$onFileSystemChange(handle: number, resource: IFileChangeDto[]): void;
|
||||
|
||||
$stat(uri: UriComponents): Promise<files.IStat>;
|
||||
$readdir(resource: UriComponents): Promise<[string, files.FileType][]>;
|
||||
$readFile(resource: UriComponents): Promise<VSBuffer>;
|
||||
$writeFile(resource: UriComponents, content: VSBuffer): Promise<void>;
|
||||
$rename(resource: UriComponents, target: UriComponents, opts: files.FileOverwriteOptions): Promise<void>;
|
||||
$copy(resource: UriComponents, target: UriComponents, opts: files.FileOverwriteOptions): Promise<void>;
|
||||
$mkdir(resource: UriComponents): Promise<void>;
|
||||
$delete(resource: UriComponents, opts: files.FileDeleteOptions): Promise<void>;
|
||||
}
|
||||
|
||||
export interface MainThreadLabelServiceShape extends IDisposable {
|
||||
$registerResourceLabelFormatter(handle: number, formatter: ResourceLabelFormatter): void;
|
||||
$unregisterResourceLabelFormatter(handle: number): void;
|
||||
$onFileSystemChange(handle: number, resource: IFileChangeDto[]): void;
|
||||
}
|
||||
|
||||
export interface MainThreadSearchShape extends IDisposable {
|
||||
@@ -597,7 +622,7 @@ export interface MainThreadSearchShape extends IDisposable {
|
||||
|
||||
export interface MainThreadTaskShape extends IDisposable {
|
||||
$createTaskId(task: tasks.TaskDTO): Promise<string>;
|
||||
$registerTaskProvider(handle: number): Promise<void>;
|
||||
$registerTaskProvider(handle: number, type: string): Promise<void>;
|
||||
$unregisterTaskProvider(handle: number): Promise<void>;
|
||||
$fetchTasks(filter?: tasks.TaskFilterDTO): Promise<tasks.TaskDTO[]>;
|
||||
$executeTask(task: tasks.TaskHandleDTO | tasks.TaskDTO): Promise<tasks.TaskExecutionDTO>;
|
||||
@@ -813,6 +838,10 @@ export interface ExtHostFileSystemShape {
|
||||
$write(handle: number, fd: number, pos: number, data: VSBuffer): Promise<number>;
|
||||
}
|
||||
|
||||
export interface ExtHostLabelServiceShape {
|
||||
$registerResourceLabelFormatter(formatter: ResourceLabelFormatter): IDisposable;
|
||||
}
|
||||
|
||||
export interface ExtHostSearchShape {
|
||||
$provideFileSearchResults(handle: number, session: number, query: search.IRawQuery, token: CancellationToken): Promise<search.ISearchCompleteStats>;
|
||||
$provideTextSearchResults(handle: number, session: number, query: search.IRawTextQuery, token: CancellationToken): Promise<search.ISearchCompleteStats>;
|
||||
@@ -916,6 +945,20 @@ export interface SuggestResultDto {
|
||||
c?: boolean;
|
||||
}
|
||||
|
||||
export interface SignatureHelpDto {
|
||||
id: CacheId;
|
||||
signatures: modes.SignatureInformation[];
|
||||
activeSignature: number;
|
||||
activeParameter: number;
|
||||
}
|
||||
|
||||
export interface SignatureHelpContextDto {
|
||||
readonly triggerKind: modes.SignatureHelpTriggerKind;
|
||||
readonly triggerCharacter?: string;
|
||||
readonly isRetrigger: boolean;
|
||||
readonly activeSignatureHelp?: SignatureHelpDto;
|
||||
}
|
||||
|
||||
export interface LocationDto {
|
||||
uri: UriComponents;
|
||||
range: IRange;
|
||||
@@ -988,6 +1031,11 @@ export interface CodeActionDto {
|
||||
isPreferred?: boolean;
|
||||
}
|
||||
|
||||
export interface CodeActionListDto {
|
||||
cacheId: number;
|
||||
actions: ReadonlyArray<CodeActionDto>;
|
||||
}
|
||||
|
||||
export type CacheId = number;
|
||||
export type ChainedCacheId = [CacheId, CacheId];
|
||||
|
||||
@@ -1000,16 +1048,20 @@ export interface LinkDto {
|
||||
cacheId?: ChainedCacheId;
|
||||
range: IRange;
|
||||
url?: string | UriComponents;
|
||||
tooltip?: string;
|
||||
}
|
||||
|
||||
export interface CodeLensDto extends ObjectIdentifier {
|
||||
export interface CodeLensListDto {
|
||||
cacheId?: number;
|
||||
lenses: CodeLensDto[];
|
||||
}
|
||||
|
||||
export interface CodeLensDto {
|
||||
cacheId?: ChainedCacheId;
|
||||
range: IRange;
|
||||
id?: string;
|
||||
command?: CommandDto;
|
||||
}
|
||||
|
||||
export type CodeInsetDto = ObjectIdentifier & codeInset.ICodeInsetSymbol;
|
||||
|
||||
export interface CallHierarchyDto {
|
||||
_id: number;
|
||||
kind: modes.SymbolKind;
|
||||
@@ -1022,10 +1074,9 @@ 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<CodeLensDto[]>;
|
||||
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<CodeLensListDto | undefined>;
|
||||
$resolveCodeLens(handle: number, symbol: CodeLensDto, token: CancellationToken): Promise<CodeLensDto | undefined>;
|
||||
$provideCodeInsets(handle: number, resource: UriComponents, token: CancellationToken): Promise<CodeInsetDto[] | undefined>;
|
||||
$resolveCodeInset(handle: number, resource: UriComponents, symbol: CodeInsetDto, token: CancellationToken): Promise<CodeInsetDto>;
|
||||
$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[]>;
|
||||
@@ -1033,7 +1084,8 @@ export interface ExtHostLanguageFeaturesShape {
|
||||
$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<CodeActionDto[] | undefined>;
|
||||
$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<CodeActionListDto | 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>;
|
||||
@@ -1045,7 +1097,8 @@ export interface ExtHostLanguageFeaturesShape {
|
||||
$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>;
|
||||
$releaseCompletionItems(handle: number, id: number): void;
|
||||
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<modes.SignatureHelp | undefined>;
|
||||
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<SignatureHelpDto | 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>;
|
||||
$releaseDocumentLinks(handle: number, id: number): void;
|
||||
@@ -1076,6 +1129,21 @@ export interface ShellLaunchConfigDto {
|
||||
env?: { [key: string]: string | null };
|
||||
}
|
||||
|
||||
export interface IShellDefinitionDto {
|
||||
label: string;
|
||||
path: string;
|
||||
}
|
||||
|
||||
export interface IShellAndArgsDto {
|
||||
shell: string;
|
||||
args: string[] | string | undefined;
|
||||
}
|
||||
|
||||
export interface ITerminalDimensionsDto {
|
||||
columns: number;
|
||||
rows: number;
|
||||
}
|
||||
|
||||
export interface ExtHostTerminalServiceShape {
|
||||
$acceptTerminalClosed(id: number): void;
|
||||
$acceptTerminalOpened(id: number, name: string): void;
|
||||
@@ -1085,13 +1153,18 @@ export interface ExtHostTerminalServiceShape {
|
||||
$acceptTerminalRendererInput(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;
|
||||
$createProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, activeWorkspaceRootUri: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void;
|
||||
$startVirtualProcess(id: number, initialDimensions: ITerminalDimensionsDto | undefined): void;
|
||||
$acceptProcessInput(id: number, data: string): void;
|
||||
$acceptProcessResize(id: number, cols: number, rows: number): void;
|
||||
$acceptProcessShutdown(id: number, immediate: boolean): void;
|
||||
$acceptProcessRequestInitialCwd(id: number): void;
|
||||
$acceptProcessRequestCwd(id: number): void;
|
||||
$acceptProcessRequestLatency(id: number): number;
|
||||
$acceptWorkspacePermissionsChanged(isAllowed: boolean): void;
|
||||
$requestAvailableShells(): Promise<IShellDefinitionDto[]>;
|
||||
$requestDefaultShellAndArgs(): Promise<IShellAndArgsDto>;
|
||||
}
|
||||
|
||||
export interface ExtHostSCMShape {
|
||||
@@ -1104,6 +1177,7 @@ export interface ExtHostSCMShape {
|
||||
|
||||
export interface ExtHostTaskShape {
|
||||
$provideTasks(handle: number, validTypes: { [key: string]: boolean; }): Thenable<tasks.TaskSetDTO>;
|
||||
$resolveTask(handle: number, taskDTO: tasks.TaskDTO): Thenable<tasks.TaskDTO | undefined>;
|
||||
$onDidStartTask(execution: tasks.TaskExecutionDTO, terminalId: number): void;
|
||||
$onDidStartTaskProcess(value: tasks.TaskProcessStartedDTO): void;
|
||||
$onDidEndTaskProcess(value: tasks.TaskProcessEndedDTO): void;
|
||||
@@ -1209,25 +1283,12 @@ export interface ExtHostProgressShape {
|
||||
}
|
||||
|
||||
export interface ExtHostCommentsShape {
|
||||
$provideDocumentComments(handle: number, document: UriComponents): Promise<modes.CommentInfo | null>;
|
||||
$createNewCommentThread(handle: number, document: UriComponents, range: IRange, text: string): Promise<modes.CommentThread | null>;
|
||||
$createCommentThreadTemplate(commentControllerHandle: number, uriComponents: UriComponents, range: IRange): void;
|
||||
$onCommentWidgetInputChange(commentControllerHandle: number, document: UriComponents, range: IRange, input: string | undefined): Promise<number | undefined>;
|
||||
$updateCommentThreadTemplate(commentControllerHandle: number, threadHandle: number, range: IRange): Promise<void>;
|
||||
$deleteCommentThread(commentControllerHandle: number, commentThreadHandle: number): void;
|
||||
$provideCommentingRanges(commentControllerHandle: number, uriComponents: UriComponents, token: CancellationToken): Promise<IRange[] | undefined>;
|
||||
$checkStaticContribution(commentControllerHandle: number): Promise<boolean>;
|
||||
$provideReactionGroup(commentControllerHandle: number): Promise<modes.CommentReaction[] | undefined>;
|
||||
$toggleReaction(commentControllerHandle: number, threadHandle: number, uri: UriComponents, comment: modes.Comment, reaction: modes.CommentReaction): Promise<void>;
|
||||
$createNewCommentWidgetCallback(commentControllerHandle: number, uriComponents: UriComponents, range: IRange, token: CancellationToken): Promise<void>;
|
||||
$replyToCommentThread(handle: number, document: UriComponents, range: IRange, commentThread: modes.CommentThread, text: string): Promise<modes.CommentThread | null>;
|
||||
$editComment(handle: number, document: UriComponents, comment: modes.Comment, text: string): Promise<void>;
|
||||
$deleteComment(handle: number, document: UriComponents, comment: modes.Comment): Promise<void>;
|
||||
$startDraft(handle: number, document: UriComponents): Promise<void>;
|
||||
$deleteDraft(handle: number, document: UriComponents): Promise<void>;
|
||||
$finishDraft(handle: number, document: UriComponents): Promise<void>;
|
||||
$addReaction(handle: number, document: UriComponents, comment: modes.Comment, reaction: modes.CommentReaction): Promise<void>;
|
||||
$deleteReaction(handle: number, document: UriComponents, comment: modes.Comment, reaction: modes.CommentReaction): Promise<void>;
|
||||
$provideWorkspaceComments(handle: number): Promise<modes.CommentThread[] | null>;
|
||||
}
|
||||
|
||||
export interface ExtHostStorageShape {
|
||||
@@ -1249,6 +1310,7 @@ export const MainContext = {
|
||||
MainThreadDocuments: createMainId<MainThreadDocumentsShape>('MainThreadDocuments'),
|
||||
MainThreadDocumentContentProviders: createMainId<MainThreadDocumentContentProvidersShape>('MainThreadDocumentContentProviders'),
|
||||
MainThreadTextEditors: createMainId<MainThreadTextEditorsShape>('MainThreadTextEditors'),
|
||||
MainThreadEditorInsets: createMainId<MainThreadEditorInsetsShape>('MainThreadEditorInsets'),
|
||||
MainThreadErrors: createMainId<MainThreadErrorsShape>('MainThreadErrors'),
|
||||
MainThreadTreeViews: createMainId<MainThreadTreeViewsShape>('MainThreadTreeViews'),
|
||||
MainThreadKeytar: createMainId<MainThreadKeytarShape>('MainThreadKeytar'),
|
||||
@@ -1271,6 +1333,7 @@ export const MainContext = {
|
||||
MainThreadSearch: createMainId<MainThreadSearchShape>('MainThreadSearch'),
|
||||
MainThreadTask: createMainId<MainThreadTaskShape>('MainThreadTask'),
|
||||
MainThreadWindow: createMainId<MainThreadWindowShape>('MainThreadWindow'),
|
||||
MainThreadLabelService: createMainId<MainThreadLabelServiceShape>('MainThreadLabelService')
|
||||
};
|
||||
|
||||
export const ExtHostContext = {
|
||||
@@ -1287,7 +1350,6 @@ export const ExtHostContext = {
|
||||
ExtHostTreeViews: createExtId<ExtHostTreeViewsShape>('ExtHostTreeViews'),
|
||||
ExtHostFileSystem: createExtId<ExtHostFileSystemShape>('ExtHostFileSystem'),
|
||||
ExtHostFileSystemEventService: createExtId<ExtHostFileSystemEventServiceShape>('ExtHostFileSystemEventService'),
|
||||
ExtHostHeapService: createExtId<ExtHostHeapServiceShape>('ExtHostHeapMonitor'),
|
||||
ExtHostLanguageFeatures: createExtId<ExtHostLanguageFeaturesShape>('ExtHostLanguageFeatures'),
|
||||
ExtHostQuickOpen: createExtId<ExtHostQuickOpenShape>('ExtHostQuickOpen'),
|
||||
ExtHostExtensionService: createExtId<ExtHostExtensionServiceShape>('ExtHostExtensionService'),
|
||||
@@ -1299,9 +1361,11 @@ export const ExtHostContext = {
|
||||
ExtHostWorkspace: createExtId<ExtHostWorkspaceShape>('ExtHostWorkspace'),
|
||||
ExtHostWindow: createExtId<ExtHostWindowShape>('ExtHostWindow'),
|
||||
ExtHostWebviews: createExtId<ExtHostWebviewsShape>('ExtHostWebviews'),
|
||||
ExtHostEditorInsets: createExtId<ExtHostEditorInsetsShape>('ExtHostEditorInsets'),
|
||||
ExtHostProgress: createMainId<ExtHostProgressShape>('ExtHostProgress'),
|
||||
ExtHostComments: createMainId<ExtHostCommentsShape>('ExtHostComments'),
|
||||
ExtHostStorage: createMainId<ExtHostStorageShape>('ExtHostStorage'),
|
||||
ExtHostUrls: createExtId<ExtHostUrlsShape>('ExtHostUrls'),
|
||||
ExtHostOutputService: createMainId<ExtHostOutputServiceShape>('ExtHostOutputService'),
|
||||
ExtHosLabelService: createMainId<ExtHostLabelServiceShape>('ExtHostLabelService')
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ import { CustomCodeAction } from 'vs/workbench/api/common/extHostLanguageFeature
|
||||
import { ICommandsExecutor, OpenFolderAPICommand, DiffAPICommand, OpenAPICommand, RemoveFromRecentlyOpenedAPICommand, SetEditorLayoutAPICommand, OpenIssueReporter } from './apiCommands';
|
||||
import { EditorGroupLayout } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
|
||||
export class ExtHostApiCommands {
|
||||
|
||||
@@ -143,7 +144,7 @@ export class ExtHostApiCommands {
|
||||
description: 'Execute CodeLens provider.',
|
||||
args: [
|
||||
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
|
||||
{ name: 'itemResolveCount', description: '(optional) Number of lenses that should be resolved and returned. Will only retrun resolved lenses, will impact performance)', constraint: (value: any) => value === undefined || typeof value === 'number' }
|
||||
{ name: 'itemResolveCount', description: '(optional) Number of lenses that should be resolved and returned. Will only return resolved lenses, will impact performance)', constraint: (value: any) => value === undefined || typeof value === 'number' }
|
||||
],
|
||||
returns: 'A promise that resolves to an array of CodeLens-instances.'
|
||||
});
|
||||
@@ -223,7 +224,7 @@ export class ExtHostApiCommands {
|
||||
description: 'Open a folder or workspace in the current window or new window depending on the newWindow argument. Note that opening in the same window will shutdown the current extension host process and start a new one on the given folder/workspace unless the newWindow parameter is set to true.',
|
||||
args: [
|
||||
{ name: 'uri', description: '(optional) Uri of the folder or workspace file to open. If not provided, a native dialog will ask the user for the folder', constraint: (value: any) => value === undefined || value instanceof URI },
|
||||
{ name: 'options', description: '(optional) Options. Object with the following properties: `forceNewWindow `: Whether to open the folder/workspace in a new window or the same. Defaults to opening in the same window. `noRecentEntry`: Wheter the opened URI will appear in the \'Open Recent\' list. Defaults to true. Note, for backward compatibility, options can also be of type boolean, representing the `forceNewWindow` setting.', constraint: (value: any) => value === undefined || typeof value === 'object' || typeof value === 'boolean' }
|
||||
{ name: 'options', description: '(optional) Options. Object with the following properties: `forceNewWindow `: Whether to open the folder/workspace in a new window or the same. Defaults to opening in the same window. `noRecentEntry`: Whether the opened URI will appear in the \'Open Recent\' list. Defaults to true. Note, for backward compatibility, options can also be of type boolean, representing the `forceNewWindow` setting.', constraint: (value: any) => value === undefined || typeof value === 'object' || typeof value === 'boolean' }
|
||||
]
|
||||
});
|
||||
|
||||
@@ -414,15 +415,21 @@ export class ExtHostApiCommands {
|
||||
});
|
||||
}
|
||||
|
||||
private _executeSelectionRangeProvider(resource: URI, positions: types.Position[]): Promise<vscode.SelectionRange[][]> {
|
||||
private _executeSelectionRangeProvider(resource: URI, positions: types.Position[]): Promise<vscode.SelectionRange[]> {
|
||||
const pos = positions.map(typeConverters.Position.from);
|
||||
const args = {
|
||||
resource,
|
||||
position: pos[0],
|
||||
positions: pos
|
||||
};
|
||||
return this._commands.executeCommand<modes.SelectionRange[][]>('_executeSelectionRangeProvider', args).then(result => {
|
||||
return result.map(oneResult => oneResult.map(typeConverters.SelectionRange.to));
|
||||
return this._commands.executeCommand<IRange[][]>('_executeSelectionRangeProvider', args).then(result => {
|
||||
return result.map(ranges => {
|
||||
let node: types.SelectionRange | undefined;
|
||||
for (const range of ranges.reverse()) {
|
||||
node = new types.SelectionRange(typeConverters.Range.to(range), node);
|
||||
}
|
||||
return node!;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -473,7 +480,7 @@ export class ExtHostApiCommands {
|
||||
});
|
||||
}
|
||||
|
||||
private _executeCodeActionProvider(resource: URI, range: types.Range, kind?: string): Promise<(vscode.CodeAction | vscode.Command)[] | undefined> {
|
||||
private _executeCodeActionProvider(resource: URI, range: types.Range, kind?: string): Promise<(vscode.CodeAction | vscode.Command | undefined)[] | undefined> {
|
||||
const args = {
|
||||
resource,
|
||||
range: typeConverters.Range.from(range),
|
||||
@@ -504,7 +511,7 @@ export class ExtHostApiCommands {
|
||||
|
||||
private _executeCodeLensProvider(resource: URI, itemResolveCount: number): Promise<vscode.CodeLens[] | undefined> {
|
||||
const args = { resource, itemResolveCount };
|
||||
return this._commands.executeCommand<modes.ICodeLensSymbol[]>('_executeCodeLensProvider', args)
|
||||
return this._commands.executeCommand<modes.CodeLens[]>('_executeCodeLensProvider', args)
|
||||
.then(tryMapWith(item => {
|
||||
return new types.CodeLens(
|
||||
typeConverters.Range.to(item.range),
|
||||
|
||||
143
src/vs/workbench/api/common/extHostCodeInsets.ts
Normal file
143
src/vs/workbench/api/common/extHostCodeInsets.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { ExtHostTextEditor } from 'vs/workbench/api/common/extHostTextEditor';
|
||||
import { ExtHostEditors } from 'vs/workbench/api/common/extHostTextEditors';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostEditorInsetsShape, MainThreadEditorInsetsShape } from './extHost.protocol';
|
||||
import { toWebviewResource, WebviewInitData } from 'vs/workbench/api/common/shared/webview';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
|
||||
export class ExtHostEditorInsets implements ExtHostEditorInsetsShape {
|
||||
|
||||
private _handlePool = 0;
|
||||
private _disposables = new DisposableStore();
|
||||
private _insets = new Map<number, { editor: vscode.TextEditor, inset: vscode.WebviewEditorInset, onDidReceiveMessage: Emitter<any> }>();
|
||||
|
||||
constructor(
|
||||
private readonly _proxy: MainThreadEditorInsetsShape,
|
||||
private readonly _editors: ExtHostEditors,
|
||||
private readonly _initData: WebviewInitData
|
||||
) {
|
||||
|
||||
// dispose editor inset whenever the hosting editor goes away
|
||||
this._disposables.add(_editors.onDidChangeVisibleTextEditors(() => {
|
||||
const visibleEditor = _editors.getVisibleTextEditors();
|
||||
this._insets.forEach(value => {
|
||||
if (visibleEditor.indexOf(value.editor) < 0) {
|
||||
value.inset.dispose(); // will remove from `this._insets`
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._insets.forEach(value => value.inset.dispose());
|
||||
this._disposables.dispose();
|
||||
}
|
||||
|
||||
createWebviewEditorInset(editor: vscode.TextEditor, line: number, height: number, options: vscode.WebviewOptions | undefined, extension: IExtensionDescription): vscode.WebviewEditorInset {
|
||||
|
||||
let apiEditor: ExtHostTextEditor | undefined;
|
||||
for (const candidate of this._editors.getVisibleTextEditors()) {
|
||||
if (candidate === editor) {
|
||||
apiEditor = <ExtHostTextEditor>candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!apiEditor) {
|
||||
throw new Error('not a visible editor');
|
||||
}
|
||||
|
||||
const that = this;
|
||||
const handle = this._handlePool++;
|
||||
const onDidReceiveMessage = new Emitter<any>();
|
||||
const onDidDispose = new Emitter<void>();
|
||||
|
||||
const webview = new class implements vscode.Webview {
|
||||
|
||||
private readonly _uuid = generateUuid();
|
||||
private _html: string = '';
|
||||
private _options: vscode.WebviewOptions;
|
||||
|
||||
toWebviewResource(resource: vscode.Uri): vscode.Uri {
|
||||
return toWebviewResource(that._initData, this._uuid, resource);
|
||||
}
|
||||
|
||||
get cspSource(): string {
|
||||
return that._initData.webviewCspSource;
|
||||
}
|
||||
|
||||
set options(value: vscode.WebviewOptions) {
|
||||
this._options = value;
|
||||
that._proxy.$setOptions(handle, value);
|
||||
}
|
||||
|
||||
get options(): vscode.WebviewOptions {
|
||||
return this._options;
|
||||
}
|
||||
|
||||
set html(value: string) {
|
||||
this._html = value;
|
||||
that._proxy.$setHtml(handle, value);
|
||||
}
|
||||
|
||||
get html(): string {
|
||||
return this._html;
|
||||
}
|
||||
|
||||
get onDidReceiveMessage(): vscode.Event<any> {
|
||||
return onDidReceiveMessage.event;
|
||||
}
|
||||
|
||||
postMessage(message: any): Thenable<boolean> {
|
||||
return that._proxy.$postMessage(handle, message);
|
||||
}
|
||||
};
|
||||
|
||||
const inset = new class implements vscode.WebviewEditorInset {
|
||||
|
||||
readonly editor: vscode.TextEditor = editor;
|
||||
readonly line: number = line;
|
||||
readonly height: number = height;
|
||||
readonly webview: vscode.Webview = webview;
|
||||
readonly onDidDispose: vscode.Event<void> = onDidDispose.event;
|
||||
|
||||
dispose(): void {
|
||||
if (that._insets.has(handle)) {
|
||||
that._insets.delete(handle);
|
||||
that._proxy.$disposeEditorInset(handle);
|
||||
onDidDispose.fire();
|
||||
|
||||
// final cleanup
|
||||
onDidDispose.dispose();
|
||||
onDidReceiveMessage.dispose();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this._proxy.$createEditorInset(handle, apiEditor.id, apiEditor.document.uri, line + 1, height, options || {}, extension.identifier, extension.extensionLocation);
|
||||
this._insets.set(handle, { editor, inset, onDidReceiveMessage });
|
||||
|
||||
return inset;
|
||||
}
|
||||
|
||||
$onDidDispose(handle: number): void {
|
||||
const value = this._insets.get(handle);
|
||||
if (value) {
|
||||
value.inset.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
$onDidReceiveMessage(handle: number, message: any): void {
|
||||
const value = this._insets.get(handle);
|
||||
if (value) {
|
||||
value.onDidReceiveMessage.fire(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ 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 { ExtHostHeapService } from 'vs/workbench/api/common/extHostHeapService';
|
||||
import { isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import * as vscode from 'vscode';
|
||||
@@ -18,6 +17,7 @@ import { revive } from 'vs/base/common/marshalling';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
interface CommandHandler {
|
||||
callback: Function;
|
||||
@@ -39,12 +39,11 @@ export class ExtHostCommands implements ExtHostCommandsShape {
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
heapService: ExtHostHeapService,
|
||||
logService: ILogService
|
||||
) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadCommands);
|
||||
this._logService = logService;
|
||||
this._converter = new CommandsConverter(this, heapService);
|
||||
this._converter = new CommandsConverter(this);
|
||||
this._argumentProcessors = [
|
||||
{
|
||||
processArgument(a) {
|
||||
@@ -200,21 +199,18 @@ export class ExtHostCommands implements ExtHostCommandsShape {
|
||||
export class CommandsConverter {
|
||||
|
||||
private readonly _delegatingCommandId: string;
|
||||
private _commands: ExtHostCommands;
|
||||
private _heap: ExtHostHeapService;
|
||||
private readonly _commands: ExtHostCommands;
|
||||
private readonly _cache = new Map<number, vscode.Command>();
|
||||
private _cachIdPool = 0;
|
||||
|
||||
// --- conversion between internal and api commands
|
||||
constructor(commands: ExtHostCommands, heap: ExtHostHeapService) {
|
||||
constructor(commands: ExtHostCommands) {
|
||||
this._delegatingCommandId = `_internal_command_delegation_${Date.now()}`;
|
||||
this._commands = commands;
|
||||
this._heap = heap;
|
||||
this._commands.registerCommand(true, this._delegatingCommandId, this._executeConvertedCommand, this);
|
||||
}
|
||||
|
||||
toInternal(command: vscode.Command): CommandDto;
|
||||
toInternal(command: undefined): undefined;
|
||||
toInternal(command: vscode.Command | undefined): CommandDto | undefined;
|
||||
toInternal(command: vscode.Command | undefined): CommandDto | undefined {
|
||||
toInternal(command: vscode.Command | undefined, disposables: DisposableStore): CommandDto | undefined {
|
||||
|
||||
if (!command) {
|
||||
return undefined;
|
||||
@@ -224,31 +220,31 @@ export class CommandsConverter {
|
||||
$ident: undefined,
|
||||
id: command.command,
|
||||
title: command.title,
|
||||
tooltip: command.tooltip
|
||||
};
|
||||
|
||||
if (command.command && isNonEmptyArray(command.arguments)) {
|
||||
// we have a contributed command with arguments. that
|
||||
// means we don't want to send the arguments around
|
||||
|
||||
const id = this._heap.keep(command);
|
||||
const id = ++this._cachIdPool;
|
||||
this._cache.set(id, command);
|
||||
disposables.add(toDisposable(() => this._cache.delete(id)));
|
||||
result.$ident = id;
|
||||
|
||||
result.id = this._delegatingCommandId;
|
||||
result.arguments = [id];
|
||||
}
|
||||
|
||||
if (command.tooltip) {
|
||||
result.tooltip = command.tooltip;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fromInternal(command: modes.Command): vscode.Command {
|
||||
fromInternal(command: modes.Command): vscode.Command | undefined {
|
||||
|
||||
const id = ObjectIdentifier.of(command);
|
||||
if (typeof id === 'number') {
|
||||
return this._heap.get<vscode.Command>(id);
|
||||
return this._cache.get(id);
|
||||
|
||||
} else {
|
||||
return {
|
||||
@@ -260,7 +256,10 @@ export class CommandsConverter {
|
||||
}
|
||||
|
||||
private _executeConvertedCommand<R>(...args: any[]): Promise<R> {
|
||||
const actualCmd = this._heap.get<vscode.Command>(args[0]);
|
||||
const actualCmd = this._cache.get(args[0]);
|
||||
if (!actualCmd) {
|
||||
return Promise.reject('actual command NOT FOUND');
|
||||
}
|
||||
return this._commands.executeCommand(actualCmd.command, ...(actualCmd.arguments || []));
|
||||
}
|
||||
|
||||
|
||||
@@ -4,29 +4,25 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { asPromise } from 'vs/base/common/async';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { debounce } from 'vs/base/common/decorators';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { DisposableStore, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
import * as extHostTypeConverter from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import * as types from 'vs/workbench/api/common/extHostTypes';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostCommentsShape, IMainContext, MainContext, MainThreadCommentsShape } from './extHost.protocol';
|
||||
import { CommandsConverter, ExtHostCommands } from './extHostCommands';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { debounce } from 'vs/base/common/decorators';
|
||||
|
||||
interface HandlerData<T> {
|
||||
|
||||
extensionId: ExtensionIdentifier;
|
||||
provider: T;
|
||||
}
|
||||
import { ExtHostCommands } from './extHostCommands';
|
||||
|
||||
type ProviderHandle = number;
|
||||
|
||||
export class ExtHostComments implements ExtHostCommentsShape {
|
||||
export class ExtHostComments implements ExtHostCommentsShape, IDisposable {
|
||||
|
||||
private static handlePool = 0;
|
||||
|
||||
private _proxy: MainThreadCommentsShape;
|
||||
@@ -35,17 +31,15 @@ export class ExtHostComments implements ExtHostCommentsShape {
|
||||
|
||||
private _commentControllersByExtension: Map<string, ExtHostCommentController[]> = new Map<string, ExtHostCommentController[]>();
|
||||
|
||||
private _documentProviders = new Map<number, HandlerData<vscode.DocumentCommentProvider>>();
|
||||
private _workspaceProviders = new Map<number, HandlerData<vscode.WorkspaceCommentProvider>>();
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
private _commands: ExtHostCommands,
|
||||
commands: ExtHostCommands,
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadComments);
|
||||
|
||||
_commands.registerArgumentProcessor({
|
||||
commands.registerArgumentProcessor({
|
||||
processArgument: arg => {
|
||||
if (arg && arg.$mid === 6) {
|
||||
const commentController = this._commentControllers.get(arg.handle);
|
||||
@@ -142,7 +136,7 @@ export class ExtHostComments implements ExtHostCommentsShape {
|
||||
|
||||
createCommentController(extension: IExtensionDescription, id: string, label: string): vscode.CommentController {
|
||||
const handle = ExtHostComments.handlePool++;
|
||||
const commentController = new ExtHostCommentController(extension, handle, this._commands.converter, this._proxy, id, label);
|
||||
const commentController = new ExtHostCommentController(extension, handle, this._proxy, id, label);
|
||||
this._commentControllers.set(commentController.handle, commentController);
|
||||
|
||||
const commentControllers = this._commentControllersByExtension.get(ExtensionIdentifier.toKey(extension.identifier)) || [];
|
||||
@@ -162,15 +156,14 @@ export class ExtHostComments implements ExtHostCommentsShape {
|
||||
commentController.$createCommentThreadTemplate(uriComponents, range);
|
||||
}
|
||||
|
||||
$onCommentWidgetInputChange(commentControllerHandle: number, uriComponents: UriComponents, range: IRange, input: string): Promise<number | undefined> {
|
||||
async $updateCommentThreadTemplate(commentControllerHandle: number, threadHandle: number, range: IRange) {
|
||||
const commentController = this._commentControllers.get(commentControllerHandle);
|
||||
|
||||
if (!commentController) {
|
||||
return Promise.resolve(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
commentController.$onCommentWidgetInputChange(uriComponents, range, input);
|
||||
return Promise.resolve(commentControllerHandle);
|
||||
commentController.$updateCommentThreadTemplate(threadHandle, range);
|
||||
}
|
||||
|
||||
$deleteCommentThread(commentControllerHandle: number, commentThreadHandle: number) {
|
||||
@@ -203,14 +196,14 @@ export class ExtHostComments implements ExtHostCommentsShape {
|
||||
|
||||
return asPromise(() => {
|
||||
return commentController!.reactionProvider!.availableReactions;
|
||||
}).then(reactions => reactions.map(reaction => convertToReaction2(commentController.reactionProvider, reaction)));
|
||||
}).then(reactions => reactions.map(reaction => convertToReaction(commentController.reactionProvider, reaction)));
|
||||
}
|
||||
|
||||
$toggleReaction(commentControllerHandle: number, threadHandle: number, uri: UriComponents, comment: modes.Comment, reaction: modes.CommentReaction): Promise<void> {
|
||||
const document = this._documents.getDocument(URI.revive(uri));
|
||||
const commentController = this._commentControllers.get(commentControllerHandle);
|
||||
|
||||
if (!commentController || !commentController.reactionProvider || !commentController.reactionProvider.toggleReaction) {
|
||||
if (!commentController || !((commentController.reactionProvider && commentController.reactionProvider.toggleReaction) || commentController.reactionHandler)) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
@@ -219,238 +212,24 @@ export class ExtHostComments implements ExtHostCommentsShape {
|
||||
if (commentThread) {
|
||||
const vscodeComment = commentThread.getComment(comment.commentId);
|
||||
|
||||
if (commentController !== undefined && commentController.reactionProvider && commentController.reactionProvider.toggleReaction && vscodeComment) {
|
||||
return commentController.reactionProvider.toggleReaction(document, vscodeComment, convertFromReaction(reaction));
|
||||
if (commentController !== undefined && vscodeComment) {
|
||||
if (commentController.reactionHandler) {
|
||||
return commentController.reactionHandler(vscodeComment, convertFromReaction(reaction));
|
||||
}
|
||||
|
||||
if (commentController.reactionProvider && commentController.reactionProvider.toggleReaction) {
|
||||
return commentController.reactionProvider.toggleReaction(document, vscodeComment, convertFromReaction(reaction));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return Promise.resolve(undefined);
|
||||
});
|
||||
}
|
||||
|
||||
$createNewCommentWidgetCallback(commentControllerHandle: number, uriComponents: UriComponents, range: IRange, token: CancellationToken): Promise<void> {
|
||||
const commentController = this._commentControllers.get(commentControllerHandle);
|
||||
dispose() {
|
||||
|
||||
if (!commentController) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
if (!(commentController as any).emptyCommentThreadFactory) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const document = this._documents.getDocument(URI.revive(uriComponents));
|
||||
return asPromise(() => {
|
||||
if ((commentController as any).emptyCommentThreadFactory) {
|
||||
return (commentController as any).emptyCommentThreadFactory!.createEmptyCommentThread(document, extHostTypeConverter.Range.to(range));
|
||||
}
|
||||
}).then(() => Promise.resolve());
|
||||
}
|
||||
|
||||
$checkStaticContribution(commentControllerHandle: number): Promise<boolean> {
|
||||
const commentController = this._commentControllers.get(commentControllerHandle);
|
||||
|
||||
if (!commentController) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
if (!(commentController as any).emptyCommentThreadFactory) {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
registerWorkspaceCommentProvider(
|
||||
extensionId: ExtensionIdentifier,
|
||||
provider: vscode.WorkspaceCommentProvider
|
||||
): vscode.Disposable {
|
||||
const handle = ExtHostComments.handlePool++;
|
||||
this._workspaceProviders.set(handle, {
|
||||
extensionId,
|
||||
provider
|
||||
});
|
||||
this._proxy.$registerWorkspaceCommentProvider(handle, extensionId);
|
||||
this.registerListeners(handle, extensionId, provider);
|
||||
|
||||
return {
|
||||
dispose: () => {
|
||||
this._proxy.$unregisterWorkspaceCommentProvider(handle);
|
||||
this._workspaceProviders.delete(handle);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
registerDocumentCommentProvider(
|
||||
extensionId: ExtensionIdentifier,
|
||||
provider: vscode.DocumentCommentProvider
|
||||
): vscode.Disposable {
|
||||
const handle = ExtHostComments.handlePool++;
|
||||
this._documentProviders.set(handle, {
|
||||
extensionId,
|
||||
provider
|
||||
});
|
||||
this._proxy.$registerDocumentCommentProvider(handle, {
|
||||
startDraftLabel: provider.startDraftLabel,
|
||||
deleteDraftLabel: provider.deleteDraftLabel,
|
||||
finishDraftLabel: provider.finishDraftLabel,
|
||||
reactionGroup: provider.reactionGroup ? provider.reactionGroup.map(reaction => convertToReaction(provider, reaction)) : undefined
|
||||
});
|
||||
this.registerListeners(handle, extensionId, provider);
|
||||
|
||||
return {
|
||||
dispose: () => {
|
||||
this._proxy.$unregisterDocumentCommentProvider(handle);
|
||||
this._documentProviders.delete(handle);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
$createNewCommentThread(handle: number, uri: UriComponents, range: IRange, text: string): Promise<modes.CommentThread | null> {
|
||||
const data = this._documents.getDocumentData(URI.revive(uri));
|
||||
const ran = <vscode.Range>extHostTypeConverter.Range.to(range);
|
||||
|
||||
if (!data || !data.document) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
const handlerData = this.getDocumentProvider(handle);
|
||||
return asPromise(() => {
|
||||
return handlerData.provider.createNewCommentThread(data.document, ran, text, CancellationToken.None);
|
||||
}).then(commentThread => commentThread ? convertToCommentThread(handlerData.extensionId, handlerData.provider, commentThread, this._commands.converter) : null);
|
||||
}
|
||||
|
||||
$replyToCommentThread(handle: number, uri: UriComponents, range: IRange, thread: modes.CommentThread, text: string): Promise<modes.CommentThread | null> {
|
||||
const data = this._documents.getDocumentData(URI.revive(uri));
|
||||
const ran = <vscode.Range>extHostTypeConverter.Range.to(range);
|
||||
|
||||
if (!data || !data.document) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
const handlerData = this.getDocumentProvider(handle);
|
||||
return asPromise(() => {
|
||||
return handlerData.provider.replyToCommentThread(data.document, ran, convertFromCommentThread(thread), text, CancellationToken.None);
|
||||
}).then(commentThread => commentThread ? convertToCommentThread(handlerData.extensionId, handlerData.provider, commentThread, this._commands.converter) : null);
|
||||
}
|
||||
|
||||
$editComment(handle: number, uri: UriComponents, comment: modes.Comment, text: string): Promise<void> {
|
||||
const document = this._documents.getDocument(URI.revive(uri));
|
||||
const handlerData = this.getDocumentProvider(handle);
|
||||
if (!handlerData.provider.editComment) {
|
||||
return Promise.reject(new Error('not implemented'));
|
||||
}
|
||||
return asPromise(() => {
|
||||
return handlerData.provider.editComment!(document, convertFromComment(comment), text, CancellationToken.None);
|
||||
});
|
||||
}
|
||||
|
||||
$deleteComment(handle: number, uri: UriComponents, comment: modes.Comment): Promise<void> {
|
||||
const document = this._documents.getDocument(URI.revive(uri));
|
||||
const handlerData = this.getDocumentProvider(handle);
|
||||
if (!handlerData.provider.deleteComment) {
|
||||
return Promise.reject(new Error('not implemented'));
|
||||
}
|
||||
return asPromise(() => {
|
||||
return handlerData.provider.deleteComment!(document, convertFromComment(comment), CancellationToken.None);
|
||||
});
|
||||
}
|
||||
|
||||
$startDraft(handle: number, uri: UriComponents): Promise<void> {
|
||||
const document = this._documents.getDocument(URI.revive(uri));
|
||||
|
||||
const handlerData = this.getDocumentProvider(handle);
|
||||
if (!handlerData.provider.startDraft) {
|
||||
return Promise.reject(new Error('not implemented'));
|
||||
}
|
||||
return asPromise(() => {
|
||||
return handlerData.provider.startDraft!(document, CancellationToken.None);
|
||||
});
|
||||
}
|
||||
|
||||
$deleteDraft(handle: number, uri: UriComponents): Promise<void> {
|
||||
const document = this._documents.getDocument(URI.revive(uri));
|
||||
const handlerData = this.getDocumentProvider(handle);
|
||||
if (!handlerData.provider.deleteDraft) {
|
||||
return Promise.reject(new Error('not implemented'));
|
||||
}
|
||||
return asPromise(() => {
|
||||
return handlerData.provider.deleteDraft!(document, CancellationToken.None);
|
||||
});
|
||||
}
|
||||
|
||||
$finishDraft(handle: number, uri: UriComponents): Promise<void> {
|
||||
const document = this._documents.getDocument(URI.revive(uri));
|
||||
const handlerData = this.getDocumentProvider(handle);
|
||||
if (!handlerData.provider.finishDraft) {
|
||||
return Promise.reject(new Error('not implemented'));
|
||||
}
|
||||
return asPromise(() => {
|
||||
return handlerData.provider.finishDraft!(document, CancellationToken.None);
|
||||
});
|
||||
}
|
||||
|
||||
$addReaction(handle: number, uri: UriComponents, comment: modes.Comment, reaction: modes.CommentReaction): Promise<void> {
|
||||
const document = this._documents.getDocument(URI.revive(uri));
|
||||
const handlerData = this.getDocumentProvider(handle);
|
||||
if (!handlerData.provider.addReaction) {
|
||||
return Promise.reject(new Error('not implemented'));
|
||||
}
|
||||
return asPromise(() => {
|
||||
return handlerData.provider.addReaction!(document, convertFromComment(comment), convertFromReaction(reaction));
|
||||
});
|
||||
}
|
||||
|
||||
$deleteReaction(handle: number, uri: UriComponents, comment: modes.Comment, reaction: modes.CommentReaction): Promise<void> {
|
||||
const document = this._documents.getDocument(URI.revive(uri));
|
||||
const handlerData = this.getDocumentProvider(handle);
|
||||
if (!handlerData.provider.deleteReaction) {
|
||||
return Promise.reject(new Error('not implemented'));
|
||||
}
|
||||
return asPromise(() => {
|
||||
return handlerData.provider.deleteReaction!(document, convertFromComment(comment), convertFromReaction(reaction));
|
||||
});
|
||||
}
|
||||
|
||||
$provideDocumentComments(handle: number, uri: UriComponents): Promise<modes.CommentInfo | null> {
|
||||
const document = this._documents.getDocument(URI.revive(uri));
|
||||
const handlerData = this.getDocumentProvider(handle);
|
||||
return asPromise(() => {
|
||||
return handlerData.provider.provideDocumentComments(document, CancellationToken.None);
|
||||
}).then(commentInfo => commentInfo ? convertCommentInfo(handle, handlerData.extensionId, handlerData.provider, commentInfo, this._commands.converter) : null);
|
||||
}
|
||||
|
||||
$provideWorkspaceComments(handle: number): Promise<modes.CommentThread[] | null> {
|
||||
const handlerData = this._workspaceProviders.get(handle);
|
||||
if (!handlerData) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
return asPromise(() => {
|
||||
return handlerData.provider.provideWorkspaceComments(CancellationToken.None);
|
||||
}).then(comments =>
|
||||
comments.map(comment => convertToCommentThread(handlerData.extensionId, handlerData.provider, comment, this._commands.converter)
|
||||
));
|
||||
}
|
||||
|
||||
private registerListeners(handle: number, extensionId: ExtensionIdentifier, provider: vscode.DocumentCommentProvider | vscode.WorkspaceCommentProvider) {
|
||||
provider.onDidChangeCommentThreads(event => {
|
||||
|
||||
this._proxy.$onDidCommentThreadsChange(handle, {
|
||||
changed: event.changed.map(thread => convertToCommentThread(extensionId, provider, thread, this._commands.converter)),
|
||||
added: event.added.map(thread => convertToCommentThread(extensionId, provider, thread, this._commands.converter)),
|
||||
removed: event.removed.map(thread => convertToCommentThread(extensionId, provider, thread, this._commands.converter)),
|
||||
draftMode: !!(provider as vscode.DocumentCommentProvider).startDraft && !!(provider as vscode.DocumentCommentProvider).finishDraft ? (event.inDraftMode ? modes.DraftMode.InDraft : modes.DraftMode.NotInDraft) : modes.DraftMode.NotSupported
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private getDocumentProvider(handle: number): HandlerData<vscode.DocumentCommentProvider> {
|
||||
const provider = this._documentProviders.get(handle);
|
||||
if (!provider) {
|
||||
throw new Error('unknown provider');
|
||||
}
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -524,36 +303,6 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
||||
this._onDidUpdateCommentThread.fire();
|
||||
}
|
||||
|
||||
private _acceptInputCommand: vscode.Command;
|
||||
get acceptInputCommand(): vscode.Command {
|
||||
return this._acceptInputCommand;
|
||||
}
|
||||
|
||||
set acceptInputCommand(acceptInputCommand: vscode.Command) {
|
||||
this._acceptInputCommand = acceptInputCommand;
|
||||
this._onDidUpdateCommentThread.fire();
|
||||
}
|
||||
|
||||
private _additionalCommands: vscode.Command[] = [];
|
||||
get additionalCommands(): vscode.Command[] {
|
||||
return this._additionalCommands;
|
||||
}
|
||||
|
||||
set additionalCommands(additionalCommands: vscode.Command[]) {
|
||||
this._additionalCommands = additionalCommands;
|
||||
this._onDidUpdateCommentThread.fire();
|
||||
}
|
||||
|
||||
private _deleteCommand?: vscode.Command;
|
||||
get deleteComand(): vscode.Command | undefined {
|
||||
return this._deleteCommand;
|
||||
}
|
||||
|
||||
set deleteCommand(deleteCommand: vscode.Command) {
|
||||
this._deleteCommand = deleteCommand;
|
||||
this._onDidUpdateCommentThread.fire();
|
||||
}
|
||||
|
||||
private _collapseState?: vscode.CommentThreadCollapsibleState;
|
||||
|
||||
get collapsibleState(): vscode.CommentThreadCollapsibleState {
|
||||
@@ -575,15 +324,19 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
||||
|
||||
private _commentsMap: Map<vscode.Comment, number> = new Map<vscode.Comment, number>();
|
||||
|
||||
private _acceptInputDisposables = new MutableDisposable<DisposableStore>();
|
||||
|
||||
constructor(
|
||||
private _proxy: MainThreadCommentsShape,
|
||||
private readonly _commandsConverter: CommandsConverter,
|
||||
private _commentController: ExtHostCommentController,
|
||||
private _id: string | undefined,
|
||||
private _uri: vscode.Uri,
|
||||
private _range: vscode.Range,
|
||||
private _comments: vscode.Comment[]
|
||||
private _comments: vscode.Comment[],
|
||||
extensionId: ExtensionIdentifier
|
||||
) {
|
||||
this._acceptInputDisposables.value = new DisposableStore();
|
||||
|
||||
if (this._id === undefined) {
|
||||
this._id = `${_commentController.id}.${this.handle}`;
|
||||
}
|
||||
@@ -593,7 +346,8 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
||||
this.handle,
|
||||
this._id,
|
||||
this._uri,
|
||||
extHostTypeConverter.Range.from(this._range)
|
||||
extHostTypeConverter.Range.from(this._range),
|
||||
extensionId
|
||||
);
|
||||
|
||||
this._localDisposables = [];
|
||||
@@ -607,15 +361,21 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
||||
this.comments = _comments;
|
||||
}
|
||||
|
||||
|
||||
@debounce(100)
|
||||
eventuallyUpdateCommentThread(): void {
|
||||
if (this._isDiposed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._acceptInputDisposables.value) {
|
||||
this._acceptInputDisposables.value = new DisposableStore();
|
||||
}
|
||||
|
||||
const commentThreadRange = extHostTypeConverter.Range.from(this._range);
|
||||
const label = this.label;
|
||||
const contextValue = this.contextValue;
|
||||
const comments = this._comments.map(cmt => { return convertToModeComment2(this, this._commentController, cmt, this._commandsConverter, this._commentsMap); });
|
||||
const acceptInputCommand = this._acceptInputCommand ? this._commandsConverter.toInternal(this._acceptInputCommand) : undefined;
|
||||
const additionalCommands = this._additionalCommands ? this._additionalCommands.map(x => this._commandsConverter.toInternal(x)) : [];
|
||||
const deleteCommand = this._deleteCommand ? this._commandsConverter.toInternal(this._deleteCommand) : undefined;
|
||||
const comments = this._comments.map(cmt => { return convertToModeComment(this, this._commentController, cmt, this._commentsMap); });
|
||||
const collapsibleState = convertToCollapsibleState(this._collapseState);
|
||||
|
||||
this._proxy.$updateCommentThread(
|
||||
@@ -627,9 +387,6 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
||||
label,
|
||||
contextValue,
|
||||
comments,
|
||||
acceptInputCommand,
|
||||
additionalCommands,
|
||||
deleteCommand,
|
||||
collapsibleState
|
||||
);
|
||||
}
|
||||
@@ -657,56 +414,18 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._isDiposed = true;
|
||||
this._acceptInputDisposables.dispose();
|
||||
this._localDisposables.forEach(disposable => disposable.dispose());
|
||||
this._proxy.$deleteCommentThread(
|
||||
this._commentController.handle,
|
||||
this.handle
|
||||
);
|
||||
this._isDiposed = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class ExtHostCommentInputBox implements vscode.CommentInputBox {
|
||||
get resource(): vscode.Uri {
|
||||
return this._resource;
|
||||
}
|
||||
|
||||
get range(): vscode.Range {
|
||||
return this._range;
|
||||
}
|
||||
|
||||
get value(): string {
|
||||
return this._value;
|
||||
}
|
||||
|
||||
set value(newInput: string) {
|
||||
this._value = newInput;
|
||||
this._onDidChangeValue.fire(this._value);
|
||||
this._proxy.$setInputValue(this.commentControllerHandle, newInput);
|
||||
}
|
||||
|
||||
private _onDidChangeValue = new Emitter<string>();
|
||||
|
||||
get onDidChangeValue(): Event<string> {
|
||||
return this._onDidChangeValue.event;
|
||||
}
|
||||
|
||||
constructor(
|
||||
private _proxy: MainThreadCommentsShape,
|
||||
public commentControllerHandle: number,
|
||||
private _resource: vscode.Uri,
|
||||
private _range: vscode.Range,
|
||||
private _value: string
|
||||
) {
|
||||
}
|
||||
|
||||
setInput(resource: vscode.Uri, range: vscode.Range, input: string) {
|
||||
this._resource = resource;
|
||||
this._range = range;
|
||||
this._value = input;
|
||||
}
|
||||
}
|
||||
|
||||
type ReactionHandler = (comment: vscode.Comment, reaction: vscode.CommentReaction) => Promise<void>;
|
||||
|
||||
class ExtHostCommentController implements vscode.CommentController {
|
||||
get id(): string {
|
||||
return this._id;
|
||||
@@ -716,16 +435,12 @@ class ExtHostCommentController implements vscode.CommentController {
|
||||
return this._label;
|
||||
}
|
||||
|
||||
public inputBox: ExtHostCommentInputBox | undefined;
|
||||
|
||||
public activeCommentingRange?: vscode.Range;
|
||||
|
||||
public get handle(): number {
|
||||
return this._handle;
|
||||
}
|
||||
|
||||
private _threads: Map<number, ExtHostCommentThread> = new Map<number, ExtHostCommentThread>();
|
||||
commentingRangeProvider?: vscode.CommentingRangeProvider & { createEmptyCommentThread: (document: vscode.TextDocument, range: types.Range) => Promise<vscode.CommentThread>; };
|
||||
commentingRangeProvider?: vscode.CommentingRangeProvider;
|
||||
|
||||
private _commentReactionProvider?: vscode.CommentReactionProvider;
|
||||
|
||||
@@ -736,14 +451,25 @@ class ExtHostCommentController implements vscode.CommentController {
|
||||
set reactionProvider(provider: vscode.CommentReactionProvider | undefined) {
|
||||
this._commentReactionProvider = provider;
|
||||
if (provider) {
|
||||
this._proxy.$updateCommentControllerFeatures(this.handle, { reactionGroup: provider.availableReactions.map(reaction => convertToReaction2(provider, reaction)) });
|
||||
this._proxy.$updateCommentControllerFeatures(this.handle, { reactionGroup: provider.availableReactions.map(reaction => convertToReaction(provider, reaction)) });
|
||||
}
|
||||
}
|
||||
|
||||
private _reactionHandler?: ReactionHandler;
|
||||
|
||||
get reactionHandler(): ReactionHandler | undefined {
|
||||
return this._reactionHandler;
|
||||
}
|
||||
|
||||
set reactionHandler(handler: ReactionHandler | undefined) {
|
||||
this._reactionHandler = handler;
|
||||
|
||||
this._proxy.$updateCommentControllerFeatures(this.handle, { reactionHandler: !!handler });
|
||||
}
|
||||
|
||||
constructor(
|
||||
_extension: IExtensionDescription,
|
||||
private _extension: IExtensionDescription,
|
||||
private _handle: number,
|
||||
private readonly _commandsConverter: CommandsConverter,
|
||||
private _proxy: MainThreadCommentsShape,
|
||||
private _id: string,
|
||||
private _label: string
|
||||
@@ -752,27 +478,33 @@ class ExtHostCommentController implements vscode.CommentController {
|
||||
}
|
||||
|
||||
createCommentThread(resource: vscode.Uri, range: vscode.Range, comments: vscode.Comment[]): vscode.CommentThread;
|
||||
createCommentThread(id: string, resource: vscode.Uri, range: vscode.Range, comments: vscode.Comment[]): vscode.CommentThread;
|
||||
createCommentThread(arg0: vscode.Uri | string, arg1: vscode.Uri | vscode.Range, arg2: vscode.Range | vscode.Comment[], arg3?: vscode.Comment[]): vscode.CommentThread {
|
||||
if (typeof arg0 === 'string') {
|
||||
const commentThread = new ExtHostCommentThread(this._proxy, this._commandsConverter, this, arg0, arg1 as vscode.Uri, arg2 as vscode.Range, arg3 as vscode.Comment[]);
|
||||
const commentThread = new ExtHostCommentThread(this._proxy, this, arg0, arg1 as vscode.Uri, arg2 as vscode.Range, arg3 as vscode.Comment[], this._extension.identifier);
|
||||
this._threads.set(commentThread.handle, commentThread);
|
||||
return commentThread;
|
||||
} else {
|
||||
const commentThread = new ExtHostCommentThread(this._proxy, this._commandsConverter, this, undefined, arg0 as vscode.Uri, arg1 as vscode.Range, arg2 as vscode.Comment[]);
|
||||
const commentThread = new ExtHostCommentThread(this._proxy, this, undefined, arg0 as vscode.Uri, arg1 as vscode.Range, arg2 as vscode.Comment[], this._extension.identifier);
|
||||
this._threads.set(commentThread.handle, commentThread);
|
||||
return commentThread;
|
||||
}
|
||||
}
|
||||
|
||||
$createCommentThreadTemplate(uriComponents: UriComponents, range: IRange) {
|
||||
const commentThread = new ExtHostCommentThread(this._proxy, this._commandsConverter, this, undefined, URI.revive(uriComponents), extHostTypeConverter.Range.to(range), []);
|
||||
$createCommentThreadTemplate(uriComponents: UriComponents, range: IRange): ExtHostCommentThread {
|
||||
const commentThread = new ExtHostCommentThread(this._proxy, this, undefined, URI.revive(uriComponents), extHostTypeConverter.Range.to(range), [], this._extension.identifier);
|
||||
commentThread.collapsibleState = modes.CommentThreadCollapsibleState.Expanded;
|
||||
this._threads.set(commentThread.handle, commentThread);
|
||||
return commentThread;
|
||||
}
|
||||
|
||||
$deleteCommentThread(threadHandle: number) {
|
||||
$updateCommentThreadTemplate(threadHandle: number, range: IRange): void {
|
||||
let thread = this._threads.get(threadHandle);
|
||||
if (thread) {
|
||||
thread.range = extHostTypeConverter.Range.to(range);
|
||||
}
|
||||
}
|
||||
|
||||
$deleteCommentThread(threadHandle: number): void {
|
||||
let thread = this._threads.get(threadHandle);
|
||||
|
||||
if (thread) {
|
||||
@@ -782,15 +514,7 @@ class ExtHostCommentController implements vscode.CommentController {
|
||||
this._threads.delete(threadHandle);
|
||||
}
|
||||
|
||||
$onCommentWidgetInputChange(uriComponents: UriComponents, range: IRange, input: string) {
|
||||
if (!this.inputBox) {
|
||||
this.inputBox = new ExtHostCommentInputBox(this._proxy, this.handle, URI.revive(uriComponents), extHostTypeConverter.Range.to(range), input);
|
||||
} else {
|
||||
this.inputBox.setInput(URI.revive(uriComponents), extHostTypeConverter.Range.to(range), input);
|
||||
}
|
||||
}
|
||||
|
||||
getCommentThread(handle: number) {
|
||||
getCommentThread(handle: number): ExtHostCommentThread | undefined {
|
||||
return this._threads.get(handle);
|
||||
}
|
||||
|
||||
@@ -803,74 +527,7 @@ class ExtHostCommentController implements vscode.CommentController {
|
||||
}
|
||||
}
|
||||
|
||||
function convertCommentInfo(owner: number, extensionId: ExtensionIdentifier, provider: vscode.DocumentCommentProvider, vscodeCommentInfo: vscode.CommentInfo, commandsConverter: CommandsConverter): modes.CommentInfo {
|
||||
return {
|
||||
extensionId: extensionId.value,
|
||||
threads: vscodeCommentInfo.threads.map(x => convertToCommentThread(extensionId, provider, x, commandsConverter)),
|
||||
commentingRanges: vscodeCommentInfo.commentingRanges ? vscodeCommentInfo.commentingRanges.map(range => extHostTypeConverter.Range.from(range)) : [],
|
||||
draftMode: provider.startDraft && provider.finishDraft ? (vscodeCommentInfo.inDraftMode ? modes.DraftMode.InDraft : modes.DraftMode.NotInDraft) : modes.DraftMode.NotSupported
|
||||
};
|
||||
}
|
||||
|
||||
function convertToCommentThread(extensionId: ExtensionIdentifier, provider: vscode.DocumentCommentProvider | vscode.WorkspaceCommentProvider, vscodeCommentThread: vscode.CommentThread, commandsConverter: CommandsConverter): modes.CommentThread {
|
||||
return {
|
||||
extensionId: extensionId.value,
|
||||
threadId: vscodeCommentThread.id,
|
||||
resource: vscodeCommentThread.resource.toString(),
|
||||
range: extHostTypeConverter.Range.from(vscodeCommentThread.range),
|
||||
comments: vscodeCommentThread.comments.map(comment => convertToComment(provider, comment as vscode.Comment, commandsConverter)),
|
||||
collapsibleState: vscodeCommentThread.collapsibleState
|
||||
};
|
||||
}
|
||||
|
||||
function convertFromCommentThread(commentThread: modes.CommentThread): vscode.CommentThread {
|
||||
return {
|
||||
id: commentThread.threadId!,
|
||||
threadId: commentThread.threadId!,
|
||||
uri: URI.parse(commentThread.resource!),
|
||||
resource: URI.parse(commentThread.resource!),
|
||||
range: extHostTypeConverter.Range.to(commentThread.range),
|
||||
comments: commentThread.comments ? commentThread.comments.map(convertFromComment) : [],
|
||||
collapsibleState: commentThread.collapsibleState,
|
||||
dispose: () => { }
|
||||
} as vscode.CommentThread;
|
||||
}
|
||||
|
||||
function convertFromComment(comment: modes.Comment): vscode.Comment {
|
||||
let userIconPath: URI | undefined;
|
||||
if (comment.userIconPath) {
|
||||
try {
|
||||
userIconPath = URI.parse(comment.userIconPath);
|
||||
} catch (e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
id: comment.commentId,
|
||||
commentId: comment.commentId,
|
||||
body: extHostTypeConverter.MarkdownString.to(comment.body),
|
||||
author: {
|
||||
name: comment.userName,
|
||||
iconPath: userIconPath
|
||||
},
|
||||
userName: comment.userName,
|
||||
userIconPath: userIconPath,
|
||||
canEdit: comment.canEdit,
|
||||
canDelete: comment.canDelete,
|
||||
isDraft: comment.isDraft,
|
||||
commentReactions: comment.commentReactions ? comment.commentReactions.map(reaction => {
|
||||
return {
|
||||
label: reaction.label,
|
||||
count: reaction.count,
|
||||
hasReacted: reaction.hasReacted
|
||||
};
|
||||
}) : undefined,
|
||||
mode: comment.mode ? comment.mode : modes.CommentMode.Preview
|
||||
};
|
||||
}
|
||||
|
||||
function convertToModeComment2(thread: ExtHostCommentThread, commentController: ExtHostCommentController, vscodeComment: vscode.Comment, commandsConverter: CommandsConverter, commentsMap: Map<vscode.Comment, number>): modes.Comment {
|
||||
function convertToModeComment(thread: ExtHostCommentThread, commentController: ExtHostCommentController, vscodeComment: vscode.Comment, commentsMap: Map<vscode.Comment, number>): modes.Comment {
|
||||
let commentUniqueId = commentsMap.get(vscodeComment)!;
|
||||
if (!commentUniqueId) {
|
||||
commentUniqueId = ++thread.commentHandle;
|
||||
@@ -880,54 +537,19 @@ function convertToModeComment2(thread: ExtHostCommentThread, commentController:
|
||||
const iconPath = vscodeComment.author && vscodeComment.author.iconPath ? vscodeComment.author.iconPath.toString() : undefined;
|
||||
|
||||
return {
|
||||
commentId: vscodeComment.id || vscodeComment.commentId,
|
||||
commentId: vscodeComment.commentId,
|
||||
mode: vscodeComment.mode,
|
||||
contextValue: vscodeComment.contextValue,
|
||||
uniqueIdInThread: commentUniqueId,
|
||||
body: extHostTypeConverter.MarkdownString.from(vscodeComment.body),
|
||||
userName: vscodeComment.author ? vscodeComment.author.name : vscodeComment.userName,
|
||||
userName: vscodeComment.author.name,
|
||||
userIconPath: iconPath,
|
||||
isDraft: vscodeComment.isDraft,
|
||||
selectCommand: vscodeComment.selectCommand ? commandsConverter.toInternal(vscodeComment.selectCommand) : undefined,
|
||||
editCommand: vscodeComment.editCommand ? commandsConverter.toInternal(vscodeComment.editCommand) : undefined,
|
||||
deleteCommand: vscodeComment.deleteCommand ? commandsConverter.toInternal(vscodeComment.deleteCommand) : undefined,
|
||||
label: vscodeComment.label,
|
||||
commentReactions: vscodeComment.commentReactions ? vscodeComment.commentReactions.map(reaction => convertToReaction2(commentController.reactionProvider, reaction)) : undefined
|
||||
commentReactions: vscodeComment.reactions ? vscodeComment.reactions.map(reaction => convertToReaction(commentController.reactionProvider, reaction)) : undefined
|
||||
};
|
||||
}
|
||||
|
||||
function convertToComment(provider: vscode.DocumentCommentProvider | vscode.WorkspaceCommentProvider, vscodeComment: vscode.Comment, commandsConverter: CommandsConverter): modes.Comment {
|
||||
const canEdit = !!(provider as vscode.DocumentCommentProvider).editComment && vscodeComment.canEdit;
|
||||
const canDelete = !!(provider as vscode.DocumentCommentProvider).deleteComment && vscodeComment.canDelete;
|
||||
const iconPath = vscodeComment.userIconPath ? vscodeComment.userIconPath.toString() : vscodeComment.gravatar;
|
||||
|
||||
return {
|
||||
commentId: vscodeComment.commentId,
|
||||
body: extHostTypeConverter.MarkdownString.from(vscodeComment.body),
|
||||
userName: vscodeComment.userName,
|
||||
userIconPath: iconPath,
|
||||
canEdit: canEdit,
|
||||
canDelete: canDelete,
|
||||
selectCommand: vscodeComment.command ? commandsConverter.toInternal(vscodeComment.command) : undefined,
|
||||
isDraft: vscodeComment.isDraft,
|
||||
commentReactions: vscodeComment.commentReactions ? vscodeComment.commentReactions.map(reaction => convertToReaction(provider, reaction)) : undefined
|
||||
};
|
||||
}
|
||||
|
||||
function convertToReaction(provider: vscode.DocumentCommentProvider | vscode.WorkspaceCommentProvider, reaction: vscode.CommentReaction): modes.CommentReaction {
|
||||
const providerCanDeleteReaction = !!(provider as vscode.DocumentCommentProvider).deleteReaction;
|
||||
const providerCanAddReaction = !!(provider as vscode.DocumentCommentProvider).addReaction;
|
||||
|
||||
return {
|
||||
label: reaction.label,
|
||||
iconPath: reaction.iconPath ? extHostTypeConverter.pathOrURIToURI(reaction.iconPath) : undefined,
|
||||
count: reaction.count,
|
||||
hasReacted: reaction.hasReacted,
|
||||
canEdit: (reaction.hasReacted && providerCanDeleteReaction) || (!reaction.hasReacted && providerCanAddReaction)
|
||||
};
|
||||
}
|
||||
|
||||
function convertToReaction2(provider: vscode.CommentReactionProvider | undefined, reaction: vscode.CommentReaction): modes.CommentReaction {
|
||||
function convertToReaction(provider: vscode.CommentReactionProvider | undefined, reaction: vscode.CommentReaction): modes.CommentReaction {
|
||||
return {
|
||||
label: reaction.label,
|
||||
iconPath: reaction.iconPath ? extHostTypeConverter.pathOrURIToURI(reaction.iconPath) : undefined,
|
||||
@@ -939,9 +561,11 @@ function convertToReaction2(provider: vscode.CommentReactionProvider | undefined
|
||||
|
||||
function convertFromReaction(reaction: modes.CommentReaction): vscode.CommentReaction {
|
||||
return {
|
||||
label: reaction.label,
|
||||
count: reaction.count,
|
||||
hasReacted: reaction.hasReacted
|
||||
label: reaction.label || '',
|
||||
count: reaction.count || 0,
|
||||
iconPath: reaction.iconPath ? URI.revive(reaction.iconPath) : '',
|
||||
hasReacted: reaction.hasReacted,
|
||||
authorHasReacted: reaction.hasReacted || false
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -71,14 +71,14 @@ export class ExtHostConfigProvider {
|
||||
private readonly _onDidChangeConfiguration = new Emitter<vscode.ConfigurationChangeEvent>();
|
||||
private readonly _proxy: MainThreadConfigurationShape;
|
||||
private readonly _extHostWorkspace: ExtHostWorkspace;
|
||||
private _configurationScopes: { [key: string]: ConfigurationScope };
|
||||
private _configurationScopes: Map<string, ConfigurationScope | undefined>;
|
||||
private _configuration: Configuration;
|
||||
|
||||
constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace, data: IConfigurationInitData) {
|
||||
this._proxy = proxy;
|
||||
this._extHostWorkspace = extHostWorkspace;
|
||||
this._configuration = ExtHostConfigProvider.parse(data);
|
||||
this._configurationScopes = data.configurationScopes;
|
||||
this._configurationScopes = this._toMap(data.configurationScopes);
|
||||
}
|
||||
|
||||
get onDidChangeConfiguration(): Event<vscode.ConfigurationChangeEvent> {
|
||||
@@ -87,7 +87,7 @@ export class ExtHostConfigProvider {
|
||||
|
||||
$acceptConfigurationChanged(data: IConfigurationInitData, eventData: IWorkspaceConfigurationChangeEventData) {
|
||||
this._configuration = ExtHostConfigProvider.parse(data);
|
||||
this._configurationScopes = data.configurationScopes;
|
||||
this._configurationScopes = this._toMap(data.configurationScopes);
|
||||
this._onDidChangeConfiguration.fire(this._toConfigurationChangeEvent(eventData));
|
||||
}
|
||||
|
||||
@@ -225,7 +225,7 @@ export class ExtHostConfigProvider {
|
||||
}
|
||||
|
||||
private _validateConfigurationAccess(key: string, resource: URI | undefined, extensionId?: ExtensionIdentifier): void {
|
||||
const scope = OVERRIDE_PROPERTY_PATTERN.test(key) ? ConfigurationScope.RESOURCE : this._configurationScopes[key];
|
||||
const scope = OVERRIDE_PROPERTY_PATTERN.test(key) ? ConfigurationScope.RESOURCE : this._configurationScopes.get(key);
|
||||
const extensionIdText = extensionId ? `[${extensionId.value}] ` : '';
|
||||
if (ConfigurationScope.RESOURCE === scope) {
|
||||
if (resource === undefined) {
|
||||
@@ -255,6 +255,10 @@ export class ExtHostConfigProvider {
|
||||
});
|
||||
}
|
||||
|
||||
private _toMap(scopes: [string, ConfigurationScope | undefined][]): Map<string, ConfigurationScope | undefined> {
|
||||
return scopes.reduce((result, scope) => { result.set(scope[0], scope[1]); return result; }, new Map<string, ConfigurationScope | undefined>());
|
||||
}
|
||||
|
||||
private static parse(data: IConfigurationData): Configuration {
|
||||
const defaultConfiguration = ExtHostConfigProvider.parseConfigurationModel(data.defaults);
|
||||
const userConfiguration = ExtHostConfigProvider.parseConfigurationModel(data.user);
|
||||
|
||||
@@ -47,9 +47,9 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
set(uri: vscode.Uri, diagnostics: vscode.Diagnostic[]): void;
|
||||
set(entries: [vscode.Uri, vscode.Diagnostic[]][]): void;
|
||||
set(first: vscode.Uri | [vscode.Uri, vscode.Diagnostic[]][], diagnostics?: vscode.Diagnostic[]) {
|
||||
set(uri: vscode.Uri, diagnostics: ReadonlyArray<vscode.Diagnostic>): void;
|
||||
set(entries: ReadonlyArray<[vscode.Uri, ReadonlyArray<vscode.Diagnostic>]>): void;
|
||||
set(first: vscode.Uri | ReadonlyArray<[vscode.Uri, ReadonlyArray<vscode.Diagnostic>]>, diagnostics?: ReadonlyArray<vscode.Diagnostic>) {
|
||||
|
||||
if (!first) {
|
||||
// this set-call is a clear-call
|
||||
@@ -167,7 +167,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
|
||||
this._proxy.$clear(this._owner);
|
||||
}
|
||||
|
||||
forEach(callback: (uri: URI, diagnostics: vscode.Diagnostic[], collection: DiagnosticCollection) => any, thisArg?: any): void {
|
||||
forEach(callback: (uri: URI, diagnostics: ReadonlyArray<vscode.Diagnostic>, collection: DiagnosticCollection) => any, thisArg?: any): void {
|
||||
this._checkDisposed();
|
||||
this._data.forEach((value, key) => {
|
||||
const uri = URI.parse(key);
|
||||
@@ -175,11 +175,11 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
|
||||
});
|
||||
}
|
||||
|
||||
get(uri: URI): vscode.Diagnostic[] {
|
||||
get(uri: URI): ReadonlyArray<vscode.Diagnostic> {
|
||||
this._checkDisposed();
|
||||
const result = this._data.get(uri.toString());
|
||||
if (Array.isArray(result)) {
|
||||
return <vscode.Diagnostic[]>Object.freeze(result.slice(0));
|
||||
return <ReadonlyArray<vscode.Diagnostic>>Object.freeze(result.slice(0));
|
||||
}
|
||||
return [];
|
||||
}
|
||||
@@ -278,10 +278,10 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
|
||||
return result;
|
||||
}
|
||||
|
||||
getDiagnostics(resource: vscode.Uri): vscode.Diagnostic[];
|
||||
getDiagnostics(): [vscode.Uri, vscode.Diagnostic[]][];
|
||||
getDiagnostics(resource?: vscode.Uri): vscode.Diagnostic[] | [vscode.Uri, vscode.Diagnostic[]][];
|
||||
getDiagnostics(resource?: vscode.Uri): vscode.Diagnostic[] | [vscode.Uri, vscode.Diagnostic[]][] {
|
||||
getDiagnostics(resource: vscode.Uri): ReadonlyArray<vscode.Diagnostic>;
|
||||
getDiagnostics(): ReadonlyArray<[vscode.Uri, ReadonlyArray<vscode.Diagnostic>]>;
|
||||
getDiagnostics(resource?: vscode.Uri): ReadonlyArray<vscode.Diagnostic> | ReadonlyArray<[vscode.Uri, ReadonlyArray<vscode.Diagnostic>]>;
|
||||
getDiagnostics(resource?: vscode.Uri): ReadonlyArray<vscode.Diagnostic> | ReadonlyArray<[vscode.Uri, ReadonlyArray<vscode.Diagnostic>]> {
|
||||
if (resource) {
|
||||
return this._getDiagnostics(resource);
|
||||
} else {
|
||||
@@ -302,7 +302,7 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
|
||||
}
|
||||
}
|
||||
|
||||
private _getDiagnostics(resource: vscode.Uri): vscode.Diagnostic[] {
|
||||
private _getDiagnostics(resource: vscode.Uri): ReadonlyArray<vscode.Diagnostic> {
|
||||
let res: vscode.Diagnostic[] = [];
|
||||
this._collections.forEach(collection => {
|
||||
if (collection.has(resource)) {
|
||||
|
||||
@@ -29,14 +29,10 @@ export class ExtHostDocumentContentProvider implements ExtHostDocumentContentPro
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadDocumentContentProviders);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
// todo@joh
|
||||
}
|
||||
|
||||
registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider): vscode.Disposable {
|
||||
// todo@remote
|
||||
// check with scheme from fs-providers!
|
||||
if (scheme === Schemas.file || scheme === Schemas.untitled) {
|
||||
if (Object.keys(Schemas).indexOf(scheme) >= 0) {
|
||||
throw new Error(`scheme '${scheme}' already registered`);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { IModelChangedEvent } from 'vs/editor/common/model/mirrorTextModel';
|
||||
import { ExtHostDocumentsShape, IMainContext, MainContext, MainThreadDocumentsShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
@@ -25,7 +25,7 @@ export class ExtHostDocuments implements ExtHostDocumentsShape {
|
||||
readonly onDidChangeDocument: Event<vscode.TextDocumentChangeEvent> = this._onDidChangeDocument.event;
|
||||
readonly onDidSaveDocument: Event<vscode.TextDocument> = this._onDidSaveDocument.event;
|
||||
|
||||
private _toDispose: IDisposable[];
|
||||
private readonly _toDispose = new DisposableStore();
|
||||
private _proxy: MainThreadDocumentsShape;
|
||||
private _documentsAndEditors: ExtHostDocumentsAndEditors;
|
||||
private _documentLoader = new Map<string, Promise<ExtHostDocumentData>>();
|
||||
@@ -34,22 +34,20 @@ export class ExtHostDocuments implements ExtHostDocumentsShape {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadDocuments);
|
||||
this._documentsAndEditors = documentsAndEditors;
|
||||
|
||||
this._toDispose = [
|
||||
this._documentsAndEditors.onDidRemoveDocuments(documents => {
|
||||
for (const data of documents) {
|
||||
this._onDidRemoveDocument.fire(data.document);
|
||||
}
|
||||
}),
|
||||
this._documentsAndEditors.onDidAddDocuments(documents => {
|
||||
for (const data of documents) {
|
||||
this._onDidAddDocument.fire(data.document);
|
||||
}
|
||||
})
|
||||
];
|
||||
this._documentsAndEditors.onDidRemoveDocuments(documents => {
|
||||
for (const data of documents) {
|
||||
this._onDidRemoveDocument.fire(data.document);
|
||||
}
|
||||
}, undefined, this._toDispose);
|
||||
this._documentsAndEditors.onDidAddDocuments(documents => {
|
||||
for (const data of documents) {
|
||||
this._onDidAddDocument.fire(data.document);
|
||||
}
|
||||
}, undefined, this._toDispose);
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
dispose(this._toDispose);
|
||||
this._toDispose.dispose();
|
||||
}
|
||||
|
||||
public getAllDocumentData(): ExtHostDocumentData[] {
|
||||
|
||||
@@ -12,8 +12,9 @@ import { ExtensionActivationError, MissingDependencyError } from 'vs/workbench/s
|
||||
const NO_OP_VOID_PROMISE = Promise.resolve<void>(undefined);
|
||||
|
||||
export interface IExtensionMemento {
|
||||
get<T>(key: string): T | undefined;
|
||||
get<T>(key: string, defaultValue: T): T;
|
||||
update(key: string, value: any): Promise<boolean>;
|
||||
update(key: string, value: any): Promise<void>;
|
||||
}
|
||||
|
||||
export interface IExtensionContext {
|
||||
@@ -43,14 +44,13 @@ export interface IExtensionAPI {
|
||||
// _extensionAPIBrand: any;
|
||||
}
|
||||
|
||||
/* __GDPR__FRAGMENT__
|
||||
"ExtensionActivationTimes" : {
|
||||
"startup": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true },
|
||||
"codeLoadingTime" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true },
|
||||
"activateCallTime" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true },
|
||||
"activateResolvedTime" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }
|
||||
}
|
||||
*/
|
||||
export type ExtensionActivationTimesFragment = {
|
||||
startup?: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
codeLoadingTime?: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
activateCallTime?: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
activateResolvedTime?: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
};
|
||||
|
||||
export class ExtensionActivationTimes {
|
||||
|
||||
public static readonly NONE = new ExtensionActivationTimes(false, -1, -1, -1);
|
||||
|
||||
@@ -8,11 +8,10 @@ import { MainContext, IMainContext, ExtHostFileSystemShape, MainThreadFileSystem
|
||||
import * as vscode from 'vscode';
|
||||
import * as files from 'vs/platform/files/common/files';
|
||||
import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { FileChangeType } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { FileChangeType, FileSystemError } from 'vs/workbench/api/common/extHostTypes';
|
||||
import * as typeConverter from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { ExtHostLanguageFeatures } from 'vs/workbench/api/common/extHostLanguageFeatures';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { ResourceLabelFormatter } from 'vs/platform/label/common/label';
|
||||
import { State, StateMachine, LinkComputer, Edge } from 'vs/editor/common/modes/linkComputer';
|
||||
import { commonPrefixLength } from 'vs/base/common/strings';
|
||||
import { CharCode } from 'vs/base/common/charCode';
|
||||
@@ -104,6 +103,50 @@ class FsLinkProvider {
|
||||
}
|
||||
}
|
||||
|
||||
class ConsumerFileSystem implements vscode.FileSystem {
|
||||
|
||||
constructor(private _proxy: MainThreadFileSystemShape) { }
|
||||
|
||||
stat(uri: vscode.Uri): Promise<vscode.FileStat> {
|
||||
return this._proxy.$stat(uri).catch(ConsumerFileSystem._handleError);
|
||||
}
|
||||
readDirectory(uri: vscode.Uri): Promise<[string, vscode.FileType][]> {
|
||||
return this._proxy.$readdir(uri).catch(ConsumerFileSystem._handleError);
|
||||
}
|
||||
createDirectory(uri: vscode.Uri): Promise<void> {
|
||||
return this._proxy.$mkdir(uri).catch(ConsumerFileSystem._handleError);
|
||||
}
|
||||
async readFile(uri: vscode.Uri): Promise<Uint8Array> {
|
||||
return this._proxy.$readFile(uri).then(buff => buff.buffer).catch(ConsumerFileSystem._handleError);
|
||||
}
|
||||
writeFile(uri: vscode.Uri, content: Uint8Array): Promise<void> {
|
||||
return this._proxy.$writeFile(uri, VSBuffer.wrap(content)).catch(ConsumerFileSystem._handleError);
|
||||
}
|
||||
delete(uri: vscode.Uri, options?: { recursive?: boolean; useTrash?: boolean; }): Promise<void> {
|
||||
return this._proxy.$delete(uri, { ...{ recursive: false, useTrash: false }, ...options }).catch(ConsumerFileSystem._handleError);
|
||||
}
|
||||
rename(oldUri: vscode.Uri, newUri: vscode.Uri, options?: { overwrite?: boolean; }): Promise<void> {
|
||||
return this._proxy.$rename(oldUri, newUri, { ...{ overwrite: false }, ...options }).catch(ConsumerFileSystem._handleError);
|
||||
}
|
||||
copy(source: vscode.Uri, destination: vscode.Uri, options?: { overwrite?: boolean }): Promise<void> {
|
||||
return this._proxy.$copy(source, destination, { ...{ overwrite: false }, ...options }).catch(ConsumerFileSystem._handleError);
|
||||
}
|
||||
private static _handleError(err: any): never {
|
||||
// generic error
|
||||
if (!(err instanceof Error)) {
|
||||
throw new FileSystemError(String(err));
|
||||
}
|
||||
|
||||
// no provider (unknown scheme) error
|
||||
if (err.name === 'ENOPRO') {
|
||||
throw FileSystemError.Unavailable(err.message);
|
||||
}
|
||||
|
||||
// file system error
|
||||
throw new FileSystemError(err.message, err.name as files.FileSystemProviderErrorCode);
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
|
||||
private readonly _proxy: MainThreadFileSystemShape;
|
||||
@@ -113,21 +156,16 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
private readonly _watches = new Map<number, IDisposable>();
|
||||
|
||||
private _linkProviderRegistration: IDisposable;
|
||||
// Used as a handle both for file system providers and resource label formatters (being lazy)
|
||||
private _handlePool: number = 0;
|
||||
|
||||
readonly fileSystem: vscode.FileSystem;
|
||||
|
||||
constructor(mainContext: IMainContext, private _extHostLanguageFeatures: ExtHostLanguageFeatures) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadFileSystem);
|
||||
this._usedSchemes.add(Schemas.file);
|
||||
this._usedSchemes.add(Schemas.untitled);
|
||||
this._usedSchemes.add(Schemas.vscode);
|
||||
this._usedSchemes.add(Schemas.inMemory);
|
||||
this._usedSchemes.add(Schemas.internal);
|
||||
this._usedSchemes.add(Schemas.http);
|
||||
this._usedSchemes.add(Schemas.https);
|
||||
this._usedSchemes.add(Schemas.mailto);
|
||||
this._usedSchemes.add(Schemas.data);
|
||||
this._usedSchemes.add(Schemas.command);
|
||||
this.fileSystem = new ConsumerFileSystem(this._proxy);
|
||||
|
||||
// register used schemes
|
||||
Object.keys(Schemas).forEach(scheme => this._usedSchemes.add(scheme));
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
@@ -154,23 +192,23 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
this._usedSchemes.add(scheme);
|
||||
this._fsProvider.set(handle, provider);
|
||||
|
||||
let capabilites = files.FileSystemProviderCapabilities.FileReadWrite;
|
||||
let capabilities = files.FileSystemProviderCapabilities.FileReadWrite;
|
||||
if (options.isCaseSensitive) {
|
||||
capabilites += files.FileSystemProviderCapabilities.PathCaseSensitive;
|
||||
capabilities += files.FileSystemProviderCapabilities.PathCaseSensitive;
|
||||
}
|
||||
if (options.isReadonly) {
|
||||
capabilites += files.FileSystemProviderCapabilities.Readonly;
|
||||
capabilities += files.FileSystemProviderCapabilities.Readonly;
|
||||
}
|
||||
if (typeof provider.copy === 'function') {
|
||||
capabilites += files.FileSystemProviderCapabilities.FileFolderCopy;
|
||||
capabilities += files.FileSystemProviderCapabilities.FileFolderCopy;
|
||||
}
|
||||
if (typeof provider.open === 'function' && typeof provider.close === 'function'
|
||||
&& typeof provider.read === 'function' && typeof provider.write === 'function'
|
||||
) {
|
||||
capabilites += files.FileSystemProviderCapabilities.FileOpenReadWriteClose;
|
||||
capabilities += files.FileSystemProviderCapabilities.FileOpenReadWriteClose;
|
||||
}
|
||||
|
||||
this._proxy.$registerFileSystemProvider(handle, scheme, capabilites);
|
||||
this._proxy.$registerFileSystemProvider(handle, scheme, capabilities);
|
||||
|
||||
const subscription = provider.onDidChangeFile(event => {
|
||||
const mapped: IFileChangeDto[] = [];
|
||||
@@ -208,46 +246,37 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
});
|
||||
}
|
||||
|
||||
registerResourceLabelFormatter(formatter: ResourceLabelFormatter): IDisposable {
|
||||
const handle = this._handlePool++;
|
||||
this._proxy.$registerResourceLabelFormatter(handle, formatter);
|
||||
|
||||
return toDisposable(() => {
|
||||
this._proxy.$unregisterResourceLabelFormatter(handle);
|
||||
});
|
||||
}
|
||||
|
||||
private static _asIStat(stat: vscode.FileStat): files.IStat {
|
||||
const { type, ctime, mtime, size } = stat;
|
||||
return { type, ctime, mtime, size };
|
||||
}
|
||||
|
||||
$stat(handle: number, resource: UriComponents): Promise<files.IStat> {
|
||||
return Promise.resolve(this.getProvider(handle).stat(URI.revive(resource))).then(ExtHostFileSystem._asIStat);
|
||||
return Promise.resolve(this._getFsProvider(handle).stat(URI.revive(resource))).then(ExtHostFileSystem._asIStat);
|
||||
}
|
||||
|
||||
$readdir(handle: number, resource: UriComponents): Promise<[string, files.FileType][]> {
|
||||
return Promise.resolve(this.getProvider(handle).readDirectory(URI.revive(resource)));
|
||||
return Promise.resolve(this._getFsProvider(handle).readDirectory(URI.revive(resource)));
|
||||
}
|
||||
|
||||
$readFile(handle: number, resource: UriComponents): Promise<VSBuffer> {
|
||||
return Promise.resolve(this.getProvider(handle).readFile(URI.revive(resource))).then(data => VSBuffer.wrap(data));
|
||||
return Promise.resolve(this._getFsProvider(handle).readFile(URI.revive(resource))).then(data => VSBuffer.wrap(data));
|
||||
}
|
||||
|
||||
$writeFile(handle: number, resource: UriComponents, content: VSBuffer, opts: files.FileWriteOptions): Promise<void> {
|
||||
return Promise.resolve(this.getProvider(handle).writeFile(URI.revive(resource), content.buffer, opts));
|
||||
return Promise.resolve(this._getFsProvider(handle).writeFile(URI.revive(resource), content.buffer, opts));
|
||||
}
|
||||
|
||||
$delete(handle: number, resource: UriComponents, opts: files.FileDeleteOptions): Promise<void> {
|
||||
return Promise.resolve(this.getProvider(handle).delete(URI.revive(resource), opts));
|
||||
return Promise.resolve(this._getFsProvider(handle).delete(URI.revive(resource), opts));
|
||||
}
|
||||
|
||||
$rename(handle: number, oldUri: UriComponents, newUri: UriComponents, opts: files.FileOverwriteOptions): Promise<void> {
|
||||
return Promise.resolve(this.getProvider(handle).rename(URI.revive(oldUri), URI.revive(newUri), opts));
|
||||
return Promise.resolve(this._getFsProvider(handle).rename(URI.revive(oldUri), URI.revive(newUri), opts));
|
||||
}
|
||||
|
||||
$copy(handle: number, oldUri: UriComponents, newUri: UriComponents, opts: files.FileOverwriteOptions): Promise<void> {
|
||||
const provider = this.getProvider(handle);
|
||||
const provider = this._getFsProvider(handle);
|
||||
if (!provider.copy) {
|
||||
throw new Error('FileSystemProvider does not implement "copy"');
|
||||
}
|
||||
@@ -255,11 +284,11 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
}
|
||||
|
||||
$mkdir(handle: number, resource: UriComponents): Promise<void> {
|
||||
return Promise.resolve(this.getProvider(handle).createDirectory(URI.revive(resource)));
|
||||
return Promise.resolve(this._getFsProvider(handle).createDirectory(URI.revive(resource)));
|
||||
}
|
||||
|
||||
$watch(handle: number, session: number, resource: UriComponents, opts: files.IWatchOptions): void {
|
||||
const subscription = this.getProvider(handle).watch(URI.revive(resource), opts);
|
||||
const subscription = this._getFsProvider(handle).watch(URI.revive(resource), opts);
|
||||
this._watches.set(session, subscription);
|
||||
}
|
||||
|
||||
@@ -272,7 +301,7 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
}
|
||||
|
||||
$open(handle: number, resource: UriComponents, opts: files.FileOpenOptions): Promise<number> {
|
||||
const provider = this.getProvider(handle);
|
||||
const provider = this._getFsProvider(handle);
|
||||
if (!provider.open) {
|
||||
throw new Error('FileSystemProvider does not implement "open"');
|
||||
}
|
||||
@@ -280,7 +309,7 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
}
|
||||
|
||||
$close(handle: number, fd: number): Promise<void> {
|
||||
const provider = this.getProvider(handle);
|
||||
const provider = this._getFsProvider(handle);
|
||||
if (!provider.close) {
|
||||
throw new Error('FileSystemProvider does not implement "close"');
|
||||
}
|
||||
@@ -288,7 +317,7 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
}
|
||||
|
||||
$read(handle: number, fd: number, pos: number, length: number): Promise<VSBuffer> {
|
||||
const provider = this.getProvider(handle);
|
||||
const provider = this._getFsProvider(handle);
|
||||
if (!provider.read) {
|
||||
throw new Error('FileSystemProvider does not implement "read"');
|
||||
}
|
||||
@@ -299,14 +328,14 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
}
|
||||
|
||||
$write(handle: number, fd: number, pos: number, data: VSBuffer): Promise<number> {
|
||||
const provider = this.getProvider(handle);
|
||||
const provider = this._getFsProvider(handle);
|
||||
if (!provider.write) {
|
||||
throw new Error('FileSystemProvider does not implement "write"');
|
||||
}
|
||||
return Promise.resolve(provider.write(fd, pos, data.buffer, 0, data.byteLength));
|
||||
}
|
||||
|
||||
private getProvider(handle: number): vscode.FileSystemProvider {
|
||||
private _getFsProvider(handle: number): vscode.FileSystemProvider {
|
||||
const provider = this._fsProvider.get(handle);
|
||||
if (!provider) {
|
||||
const err = new Error();
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ExtHostHeapServiceShape } from './extHost.protocol';
|
||||
|
||||
export class ExtHostHeapService implements ExtHostHeapServiceShape {
|
||||
|
||||
private static _idPool = 0;
|
||||
|
||||
private _data = new Map<number, any>();
|
||||
|
||||
keep(obj: any): number {
|
||||
const id = ExtHostHeapService._idPool++;
|
||||
this._data.set(id, obj);
|
||||
return id;
|
||||
}
|
||||
|
||||
delete(id: number): boolean {
|
||||
return this._data.delete(id);
|
||||
}
|
||||
|
||||
get<T>(id: number): T {
|
||||
return this._data.get(id);
|
||||
}
|
||||
|
||||
$onGarbageCollection(ids: number[]): void {
|
||||
for (const id of ids) {
|
||||
this.delete(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
src/vs/workbench/api/common/extHostLabelService.ts
Normal file
27
src/vs/workbench/api/common/extHostLabelService.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ResourceLabelFormatter } from 'vs/platform/label/common/label';
|
||||
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { MainThreadLabelServiceShape, ExtHostLabelServiceShape, MainContext, IMainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
|
||||
export class ExtHostLabelService implements ExtHostLabelServiceShape {
|
||||
|
||||
private readonly _proxy: MainThreadLabelServiceShape;
|
||||
private _handlePool: number = 0;
|
||||
|
||||
constructor(mainContext: IMainContext) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadLabelService);
|
||||
}
|
||||
|
||||
$registerResourceLabelFormatter(formatter: ResourceLabelFormatter): IDisposable {
|
||||
const handle = this._handlePool++;
|
||||
this._proxy.$registerResourceLabelFormatter(handle, formatter);
|
||||
|
||||
return toDisposable(() => {
|
||||
this._proxy.$unregisterResourceLabelFormatter(handle);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -10,12 +10,11 @@ import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, DocumentSymbol } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { ISingleEditOperation } from 'vs/editor/common/model';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { ExtHostHeapService } from 'vs/workbench/api/common/extHostHeapService';
|
||||
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, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, WorkspaceSymbolDto, SuggestResultDto, WorkspaceSymbolsDto, CodeActionDto, ISerializedDocumentFilter, WorkspaceEditDto, ISerializedSignatureHelpProviderMetadata, LinkDto, CodeLensDto, MainThreadWebviewsShape, CodeInsetDto, SuggestDataDto, LinksListDto, ChainedCacheId } from './extHost.protocol';
|
||||
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 { 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';
|
||||
@@ -25,11 +24,10 @@ import { ISelection, Selection } from 'vs/editor/common/core/selection';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { ExtHostWebview } from 'vs/workbench/api/common/extHostWebview';
|
||||
import * as codeInset from 'vs/workbench/contrib/codeinset/common/codeInset';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import * as callHierarchy from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
|
||||
import { LRUCache } from 'vs/base/common/map';
|
||||
import { IURITransformer } from 'vs/base/common/uriIpc';
|
||||
import { DisposableStore, dispose } from 'vs/base/common/lifecycle';
|
||||
|
||||
// --- adapter
|
||||
|
||||
@@ -104,34 +102,48 @@ class CodeLensAdapter {
|
||||
|
||||
private static _badCmd: vscode.Command = { command: 'missing', title: '!!MISSING: command!!' };
|
||||
|
||||
private readonly _cache = new Cache<vscode.CodeLens>('CodeLens');
|
||||
private readonly _disposables = new Map<number, DisposableStore>();
|
||||
|
||||
constructor(
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
private readonly _commands: CommandsConverter,
|
||||
private readonly _heapService: ExtHostHeapService,
|
||||
private readonly _provider: vscode.CodeLensProvider
|
||||
) { }
|
||||
|
||||
provideCodeLenses(resource: URI, token: CancellationToken): Promise<CodeLensDto[]> {
|
||||
provideCodeLenses(resource: URI, token: CancellationToken): Promise<CodeLensListDto | undefined> {
|
||||
const doc = this._documents.getDocument(resource);
|
||||
|
||||
return asPromise(() => this._provider.provideCodeLenses(doc, token)).then(lenses => {
|
||||
const result: CodeLensDto[] = [];
|
||||
if (isNonEmptyArray(lenses)) {
|
||||
for (const lens of lenses) {
|
||||
const id = this._heapService.keep(lens);
|
||||
result.push(ObjectIdentifier.mixin({
|
||||
range: typeConvert.Range.from(lens.range),
|
||||
command: this._commands.toInternal(lens.command)
|
||||
}, id));
|
||||
}
|
||||
|
||||
if (!lenses || token.isCancellationRequested) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const cacheId = this._cache.add(lenses);
|
||||
const disposables = new DisposableStore();
|
||||
this._disposables.set(cacheId, disposables);
|
||||
|
||||
const result: CodeLensListDto = {
|
||||
cacheId,
|
||||
lenses: [],
|
||||
};
|
||||
|
||||
for (let i = 0; i < lenses.length; i++) {
|
||||
result.lenses.push({
|
||||
cacheId: [cacheId, i],
|
||||
range: typeConvert.Range.from(lenses[i].range),
|
||||
command: this._commands.toInternal(lenses[i].command, disposables)
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
resolveCodeLens(symbol: CodeLensDto, token: CancellationToken): Promise<CodeLensDto | undefined> {
|
||||
|
||||
const lens = this._heapService.get<vscode.CodeLens>(ObjectIdentifier.of(symbol));
|
||||
const lens = symbol.cacheId && this._cache.get(...symbol.cacheId);
|
||||
if (!lens) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
@@ -144,51 +156,26 @@ class CodeLensAdapter {
|
||||
}
|
||||
|
||||
return resolve.then(newLens => {
|
||||
newLens = newLens || lens;
|
||||
symbol.command = this._commands.toInternal(newLens.command || CodeLensAdapter._badCmd);
|
||||
return symbol;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class CodeInsetAdapter {
|
||||
|
||||
constructor(
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
private readonly _heapService: ExtHostHeapService,
|
||||
private readonly _provider: vscode.CodeInsetProvider
|
||||
) { }
|
||||
|
||||
provideCodeInsets(resource: URI, token: CancellationToken): Promise<CodeInsetDto[] | undefined> {
|
||||
const doc = this._documents.getDocument(resource);
|
||||
return asPromise(() => this._provider.provideCodeInsets(doc, token)).then(insets => {
|
||||
if (Array.isArray(insets)) {
|
||||
return insets.map(inset => {
|
||||
const $ident = this._heapService.keep(inset);
|
||||
const id = generateUuid();
|
||||
return {
|
||||
$ident,
|
||||
id,
|
||||
range: typeConvert.Range.from(inset.range),
|
||||
height: inset.height
|
||||
};
|
||||
});
|
||||
if (token.isCancellationRequested) {
|
||||
return undefined;
|
||||
}
|
||||
return undefined;
|
||||
|
||||
const disposables = symbol.cacheId && this._disposables.get(symbol.cacheId[0]);
|
||||
if (!disposables) {
|
||||
// We've already been disposed of
|
||||
return undefined;
|
||||
}
|
||||
|
||||
newLens = newLens || lens;
|
||||
symbol.command = this._commands.toInternal(newLens.command || CodeLensAdapter._badCmd, disposables);
|
||||
return symbol;
|
||||
});
|
||||
}
|
||||
|
||||
resolveCodeInset(symbol: CodeInsetDto, webview: vscode.Webview, token: CancellationToken): Promise<CodeInsetDto> {
|
||||
|
||||
const inset = this._heapService.get<vscode.CodeInset>(ObjectIdentifier.of(symbol));
|
||||
if (!inset) {
|
||||
return Promise.resolve(symbol);
|
||||
}
|
||||
|
||||
return asPromise(() => this._provider.resolveCodeInset(inset, webview, token)).then(newInset => {
|
||||
newInset = newInset || inset;
|
||||
return symbol;
|
||||
});
|
||||
releaseCodeLenses(cachedId: number): void {
|
||||
dispose(this._disposables.get(cachedId));
|
||||
this._disposables.delete(cachedId);
|
||||
this._cache.delete(cachedId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,6 +315,9 @@ export interface CustomCodeAction extends CodeActionDto {
|
||||
class CodeActionAdapter {
|
||||
private static readonly _maxCodeActionsPerFile: number = 1000;
|
||||
|
||||
private readonly _cache = new Cache<vscode.CodeAction | vscode.Command>('CodeAction');
|
||||
private readonly _disposables = new Map<number, DisposableStore>();
|
||||
|
||||
constructor(
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
private readonly _commands: CommandsConverter,
|
||||
@@ -337,7 +327,7 @@ class CodeActionAdapter {
|
||||
private readonly _extensionId: ExtensionIdentifier
|
||||
) { }
|
||||
|
||||
provideCodeActions(resource: URI, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<CodeActionDto[] | undefined> {
|
||||
provideCodeActions(resource: URI, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<CodeActionListDto | undefined> {
|
||||
|
||||
const doc = this._documents.getDocument(resource);
|
||||
const ran = Selection.isISelection(rangeOrSelection)
|
||||
@@ -360,34 +350,39 @@ class CodeActionAdapter {
|
||||
};
|
||||
|
||||
return asPromise(() => this._provider.provideCodeActions(doc, ran, codeActionContext, token)).then(commandsOrActions => {
|
||||
if (!isNonEmptyArray(commandsOrActions)) {
|
||||
if (!isNonEmptyArray(commandsOrActions) || token.isCancellationRequested) {
|
||||
return undefined;
|
||||
}
|
||||
const result: CustomCodeAction[] = [];
|
||||
|
||||
const cacheId = this._cache.add(commandsOrActions);
|
||||
const disposables = new DisposableStore();
|
||||
this._disposables.set(cacheId, disposables);
|
||||
|
||||
const actions: CustomCodeAction[] = [];
|
||||
for (const candidate of commandsOrActions) {
|
||||
if (!candidate) {
|
||||
continue;
|
||||
}
|
||||
if (CodeActionAdapter._isCommand(candidate)) {
|
||||
// old school: synthetic code action
|
||||
result.push({
|
||||
actions.push({
|
||||
_isSynthetic: true,
|
||||
title: candidate.title,
|
||||
command: this._commands.toInternal(candidate),
|
||||
command: this._commands.toInternal(candidate, disposables),
|
||||
});
|
||||
} else {
|
||||
if (codeActionContext.only) {
|
||||
if (!candidate.kind) {
|
||||
this._logService.warn(`${this._extensionId.value} - Code actions of kind '${codeActionContext.only.value} 'requested but returned code action does not have a 'kind'. Code action will be dropped. Please set 'CodeAction.kind'.`);
|
||||
} else if (!codeActionContext.only.contains(candidate.kind)) {
|
||||
this._logService.warn(`${this._extensionId.value} -Code actions of kind '${codeActionContext.only.value} 'requested but returned code action is of kind '${candidate.kind.value}'. Code action will be dropped. Please check 'CodeActionContext.only' to only return requested code actions.`);
|
||||
this._logService.warn(`${this._extensionId.value} - Code actions of kind '${codeActionContext.only.value} 'requested but returned code action is of kind '${candidate.kind.value}'. Code action will be dropped. Please check 'CodeActionContext.only' to only return requested code actions.`);
|
||||
}
|
||||
}
|
||||
|
||||
// new school: convert code action
|
||||
result.push({
|
||||
actions.push({
|
||||
title: candidate.title,
|
||||
command: candidate.command && this._commands.toInternal(candidate.command),
|
||||
command: candidate.command && this._commands.toInternal(candidate.command, disposables),
|
||||
diagnostics: candidate.diagnostics && candidate.diagnostics.map(typeConvert.Diagnostic.from),
|
||||
edit: candidate.edit && typeConvert.WorkspaceEdit.from(candidate.edit),
|
||||
kind: candidate.kind && candidate.kind.value,
|
||||
@@ -396,10 +391,16 @@ class CodeActionAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return <CodeActionListDto>{ cacheId, actions };
|
||||
});
|
||||
}
|
||||
|
||||
public releaseCodeActions(cachedId: number): void {
|
||||
dispose(this._disposables.get(cachedId));
|
||||
this._disposables.delete(cachedId);
|
||||
this._cache.delete(cachedId);
|
||||
}
|
||||
|
||||
private static _isCommand(thing: any): thing is vscode.Command {
|
||||
return typeof (<vscode.Command>thing).command === 'string' && typeof (<vscode.Command>thing).title === 'string';
|
||||
}
|
||||
@@ -623,7 +624,8 @@ class SuggestAdapter {
|
||||
private _commands: CommandsConverter;
|
||||
private _provider: vscode.CompletionItemProvider;
|
||||
|
||||
private _cache = new Cache<vscode.CompletionItem>();
|
||||
private _cache = new Cache<vscode.CompletionItem>('CompletionItem');
|
||||
private _disposables = new Map<number, DisposableStore>();
|
||||
|
||||
constructor(documents: ExtHostDocuments, commands: CommandsConverter, provider: vscode.CompletionItemProvider) {
|
||||
this._documents = documents;
|
||||
@@ -643,13 +645,18 @@ class SuggestAdapter {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let list = Array.isArray(value) ? new CompletionList(value) : value;
|
||||
let pid: number | undefined;
|
||||
if (token.isCancellationRequested) {
|
||||
// cancelled -> return without further ado, esp no caching
|
||||
// of results as they will leak
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const list = Array.isArray(value) ? new CompletionList(value) : value;
|
||||
|
||||
// keep result for providers that support resolving
|
||||
if (SuggestAdapter.supportsResolving(this._provider)) {
|
||||
pid = this._cache.add(list.items);
|
||||
}
|
||||
const pid: number = SuggestAdapter.supportsResolving(this._provider) ? this._cache.add(list.items) : this._cache.add([]);
|
||||
const disposables = new DisposableStore();
|
||||
this._disposables.set(pid, disposables);
|
||||
|
||||
// the default text edit range
|
||||
const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) as Range || new Range(pos, pos))
|
||||
@@ -663,7 +670,7 @@ class SuggestAdapter {
|
||||
};
|
||||
|
||||
for (let i = 0; i < list.items.length; i++) {
|
||||
const suggestion = this._convertCompletionItem(list.items[i], pos, pid && [pid, i] || undefined);
|
||||
const suggestion = this._convertCompletionItem(list.items[i], pos, [pid, i]);
|
||||
// check for bad completion item
|
||||
// for the converter did warn
|
||||
if (suggestion) {
|
||||
@@ -698,15 +705,22 @@ class SuggestAdapter {
|
||||
}
|
||||
|
||||
releaseCompletionItems(id: number): any {
|
||||
dispose(this._disposables.get(id));
|
||||
this._disposables.delete(id);
|
||||
this._cache.delete(id);
|
||||
}
|
||||
|
||||
private _convertCompletionItem(item: vscode.CompletionItem, position: vscode.Position, id: ChainedCacheId | undefined): SuggestDataDto | undefined {
|
||||
private _convertCompletionItem(item: vscode.CompletionItem, position: vscode.Position, id: ChainedCacheId): SuggestDataDto | undefined {
|
||||
if (typeof item.label !== 'string' || item.label.length === 0) {
|
||||
console.warn('INVALID text edit -> must have at least a label');
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const disposables = this._disposables.get(id[0]);
|
||||
if (!disposables) {
|
||||
throw Error('DisposableStore is missing...');
|
||||
}
|
||||
|
||||
const result: SuggestDataDto = {
|
||||
//
|
||||
x: id,
|
||||
@@ -721,7 +735,7 @@ class SuggestAdapter {
|
||||
i: item.keepWhitespace ? modes.CompletionItemInsertTextRule.KeepWhitespace : 0,
|
||||
k: item.commitCharacters,
|
||||
l: item.additionalTextEdits && item.additionalTextEdits.map(typeConvert.TextEdit.from),
|
||||
m: this._commands.toInternal(item.command),
|
||||
m: this._commands.toInternal(item.command, disposables),
|
||||
};
|
||||
|
||||
// 'insertText'-logic
|
||||
@@ -756,31 +770,32 @@ class SuggestAdapter {
|
||||
|
||||
class SignatureHelpAdapter {
|
||||
|
||||
private readonly _cache = new Cache<vscode.SignatureHelp>('SignatureHelp');
|
||||
|
||||
constructor(
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
private readonly _provider: vscode.SignatureHelpProvider,
|
||||
private readonly _heap: ExtHostHeapService,
|
||||
) { }
|
||||
|
||||
provideSignatureHelp(resource: URI, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<modes.SignatureHelp | undefined> {
|
||||
provideSignatureHelp(resource: URI, position: IPosition, context: SignatureHelpContextDto, token: CancellationToken): Promise<SignatureHelpDto | undefined> {
|
||||
const doc = this._documents.getDocument(resource);
|
||||
const pos = typeConvert.Position.to(position);
|
||||
const vscodeContext = this.reviveContext(context);
|
||||
|
||||
return asPromise(() => this._provider.provideSignatureHelp(doc, pos, token, vscodeContext)).then(value => {
|
||||
if (value) {
|
||||
const id = this._heap.keep(value);
|
||||
return ObjectIdentifier.mixin(typeConvert.SignatureHelp.from(value), id);
|
||||
const id = this._cache.add([value]);
|
||||
return { ...typeConvert.SignatureHelp.from(value), id };
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
private reviveContext(context: modes.SignatureHelpContext): vscode.SignatureHelpContext {
|
||||
private reviveContext(context: SignatureHelpContextDto): vscode.SignatureHelpContext {
|
||||
let activeSignatureHelp: vscode.SignatureHelp | undefined = undefined;
|
||||
if (context.activeSignatureHelp) {
|
||||
const revivedSignatureHelp = typeConvert.SignatureHelp.to(context.activeSignatureHelp);
|
||||
const saved = this._heap.get<vscode.SignatureHelp>(ObjectIdentifier.of(context.activeSignatureHelp));
|
||||
const saved = this._cache.get(context.activeSignatureHelp.id, 0);
|
||||
if (saved) {
|
||||
activeSignatureHelp = saved;
|
||||
activeSignatureHelp.activeSignature = revivedSignatureHelp.activeSignature;
|
||||
@@ -791,16 +806,26 @@ class SignatureHelpAdapter {
|
||||
}
|
||||
return { ...context, activeSignatureHelp };
|
||||
}
|
||||
|
||||
releaseSignatureHelp(id: number): any {
|
||||
this._cache.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
class Cache<T> {
|
||||
private static readonly enableDebugLogging = false;
|
||||
|
||||
private _data = new Map<number, T[]>();
|
||||
private readonly _data = new Map<number, readonly T[]>();
|
||||
private _idPool = 1;
|
||||
|
||||
add(item: T[]): number {
|
||||
constructor(
|
||||
private readonly id: string
|
||||
) { }
|
||||
|
||||
add(item: readonly T[]): number {
|
||||
const id = this._idPool++;
|
||||
this._data.set(id, item);
|
||||
this.logDebugInfo();
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -810,12 +835,20 @@ class Cache<T> {
|
||||
|
||||
delete(id: number) {
|
||||
this._data.delete(id);
|
||||
this.logDebugInfo();
|
||||
}
|
||||
|
||||
private logDebugInfo() {
|
||||
if (!Cache.enableDebugLogging) {
|
||||
return;
|
||||
}
|
||||
console.log(`${this.id} cache size — ${this._data.size}`);
|
||||
}
|
||||
}
|
||||
|
||||
class LinkProviderAdapter {
|
||||
|
||||
private _cache = new Cache<vscode.DocumentLink>();
|
||||
private _cache = new Cache<vscode.DocumentLink>('DocumentLink');
|
||||
|
||||
constructor(
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
@@ -831,6 +864,12 @@ class LinkProviderAdapter {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (token.isCancellationRequested) {
|
||||
// cancelled -> return without further ado, esp no caching
|
||||
// of results as they will leak
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (typeof this._provider.resolveDocumentLink !== 'function') {
|
||||
// no resolve -> no caching
|
||||
return { links: links.map(typeConvert.DocumentLink.from) };
|
||||
@@ -877,7 +916,7 @@ class ColorProviderAdapter {
|
||||
provideColors(resource: URI, token: CancellationToken): Promise<IRawColorInfo[]> {
|
||||
const doc = this._documents.getDocument(resource);
|
||||
return asPromise(() => this._provider.provideDocumentColors(doc, token)).then(colors => {
|
||||
if (!Array.isArray(colors)) {
|
||||
if (!Array.isArray<vscode.ColorInformation>(colors)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -1027,7 +1066,7 @@ type Adapter = DocumentSymbolAdapter | CodeLensAdapter | DefinitionAdapter | Hov
|
||||
| DocumentHighlightAdapter | ReferenceAdapter | CodeActionAdapter | DocumentFormattingAdapter
|
||||
| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
|
||||
| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter
|
||||
| ColorProviderAdapter | FoldingProviderAdapter | CodeInsetAdapter | DeclarationAdapter | SelectionRangeAdapter | CallHierarchyAdapter;
|
||||
| ColorProviderAdapter | FoldingProviderAdapter | DeclarationAdapter | SelectionRangeAdapter | CallHierarchyAdapter;
|
||||
|
||||
class AdapterData {
|
||||
constructor(
|
||||
@@ -1036,41 +1075,32 @@ class AdapterData {
|
||||
) { }
|
||||
}
|
||||
|
||||
export interface ISchemeTransformer {
|
||||
transformOutgoing(scheme: string): string;
|
||||
}
|
||||
|
||||
export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
private static _handlePool: number = 0;
|
||||
|
||||
private readonly _schemeTransformer: ISchemeTransformer | null;
|
||||
private readonly _uriTransformer: IURITransformer | null;
|
||||
private _proxy: MainThreadLanguageFeaturesShape;
|
||||
private _documents: ExtHostDocuments;
|
||||
private _commands: ExtHostCommands;
|
||||
private _heapService: ExtHostHeapService;
|
||||
private _diagnostics: ExtHostDiagnostics;
|
||||
private _adapter = new Map<number, AdapterData>();
|
||||
private readonly _logService: ILogService;
|
||||
private _webviewProxy: MainThreadWebviewsShape;
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
schemeTransformer: ISchemeTransformer | null,
|
||||
uriTransformer: IURITransformer | null,
|
||||
documents: ExtHostDocuments,
|
||||
commands: ExtHostCommands,
|
||||
heapMonitor: ExtHostHeapService,
|
||||
diagnostics: ExtHostDiagnostics,
|
||||
logService: ILogService
|
||||
) {
|
||||
this._schemeTransformer = schemeTransformer;
|
||||
this._uriTransformer = uriTransformer;
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadLanguageFeatures);
|
||||
this._documents = documents;
|
||||
this._commands = commands;
|
||||
this._heapService = heapMonitor;
|
||||
this._diagnostics = diagnostics;
|
||||
this._logService = logService;
|
||||
this._webviewProxy = mainContext.getProxy(MainContext.MainThreadWebviews);
|
||||
}
|
||||
|
||||
private _transformDocumentSelector(selector: vscode.DocumentSelector): Array<ISerializedDocumentFilter> {
|
||||
@@ -1099,8 +1129,8 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
}
|
||||
|
||||
private _transformScheme(scheme: string | undefined): string | undefined {
|
||||
if (this._schemeTransformer && typeof scheme === 'string') {
|
||||
return this._schemeTransformer.transformOutgoing(scheme);
|
||||
if (this._uriTransformer && typeof scheme === 'string') {
|
||||
return this._uriTransformer.transformOutgoingScheme(scheme);
|
||||
}
|
||||
return scheme;
|
||||
}
|
||||
@@ -1173,7 +1203,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
const handle = this._nextHandle();
|
||||
const eventHandle = typeof provider.onDidChangeCodeLenses === 'function' ? this._nextHandle() : undefined;
|
||||
|
||||
this._adapter.set(handle, new AdapterData(new CodeLensAdapter(this._documents, this._commands.converter, this._heapService, provider), extension));
|
||||
this._adapter.set(handle, new AdapterData(new CodeLensAdapter(this._documents, this._commands.converter, provider), extension));
|
||||
this._proxy.$registerCodeLensSupport(handle, this._transformDocumentSelector(selector), eventHandle);
|
||||
let result = this._createDisposable(handle);
|
||||
|
||||
@@ -1185,43 +1215,16 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
return result;
|
||||
}
|
||||
|
||||
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<modes.ICodeLensSymbol[]> {
|
||||
return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.provideCodeLenses(URI.revive(resource), token), []);
|
||||
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<CodeLensListDto | undefined> {
|
||||
return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.provideCodeLenses(URI.revive(resource), token), undefined);
|
||||
}
|
||||
|
||||
$resolveCodeLens(handle: number, symbol: modes.ICodeLensSymbol, token: CancellationToken): Promise<modes.ICodeLensSymbol | undefined> {
|
||||
$resolveCodeLens(handle: number, symbol: CodeLensDto, token: CancellationToken): Promise<CodeLensDto | undefined> {
|
||||
return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.resolveCodeLens(symbol, token), undefined);
|
||||
}
|
||||
|
||||
// --- code insets
|
||||
|
||||
registerCodeInsetProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CodeInsetProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
const eventHandle = typeof provider.onDidChangeCodeInsets === 'function' ? this._nextHandle() : undefined;
|
||||
|
||||
this._adapter.set(handle, new AdapterData(new CodeInsetAdapter(this._documents, this._heapService, provider), extension));
|
||||
this._proxy.$registerCodeInsetSupport(handle, this._transformDocumentSelector(selector), eventHandle);
|
||||
let result = this._createDisposable(handle);
|
||||
|
||||
if (eventHandle !== undefined && provider.onDidChangeCodeInsets) {
|
||||
const subscription = provider.onDidChangeCodeInsets(_ => this._proxy.$emitCodeLensEvent(eventHandle));
|
||||
result = Disposable.from(result, subscription);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
$provideCodeInsets(handle: number, resource: UriComponents, token: CancellationToken): Promise<codeInset.ICodeInsetSymbol[] | undefined> {
|
||||
return this._withAdapter(handle, CodeInsetAdapter, adapter => adapter.provideCodeInsets(URI.revive(resource), token), undefined);
|
||||
}
|
||||
|
||||
$resolveCodeInset(handle: number, _resource: UriComponents, symbol: codeInset.ICodeInsetSymbol, token: CancellationToken): Promise<codeInset.ICodeInsetSymbol> {
|
||||
const webviewHandle = Math.random();
|
||||
const webview = new ExtHostWebview(webviewHandle, this._webviewProxy, { enableScripts: true });
|
||||
return this._withAdapter(handle, CodeInsetAdapter, async (adapter, extension) => {
|
||||
await this._webviewProxy.$createWebviewCodeInset(webviewHandle, symbol.id, { enableCommandUris: true, enableScripts: true }, extension ? extension.identifier : undefined, extension ? extension.extensionLocation : undefined);
|
||||
return adapter.resolveCodeInset(symbol, webview, token);
|
||||
}, symbol);
|
||||
$releaseCodeLenses(handle: number, cacheId: number): void {
|
||||
this._withAdapter(handle, CodeLensAdapter, adapter => Promise.resolve(adapter.releaseCodeLenses(cacheId)), undefined);
|
||||
}
|
||||
|
||||
// --- declaration
|
||||
@@ -1311,10 +1314,14 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
}
|
||||
|
||||
|
||||
$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<CodeActionDto[] | undefined> {
|
||||
$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<CodeActionListDto | undefined> {
|
||||
return this._withAdapter(handle, CodeActionAdapter, adapter => adapter.provideCodeActions(URI.revive(resource), rangeOrSelection, context, token), undefined);
|
||||
}
|
||||
|
||||
$releaseCodeActions(handle: number, cacheId: number): void {
|
||||
this._withAdapter(handle, CodeActionAdapter, adapter => Promise.resolve(adapter.releaseCodeActions(cacheId)), undefined);
|
||||
}
|
||||
|
||||
// --- formatting
|
||||
|
||||
registerDocumentFormattingEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable {
|
||||
@@ -1387,7 +1394,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
registerCompletionItemProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new SuggestAdapter(this._documents, this._commands.converter, provider), extension);
|
||||
this._proxy.$registerSuggestSupport(handle, this._transformDocumentSelector(selector), triggerCharacters, SuggestAdapter.supportsResolving(provider));
|
||||
this._proxy.$registerSuggestSupport(handle, this._transformDocumentSelector(selector), triggerCharacters, SuggestAdapter.supportsResolving(provider), extension.identifier);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
@@ -1410,15 +1417,19 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
? { triggerCharacters: metadataOrTriggerChars, retriggerCharacters: [] }
|
||||
: metadataOrTriggerChars;
|
||||
|
||||
const handle = this._addNewAdapter(new SignatureHelpAdapter(this._documents, provider, this._heapService), extension);
|
||||
const handle = this._addNewAdapter(new SignatureHelpAdapter(this._documents, provider), extension);
|
||||
this._proxy.$registerSignatureHelpProvider(handle, this._transformDocumentSelector(selector), metadata);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<modes.SignatureHelp | undefined> {
|
||||
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: SignatureHelpContextDto, token: CancellationToken): Promise<SignatureHelpDto | undefined> {
|
||||
return this._withAdapter(handle, SignatureHelpAdapter, adapter => adapter.provideSignatureHelp(URI.revive(resource), position, context, token), undefined);
|
||||
}
|
||||
|
||||
$releaseSignatureHelp(handle: number, id: number): void {
|
||||
this._withAdapter(handle, SignatureHelpAdapter, adapter => adapter.releaseSignatureHelp(id), undefined);
|
||||
}
|
||||
|
||||
// --- links
|
||||
|
||||
registerDocumentLinkProvider(extension: IExtensionDescription | undefined, selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {
|
||||
|
||||
@@ -38,7 +38,9 @@ export class ExtensionMemento implements IExtensionMemento {
|
||||
return this._init;
|
||||
}
|
||||
|
||||
get<T>(key: string, defaultValue: T): T {
|
||||
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];
|
||||
if (typeof value === 'undefined') {
|
||||
value = defaultValue;
|
||||
@@ -46,11 +48,9 @@ export class ExtensionMemento implements IExtensionMemento {
|
||||
return value;
|
||||
}
|
||||
|
||||
update(key: string, value: any): Promise<boolean> {
|
||||
update(key: string, value: any): Promise<void> {
|
||||
this._value[key] = value;
|
||||
return this._storage
|
||||
.setValue(this._shared, this._id, this._value)
|
||||
.then(() => true);
|
||||
return this._storage.setValue(this._shared, this._id, this._value);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
|
||||
@@ -458,14 +458,14 @@ function getLightIconUri(iconPath: QuickInputButton['iconPath']) {
|
||||
|| iconPath instanceof URI) {
|
||||
return getIconUri(iconPath);
|
||||
}
|
||||
return getIconUri(iconPath['light']);
|
||||
return getIconUri((iconPath as any).light);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getDarkIconUri(iconPath: QuickInputButton['iconPath']) {
|
||||
if (iconPath && !(iconPath instanceof ThemeIcon) && iconPath['dark']) {
|
||||
return getIconUri(iconPath['dark']);
|
||||
if (iconPath && !(iconPath instanceof ThemeIcon) && (iconPath as any).dark) {
|
||||
return getIconUri((iconPath as any).dark);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { debounce } from 'vs/base/common/decorators';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { dispose, IDisposable, 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';
|
||||
@@ -415,6 +415,7 @@ class ExtHostSourceControl implements vscode.SourceControl {
|
||||
this._proxy.$updateSourceControl(this.handle, { commitTemplate });
|
||||
}
|
||||
|
||||
private _acceptInputDisposables = new MutableDisposable<DisposableStore>();
|
||||
private _acceptInputCommand: vscode.Command | undefined = undefined;
|
||||
|
||||
get acceptInputCommand(): vscode.Command | undefined {
|
||||
@@ -422,12 +423,15 @@ class ExtHostSourceControl implements vscode.SourceControl {
|
||||
}
|
||||
|
||||
set acceptInputCommand(acceptInputCommand: vscode.Command | undefined) {
|
||||
this._acceptInputDisposables.value = new DisposableStore();
|
||||
|
||||
this._acceptInputCommand = acceptInputCommand;
|
||||
|
||||
const internal = this._commands.converter.toInternal(acceptInputCommand);
|
||||
const internal = this._commands.converter.toInternal(acceptInputCommand, this._acceptInputDisposables.value);
|
||||
this._proxy.$updateSourceControl(this.handle, { acceptInputCommand: internal });
|
||||
}
|
||||
|
||||
private _statusBarDisposables = new MutableDisposable<DisposableStore>();
|
||||
private _statusBarCommands: vscode.Command[] | undefined = undefined;
|
||||
|
||||
get statusBarCommands(): vscode.Command[] | undefined {
|
||||
@@ -439,9 +443,11 @@ class ExtHostSourceControl implements vscode.SourceControl {
|
||||
return;
|
||||
}
|
||||
|
||||
this._statusBarDisposables.value = new DisposableStore();
|
||||
|
||||
this._statusBarCommands = statusBarCommands;
|
||||
|
||||
const internal = (statusBarCommands || []).map(c => this._commands.converter.toInternal(c)) as CommandDto[];
|
||||
const internal = (statusBarCommands || []).map(c => this._commands.converter.toInternal(c, this._statusBarDisposables.value!)) as CommandDto[];
|
||||
this._proxy.$updateSourceControl(this.handle, { statusBarCommands: internal });
|
||||
}
|
||||
|
||||
@@ -519,6 +525,9 @@ class ExtHostSourceControl implements vscode.SourceControl {
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._acceptInputDisposables.dispose();
|
||||
this._statusBarDisposables.dispose();
|
||||
|
||||
this._groups.forEach(group => group.dispose());
|
||||
this._proxy.$unregisterSourceControl(this.handle);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { StatusbarAlignment as MainThreadStatusBarAlignment } from 'vs/platform/
|
||||
import { StatusBarAlignment as ExtHostStatusBarAlignment, Disposable, ThemeColor } from './extHostTypes';
|
||||
import { StatusBarItem, StatusBarAlignment } from 'vscode';
|
||||
import { MainContext, MainThreadStatusBarShape, IMainContext } from './extHost.protocol';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { localize } from 'vs/nls';
|
||||
|
||||
export class ExtHostStatusBarEntry implements StatusBarItem {
|
||||
private static ID_GEN = 0;
|
||||
@@ -18,6 +18,9 @@ export class ExtHostStatusBarEntry implements StatusBarItem {
|
||||
private _disposed: boolean;
|
||||
private _visible: boolean;
|
||||
|
||||
private _statusId: string;
|
||||
private _statusName: string;
|
||||
|
||||
private _text: string;
|
||||
private _tooltip: string;
|
||||
private _color: string | ThemeColor;
|
||||
@@ -26,14 +29,13 @@ export class ExtHostStatusBarEntry implements StatusBarItem {
|
||||
private _timeoutHandle: any;
|
||||
private _proxy: MainThreadStatusBarShape;
|
||||
|
||||
private _extensionId?: ExtensionIdentifier;
|
||||
|
||||
constructor(proxy: MainThreadStatusBarShape, extensionId: ExtensionIdentifier | undefined, alignment: ExtHostStatusBarAlignment = ExtHostStatusBarAlignment.Left, priority?: number) {
|
||||
constructor(proxy: MainThreadStatusBarShape, id: string, name: string, alignment: ExtHostStatusBarAlignment = ExtHostStatusBarAlignment.Left, priority?: number) {
|
||||
this._id = ExtHostStatusBarEntry.ID_GEN++;
|
||||
this._proxy = proxy;
|
||||
this._statusId = id;
|
||||
this._statusName = name;
|
||||
this._alignment = alignment;
|
||||
this._priority = priority;
|
||||
this._extensionId = extensionId;
|
||||
}
|
||||
|
||||
public get id(): number {
|
||||
@@ -107,7 +109,7 @@ export class ExtHostStatusBarEntry implements StatusBarItem {
|
||||
this._timeoutHandle = undefined;
|
||||
|
||||
// Set to status bar
|
||||
this._proxy.$setEntry(this.id, this._extensionId, this.text, this.tooltip, this.command, this.color,
|
||||
this._proxy.$setEntry(this.id, this._statusId, this._statusName, this.text, this.tooltip, this.command, this.color,
|
||||
this._alignment === ExtHostStatusBarAlignment.Left ? MainThreadStatusBarAlignment.LEFT : MainThreadStatusBarAlignment.RIGHT,
|
||||
this._priority);
|
||||
}, 0);
|
||||
@@ -125,7 +127,7 @@ class StatusBarMessage {
|
||||
private _messages: { message: string }[] = [];
|
||||
|
||||
constructor(statusBar: ExtHostStatusBar) {
|
||||
this._item = statusBar.createStatusBarEntry(undefined, ExtHostStatusBarAlignment.Left, Number.MIN_VALUE);
|
||||
this._item = statusBar.createStatusBarEntry('status.extensionMessage', localize('status.extensionMessage', "Extension Status"), ExtHostStatusBarAlignment.Left, Number.MIN_VALUE);
|
||||
}
|
||||
|
||||
dispose() {
|
||||
@@ -167,8 +169,8 @@ export class ExtHostStatusBar {
|
||||
this._statusMessage = new StatusBarMessage(this);
|
||||
}
|
||||
|
||||
createStatusBarEntry(extensionId: ExtensionIdentifier | undefined, alignment?: ExtHostStatusBarAlignment, priority?: number): StatusBarItem {
|
||||
return new ExtHostStatusBarEntry(this._proxy, extensionId, alignment, priority);
|
||||
createStatusBarEntry(id: string, name: string, alignment?: ExtHostStatusBarAlignment, priority?: number): StatusBarItem {
|
||||
return new ExtHostStatusBarEntry(this._proxy, id, name, alignment, priority);
|
||||
}
|
||||
|
||||
setStatusBarMessage(text: string, timeoutOrThenable?: number | Thenable<any>): Disposable {
|
||||
|
||||
@@ -613,7 +613,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
|
||||
});
|
||||
}
|
||||
|
||||
insertSnippet(snippet: SnippetString, where?: Position | Position[] | Range | Range[], options: { undoStopBefore: boolean; undoStopAfter: boolean; } = { undoStopBefore: true, undoStopAfter: true }): Promise<boolean> {
|
||||
insertSnippet(snippet: SnippetString, where?: Position | readonly Position[] | Range | readonly Range[], options: { undoStopBefore: boolean; undoStopAfter: boolean; } = { undoStopBefore: true, undoStopAfter: true }): Promise<boolean> {
|
||||
if (this._disposed) {
|
||||
return Promise.reject(new Error('TextEditor#insertSnippet not possible on closed editors'));
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as vscode from 'vscode';
|
||||
import { basename } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ExtHostTreeViewsShape, MainThreadTreeViewsShape } from './extHost.protocol';
|
||||
import { ITreeItem, TreeViewItemHandleArg, ITreeItemLabel, IRevealOptions } from 'vs/workbench/common/views';
|
||||
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/common/extHostCommands';
|
||||
@@ -142,8 +142,7 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
|
||||
type Root = null | undefined;
|
||||
type TreeData<T> = { message: boolean, element: T | Root | false };
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
export interface TreeNode {
|
||||
export interface TreeNode extends IDisposable { // {{SQL CARBON EDIT}} export interface
|
||||
item: ITreeItem;
|
||||
parent: TreeNode | Root;
|
||||
children?: TreeNode[];
|
||||
@@ -435,6 +434,7 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
if (extTreeItem) {
|
||||
const newNode = this.createTreeNode(extElement, extTreeItem, existing.parent);
|
||||
this.updateNodeCache(extElement, newNode, existing, existing.parent);
|
||||
existing.dispose();
|
||||
return newNode;
|
||||
}
|
||||
return null;
|
||||
@@ -454,18 +454,8 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
return node;
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
protected createTreeNode(element: T, extensionTreeItem: vscode.TreeItem, parent: TreeNode | Root): TreeNode {
|
||||
return {
|
||||
item: this.createTreeItem(element, extensionTreeItem, parent),
|
||||
parent,
|
||||
children: undefined
|
||||
};
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
protected createTreeItem(element: T, extensionTreeItem: azdata.TreeItem, parent: TreeNode | Root): ITreeItem {
|
||||
|
||||
protected createTreeNode(element: T, extensionTreeItem: azdata.TreeItem, parent: TreeNode | Root): TreeNode { // {{SQL CARBON EDIT}} change to protected, change to azdata.TreeItem
|
||||
const disposable = new DisposableStore();
|
||||
const handle = this.createHandle(element, extensionTreeItem, parent);
|
||||
const icon = this.getLightIconPath(extensionTreeItem);
|
||||
const item = {
|
||||
@@ -475,7 +465,7 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
description: extensionTreeItem.description,
|
||||
resourceUri: extensionTreeItem.resourceUri,
|
||||
tooltip: typeof extensionTreeItem.tooltip === 'string' ? extensionTreeItem.tooltip : undefined,
|
||||
command: extensionTreeItem.command ? this.commands.toInternal(extensionTreeItem.command) : undefined,
|
||||
command: extensionTreeItem.command ? this.commands.toInternal(extensionTreeItem.command, disposable) : undefined,
|
||||
contextValue: extensionTreeItem.contextValue,
|
||||
icon,
|
||||
iconDark: this.getDarkIconPath(extensionTreeItem) || icon,
|
||||
@@ -487,7 +477,12 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
type: extensionTreeItem.type
|
||||
};
|
||||
|
||||
return item;
|
||||
return {
|
||||
item,
|
||||
parent,
|
||||
children: undefined,
|
||||
dispose(): void { disposable.dispose(); }
|
||||
};
|
||||
}
|
||||
|
||||
private createHandle(element: T, { id, label, resourceUri }: vscode.TreeItem, parent: TreeNode | Root, returnFirst?: boolean): TreeItemHandle {
|
||||
@@ -524,14 +519,14 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
|| extensionTreeItem.iconPath instanceof URI) {
|
||||
return this.getIconPath(extensionTreeItem.iconPath);
|
||||
}
|
||||
return this.getIconPath(extensionTreeItem.iconPath['light']);
|
||||
return this.getIconPath((<{ light: string | URI; dark: string | URI }>extensionTreeItem.iconPath).light);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private getDarkIconPath(extensionTreeItem: vscode.TreeItem): URI | undefined {
|
||||
if (extensionTreeItem.iconPath && !(extensionTreeItem.iconPath instanceof ThemeIcon) && extensionTreeItem.iconPath['dark']) {
|
||||
return this.getIconPath(extensionTreeItem.iconPath['dark']);
|
||||
if (extensionTreeItem.iconPath && !(extensionTreeItem.iconPath instanceof ThemeIcon) && (<{ light: string | URI; dark: string | URI }>extensionTreeItem.iconPath).dark) {
|
||||
return this.getIconPath((<{ light: string | URI; dark: string | URI }>extensionTreeItem.iconPath).dark);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@@ -614,6 +609,7 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
}
|
||||
this.nodes.delete(element);
|
||||
this.elements.delete(node.item.handle);
|
||||
node.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -621,6 +617,7 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
protected clearAll(): void {
|
||||
this.roots = null;
|
||||
this.elements.clear();
|
||||
this.nodes.forEach(node => node.dispose());
|
||||
this.nodes.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -237,8 +237,7 @@ export namespace MarkdownString {
|
||||
const resUris: { [href: string]: UriComponents } = Object.create(null);
|
||||
res.uris = resUris;
|
||||
|
||||
const renderer = new marked.Renderer();
|
||||
renderer.image = renderer.link = (href: string): string => {
|
||||
const collectUri = (href: string): string => {
|
||||
try {
|
||||
let uri = URI.parse(href, true);
|
||||
uri = uri.with({ query: _uriMassage(uri.query, resUris) });
|
||||
@@ -248,6 +247,10 @@ export namespace MarkdownString {
|
||||
}
|
||||
return '';
|
||||
};
|
||||
const renderer = new marked.Renderer();
|
||||
renderer.link = collectUri;
|
||||
renderer.image = href => collectUri(htmlContent.parseHrefAndDimensions(href).href);
|
||||
|
||||
marked(res.value, { renderer });
|
||||
|
||||
return res;
|
||||
@@ -808,7 +811,8 @@ export namespace DocumentLink {
|
||||
export function from(link: vscode.DocumentLink): modes.ILink {
|
||||
return {
|
||||
range: Range.from(link.range),
|
||||
url: link.target
|
||||
url: link.target,
|
||||
tooltip: link.tooltip
|
||||
};
|
||||
}
|
||||
|
||||
@@ -858,10 +862,7 @@ export namespace Color {
|
||||
|
||||
export namespace SelectionRange {
|
||||
export function from(obj: vscode.SelectionRange): modes.SelectionRange {
|
||||
return {
|
||||
kind: '',
|
||||
range: Range.from(obj.range)
|
||||
};
|
||||
return { range: Range.from(obj.range) };
|
||||
}
|
||||
|
||||
export function to(obj: modes.SelectionRange): vscode.SelectionRange {
|
||||
|
||||
@@ -1440,6 +1440,8 @@ export class DocumentLink {
|
||||
|
||||
target?: URI;
|
||||
|
||||
tooltip?: string;
|
||||
|
||||
constructor(range: Range, target: URI | undefined) {
|
||||
if (target && !(target instanceof URI)) {
|
||||
throw illegalArgument('target');
|
||||
@@ -1770,6 +1772,24 @@ export class CustomExecution implements vscode.CustomExecution {
|
||||
}
|
||||
}
|
||||
|
||||
export class CustomExecution2 implements vscode.CustomExecution2 {
|
||||
private _callback: () => Thenable<vscode.TerminalVirtualProcess>;
|
||||
constructor(callback: () => Thenable<vscode.TerminalVirtualProcess>) {
|
||||
this._callback = callback;
|
||||
}
|
||||
public computeId(): string {
|
||||
return 'customExecution' + generateUuid();
|
||||
}
|
||||
|
||||
public set callback(value: () => Thenable<vscode.TerminalVirtualProcess>) {
|
||||
this._callback = value;
|
||||
}
|
||||
|
||||
public get callback(): (() => Thenable<vscode.TerminalVirtualProcess>) {
|
||||
return this._callback;
|
||||
}
|
||||
}
|
||||
|
||||
@es5ClassCompat
|
||||
export class Task implements vscode.Task2 {
|
||||
|
||||
@@ -1783,7 +1803,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 | undefined;
|
||||
private _execution: ProcessExecution | ShellExecution | CustomExecution | CustomExecution2 | undefined;
|
||||
private _problemMatchers: string[];
|
||||
private _hasDefinedMatchers: boolean;
|
||||
private _isBackground: boolean;
|
||||
@@ -1792,8 +1812,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, problemMatchers?: string | string[]);
|
||||
constructor(definition: vscode.TaskDefinition, scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder, name: string, source: string, execution?: ProcessExecution | ShellExecution | CustomExecution, problemMatchers?: string | string[]);
|
||||
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, 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[];
|
||||
@@ -1905,18 +1925,18 @@ export class Task implements vscode.Task2 {
|
||||
}
|
||||
|
||||
get execution(): ProcessExecution | ShellExecution | undefined {
|
||||
return (this._execution instanceof CustomExecution) ? undefined : this._execution;
|
||||
return ((this._execution instanceof CustomExecution) || (this._execution instanceof CustomExecution2)) ? undefined : this._execution;
|
||||
}
|
||||
|
||||
set execution(value: ProcessExecution | ShellExecution | undefined) {
|
||||
this.execution2 = value;
|
||||
}
|
||||
|
||||
get execution2(): ProcessExecution | ShellExecution | CustomExecution | undefined {
|
||||
get execution2(): ProcessExecution | ShellExecution | CustomExecution | CustomExecution2 | undefined {
|
||||
return this._execution;
|
||||
}
|
||||
|
||||
set execution2(value: ProcessExecution | ShellExecution | CustomExecution | undefined) {
|
||||
set execution2(value: ProcessExecution | ShellExecution | CustomExecution | CustomExecution2 | undefined) {
|
||||
if (value === null) {
|
||||
value = undefined;
|
||||
}
|
||||
@@ -2317,3 +2337,8 @@ export enum ExtensionExecutionContext {
|
||||
Local = 1,
|
||||
Remote = 2
|
||||
}
|
||||
|
||||
export enum ExtensionKind {
|
||||
UI = 1,
|
||||
Workspace = 2
|
||||
}
|
||||
|
||||
@@ -8,37 +8,41 @@ import { URI } from 'vs/base/common/uri';
|
||||
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostWebviewsShape, IMainContext, MainContext, MainThreadWebviewsShape, WebviewPanelHandle, WebviewPanelViewState, WebviewInsetHandle } from './extHost.protocol';
|
||||
import { ExtHostWebviewsShape, IMainContext, MainContext, MainThreadWebviewsShape, WebviewPanelHandle, WebviewPanelViewState } from './extHost.protocol';
|
||||
import { Disposable } from './extHostTypes';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { WebviewInitData, toWebviewResource } from 'vs/workbench/api/common/shared/webview';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
|
||||
type IconPath = URI | { light: URI, dark: URI };
|
||||
|
||||
export class ExtHostWebview implements vscode.Webview {
|
||||
private readonly _handle: WebviewPanelHandle | WebviewInsetHandle;
|
||||
private readonly _proxy: MainThreadWebviewsShape;
|
||||
private _html: string;
|
||||
private _options: vscode.WebviewOptions;
|
||||
private _isDisposed: boolean = false;
|
||||
|
||||
public readonly _onMessageEmitter = new Emitter<any>();
|
||||
public readonly onDidReceiveMessage: Event<any> = this._onMessageEmitter.event;
|
||||
|
||||
constructor(
|
||||
handle: WebviewPanelHandle | WebviewInsetHandle,
|
||||
proxy: MainThreadWebviewsShape,
|
||||
options: vscode.WebviewOptions
|
||||
) {
|
||||
this._handle = handle;
|
||||
this._proxy = proxy;
|
||||
this._options = options;
|
||||
}
|
||||
private readonly _handle: WebviewPanelHandle,
|
||||
private readonly _proxy: MainThreadWebviewsShape,
|
||||
private _options: vscode.WebviewOptions,
|
||||
private readonly _initData: WebviewInitData
|
||||
) { }
|
||||
|
||||
public dispose() {
|
||||
this._onMessageEmitter.dispose();
|
||||
}
|
||||
|
||||
public toWebviewResource(resource: vscode.Uri): vscode.Uri {
|
||||
return toWebviewResource(this._initData, this._handle, resource);
|
||||
}
|
||||
|
||||
public get cspSource(): string {
|
||||
return this._initData.webviewCspSource.replace('{{uuid}}', this._handle);
|
||||
}
|
||||
|
||||
public get html(): string {
|
||||
this.assertNotDisposed();
|
||||
return this._html;
|
||||
@@ -228,10 +232,9 @@ export class ExtHostWebviewPanel implements vscode.WebviewPanel {
|
||||
}
|
||||
|
||||
export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
private static webviewHandlePool = 1;
|
||||
|
||||
private static newHandle(): WebviewPanelHandle {
|
||||
return ExtHostWebviews.webviewHandlePool++ + '';
|
||||
return generateUuid();
|
||||
}
|
||||
|
||||
private readonly _proxy: MainThreadWebviewsShape;
|
||||
@@ -239,7 +242,8 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
private readonly _serializers = new Map<string, vscode.WebviewPanelSerializer>();
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext
|
||||
mainContext: IMainContext,
|
||||
private readonly initData: WebviewInitData
|
||||
) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadWebviews);
|
||||
}
|
||||
@@ -260,7 +264,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
const handle = ExtHostWebviews.newHandle();
|
||||
this._proxy.$createWebviewPanel(handle, viewType, title, webviewShowOptions, convertWebviewOptions(options), extension.identifier, extension.extensionLocation);
|
||||
|
||||
const webview = new ExtHostWebview(handle, this._proxy, options);
|
||||
const webview = new ExtHostWebview(handle, this._proxy, options, this.initData);
|
||||
const panel = new ExtHostWebviewPanel(handle, this._proxy, viewType, title, viewColumn, options, webview);
|
||||
this._webviewPanels.set(handle, panel);
|
||||
return panel;
|
||||
@@ -333,7 +337,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
return Promise.reject(new Error(`No serializer found for '${viewType}'`));
|
||||
}
|
||||
|
||||
const webview = new ExtHostWebview(webviewHandle, this._proxy, options);
|
||||
const webview = new ExtHostWebview(webviewHandle, this._proxy, options, this.initData);
|
||||
const revivedPanel = new ExtHostWebviewPanel(webviewHandle, this._proxy, viewType, title, typeof position === 'number' && position >= 0 ? typeConverters.ViewColumn.to(position) : undefined, options, webview);
|
||||
this._webviewPanels.set(webviewHandle, revivedPanel);
|
||||
return Promise.resolve(serializer.deserializeWebviewPanel(revivedPanel, state));
|
||||
|
||||
@@ -9,7 +9,6 @@ import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { TernarySearchTree } from 'vs/base/common/map';
|
||||
import { Counter } from 'vs/base/common/numbers';
|
||||
import { isLinux } from 'vs/base/common/platform';
|
||||
import { basenameOrAuthority, dirname, isEqual, relativePath, basename } from 'vs/base/common/resources';
|
||||
import { compare } from 'vs/base/common/strings';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -34,7 +33,7 @@ export interface IExtHostWorkspaceProvider {
|
||||
}
|
||||
|
||||
function isFolderEqual(folderA: URI, folderB: URI): boolean {
|
||||
return isEqual(folderA, folderB, !isLinux);
|
||||
return isEqual(folderA, folderB);
|
||||
}
|
||||
|
||||
function compareWorkspaceFolderByUri(a: vscode.WorkspaceFolder, b: vscode.WorkspaceFolder): number {
|
||||
|
||||
@@ -21,7 +21,6 @@ namespace schema {
|
||||
export interface IUserFriendlyMenuItem {
|
||||
command: string;
|
||||
alt?: string;
|
||||
precondition?: string;
|
||||
when?: string;
|
||||
group?: string;
|
||||
}
|
||||
@@ -84,10 +83,6 @@ namespace schema {
|
||||
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'alt'));
|
||||
return false;
|
||||
}
|
||||
if (item.precondition && typeof item.precondition !== 'string') {
|
||||
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'precondition'));
|
||||
return false;
|
||||
}
|
||||
if (item.when && typeof item.when !== 'string') {
|
||||
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'when'));
|
||||
return false;
|
||||
@@ -112,10 +107,6 @@ namespace schema {
|
||||
description: localize('vscode.extension.contributes.menuItem.alt', 'Identifier of an alternative command to execute. The command must be declared in the \'commands\'-section'),
|
||||
type: 'string'
|
||||
},
|
||||
precondition: {
|
||||
description: localize('vscode.extension.contributes.menuItem.precondition', 'Condition which must be true to enable this item'),
|
||||
type: 'string'
|
||||
},
|
||||
when: {
|
||||
description: localize('vscode.extension.contributes.menuItem.when', 'Condition which must be true to show this item'),
|
||||
type: 'string'
|
||||
@@ -206,8 +197,8 @@ namespace schema {
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'comments/commentThread/actions': {
|
||||
description: localize('commentThread.actions', "The contributed comment thread actions"),
|
||||
'comments/commentThread/context': {
|
||||
description: localize('commentThread.actions', "The contributed comment thread context menu, rendered as buttons below the comment editor"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
@@ -216,8 +207,8 @@ namespace schema {
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'comments/comment/actions': {
|
||||
description: localize('comment.actions', "The contributed comment actions"),
|
||||
'comments/comment/context': {
|
||||
description: localize('comment.actions', "The contributed comment context menu, rendered as buttons below the comment editor"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
@@ -229,6 +220,7 @@ namespace schema {
|
||||
export interface IUserFriendlyCommand {
|
||||
command: string;
|
||||
title: string | ILocalizedString;
|
||||
enablement?: string;
|
||||
category?: string | ILocalizedString;
|
||||
icon?: IUserFriendlyIcon;
|
||||
}
|
||||
@@ -247,6 +239,10 @@ namespace schema {
|
||||
if (!isValidLocalizedString(command.title, collector, 'title')) {
|
||||
return false;
|
||||
}
|
||||
if (command.enablement && typeof command.enablement !== 'string') {
|
||||
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'precondition'));
|
||||
return false;
|
||||
}
|
||||
if (command.category && !isValidLocalizedString(command.category, collector, 'category')) {
|
||||
return false;
|
||||
}
|
||||
@@ -300,6 +296,10 @@ namespace schema {
|
||||
description: localize('vscode.extension.contributes.commandType.category', '(Optional) Category string by the command is grouped in the UI'),
|
||||
type: 'string'
|
||||
},
|
||||
enablement: {
|
||||
description: localize('vscode.extension.contributes.commandType.precondition', '(Optional) Condition which must be true to enable the command'),
|
||||
type: 'string'
|
||||
},
|
||||
icon: {
|
||||
description: localize('vscode.extension.contributes.commandType.icon', '(Optional) Icon which is used to represent the command in the UI. Either a file path or a themable configuration'),
|
||||
anyOf: [{
|
||||
@@ -336,10 +336,12 @@ namespace schema {
|
||||
|
||||
let _commandRegistrations: IDisposable[] = [];
|
||||
|
||||
ExtensionsRegistry.registerExtensionPoint<schema.IUserFriendlyCommand | schema.IUserFriendlyCommand[]>({
|
||||
export const commandsExtensionPoint = ExtensionsRegistry.registerExtensionPoint<schema.IUserFriendlyCommand | schema.IUserFriendlyCommand[]>({
|
||||
extensionPoint: 'commands',
|
||||
jsonSchema: schema.commandsContribution
|
||||
}).setHandler(extensions => {
|
||||
});
|
||||
|
||||
commandsExtensionPoint.setHandler(extensions => {
|
||||
|
||||
function handleCommand(userFriendlyCommand: schema.IUserFriendlyCommand, extension: IExtensionPointUser<any>, disposables: IDisposable[]) {
|
||||
|
||||
@@ -347,7 +349,7 @@ ExtensionsRegistry.registerExtensionPoint<schema.IUserFriendlyCommand | schema.I
|
||||
return;
|
||||
}
|
||||
|
||||
const { icon, category, title, command } = userFriendlyCommand;
|
||||
const { icon, enablement, category, title, command } = userFriendlyCommand;
|
||||
|
||||
let absoluteIcon: { dark: URI; light?: URI; } | undefined;
|
||||
if (icon) {
|
||||
@@ -364,7 +366,13 @@ ExtensionsRegistry.registerExtensionPoint<schema.IUserFriendlyCommand | schema.I
|
||||
if (MenuRegistry.getCommand(command)) {
|
||||
extension.collector.info(localize('dup', "Command `{0}` appears multiple times in the `commands` section.", userFriendlyCommand.command));
|
||||
}
|
||||
const registration = MenuRegistry.addCommand({ id: command, title, category, iconLocation: absoluteIcon });
|
||||
const registration = MenuRegistry.addCommand({
|
||||
id: command,
|
||||
title,
|
||||
category,
|
||||
precondition: ContextKeyExpr.deserialize(enablement),
|
||||
iconLocation: absoluteIcon
|
||||
});
|
||||
disposables.push(registration);
|
||||
}
|
||||
|
||||
@@ -439,14 +447,6 @@ ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyM
|
||||
}
|
||||
}
|
||||
|
||||
if (item.precondition) {
|
||||
command.precondition = ContextKeyExpr.deserialize(item.precondition);
|
||||
}
|
||||
|
||||
if (alt && item.precondition) {
|
||||
alt.precondition = command.precondition;
|
||||
}
|
||||
|
||||
const registration = MenuRegistry.appendMenuItem(menu, {
|
||||
command,
|
||||
alt,
|
||||
|
||||
@@ -70,6 +70,10 @@ export interface CustomExecutionDTO {
|
||||
customExecution: 'customExecution';
|
||||
}
|
||||
|
||||
export interface CustomExecution2DTO {
|
||||
customExecution: 'customExecution2';
|
||||
}
|
||||
|
||||
export interface TaskSourceDTO {
|
||||
label: string;
|
||||
extensionId?: string;
|
||||
@@ -84,7 +88,7 @@ export interface TaskHandleDTO {
|
||||
export interface TaskDTO {
|
||||
_id: string;
|
||||
name?: string;
|
||||
execution: ProcessExecutionDTO | ShellExecutionDTO | CustomExecutionDTO | undefined;
|
||||
execution: ProcessExecutionDTO | ShellExecutionDTO | CustomExecutionDTO | CustomExecution2DTO | undefined;
|
||||
definition: TaskDefinitionDTO;
|
||||
isBackground?: boolean;
|
||||
source: TaskSourceDTO;
|
||||
|
||||
24
src/vs/workbench/api/common/shared/webview.ts
Normal file
24
src/vs/workbench/api/common/shared/webview.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export interface WebviewInitData {
|
||||
readonly webviewResourceRoot: string;
|
||||
readonly webviewCspSource: string;
|
||||
}
|
||||
|
||||
export function toWebviewResource(
|
||||
initData: WebviewInitData,
|
||||
uuid: string,
|
||||
resource: vscode.Uri
|
||||
): vscode.Uri {
|
||||
const uri = initData.webviewResourceRoot
|
||||
.replace('{{resource}}', resource.toString().replace(/^\S+?:/, ''))
|
||||
.replace('{{uuid}}', uuid);
|
||||
|
||||
return URI.parse(uri);
|
||||
}
|
||||
Reference in New Issue
Block a user