mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-03 15:01:57 +01:00
Merge remote-tracking branch 'origin/master' into alex/semantic-exploration
This commit is contained in:
@@ -12,6 +12,7 @@ import { IWebviewService, WebviewElement } from 'vs/workbench/contrib/webview/br
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IActiveCodeEditor, IViewZone } from 'vs/editor/browser/editorBrowser';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { isEqual } from 'vs/base/common/resources';
|
||||
|
||||
// todo@joh move these things back into something like contrib/insets
|
||||
class EditorWebviewZone implements IViewZone {
|
||||
@@ -75,7 +76,7 @@ export class MainThreadEditorInsets implements MainThreadEditorInsetsShape {
|
||||
id = id.substr(0, id.indexOf(',')); //todo@joh HACK
|
||||
|
||||
for (const candidate of this._editorService.listCodeEditors()) {
|
||||
if (candidate.getId() === id && candidate.hasModel() && candidate.getModel()!.uri.toString() === URI.revive(uri).toString()) {
|
||||
if (candidate.getId() === id && candidate.hasModel() && isEqual(candidate.getModel().uri, URI.revive(uri))) {
|
||||
editor = candidate;
|
||||
break;
|
||||
}
|
||||
@@ -90,11 +91,11 @@ export class MainThreadEditorInsets implements MainThreadEditorInsetsShape {
|
||||
|
||||
const webview = this._webviewService.createWebview('' + handle, {
|
||||
enableFindWidget: false,
|
||||
extension: { id: extensionId, location: URI.revive(extensionLocation) }
|
||||
}, {
|
||||
allowScripts: options.enableScripts,
|
||||
localResourceRoots: options.localResourceRoots ? options.localResourceRoots.map(uri => URI.revive(uri)) : undefined
|
||||
});
|
||||
webview.extension = { id: extensionId, location: URI.revive(extensionLocation) };
|
||||
|
||||
const webviewZone = new EditorWebviewZone(editor, line, height, webview);
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import { Extensions as PanelExtensions, PanelDescriptor, PanelRegistry } from 'v
|
||||
import { ICommentInfo, ICommentService } from 'vs/workbench/contrib/comments/browser/commentService';
|
||||
import { CommentsPanel } from 'vs/workbench/contrib/comments/browser/commentsPanel';
|
||||
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
|
||||
import { CommentProviderFeatures, ExtHostCommentsShape, ExtHostContext, IExtHostContext, MainContext, MainThreadCommentsShape } from '../common/extHost.protocol';
|
||||
import { CommentProviderFeatures, ExtHostCommentsShape, ExtHostContext, IExtHostContext, MainContext, MainThreadCommentsShape, CommentThreadChanges } from '../common/extHost.protocol';
|
||||
import { COMMENTS_PANEL_ID, COMMENTS_PANEL_TITLE } from 'vs/workbench/contrib/comments/browser/commentsTreeViewer';
|
||||
|
||||
|
||||
@@ -116,17 +116,15 @@ export class MainThreadCommentThread implements modes.CommentThread {
|
||||
this._isDisposed = false;
|
||||
}
|
||||
|
||||
batchUpdate(
|
||||
range: IRange,
|
||||
label: string,
|
||||
contextValue: string | undefined,
|
||||
comments: modes.Comment[],
|
||||
collapsibleState: modes.CommentThreadCollapsibleState) {
|
||||
this._range = range;
|
||||
this._label = label;
|
||||
this._contextValue = contextValue;
|
||||
this._comments = comments;
|
||||
this._collapsibleState = collapsibleState;
|
||||
batchUpdate(changes: CommentThreadChanges) {
|
||||
const modified = (value: keyof CommentThreadChanges): boolean =>
|
||||
Object.prototype.hasOwnProperty.call(changes, value);
|
||||
|
||||
if (modified('range')) { this._range = changes.range!; }
|
||||
if (modified('label')) { this._label = changes.label; }
|
||||
if (modified('contextValue')) { this._contextValue = changes.contextValue; }
|
||||
if (modified('comments')) { this._comments = changes.comments; }
|
||||
if (modified('collapseState')) { this._collapsibleState = changes.collapseState; }
|
||||
}
|
||||
|
||||
dispose() {
|
||||
@@ -228,13 +226,9 @@ export class MainThreadCommentController {
|
||||
updateCommentThread(commentThreadHandle: number,
|
||||
threadId: string,
|
||||
resource: UriComponents,
|
||||
range: IRange,
|
||||
label: string,
|
||||
contextValue: string | undefined,
|
||||
comments: modes.Comment[],
|
||||
collapsibleState: modes.CommentThreadCollapsibleState): void {
|
||||
changes: CommentThreadChanges): void {
|
||||
let thread = this.getKnownThread(commentThreadHandle);
|
||||
thread.batchUpdate(range, label, contextValue, comments, collapsibleState);
|
||||
thread.batchUpdate(changes);
|
||||
|
||||
this._commentService.updateComments(this._uniqueId, {
|
||||
added: [],
|
||||
@@ -430,18 +424,14 @@ export class MainThreadComments extends Disposable implements MainThreadComments
|
||||
commentThreadHandle: number,
|
||||
threadId: string,
|
||||
resource: UriComponents,
|
||||
range: IRange,
|
||||
label: string,
|
||||
contextValue: string | undefined,
|
||||
comments: modes.Comment[],
|
||||
collapsibleState: modes.CommentThreadCollapsibleState): void {
|
||||
changes: CommentThreadChanges): void {
|
||||
let provider = this._commentControllers.get(handle);
|
||||
|
||||
if (!provider) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return provider.updateCommentThread(commentThreadHandle, threadId, resource, range, label, contextValue, comments, collapsibleState);
|
||||
return provider.updateCommentThread(commentThreadHandle, threadId, resource, changes);
|
||||
}
|
||||
|
||||
$deleteCommentThread(handle: number, commentThreadHandle: number) {
|
||||
|
||||
@@ -16,6 +16,7 @@ import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2
|
||||
import { IApplyEditsOptions, IEditorPropertiesChangeData, IResolvedTextEditorConfiguration, ITextEditorConfigurationUpdate, IUndoStopOptions, TextEditorRevealType } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { IEditor } from 'vs/workbench/common/editor';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { equals } from 'vs/base/common/arrays';
|
||||
|
||||
export interface IFocusTracker {
|
||||
onGainedFocus(): void;
|
||||
@@ -124,28 +125,12 @@ export class MainThreadTextEditorProperties {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static _selectionsEqual(a: Selection[], b: Selection[]): boolean {
|
||||
if (a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (!a[i].equalsSelection(b[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
private static _selectionsEqual(a: readonly Selection[], b: readonly Selection[]): boolean {
|
||||
return equals(a, b, (aValue, bValue) => aValue.equalsSelection(bValue));
|
||||
}
|
||||
|
||||
private static _rangesEqual(a: Range[], b: Range[]): boolean {
|
||||
if (a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (!a[i].equalsRange(b[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
private static _rangesEqual(a: readonly Range[], b: readonly Range[]): boolean {
|
||||
return equals(a, b, (aValue, bValue) => aValue.equalsRange(bValue));
|
||||
}
|
||||
|
||||
private static _optionsEqual(a: IResolvedTextEditorConfiguration, b: IResolvedTextEditorConfiguration): boolean {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { FileWriteOptions, FileSystemProviderCapabilities, IFileChange, IFileService, IFileSystemProvider, IStat, IWatchOptions, FileType, FileOverwriteOptions, FileDeleteOptions, FileOpenOptions, IFileStat, FileOperationError, FileOperationResult, FileSystemProviderErrorCode } from 'vs/platform/files/common/files';
|
||||
import { FileWriteOptions, FileSystemProviderCapabilities, IFileChange, IFileService, IStat, IWatchOptions, FileType, FileOverwriteOptions, FileDeleteOptions, FileOpenOptions, IFileStat, FileOperationError, FileOperationResult, FileSystemProviderErrorCode, IFileSystemProviderWithOpenReadWriteCloseCapability, IFileSystemProviderWithFileReadWriteCapability, IFileSystemProviderWithFileFolderCopyCapability } from 'vs/platform/files/common/files';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { ExtHostContext, ExtHostFileSystemShape, IExtHostContext, IFileChangeDto, MainContext, MainThreadFileSystemShape } from '../common/extHost.protocol';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
@@ -67,7 +67,7 @@ export class MainThreadFileSystem implements MainThreadFileSystemShape {
|
||||
err.name = FileSystemProviderErrorCode.FileNotADirectory;
|
||||
throw err;
|
||||
}
|
||||
return !stat.children ? [] : stat.children.map(child => [child.name, MainThreadFileSystem._getFileType(child)]);
|
||||
return !stat.children ? [] : stat.children.map(child => [child.name, MainThreadFileSystem._getFileType(child)] as [string, FileType]);
|
||||
}).catch(MainThreadFileSystem._handleError);
|
||||
}
|
||||
|
||||
@@ -80,19 +80,23 @@ export class MainThreadFileSystem implements MainThreadFileSystemShape {
|
||||
}
|
||||
|
||||
$writeFile(uri: UriComponents, content: VSBuffer): Promise<void> {
|
||||
return this._fileService.writeFile(URI.revive(uri), content).catch(MainThreadFileSystem._handleError);
|
||||
return this._fileService.writeFile(URI.revive(uri), content)
|
||||
.then(() => undefined).catch(MainThreadFileSystem._handleError);
|
||||
}
|
||||
|
||||
$rename(source: UriComponents, target: UriComponents, opts: FileOverwriteOptions): Promise<void> {
|
||||
return this._fileService.move(URI.revive(source), URI.revive(target), opts.overwrite).catch(MainThreadFileSystem._handleError);
|
||||
return this._fileService.move(URI.revive(source), URI.revive(target), opts.overwrite)
|
||||
.then(() => undefined).catch(MainThreadFileSystem._handleError);
|
||||
}
|
||||
|
||||
$copy(source: UriComponents, target: UriComponents, opts: FileOverwriteOptions): Promise<void> {
|
||||
return this._fileService.copy(URI.revive(source), URI.revive(target), opts.overwrite).catch(MainThreadFileSystem._handleError);
|
||||
return this._fileService.copy(URI.revive(source), URI.revive(target), opts.overwrite)
|
||||
.then(() => undefined).catch(MainThreadFileSystem._handleError);
|
||||
}
|
||||
|
||||
$mkdir(uri: UriComponents): Promise<void> {
|
||||
return this._fileService.createFolder(URI.revive(uri)).catch(MainThreadFileSystem._handleError);
|
||||
return this._fileService.createFolder(URI.revive(uri))
|
||||
.then(() => undefined).catch(MainThreadFileSystem._handleError);
|
||||
}
|
||||
|
||||
$delete(uri: UriComponents, opts: FileDeleteOptions): Promise<void> {
|
||||
@@ -121,12 +125,12 @@ export class MainThreadFileSystem implements MainThreadFileSystemShape {
|
||||
}
|
||||
}
|
||||
|
||||
class RemoteFileSystemProvider implements IFileSystemProvider {
|
||||
class RemoteFileSystemProvider implements IFileSystemProviderWithFileReadWriteCapability, IFileSystemProviderWithOpenReadWriteCloseCapability, IFileSystemProviderWithFileFolderCopyCapability {
|
||||
|
||||
private readonly _onDidChange = new Emitter<IFileChange[]>();
|
||||
private readonly _onDidChange = new Emitter<readonly IFileChange[]>();
|
||||
private readonly _registration: IDisposable;
|
||||
|
||||
readonly onDidChangeFile: Event<IFileChange[]> = this._onDidChange.event;
|
||||
readonly onDidChangeFile: Event<readonly IFileChange[]> = this._onDidChange.event;
|
||||
|
||||
readonly capabilities: FileSystemProviderCapabilities;
|
||||
readonly onDidChangeCapabilities: Event<void> = Event.None;
|
||||
|
||||
@@ -3,21 +3,24 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { FileChangeType, IFileService, FileOperation } from 'vs/platform/files/common/files';
|
||||
import { extHostCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { ExtHostContext, FileSystemEvents, IExtHostContext } from '../common/extHost.protocol';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
|
||||
import { localize } from 'vs/nls';
|
||||
|
||||
@extHostCustomer
|
||||
export class MainThreadFileSystemEventService {
|
||||
|
||||
private readonly _listener = new Array<IDisposable>();
|
||||
private readonly _listener = new DisposableStore();
|
||||
|
||||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
@IFileService fileService: IFileService,
|
||||
@ITextFileService textfileService: ITextFileService,
|
||||
@ITextFileService textFileService: ITextFileService,
|
||||
@IProgressService progressService: IProgressService
|
||||
) {
|
||||
|
||||
const proxy = extHostContext.getProxy(ExtHostContext.ExtHostFileSystemEventService);
|
||||
@@ -28,7 +31,7 @@ export class MainThreadFileSystemEventService {
|
||||
changed: [],
|
||||
deleted: []
|
||||
};
|
||||
fileService.onFileChanges(event => {
|
||||
this._listener.add(fileService.onFileChanges(event => {
|
||||
for (let change of event.changes) {
|
||||
switch (change.type) {
|
||||
case FileChangeType.ADDED:
|
||||
@@ -47,22 +50,35 @@ export class MainThreadFileSystemEventService {
|
||||
events.created.length = 0;
|
||||
events.changed.length = 0;
|
||||
events.deleted.length = 0;
|
||||
}, undefined, this._listener);
|
||||
}));
|
||||
|
||||
// file operation events - (changes the editor makes)
|
||||
fileService.onAfterOperation(e => {
|
||||
if (e.isOperation(FileOperation.MOVE)) {
|
||||
proxy.$onFileRename(e.resource, e.target.resource);
|
||||
}
|
||||
}, undefined, this._listener);
|
||||
|
||||
textfileService.onWillMove(e => {
|
||||
const promise = proxy.$onWillRename(e.oldResource, e.newResource);
|
||||
e.waitUntil(promise);
|
||||
}, undefined, this._listener);
|
||||
// BEFORE file operation
|
||||
const messages = new Map<FileOperation, string>();
|
||||
messages.set(FileOperation.CREATE, localize('msg-create', "Running 'File Create' participants..."));
|
||||
messages.set(FileOperation.DELETE, localize('msg-delete', "Running 'File Delete' participants..."));
|
||||
messages.set(FileOperation.MOVE, localize('msg-rename', "Running 'File Rename' participants..."));
|
||||
|
||||
this._listener.add(textFileService.onWillRunOperation(e => {
|
||||
const p = progressService.withProgress({ location: ProgressLocation.Window }, progress => {
|
||||
|
||||
progress.report({ message: messages.get(e.operation) });
|
||||
|
||||
const p1 = proxy.$onWillRunFileOperation(e.operation, e.target, e.source);
|
||||
const p2 = new Promise((_resolve, reject) => {
|
||||
setTimeout(() => reject(new Error('timeout')), 5000);
|
||||
});
|
||||
return Promise.race([p1, p2]);
|
||||
});
|
||||
|
||||
e.waitUntil(p);
|
||||
}));
|
||||
|
||||
// AFTER file operation
|
||||
this._listener.add(textFileService.onDidRunOperation(e => proxy.$onDidRunFileOperation(e.operation, e.target, e.source)));
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
dispose(this._listener);
|
||||
this._listener.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import * as search from 'vs/workbench/contrib/search/common/search';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Position as EditorPosition } from 'vs/editor/common/core/position';
|
||||
import { Range as EditorRange, IRange } from 'vs/editor/common/core/range';
|
||||
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ILanguageConfigurationDto, IRegExpDto, IIndentationRuleDto, IOnEnterRuleDto, ILocationDto, IWorkspaceSymbolDto, reviveWorkspaceEditDto, IDocumentFilterDto, IDefinitionLinkDto, ISignatureHelpProviderMetadataDto, ILinkDto, ICallHierarchyItemDto, ISuggestDataDto, ICodeActionDto } from '../common/extHost.protocol';
|
||||
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ILanguageConfigurationDto, IRegExpDto, IIndentationRuleDto, IOnEnterRuleDto, ILocationDto, IWorkspaceSymbolDto, reviveWorkspaceEditDto, IDocumentFilterDto, IDefinitionLinkDto, ISignatureHelpProviderMetadataDto, ILinkDto, ICallHierarchyItemDto, ISuggestDataDto, ICodeActionDto, ISuggestDataDtoField } from '../common/extHost.protocol';
|
||||
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
|
||||
import { LanguageConfiguration, IndentationRule, OnEnterRule } from 'vs/editor/common/modes/languageConfiguration';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
@@ -333,22 +333,23 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- suggest
|
||||
|
||||
private static _inflateSuggestDto(defaultRange: IRange, data: ISuggestDataDto): modes.CompletionItem {
|
||||
private static _inflateSuggestDto(defaultRange: IRange | { insert: IRange, replace: IRange }, data: ISuggestDataDto): modes.CompletionItem {
|
||||
|
||||
return {
|
||||
label: data.a,
|
||||
kind: data.b,
|
||||
tags: data.n,
|
||||
detail: data.c,
|
||||
documentation: data.d,
|
||||
sortText: data.e,
|
||||
filterText: data.f,
|
||||
preselect: data.g,
|
||||
insertText: typeof data.h === 'undefined' ? data.a : data.h,
|
||||
insertTextRules: data.i,
|
||||
range: data.j || defaultRange,
|
||||
commitCharacters: data.k,
|
||||
additionalTextEdits: data.l,
|
||||
command: data.m,
|
||||
label: data[ISuggestDataDtoField.label],
|
||||
kind: data[ISuggestDataDtoField.kind],
|
||||
tags: data[ISuggestDataDtoField.kindModifier],
|
||||
detail: data[ISuggestDataDtoField.detail],
|
||||
documentation: data[ISuggestDataDtoField.documentation],
|
||||
sortText: data[ISuggestDataDtoField.sortText],
|
||||
filterText: data[ISuggestDataDtoField.filterText],
|
||||
preselect: data[ISuggestDataDtoField.preselect],
|
||||
insertText: typeof data.h === 'undefined' ? data[ISuggestDataDtoField.label] : data.h,
|
||||
range: data[ISuggestDataDtoField.range] || defaultRange,
|
||||
insertTextRules: data[ISuggestDataDtoField.insertTextRules],
|
||||
commitCharacters: data[ISuggestDataDtoField.commitCharacters],
|
||||
additionalTextEdits: data[ISuggestDataDtoField.additionalTextEdits],
|
||||
command: data[ISuggestDataDtoField.command],
|
||||
// not-standard
|
||||
_id: data.x,
|
||||
};
|
||||
@@ -377,6 +378,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
if (!result) {
|
||||
return suggestion;
|
||||
}
|
||||
|
||||
let newSuggestion = MainThreadLanguageFeatures._inflateSuggestDto(suggestion.range, result);
|
||||
return mixin(suggestion, newSuggestion, true);
|
||||
});
|
||||
@@ -501,27 +503,39 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
$registerCallHierarchyProvider(handle: number, selector: IDocumentFilterDto[]): void {
|
||||
this._registrations.set(handle, callh.CallHierarchyProviderRegistry.register(selector, {
|
||||
provideOutgoingCalls: async (model, position, token) => {
|
||||
const outgoing = await this._proxy.$provideCallHierarchyOutgoingCalls(handle, model.uri, position, token);
|
||||
|
||||
prepareCallHierarchy: async (document, position, token) => {
|
||||
const result = await this._proxy.$prepareCallHierarchy(handle, document.uri, position, token);
|
||||
if (!result) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
dispose: () => this._proxy.$releaseCallHierarchy(handle, result.sessionId),
|
||||
root: MainThreadLanguageFeatures._reviveCallHierarchyItemDto(result.root)
|
||||
};
|
||||
},
|
||||
|
||||
provideOutgoingCalls: async (item, token) => {
|
||||
const outgoing = await this._proxy.$provideCallHierarchyOutgoingCalls(handle, item.id, token);
|
||||
if (!outgoing) {
|
||||
return outgoing;
|
||||
}
|
||||
return outgoing.map(([item, sourceRanges]): callh.OutgoingCall => {
|
||||
return outgoing.map(([item, fromRanges]): callh.OutgoingCall => {
|
||||
return {
|
||||
target: MainThreadLanguageFeatures._reviveCallHierarchyItemDto(item),
|
||||
sourceRanges
|
||||
to: MainThreadLanguageFeatures._reviveCallHierarchyItemDto(item),
|
||||
fromRanges
|
||||
};
|
||||
});
|
||||
},
|
||||
provideIncomingCalls: async (model, position, token) => {
|
||||
const incoming = await this._proxy.$provideCallHierarchyIncomingCalls(handle, model.uri, position, token);
|
||||
provideIncomingCalls: async (item, token) => {
|
||||
const incoming = await this._proxy.$provideCallHierarchyIncomingCalls(handle, item.id, token);
|
||||
if (!incoming) {
|
||||
return incoming;
|
||||
}
|
||||
return incoming.map(([item, sourceRanges]): callh.IncomingCall => {
|
||||
return incoming.map(([item, fromRanges]): callh.IncomingCall => {
|
||||
return {
|
||||
source: MainThreadLanguageFeatures._reviveCallHierarchyItemDto(item),
|
||||
sourceRanges
|
||||
from: MainThreadLanguageFeatures._reviveCallHierarchyItemDto(item),
|
||||
fromRanges
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ class MainThreadSCMProvider implements ISCMProvider {
|
||||
get rootUri(): URI | undefined { return this._rootUri; }
|
||||
get contextValue(): string { return this._contextValue; }
|
||||
|
||||
get commitTemplate(): string | undefined { return this.features.commitTemplate; }
|
||||
get commitTemplate(): string { return this.features.commitTemplate || ''; }
|
||||
get acceptInputCommand(): Command | undefined { return this.features.acceptInputCommand; }
|
||||
get statusBarCommands(): Command[] | undefined { return this.features.statusBarCommands; }
|
||||
get count(): number | undefined { return this.features.count; }
|
||||
@@ -288,7 +288,7 @@ export class MainThreadSCM implements MainThreadSCMShape {
|
||||
}
|
||||
|
||||
$registerSourceControl(handle: number, id: string, label: string, rootUri: UriComponents | undefined): void {
|
||||
const provider = new MainThreadSCMProvider(this._proxy, handle, id, label, rootUri && URI.revive(rootUri), this.scmService);
|
||||
const provider = new MainThreadSCMProvider(this._proxy, handle, id, label, rootUri ? URI.revive(rootUri) : undefined, this.scmService);
|
||||
const repository = this.scmService.registerSCMProvider(provider);
|
||||
this._repositories.set(handle, repository);
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ class TrimWhitespaceParticipant implements ISaveParticipantParticipant {
|
||||
// Nothing
|
||||
}
|
||||
|
||||
async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise<void> {
|
||||
async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise<void> {
|
||||
if (this.configurationService.getValue('files.trimTrailingWhitespace', { overrideIdentifier: model.textEditorModel.getLanguageIdentifier().language, resource: model.getResource() })) {
|
||||
this.doTrimTrailingWhitespace(model.textEditorModel, env.reason === SaveReason.AUTO);
|
||||
}
|
||||
@@ -112,7 +112,7 @@ export class FinalNewLineParticipant implements ISaveParticipantParticipant {
|
||||
// Nothing
|
||||
}
|
||||
|
||||
async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise<void> {
|
||||
async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise<void> {
|
||||
if (this.configurationService.getValue('files.insertFinalNewline', { overrideIdentifier: model.textEditorModel.getLanguageIdentifier().language, resource: model.getResource() })) {
|
||||
this.doInsertFinalNewLine(model.textEditorModel);
|
||||
}
|
||||
@@ -146,7 +146,7 @@ export class TrimFinalNewLinesParticipant implements ISaveParticipantParticipant
|
||||
// Nothing
|
||||
}
|
||||
|
||||
async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise<void> {
|
||||
async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise<void> {
|
||||
if (this.configurationService.getValue('files.trimFinalNewlines', { overrideIdentifier: model.textEditorModel.getLanguageIdentifier().language, resource: model.getResource() })) {
|
||||
this.doTrimFinalNewLines(model.textEditorModel, env.reason === SaveReason.AUTO);
|
||||
}
|
||||
@@ -216,7 +216,7 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant {
|
||||
// Nothing
|
||||
}
|
||||
|
||||
async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise<void> {
|
||||
async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise<void> {
|
||||
|
||||
const model = editorModel.textEditorModel;
|
||||
const overrides = { overrideIdentifier: model.getLanguageIdentifier().language, resource: model.uri };
|
||||
@@ -250,7 +250,7 @@ class CodeActionOnSaveParticipant implements ISaveParticipant {
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
) { }
|
||||
|
||||
async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise<void> {
|
||||
async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise<void> {
|
||||
if (env.reason === SaveReason.AUTO) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -333,7 +333,7 @@ class ExtHostSaveParticipant implements ISaveParticipantParticipant {
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDocumentSaveParticipant);
|
||||
}
|
||||
|
||||
async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise<void> {
|
||||
async participate(editorModel: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise<void> {
|
||||
|
||||
if (!shouldSynchronizeModel(editorModel.textEditorModel)) {
|
||||
// the model never made it to the extension
|
||||
@@ -344,10 +344,8 @@ class ExtHostSaveParticipant implements ISaveParticipantParticipant {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
setTimeout(() => reject(localize('timeout.onWillSave', "Aborted onWillSaveTextDocument-event after 1750ms")), 1750);
|
||||
this._proxy.$participateInSave(editorModel.getResource(), env.reason).then(values => {
|
||||
for (const success of values) {
|
||||
if (!success) {
|
||||
return Promise.reject(new Error('listener failed'));
|
||||
}
|
||||
if (!values.every(success => success)) {
|
||||
return Promise.reject(new Error('listener failed'));
|
||||
}
|
||||
return undefined;
|
||||
}).then(resolve, reject);
|
||||
@@ -384,7 +382,7 @@ export class SaveParticipant implements ISaveParticipant {
|
||||
this._saveParticipants.dispose();
|
||||
}
|
||||
|
||||
async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason }): Promise<void> {
|
||||
async participate(model: IResolvedTextFileEditorModel, env: { reason: SaveReason; }): Promise<void> {
|
||||
return this._progressService.withProgress({ location: ProgressLocation.Window }, progress => {
|
||||
progress.report({ message: localize('saveParticipants', "Running Save Participants...") });
|
||||
const promiseFactory = this._saveParticipants.getValue().map(p => () => {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IStatusbarService, StatusbarAlignment as MainThreadStatusBarAlignment, IStatusbarEntryAccessor, IStatusbarEntry } from 'vs/platform/statusbar/common/statusbar';
|
||||
import { IStatusbarService, StatusbarAlignment as MainThreadStatusBarAlignment, IStatusbarEntryAccessor, IStatusbarEntry } from 'vs/workbench/services/statusbar/common/statusbar';
|
||||
import { MainThreadStatusBarShape, MainContext, IExtHostContext } from '../common/extHost.protocol';
|
||||
import { ThemeColor } from 'vs/platform/theme/common/themeService';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
@@ -24,9 +24,13 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape {
|
||||
this.entries.clear();
|
||||
}
|
||||
|
||||
$setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string, command: string, color: string | ThemeColor, alignment: MainThreadStatusBarAlignment, priority: number): void {
|
||||
$setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string | undefined, command: string | undefined, color: string | ThemeColor | undefined, alignment: MainThreadStatusBarAlignment, priority: number | undefined): void {
|
||||
const entry: IStatusbarEntry = { text, tooltip, command, color };
|
||||
|
||||
if (typeof priority === 'undefined') {
|
||||
priority = 0;
|
||||
}
|
||||
|
||||
// Reset existing entry if alignment or priority changed
|
||||
let existingEntry = this.entries.get(id);
|
||||
if (existingEntry && (existingEntry.alignment !== alignment || existingEntry.priority !== priority)) {
|
||||
|
||||
@@ -29,7 +29,7 @@ import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { ExtHostContext, MainThreadTaskShape, ExtHostTaskShape, MainContext, IExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import {
|
||||
TaskDefinitionDTO, TaskExecutionDTO, ProcessExecutionOptionsDTO, TaskPresentationOptionsDTO,
|
||||
ProcessExecutionDTO, ShellExecutionDTO, ShellExecutionOptionsDTO, CustomExecution2DTO, TaskDTO, TaskSourceDTO, TaskHandleDTO, TaskFilterDTO, TaskProcessStartedDTO, TaskProcessEndedDTO, TaskSystemInfoDTO,
|
||||
ProcessExecutionDTO, ShellExecutionDTO, ShellExecutionOptionsDTO, CustomExecutionDTO, TaskDTO, TaskSourceDTO, TaskHandleDTO, TaskFilterDTO, TaskProcessStartedDTO, TaskProcessEndedDTO, TaskSystemInfoDTO,
|
||||
RunOptionsDTO
|
||||
} from 'vs/workbench/api/common/shared/tasks';
|
||||
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
|
||||
@@ -131,7 +131,7 @@ namespace ProcessExecutionOptionsDTO {
|
||||
}
|
||||
|
||||
namespace ProcessExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecution2DTO): value is ProcessExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecutionDTO): value is ProcessExecutionDTO {
|
||||
const candidate = value as ProcessExecutionDTO;
|
||||
return candidate && !!candidate.process;
|
||||
}
|
||||
@@ -199,7 +199,7 @@ namespace ShellExecutionOptionsDTO {
|
||||
}
|
||||
|
||||
namespace ShellExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecution2DTO): value is ShellExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecutionDTO): value is ShellExecutionDTO {
|
||||
const candidate = value as ShellExecutionDTO;
|
||||
return candidate && (!!candidate.commandLine || !!candidate.command);
|
||||
}
|
||||
@@ -230,21 +230,21 @@ namespace ShellExecutionDTO {
|
||||
}
|
||||
}
|
||||
|
||||
namespace CustomExecution2DTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecution2DTO): value is CustomExecution2DTO {
|
||||
const candidate = value as CustomExecution2DTO;
|
||||
return candidate && candidate.customExecution === 'customExecution2';
|
||||
namespace CustomExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomExecutionDTO): value is CustomExecutionDTO {
|
||||
const candidate = value as CustomExecutionDTO;
|
||||
return candidate && candidate.customExecution === 'customExecution';
|
||||
}
|
||||
|
||||
export function from(value: CommandConfiguration): CustomExecution2DTO {
|
||||
export function from(value: CommandConfiguration): CustomExecutionDTO {
|
||||
return {
|
||||
customExecution: 'customExecution2'
|
||||
customExecution: 'customExecution'
|
||||
};
|
||||
}
|
||||
|
||||
export function to(value: CustomExecution2DTO): CommandConfiguration {
|
||||
export function to(value: CustomExecutionDTO): CommandConfiguration {
|
||||
return {
|
||||
runtime: RuntimeType.CustomExecution2,
|
||||
runtime: RuntimeType.CustomExecution,
|
||||
presentation: undefined
|
||||
};
|
||||
}
|
||||
@@ -264,7 +264,7 @@ namespace TaskSourceDTO {
|
||||
}
|
||||
} else if (value.kind === TaskSourceKind.Workspace) {
|
||||
result.extensionId = '$core';
|
||||
result.scope = value.config.workspaceFolder.uri;
|
||||
result.scope = value.config.workspaceFolder ? value.config.workspaceFolder.uri : TaskScope.Global;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -311,7 +311,7 @@ namespace TaskDTO {
|
||||
const result: TaskDTO = {
|
||||
_id: task._id,
|
||||
name: task.configurationProperties.name,
|
||||
definition: TaskDefinitionDTO.from(task.getDefinition()),
|
||||
definition: TaskDefinitionDTO.from(task.getDefinition(true)),
|
||||
source: TaskSourceDTO.from(task._source),
|
||||
execution: undefined,
|
||||
presentationOptions: !ConfiguringTask.is(task) && task.command ? TaskPresentationOptionsDTO.from(task.command.presentation) : undefined,
|
||||
@@ -323,6 +323,9 @@ namespace TaskDTO {
|
||||
if (task.configurationProperties.group) {
|
||||
result.group = task.configurationProperties.group;
|
||||
}
|
||||
if (task.configurationProperties.detail) {
|
||||
result.detail = task.configurationProperties.detail;
|
||||
}
|
||||
if (!ConfiguringTask.is(task) && task.command) {
|
||||
if (task.command.runtime === RuntimeType.Process) {
|
||||
result.execution = ProcessExecutionDTO.from(task.command);
|
||||
@@ -351,8 +354,8 @@ namespace TaskDTO {
|
||||
command = ShellExecutionDTO.to(task.execution);
|
||||
} else if (ProcessExecutionDTO.is(task.execution)) {
|
||||
command = ProcessExecutionDTO.to(task.execution);
|
||||
} else if (CustomExecution2DTO.is(task.execution)) {
|
||||
command = CustomExecution2DTO.to(task.execution);
|
||||
} else if (CustomExecutionDTO.is(task.execution)) {
|
||||
command = CustomExecutionDTO.to(task.execution);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,6 +383,7 @@ namespace TaskDTO {
|
||||
group: task.group,
|
||||
isBackground: !!task.isBackground,
|
||||
problemMatchers: task.problemMatchers.slice(),
|
||||
detail: task.detail
|
||||
}
|
||||
);
|
||||
return result;
|
||||
|
||||
@@ -12,6 +12,7 @@ import { StopWatch } from 'vs/base/common/stopwatch';
|
||||
import { ITerminalInstanceService, ITerminalService, ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { TerminalDataBufferer } from 'vs/workbench/contrib/terminal/common/terminalDataBuffering';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadTerminalService)
|
||||
export class MainThreadTerminalService implements MainThreadTerminalServiceShape {
|
||||
@@ -327,16 +328,23 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
* listeners are removed.
|
||||
*/
|
||||
class TerminalDataEventTracker extends Disposable {
|
||||
private readonly _bufferer: TerminalDataBufferer;
|
||||
|
||||
constructor(
|
||||
private readonly _callback: (id: number, data: string) => void,
|
||||
@ITerminalService private readonly _terminalService: ITerminalService
|
||||
) {
|
||||
super();
|
||||
|
||||
this._register(this._bufferer = new TerminalDataBufferer());
|
||||
|
||||
this._terminalService.terminalInstances.forEach(instance => this._registerInstance(instance));
|
||||
this._register(this._terminalService.onInstanceCreated(instance => this._registerInstance(instance)));
|
||||
this._register(this._terminalService.onInstanceDisposed(instance => this._bufferer.stopBuffering(instance.id)));
|
||||
}
|
||||
|
||||
private _registerInstance(instance: ITerminalInstance): void {
|
||||
this._register(instance.onData(e => this._callback(instance.id, e)));
|
||||
// Buffer data events to reduce the amount of messages going to the extension host
|
||||
this._register(this._bufferer.startBuffering(instance.id, instance.onData, this._callback));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { ExtHostContext, IExtHostContext, MainContext, MainThreadUrlsShape, ExtHostUrlsShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { extHostNamedCustomer } from '../common/extHostCustomers';
|
||||
import { IURLService, IURLHandler } from 'vs/platform/url/common/url';
|
||||
import { IURLService, IURLHandler, IOpenURLOptions } from 'vs/platform/url/common/url';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IExtensionUrlHandler } from 'vs/workbench/services/extensions/browser/extensionUrlHandler';
|
||||
@@ -19,7 +19,7 @@ class ExtensionUrlHandler implements IURLHandler {
|
||||
readonly extensionId: ExtensionIdentifier
|
||||
) { }
|
||||
|
||||
handleURL(uri: URI): Promise<boolean> {
|
||||
handleURL(uri: URI, options?: IOpenURLOptions): Promise<boolean> {
|
||||
if (!ExtensionIdentifier.equals(this.extensionId, uri.authority)) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
@@ -68,7 +68,11 @@ export class MainThreadUrls implements MainThreadUrlsShape {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
async $createAppUri(extensionId: ExtensionIdentifier, options?: { payload?: Partial<UriComponents> }): Promise<URI> {
|
||||
async $createAppUri(uri: UriComponents): Promise<URI> {
|
||||
return this.urlService.create(uri);
|
||||
}
|
||||
|
||||
async $proposedCreateAppUri(extensionId: ExtensionIdentifier, options?: { payload?: Partial<UriComponents> }): Promise<URI> {
|
||||
const payload: Partial<UriComponents> = options && options.payload ? options.payload : Object.create(null);
|
||||
|
||||
// we define the authority to be the extension ID to ensure
|
||||
|
||||
@@ -5,23 +5,24 @@
|
||||
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
import { startsWith } from 'vs/base/common/strings';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { localize } from 'vs/nls';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ExtHostContext, ExtHostWebviewsShape, IExtHostContext, MainContext, MainThreadWebviewsShape, WebviewPanelHandle, WebviewPanelShowOptions, WebviewPanelViewStateData } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { editorGroupToViewColumn, EditorViewColumn, viewColumnToEditorGroup } from 'vs/workbench/api/common/shared/editor';
|
||||
import { IEditorInput } from 'vs/workbench/common/editor';
|
||||
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
|
||||
import { CustomFileEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput';
|
||||
import { WebviewExtensionDescription } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { WebviewInput } from 'vs/workbench/contrib/webview/browser/webviewEditorInput';
|
||||
import { ICreateWebViewShowOptions, IWebviewEditorService, WebviewInputOptions } from 'vs/workbench/contrib/webview/browser/webviewEditorService';
|
||||
import { ICreateWebViewShowOptions, IWebviewWorkbenchService, WebviewInputOptions } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService';
|
||||
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
@@ -30,7 +31,7 @@ import { extHostNamedCustomer } from '../common/extHostCustomers';
|
||||
/**
|
||||
* Bi-directional map between webview handles and inputs.
|
||||
*/
|
||||
class WebviewHandleStore {
|
||||
class WebviewInputStore {
|
||||
private readonly _handlesToInputs = new Map<string, WebviewInput>();
|
||||
private readonly _inputsToHandles = new Map<WebviewInput, string>();
|
||||
|
||||
@@ -60,47 +61,66 @@ class WebviewHandleStore {
|
||||
}
|
||||
}
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadWebviews)
|
||||
export class MainThreadWebviews extends Disposable implements MainThreadWebviewsShape {
|
||||
class WebviewViewTypeTransformer {
|
||||
public constructor(
|
||||
public readonly prefix: string,
|
||||
) { }
|
||||
|
||||
public fromExternal(viewType: string): string {
|
||||
return this.prefix + viewType;
|
||||
}
|
||||
|
||||
public toExternal(viewType: string): string | undefined {
|
||||
return startsWith(viewType, this.prefix)
|
||||
? viewType.substr(this.prefix.length)
|
||||
: undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const webviewPanelViewType = new WebviewViewTypeTransformer('mainThreadWebview-');
|
||||
|
||||
@extHostNamedCustomer(extHostProtocol.MainContext.MainThreadWebviews)
|
||||
export class MainThreadWebviews extends Disposable implements extHostProtocol.MainThreadWebviewsShape {
|
||||
|
||||
private static readonly standardSupportedLinkSchemes = new Set([
|
||||
'http',
|
||||
'https',
|
||||
'mailto',
|
||||
'vscode',
|
||||
Schemas.http,
|
||||
Schemas.https,
|
||||
Schemas.mailto,
|
||||
Schemas.vscode,
|
||||
'vscode-insider',
|
||||
]);
|
||||
|
||||
private readonly _proxy: ExtHostWebviewsShape;
|
||||
private readonly _webviewEditorInputs = new WebviewHandleStore();
|
||||
private readonly _proxy: extHostProtocol.ExtHostWebviewsShape;
|
||||
private readonly _webviewInputs = new WebviewInputStore();
|
||||
private readonly _revivers = new Map<string, IDisposable>();
|
||||
private readonly _editorProviders = new Map<string, IDisposable>();
|
||||
|
||||
constructor(
|
||||
context: IExtHostContext,
|
||||
context: extHostProtocol.IExtHostContext,
|
||||
@IExtensionService extensionService: IExtensionService,
|
||||
@IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService,
|
||||
@IEditorService private readonly _editorService: IEditorService,
|
||||
@IWebviewEditorService private readonly _webviewEditorService: IWebviewEditorService,
|
||||
@IOpenerService private readonly _openerService: IOpenerService,
|
||||
@ITelemetryService private readonly _telemetryService: ITelemetryService,
|
||||
@IProductService private readonly _productService: IProductService,
|
||||
@ITelemetryService private readonly _telemetryService: ITelemetryService,
|
||||
@IWebviewWorkbenchService private readonly _webviewWorkbenchService: IWebviewWorkbenchService,
|
||||
) {
|
||||
super();
|
||||
|
||||
this._proxy = context.getProxy(ExtHostContext.ExtHostWebviews);
|
||||
this._proxy = context.getProxy(extHostProtocol.ExtHostContext.ExtHostWebviews);
|
||||
this._register(_editorService.onDidActiveEditorChange(this.updateWebviewViewStates, this));
|
||||
this._register(_editorService.onDidVisibleEditorsChange(this.updateWebviewViewStates, this));
|
||||
|
||||
// This reviver's only job is to activate webview panel extensions
|
||||
// This should trigger the real reviver to be registered from the extension host side.
|
||||
this._register(_webviewEditorService.registerResolver({
|
||||
this._register(_webviewWorkbenchService.registerResolver({
|
||||
canResolve: (webview: WebviewInput) => {
|
||||
if (webview.getTypeId() === CustomFileEditorInput.typeId) {
|
||||
if (webview instanceof CustomFileEditorInput) {
|
||||
extensionService.activateByEvent(`onWebviewEditor:${webview.viewType}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
const viewType = this.fromInternalWebviewViewType(webview.viewType);
|
||||
const viewType = webviewPanelViewType.toExternal(webview.viewType);
|
||||
if (typeof viewType === 'string') {
|
||||
extensionService.activateByEvent(`onWebviewPanel:${viewType}`);
|
||||
}
|
||||
@@ -111,13 +131,12 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
|
||||
}
|
||||
|
||||
public $createWebviewPanel(
|
||||
handle: WebviewPanelHandle,
|
||||
extensionData: extHostProtocol.WebviewExtensionDescription,
|
||||
handle: extHostProtocol.WebviewPanelHandle,
|
||||
viewType: string,
|
||||
title: string,
|
||||
showOptions: { viewColumn?: EditorViewColumn, preserveFocus?: boolean },
|
||||
options: WebviewInputOptions,
|
||||
extensionId: ExtensionIdentifier,
|
||||
extensionLocation: UriComponents
|
||||
showOptions: { viewColumn?: EditorViewColumn, preserveFocus?: boolean; },
|
||||
options: WebviewInputOptions
|
||||
): void {
|
||||
const mainThreadShowOptions: ICreateWebViewShowOptions = Object.create(null);
|
||||
if (showOptions) {
|
||||
@@ -125,68 +144,59 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
|
||||
mainThreadShowOptions.group = viewColumnToEditorGroup(this._editorGroupService, showOptions.viewColumn);
|
||||
}
|
||||
|
||||
const webview = this._webviewEditorService.createWebview(handle, this.getInternalWebviewViewType(viewType), title, mainThreadShowOptions, reviveWebviewOptions(options), {
|
||||
location: URI.revive(extensionLocation),
|
||||
id: extensionId
|
||||
});
|
||||
const extension = reviveWebviewExtension(extensionData);
|
||||
const webview = this._webviewWorkbenchService.createWebview(handle, webviewPanelViewType.fromExternal(viewType), title, mainThreadShowOptions, reviveWebviewOptions(options), extension);
|
||||
this.hookupWebviewEventDelegate(handle, webview);
|
||||
|
||||
this._webviewEditorInputs.add(handle, webview);
|
||||
this._webviewInputs.add(handle, webview);
|
||||
|
||||
/* __GDPR__
|
||||
"webviews:createWebviewPanel" : {
|
||||
"extensionId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
this._telemetryService.publicLog('webviews:createWebviewPanel', { extensionId: extensionId.value });
|
||||
this._telemetryService.publicLog('webviews:createWebviewPanel', { extensionId: extension.id.value });
|
||||
}
|
||||
|
||||
public $disposeWebview(handle: WebviewPanelHandle): void {
|
||||
const webview = this.getWebviewEditorInput(handle);
|
||||
public $disposeWebview(handle: extHostProtocol.WebviewPanelHandle): void {
|
||||
const webview = this.getWebviewInput(handle);
|
||||
webview.dispose();
|
||||
}
|
||||
|
||||
public $setTitle(handle: WebviewPanelHandle, value: string): void {
|
||||
const webview = this.getWebviewEditorInput(handle);
|
||||
public $setTitle(handle: extHostProtocol.WebviewPanelHandle, value: string): void {
|
||||
const webview = this.getWebviewInput(handle);
|
||||
webview.setName(value);
|
||||
}
|
||||
|
||||
public $setState(handle: WebviewPanelHandle, state: modes.WebviewEditorState): void {
|
||||
const webview = this.getWebviewEditorInput(handle);
|
||||
if (webview instanceof CustomFileEditorInput) {
|
||||
webview.setState(state);
|
||||
}
|
||||
}
|
||||
|
||||
public $setIconPath(handle: WebviewPanelHandle, value: { light: UriComponents, dark: UriComponents } | undefined): void {
|
||||
const webview = this.getWebviewEditorInput(handle);
|
||||
public $setIconPath(handle: extHostProtocol.WebviewPanelHandle, value: { light: UriComponents, dark: UriComponents; } | undefined): void {
|
||||
const webview = this.getWebviewInput(handle);
|
||||
webview.iconPath = reviveWebviewIcon(value);
|
||||
}
|
||||
|
||||
public $setHtml(handle: WebviewPanelHandle, value: string): void {
|
||||
const webview = this.getWebviewEditorInput(handle);
|
||||
public $setHtml(handle: extHostProtocol.WebviewPanelHandle, value: string): void {
|
||||
const webview = this.getWebviewInput(handle);
|
||||
webview.webview.html = value;
|
||||
}
|
||||
|
||||
public $setOptions(handle: WebviewPanelHandle, options: modes.IWebviewOptions): void {
|
||||
const webview = this.getWebviewEditorInput(handle);
|
||||
webview.webview.contentOptions = reviveWebviewOptions(options as any /*todo@mat */);
|
||||
public $setOptions(handle: extHostProtocol.WebviewPanelHandle, options: modes.IWebviewOptions): void {
|
||||
const webview = this.getWebviewInput(handle);
|
||||
webview.webview.contentOptions = reviveWebviewOptions(options);
|
||||
}
|
||||
|
||||
public $reveal(handle: WebviewPanelHandle, showOptions: WebviewPanelShowOptions): void {
|
||||
const webview = this.getWebviewEditorInput(handle);
|
||||
public $reveal(handle: extHostProtocol.WebviewPanelHandle, showOptions: extHostProtocol.WebviewPanelShowOptions): void {
|
||||
const webview = this.getWebviewInput(handle);
|
||||
if (webview.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const targetGroup = this._editorGroupService.getGroup(viewColumnToEditorGroup(this._editorGroupService, showOptions.viewColumn)) || this._editorGroupService.getGroup(webview.group || 0);
|
||||
if (targetGroup) {
|
||||
this._webviewEditorService.revealWebview(webview, targetGroup, !!showOptions.preserveFocus);
|
||||
this._webviewWorkbenchService.revealWebview(webview, targetGroup, !!showOptions.preserveFocus);
|
||||
}
|
||||
}
|
||||
|
||||
public async $postMessage(handle: WebviewPanelHandle, message: any): Promise<boolean> {
|
||||
const webview = this.getWebviewEditorInput(handle);
|
||||
public async $postMessage(handle: extHostProtocol.WebviewPanelHandle, message: any): Promise<boolean> {
|
||||
const webview = this.getWebviewInput(handle);
|
||||
webview.webview.sendMessage(message);
|
||||
return true;
|
||||
}
|
||||
@@ -196,35 +206,35 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
|
||||
throw new Error(`Reviver for ${viewType} already registered`);
|
||||
}
|
||||
|
||||
this._revivers.set(viewType, this._webviewEditorService.registerResolver({
|
||||
canResolve: (webviewEditorInput) => {
|
||||
return webviewEditorInput.viewType === this.getInternalWebviewViewType(viewType);
|
||||
this._revivers.set(viewType, this._webviewWorkbenchService.registerResolver({
|
||||
canResolve: (webviewInput) => {
|
||||
return webviewInput.viewType === webviewPanelViewType.fromExternal(viewType);
|
||||
},
|
||||
resolveWebview: async (webviewEditorInput): Promise<void> => {
|
||||
const viewType = this.fromInternalWebviewViewType(webviewEditorInput.viewType);
|
||||
resolveWebview: async (webviewInput): Promise<void> => {
|
||||
const viewType = webviewPanelViewType.toExternal(webviewInput.viewType);
|
||||
if (!viewType) {
|
||||
webviewEditorInput.webview.html = MainThreadWebviews.getDeserializationFailedContents(webviewEditorInput.viewType);
|
||||
webviewInput.webview.html = MainThreadWebviews.getDeserializationFailedContents(webviewInput.viewType);
|
||||
return;
|
||||
}
|
||||
|
||||
const handle = webviewEditorInput.id;
|
||||
this._webviewEditorInputs.add(handle, webviewEditorInput);
|
||||
this.hookupWebviewEventDelegate(handle, webviewEditorInput);
|
||||
const handle = webviewInput.id;
|
||||
this._webviewInputs.add(handle, webviewInput);
|
||||
this.hookupWebviewEventDelegate(handle, webviewInput);
|
||||
|
||||
let state = undefined;
|
||||
if (webviewEditorInput.webview.state) {
|
||||
if (webviewInput.webview.state) {
|
||||
try {
|
||||
state = JSON.parse(webviewEditorInput.webview.state);
|
||||
state = JSON.parse(webviewInput.webview.state);
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await this._proxy.$deserializeWebviewPanel(handle, viewType, webviewEditorInput.getTitle(), state, editorGroupToViewColumn(this._editorGroupService, webviewEditorInput.group || 0), webviewEditorInput.webview.options);
|
||||
await this._proxy.$deserializeWebviewPanel(handle, viewType, webviewInput.getTitle(), state, editorGroupToViewColumn(this._editorGroupService, webviewInput.group || 0), webviewInput.webview.options);
|
||||
} catch (error) {
|
||||
onUnexpectedError(error);
|
||||
webviewEditorInput.webview.html = MainThreadWebviews.getDeserializationFailedContents(viewType);
|
||||
webviewInput.webview.html = MainThreadWebviews.getDeserializationFailedContents(viewType);
|
||||
}
|
||||
}
|
||||
}));
|
||||
@@ -240,39 +250,37 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
|
||||
this._revivers.delete(viewType);
|
||||
}
|
||||
|
||||
public $registerEditorProvider(viewType: string): void {
|
||||
public $registerEditorProvider(extensionData: extHostProtocol.WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions): void {
|
||||
if (this._editorProviders.has(viewType)) {
|
||||
throw new Error(`Provider for ${viewType} already registered`);
|
||||
}
|
||||
|
||||
this._editorProviders.set(viewType, this._webviewEditorService.registerResolver({
|
||||
canResolve: (webviewEditorInput) => {
|
||||
return webviewEditorInput.getTypeId() !== WebviewInput.typeId && webviewEditorInput.viewType === viewType;
|
||||
},
|
||||
resolveWebview: async (webview) => {
|
||||
const handle = generateUuid();
|
||||
this._webviewEditorInputs.add(handle, webview);
|
||||
this.hookupWebviewEventDelegate(handle, webview);
|
||||
const extension = reviveWebviewExtension(extensionData);
|
||||
|
||||
if (webview instanceof CustomFileEditorInput) {
|
||||
webview.onWillSave(e => {
|
||||
e.waitUntil(this._proxy.$save(handle));
|
||||
});
|
||||
}
|
||||
this._editorProviders.set(viewType, this._webviewWorkbenchService.registerResolver({
|
||||
canResolve: (webviewInput) => {
|
||||
return webviewInput instanceof CustomFileEditorInput && webviewInput.viewType === viewType;
|
||||
},
|
||||
resolveWebview: async (webviewInput) => {
|
||||
const handle = webviewInput.id;
|
||||
this._webviewInputs.add(handle, webviewInput);
|
||||
this.hookupWebviewEventDelegate(handle, webviewInput);
|
||||
|
||||
webviewInput.webview.options = options;
|
||||
webviewInput.webview.extension = extension;
|
||||
|
||||
try {
|
||||
await this._proxy.$resolveWebviewEditor(
|
||||
webview.getResource(),
|
||||
webviewInput.getResource(),
|
||||
handle,
|
||||
viewType,
|
||||
webview.getTitle(),
|
||||
webview.webview.state,
|
||||
editorGroupToViewColumn(this._editorGroupService, webview.group || 0),
|
||||
webview.webview.options
|
||||
webviewInput.getTitle(),
|
||||
editorGroupToViewColumn(this._editorGroupService, webviewInput.group || 0),
|
||||
webviewInput.webview.options
|
||||
);
|
||||
} catch (error) {
|
||||
onUnexpectedError(error);
|
||||
webview.webview.html = MainThreadWebviews.getDeserializationFailedContents(viewType);
|
||||
webviewInput.webview.html = MainThreadWebviews.getDeserializationFailedContents(viewType);
|
||||
}
|
||||
}
|
||||
}));
|
||||
@@ -288,42 +296,24 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
|
||||
this._editorProviders.delete(viewType);
|
||||
}
|
||||
|
||||
private getInternalWebviewViewType(viewType: string): string {
|
||||
return `mainThreadWebview-${viewType}`;
|
||||
}
|
||||
|
||||
private fromInternalWebviewViewType(viewType: string): string | undefined {
|
||||
if (!startsWith(viewType, 'mainThreadWebview-')) {
|
||||
return undefined;
|
||||
}
|
||||
return viewType.replace(/^mainThreadWebview-/, '');
|
||||
}
|
||||
|
||||
private hookupWebviewEventDelegate(handle: WebviewPanelHandle, input: WebviewInput) {
|
||||
private hookupWebviewEventDelegate(handle: extHostProtocol.WebviewPanelHandle, input: WebviewInput) {
|
||||
input.webview.onDidClickLink((uri: URI) => this.onDidClickLink(handle, uri));
|
||||
input.webview.onMessage((message: any) => this._proxy.$onMessage(handle, message));
|
||||
input.onDispose(() => {
|
||||
this._proxy.$onDidDisposeWebviewPanel(handle).finally(() => {
|
||||
this._webviewEditorInputs.delete(handle);
|
||||
this._webviewInputs.delete(handle);
|
||||
});
|
||||
});
|
||||
input.webview.onDidUpdateState((newState: any) => {
|
||||
const webview = this.tryGetWebviewEditorInput(handle);
|
||||
if (!webview || webview.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
webview.webview.state = newState;
|
||||
});
|
||||
input.webview.onMissingCsp((extension: ExtensionIdentifier) => this._proxy.$onMissingCsp(handle, extension.value));
|
||||
}
|
||||
|
||||
private updateWebviewViewStates() {
|
||||
if (!this._webviewEditorInputs.size) {
|
||||
if (!this._webviewInputs.size) {
|
||||
return;
|
||||
}
|
||||
|
||||
const activeInput = this._editorService.activeControl && this._editorService.activeControl.input;
|
||||
const viewStates: WebviewPanelViewStateData = {};
|
||||
const viewStates: extHostProtocol.WebviewPanelViewStateData = {};
|
||||
|
||||
const updateViewStatesForInput = (group: IEditorGroup, topLevelInput: IEditorInput, editorInput: IEditorInput) => {
|
||||
if (!(editorInput instanceof WebviewInput)) {
|
||||
@@ -332,11 +322,11 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
|
||||
|
||||
editorInput.updateGroup(group.id);
|
||||
|
||||
const handle = this._webviewEditorInputs.getHandleForInput(editorInput);
|
||||
const handle = this._webviewInputs.getHandleForInput(editorInput);
|
||||
if (handle) {
|
||||
viewStates[handle] = {
|
||||
visible: topLevelInput.matches(group.activeEditor),
|
||||
active: topLevelInput.matches(activeInput),
|
||||
visible: topLevelInput === group.activeEditor,
|
||||
active: topLevelInput === activeInput,
|
||||
position: editorGroupToViewColumn(this._editorGroupService, group.id),
|
||||
};
|
||||
}
|
||||
@@ -358,10 +348,10 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
|
||||
}
|
||||
}
|
||||
|
||||
private onDidClickLink(handle: WebviewPanelHandle, link: URI): void {
|
||||
const webview = this.getWebviewEditorInput(handle);
|
||||
private onDidClickLink(handle: extHostProtocol.WebviewPanelHandle, link: URI): void {
|
||||
const webview = this.getWebviewInput(handle);
|
||||
if (this.isSupportedLink(webview, link)) {
|
||||
this._openerService.open(link);
|
||||
this._openerService.open(link, { fromUserGesture: true });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,19 +362,19 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
|
||||
if (!isWeb && this._productService.urlProtocol === link.scheme) {
|
||||
return true;
|
||||
}
|
||||
return !!webview.webview.contentOptions.enableCommandUris && link.scheme === 'command';
|
||||
return !!webview.webview.contentOptions.enableCommandUris && link.scheme === Schemas.command;
|
||||
}
|
||||
|
||||
private getWebviewEditorInput(handle: WebviewPanelHandle): WebviewInput {
|
||||
const webview = this.tryGetWebviewEditorInput(handle);
|
||||
private getWebviewInput(handle: extHostProtocol.WebviewPanelHandle): WebviewInput {
|
||||
const webview = this.tryGetWebviewInput(handle);
|
||||
if (!webview) {
|
||||
throw new Error('Unknown webview handle:' + handle);
|
||||
}
|
||||
return webview;
|
||||
}
|
||||
|
||||
private tryGetWebviewEditorInput(handle: WebviewPanelHandle): WebviewInput | undefined {
|
||||
return this._webviewEditorInputs.getInputForHandle(handle);
|
||||
private tryGetWebviewInput(handle: extHostProtocol.WebviewPanelHandle): WebviewInput | undefined {
|
||||
return this._webviewInputs.getInputForHandle(handle);
|
||||
}
|
||||
|
||||
private static getDeserializationFailedContents(viewType: string) {
|
||||
@@ -399,6 +389,10 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
|
||||
}
|
||||
}
|
||||
|
||||
function reviveWebviewExtension(extensionData: extHostProtocol.WebviewExtensionDescription): WebviewExtensionDescription {
|
||||
return { id: extensionData.id, location: URI.revive(extensionData.location) };
|
||||
}
|
||||
|
||||
function reviveWebviewOptions(options: modes.IWebviewOptions): WebviewInputOptions {
|
||||
return {
|
||||
...options,
|
||||
@@ -407,10 +401,9 @@ function reviveWebviewOptions(options: modes.IWebviewOptions): WebviewInputOptio
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function reviveWebviewIcon(
|
||||
value: { light: UriComponents, dark: UriComponents } | undefined
|
||||
): { light: URI, dark: URI } | undefined {
|
||||
value: { light: UriComponents, dark: UriComponents; } | undefined
|
||||
): { light: URI, dark: URI; } | undefined {
|
||||
if (!value) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ import { Event } from 'vs/base/common/event';
|
||||
import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { ExtHostContext, ExtHostWindowShape, IExtHostContext, IOpenUriOptions, MainContext, MainThreadWindowShape } from '../common/extHost.protocol';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadWindow)
|
||||
export class MainThreadWindow implements MainThreadWindowShape {
|
||||
@@ -20,12 +20,12 @@ export class MainThreadWindow implements MainThreadWindowShape {
|
||||
|
||||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@IHostService private readonly hostService: IHostService,
|
||||
@IOpenerService private readonly openerService: IOpenerService,
|
||||
) {
|
||||
this.proxy = extHostContext.getProxy(ExtHostContext.ExtHostWindow);
|
||||
|
||||
Event.latch(windowService.onDidChangeFocus)
|
||||
Event.latch(hostService.onDidChangeFocus)
|
||||
(this.proxy.$onDidChangeWindowFocus, this.proxy, this.disposables);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ export class MainThreadWindow implements MainThreadWindowShape {
|
||||
}
|
||||
|
||||
$getWindowVisibility(): Promise<boolean> {
|
||||
return this.windowService.isFocused();
|
||||
return Promise.resolve(this.hostService.hasFocus);
|
||||
}
|
||||
|
||||
async $openUri(uriComponents: UriComponents, options: IOpenUriOptions): Promise<boolean> {
|
||||
@@ -47,7 +47,7 @@ export class MainThreadWindow implements MainThreadWindowShape {
|
||||
return this.openerService.open(uri, { openExternal: true, allowTunneling: options.allowTunneling });
|
||||
}
|
||||
|
||||
async $resolveExternalUri(uriComponents: UriComponents, options: IOpenUriOptions): Promise<UriComponents> {
|
||||
async $asExternalUri(uriComponents: UriComponents, options: IOpenUriOptions): Promise<UriComponents> {
|
||||
const uri = URI.revive(uriComponents);
|
||||
const result = await this.openerService.resolveExternalUri(uri, options);
|
||||
return result.resolved;
|
||||
|
||||
@@ -16,10 +16,10 @@ import { IWorkspaceContextService, WorkbenchState, IWorkspace } from 'vs/platfor
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { ITextQueryBuilderOptions, QueryBuilder } from 'vs/workbench/contrib/search/common/queryBuilder';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
|
||||
import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing';
|
||||
import { ExtHostContext, ExtHostWorkspaceShape, IExtHostContext, MainContext, MainThreadWorkspaceShape, IWorkspaceData, ITextSearchComplete } from '../common/extHost.protocol';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { isEqualOrParent } from 'vs/base/common/resources';
|
||||
import { isUntitledWorkspace } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
@@ -121,7 +121,7 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
|
||||
}
|
||||
return {
|
||||
configuration: workspace.configuration || undefined,
|
||||
isUntitled: workspace.configuration ? isEqualOrParent(workspace.configuration, this._environmentService.untitledWorkspacesHome) : false,
|
||||
isUntitled: workspace.configuration ? isUntitledWorkspace(workspace.configuration, this._environmentService) : false,
|
||||
folders: workspace.folders,
|
||||
id: workspace.id,
|
||||
name: this._labelService.getWorkspaceLabel(workspace)
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="Canvas" fill="none">
|
||||
<g id="beaker">
|
||||
<g id="Shape">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M 20.7596 21.885L 15.6896 10.5L 15.6896 4.5L 17.1896 4.5L 17.1896 3L 3.68959 3L 3.68959 4.5L 5.18959 4.5L 5.18959 10.5L 0.134588 21.885C -0.315412 22.875 0.419588 24 1.49959 24L 19.4096 24C 20.4896 24 21.2096 22.875 20.7746 21.885L 20.7596 21.885ZM 4.81458 15L 6.68958 10.5L 6.68958 4.5L 14.1896 4.5L 14.1896 10.5L 16.0646 15L 4.81458 15ZM 11.1896 12L 12.6896 12L 12.6896 13.5L 11.1896 13.5L 11.1896 12ZM 9.68958 10.5L 8.18958 10.5L 8.18958 9L 9.68958 9L 9.68958 10.5ZM 9.68958 6L 11.1896 6L 11.1896 7.5L 9.68958 7.5L 9.68958 6ZM 9.68958 1.5L 8.18958 1.5L 8.18958 0L 9.68958 0L 9.68958 1.5Z" transform="translate(0.810059 0)" fill="white"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20.8394 20.337L14.9999 9.009V3.009H16.4999V1.509H14.9909V1.5L14.3069 1.5075H7.4999V3H8.9999V8.928L3.1589 20.3415C3.04535 20.57 2.99197 20.8237 3.00381 21.0786C3.01566 21.3335 3.09234 21.5812 3.22659 21.7982C3.36085 22.0152 3.54825 22.1944 3.77106 22.3187C3.99387 22.4431 4.24473 22.5086 4.4999 22.509H19.4999C19.7556 22.5087 20.0069 22.4431 20.2301 22.3184C20.4533 22.1937 20.6409 22.014 20.7751 21.7964C20.9093 21.5788 20.9856 21.3305 20.9969 21.075C21.0082 20.8196 20.9539 20.5656 20.8394 20.337ZM10.3394 9.612L10.4999 9.2895V3.054L13.4999 3.018V9.0105V9.3735L13.6664 9.696L16.4054 15.009H7.5734L10.3394 9.612ZM4.4999 21.0255L6.8114 16.509H17.1839L19.5044 21.009L4.4999 21.0255Z" fill="white"/>
|
||||
</svg>
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 913 B After Width: | Height: | Size: 810 B |
@@ -83,7 +83,7 @@ interface IUserFriendlyViewDescriptor {
|
||||
|
||||
// From 'remoteViewDescriptor' type
|
||||
group?: string;
|
||||
remoteAuthority?: string;
|
||||
remoteName?: string | string[];
|
||||
}
|
||||
|
||||
const viewDescriptor: IJSONSchema = {
|
||||
@@ -123,9 +123,12 @@ const remoteViewDescriptor: IJSONSchema = {
|
||||
description: localize('vscode.extension.contributes.view.group', 'Nested group in the viewlet'),
|
||||
type: 'string'
|
||||
},
|
||||
remoteAuthority: {
|
||||
description: localize('vscode.extension.contributes.view.remoteAuthority', 'The remote authority associated with this view'),
|
||||
type: 'string'
|
||||
remoteName: {
|
||||
description: localize('vscode.extension.contributes.view.remoteName', 'The name of the remote type associated with this view'),
|
||||
type: ['string', 'array'],
|
||||
items: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -363,7 +366,12 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
|
||||
|
||||
// Generate CSS to show the icon in the activity bar
|
||||
const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${cssClass}`;
|
||||
createCSSRule(iconClass, `-webkit-mask: ${asCSSUrl(icon)} no-repeat 50% 50%; -webkit-mask-size: 24px;`);
|
||||
createCSSRule(iconClass, `
|
||||
mask: ${asCSSUrl(icon)} no-repeat 50% 50%;
|
||||
mask-size: 24px;
|
||||
-webkit-mask: ${asCSSUrl(icon)} no-repeat 50% 50%;
|
||||
-webkit-mask-size: 24px;`
|
||||
);
|
||||
}
|
||||
|
||||
return viewContainer;
|
||||
@@ -435,7 +443,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
|
||||
extensionId: extension.description.identifier,
|
||||
originalContainerId: entry.key,
|
||||
group: item.group,
|
||||
remoteAuthority: item.remoteAuthority
|
||||
remoteAuthority: item.remoteName || (<any>item).remoteAuthority // TODO@roblou - delete after remote extensions are updated
|
||||
};
|
||||
|
||||
viewIds.push(viewDescriptor.id);
|
||||
|
||||
Reference in New Issue
Block a user