mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-25 11:08:51 +01:00
Merge branch 'master' into scm-multiroot
This commit is contained in:
@@ -43,7 +43,6 @@ import EditorCommon = require('vs/editor/common/editorCommon');
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import * as vscode from 'vscode';
|
||||
import * as paths from 'vs/base/common/paths';
|
||||
@@ -74,13 +73,14 @@ function proposedApiFunction<T>(extension: IExtensionDescription, fn: T): T {
|
||||
export function createApiFactory(
|
||||
initData: IInitData,
|
||||
threadService: ExtHostThreadService,
|
||||
extensionService: ExtHostExtensionService,
|
||||
telemetryService: ITelemetryService
|
||||
extensionService: ExtHostExtensionService
|
||||
): IExtensionApiFactory {
|
||||
|
||||
const mainThreadTelemetry = threadService.get(MainContext.MainThreadTelemetry);
|
||||
|
||||
// Addressable instances
|
||||
const extHostHeapService = threadService.set(ExtHostContext.ExtHostHeapService, new ExtHostHeapService());
|
||||
const extHostDocumentsAndEditors = threadService.set(ExtHostContext.ExtHostDocumentsAndEditors, new ExtHostDocumentsAndEditors(threadService));
|
||||
const extHostDocumentsAndEditors = threadService.set(ExtHostContext.ExtHostDocumentsAndEditors, new ExtHostDocumentsAndEditors(threadService, extensionService));
|
||||
const extHostDocuments = threadService.set(ExtHostContext.ExtHostDocuments, new ExtHostDocuments(threadService, extHostDocumentsAndEditors));
|
||||
const extHostDocumentContentProviders = threadService.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(threadService, extHostDocumentsAndEditors));
|
||||
const extHostDocumentSaveParticipant = threadService.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(extHostDocuments, threadService.get(MainContext.MainThreadWorkspace)));
|
||||
@@ -140,7 +140,7 @@ export function createApiFactory(
|
||||
return undefined;
|
||||
}
|
||||
this._seen.add(apiName);
|
||||
return telemetryService.publicLog('apiUsage', {
|
||||
return mainThreadTelemetry.$publicLog('apiUsage', {
|
||||
name: apiName,
|
||||
extension: extension.id
|
||||
});
|
||||
@@ -242,7 +242,7 @@ export function createApiFactory(
|
||||
return languageFeatures.registerTypeDefinitionProvider(selector, provider);
|
||||
},
|
||||
registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable {
|
||||
return languageFeatures.registerHoverProvider(selector, provider);
|
||||
return languageFeatures.registerHoverProvider(selector, provider, extension.id);
|
||||
},
|
||||
registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {
|
||||
return languageFeatures.registerDocumentHighlightProvider(selector, provider);
|
||||
@@ -327,13 +327,13 @@ export function createApiFactory(
|
||||
return extHostTerminalService.onDidCloseTerminal(listener, thisArg, disposables);
|
||||
},
|
||||
showInformationMessage(message, first, ...rest) {
|
||||
return extHostMessageService.showMessage(extension.id, Severity.Info, message, first, rest);
|
||||
return extHostMessageService.showMessage(extension, Severity.Info, message, first, rest);
|
||||
},
|
||||
showWarningMessage(message, first, ...rest) {
|
||||
return extHostMessageService.showMessage(extension.id, Severity.Warning, message, first, rest);
|
||||
return extHostMessageService.showMessage(extension, Severity.Warning, message, first, rest);
|
||||
},
|
||||
showErrorMessage(message, first, ...rest) {
|
||||
return extHostMessageService.showMessage(extension.id, Severity.Error, message, first, rest);
|
||||
return extHostMessageService.showMessage(extension, Severity.Error, message, first, rest);
|
||||
},
|
||||
showQuickPick(items: any, options: vscode.QuickPickOptions, token?: vscode.CancellationToken) {
|
||||
return extHostQuickOpen.showQuickPick(items, options, token);
|
||||
@@ -368,10 +368,10 @@ export function createApiFactory(
|
||||
},
|
||||
// proposed API
|
||||
sampleFunction: proposedApiFunction(extension, () => {
|
||||
return extHostMessageService.showMessage(extension.id, Severity.Info, 'Hello Proposed Api!', {}, []);
|
||||
return extHostMessageService.showMessage(extension, Severity.Info, 'Hello Proposed Api!', {}, []);
|
||||
}),
|
||||
showOpenDialog: proposedApiFunction(extension, () => {
|
||||
return extHostDialogs.showOpenDialog();
|
||||
showOpenDialog: proposedApiFunction(extension, options => {
|
||||
return extHostDialogs.showOpenDialog(options);
|
||||
})
|
||||
};
|
||||
|
||||
@@ -475,7 +475,7 @@ export function createApiFactory(
|
||||
return extHostSCM.getLastInputBox(extension);
|
||||
},
|
||||
createSourceControl(id: string, label: string) {
|
||||
telemetryService.publicLog('registerSCMProvider', {
|
||||
mainThreadTelemetry.$publicLog('registerSCMProvider', {
|
||||
extensionId: extension.id,
|
||||
providerId: id,
|
||||
providerLabel: label
|
||||
|
||||
@@ -113,8 +113,16 @@ export interface MainThreadDiagnosticsShape extends IDisposable {
|
||||
$clear(owner: string): TPromise<any>;
|
||||
}
|
||||
|
||||
export interface MainThreadDialogOptions {
|
||||
uri?: URI;
|
||||
openLabel?: string;
|
||||
openFiles?: boolean;
|
||||
openFolders?: boolean;
|
||||
openMany?: boolean;
|
||||
}
|
||||
|
||||
export interface MainThreadDiaglogsShape extends IDisposable {
|
||||
$showOpenDialog(): TPromise<string[]>;
|
||||
$showOpenDialog(options: MainThreadDialogOptions): TPromise<string[]>;
|
||||
}
|
||||
|
||||
export interface MainThreadDocumentContentProvidersShape extends IDisposable {
|
||||
@@ -227,7 +235,7 @@ export interface MainThreadLanguagesShape extends IDisposable {
|
||||
}
|
||||
|
||||
export interface MainThreadMessageOptions {
|
||||
extensionId?: string;
|
||||
extension?: IExtensionDescription;
|
||||
modal?: boolean;
|
||||
}
|
||||
|
||||
@@ -280,7 +288,6 @@ export interface MainThreadStorageShape extends IDisposable {
|
||||
|
||||
export interface MainThreadTelemetryShape extends IDisposable {
|
||||
$publicLog(eventName: string, data?: any): void;
|
||||
$getTelemetryInfo(): TPromise<ITelemetryInfo>;
|
||||
}
|
||||
|
||||
export interface MainThreadWorkspaceShape extends IDisposable {
|
||||
|
||||
@@ -62,7 +62,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
|
||||
|
||||
function parseConfigurationTarget(arg: boolean | ExtHostConfigurationTarget): ConfigurationTarget {
|
||||
if (arg === void 0 || arg === null) {
|
||||
return ConfigurationTarget.WORKSPACE;
|
||||
return null;
|
||||
}
|
||||
if (typeof arg === 'boolean') {
|
||||
return arg ? ConfigurationTarget.USER : ConfigurationTarget.WORKSPACE;
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { MainContext, MainThreadDiaglogsShape, IMainContext } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import * as vscode from 'vscode';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { MainContext, MainThreadDiaglogsShape, IMainContext } from 'vs/workbench/api/node/extHost.protocol';
|
||||
|
||||
export class ExtHostDialogs {
|
||||
|
||||
@@ -15,12 +16,9 @@ export class ExtHostDialogs {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadDialogs);
|
||||
}
|
||||
|
||||
showOpenDialog(): Thenable<URI[]> {
|
||||
return this._proxy.$showOpenDialog().then(filepaths => {
|
||||
if (!filepaths) {
|
||||
return undefined;
|
||||
}
|
||||
return filepaths.map(URI.file);
|
||||
showOpenDialog(options: vscode.OpenDialogOptions): Thenable<URI[]> {
|
||||
return this._proxy.$showOpenDialog(<any>options).then(filepaths => {
|
||||
return filepaths && filepaths.map(URI.file);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,10 @@ import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { dispose } from 'vs/base/common/lifecycle';
|
||||
import { MainContext, ExtHostDocumentsAndEditorsShape, IDocumentsAndEditorsDelta, IMainContext } from './extHost.protocol';
|
||||
import { ExtHostDocumentData } from './extHostDocumentData';
|
||||
import { ExtHostTextEditor } from './extHostTextEditor';
|
||||
import { ExtHostTextEditor, ExtHostTextEditor2 } from './extHostTextEditor';
|
||||
import * as assert from 'assert';
|
||||
import * as typeConverters from './extHostTypeConverters';
|
||||
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
|
||||
|
||||
export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsShape {
|
||||
|
||||
@@ -29,7 +30,8 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
|
||||
readonly onDidChangeActiveTextEditor: Event<ExtHostTextEditor> = this._onDidChangeActiveTextEditor.event;
|
||||
|
||||
constructor(
|
||||
private readonly _mainContext: IMainContext
|
||||
private readonly _mainContext: IMainContext,
|
||||
private readonly _extHostExtensions?: ExtHostExtensionService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -79,7 +81,9 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
|
||||
assert.ok(!this._editors.has(data.id), `editor '${data.id}' already exists!`);
|
||||
|
||||
const documentData = this._documents.get(data.document.toString());
|
||||
const editor = new ExtHostTextEditor(
|
||||
const editor = new ExtHostTextEditor2(
|
||||
this._extHostExtensions,
|
||||
this._mainContext.get(MainContext.MainThreadTelemetry),
|
||||
this._mainContext.get(MainContext.MainThreadEditors),
|
||||
data.id,
|
||||
documentData,
|
||||
|
||||
@@ -12,9 +12,8 @@ import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { ExtHostStorage } from 'vs/workbench/api/node/extHostStorage';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { createApiFactory, initializeExtensionApi } from 'vs/workbench/api/node/extHost.api.impl';
|
||||
import { MainContext, MainThreadExtensionServiceShape, IWorkspaceData, IEnvironment, IInitData, ExtHostExtensionServiceShape } from './extHost.protocol';
|
||||
import { MainContext, MainThreadExtensionServiceShape, IWorkspaceData, IEnvironment, IInitData, ExtHostExtensionServiceShape, MainThreadTelemetryShape } from './extHost.protocol';
|
||||
import { IExtensionMemento, ExtensionsActivator, ActivatedExtension, IExtensionAPI, IExtensionContext, EmptyExtension, IExtensionModule } from 'vs/workbench/api/node/extHostExtensionActivator';
|
||||
import { Barrier } from 'vs/workbench/services/extensions/node/barrier';
|
||||
import { ExtHostThreadService } from 'vs/workbench/services/thread/node/extHostThreadService';
|
||||
@@ -112,7 +111,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
private readonly _barrier: Barrier;
|
||||
private readonly _registry: ExtensionDescriptionRegistry;
|
||||
private readonly _threadService: ExtHostThreadService;
|
||||
private readonly _telemetryService: ITelemetryService;
|
||||
private readonly _mainThreadTelemetry: MainThreadTelemetryShape;
|
||||
private readonly _storage: ExtHostStorage;
|
||||
private readonly _storagePath: ExtensionStoragePath;
|
||||
private readonly _proxy: MainThreadExtensionServiceShape;
|
||||
@@ -121,18 +120,18 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
/**
|
||||
* This class is constructed manually because it is a service, so it doesn't use any ctor injection
|
||||
*/
|
||||
constructor(initData: IInitData, threadService: ExtHostThreadService, telemetryService: ITelemetryService) {
|
||||
constructor(initData: IInitData, threadService: ExtHostThreadService) {
|
||||
this._barrier = new Barrier();
|
||||
this._registry = new ExtensionDescriptionRegistry(initData.extensions);
|
||||
this._threadService = threadService;
|
||||
this._telemetryService = telemetryService;
|
||||
this._mainThreadTelemetry = threadService.get(MainContext.MainThreadTelemetry);
|
||||
this._storage = new ExtHostStorage(threadService);
|
||||
this._storagePath = new ExtensionStoragePath(initData.workspace, initData.environment);
|
||||
this._proxy = this._threadService.get(MainContext.MainThreadExtensionService);
|
||||
this._activator = null;
|
||||
|
||||
// initialize API first (i.e. do not release barrier until the API is initialized)
|
||||
const apiFactory = createApiFactory(initData, threadService, this, this._telemetryService);
|
||||
const apiFactory = createApiFactory(initData, threadService, this);
|
||||
|
||||
initializeExtensionApi(this, apiFactory).then(() => {
|
||||
|
||||
@@ -281,7 +280,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
|
||||
private _doActivateExtension(extensionDescription: IExtensionDescription): TPromise<ActivatedExtension> {
|
||||
let event = getTelemetryActivationEvent(extensionDescription);
|
||||
this._telemetryService.publicLog('activatePlugin', event);
|
||||
this._mainThreadTelemetry.$publicLog('activatePlugin', event);
|
||||
if (!extensionDescription.main) {
|
||||
// Treat the extension as being empty => NOT AN ERROR CASE
|
||||
return TPromise.as(new EmptyExtension());
|
||||
|
||||
@@ -18,10 +18,13 @@ import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHos
|
||||
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
|
||||
import { IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search';
|
||||
import { asWinJsPromise } from 'vs/base/common/async';
|
||||
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IRawColorFormatMap, IMainContext } from './extHost.protocol';
|
||||
import { MainContext, MainThreadTelemetryShape, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IRawColorFormatMap, IMainContext } from './extHost.protocol';
|
||||
import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import { containsCommandLink } from 'vs/base/common/htmlContent';
|
||||
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
|
||||
import { once } from 'vs/base/common/functional';
|
||||
|
||||
// --- adapter
|
||||
|
||||
@@ -173,12 +176,12 @@ class TypeDefinitionAdapter {
|
||||
|
||||
class HoverAdapter {
|
||||
|
||||
private _documents: ExtHostDocuments;
|
||||
private _provider: vscode.HoverProvider;
|
||||
|
||||
constructor(documents: ExtHostDocuments, provider: vscode.HoverProvider) {
|
||||
this._documents = documents;
|
||||
this._provider = provider;
|
||||
constructor(
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
private readonly _provider: vscode.HoverProvider,
|
||||
private readonly _telemetryLog: (name: string, data: object) => void,
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
public provideHover(resource: URI, position: IPosition): TPromise<modes.Hover> {
|
||||
@@ -187,7 +190,7 @@ class HoverAdapter {
|
||||
let pos = TypeConverters.toPosition(position);
|
||||
|
||||
return asWinJsPromise(token => this._provider.provideHover(doc, pos, token)).then(value => {
|
||||
if (!value) {
|
||||
if (!value || isFalsyOrEmpty(value.contents)) {
|
||||
return undefined;
|
||||
}
|
||||
if (!value.range) {
|
||||
@@ -197,7 +200,14 @@ class HoverAdapter {
|
||||
value.range = new Range(pos, pos);
|
||||
}
|
||||
|
||||
return TypeConverters.fromHover(value);
|
||||
const result = TypeConverters.fromHover(value);
|
||||
|
||||
// we wanna know which extension uses command links
|
||||
// because that is a potential trick-attack on users
|
||||
if (result.contents.some(h => containsCommandLink(h.value))) {
|
||||
this._telemetryLog('usesCommandLink', { from: 'hover' });
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -744,6 +754,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
private static _handlePool: number = 0;
|
||||
|
||||
private _proxy: MainThreadLanguageFeaturesShape;
|
||||
private _telemetry: MainThreadTelemetryShape;
|
||||
private _documents: ExtHostDocuments;
|
||||
private _commands: ExtHostCommands;
|
||||
private _heapService: ExtHostHeapService;
|
||||
@@ -759,6 +770,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
diagnostics: ExtHostDiagnostics
|
||||
) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadLanguageFeatures);
|
||||
this._telemetry = mainContext.get(MainContext.MainThreadTelemetry);
|
||||
this._documents = documents;
|
||||
this._commands = commands;
|
||||
this._heapService = heapMonitor;
|
||||
@@ -860,9 +872,12 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
// --- extra info
|
||||
|
||||
registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable {
|
||||
registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider, extensionId?: string): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, new HoverAdapter(this._documents, provider));
|
||||
this._adapter.set(handle, new HoverAdapter(this._documents, provider, once((name, data) => {
|
||||
data['extension'] = extensionId;
|
||||
this._telemetry.$publicLog(name, data);
|
||||
})));
|
||||
this._proxy.$registerHoverProvider(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import vscode = require('vscode');
|
||||
import { MainContext, MainThreadMessageServiceShape, MainThreadMessageOptions, IMainContext } from './extHost.protocol';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
|
||||
|
||||
function isMessageItem<T>(item: any): item is vscode.MessageItem {
|
||||
@@ -21,11 +22,11 @@ export class ExtHostMessageService {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadMessageService);
|
||||
}
|
||||
|
||||
showMessage(extensionId: string, severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | string, rest: string[]): Thenable<string | undefined>;
|
||||
showMessage(extensionId: string, severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | vscode.MessageItem, rest: vscode.MessageItem[]): Thenable<vscode.MessageItem | undefined>;
|
||||
showMessage(extensionId: string, severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | string | vscode.MessageItem, rest: (string | vscode.MessageItem)[]): Thenable<string | vscode.MessageItem | undefined> {
|
||||
showMessage(extension: IExtensionDescription, severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | string, rest: string[]): Thenable<string | undefined>;
|
||||
showMessage(extension: IExtensionDescription, severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | vscode.MessageItem, rest: vscode.MessageItem[]): Thenable<vscode.MessageItem | undefined>;
|
||||
showMessage(extension: IExtensionDescription, severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | string | vscode.MessageItem, rest: (string | vscode.MessageItem)[]): Thenable<string | vscode.MessageItem | undefined> {
|
||||
|
||||
let options: MainThreadMessageOptions = { extensionId };
|
||||
let options: MainThreadMessageOptions = { extension };
|
||||
let items: (string | vscode.MessageItem)[];
|
||||
|
||||
if (typeof optionsOrFirstItem === 'string' || isMessageItem(optionsOrFirstItem)) {
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { notImplemented } from 'vs/base/common/errors';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { ITelemetryService, ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { MainContext, MainThreadTelemetryShape, IMainContext } from './extHost.protocol';
|
||||
|
||||
export class RemoteTelemetryService implements ITelemetryService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
private _name: string;
|
||||
private _proxy: MainThreadTelemetryShape;
|
||||
|
||||
constructor(name: string, mainContext: IMainContext) {
|
||||
this._name = name;
|
||||
this._proxy = mainContext.get(MainContext.MainThreadTelemetry);
|
||||
}
|
||||
|
||||
get isOptedIn(): boolean {
|
||||
throw notImplemented();
|
||||
}
|
||||
|
||||
getTelemetryInfo(): TPromise<ITelemetryInfo> {
|
||||
return this._proxy.$getTelemetryInfo();
|
||||
}
|
||||
|
||||
publicLog(eventName: string, data?: any): TPromise<void> {
|
||||
data = data || Object.create(null);
|
||||
data[this._name] = true;
|
||||
this._proxy.$publicLog(eventName, data);
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
timedPublicLog(): any {
|
||||
throw notImplemented();
|
||||
}
|
||||
|
||||
addTelemetryAppender(): any {
|
||||
throw notImplemented();
|
||||
}
|
||||
}
|
||||
@@ -6,17 +6,19 @@
|
||||
|
||||
|
||||
import { ok } from 'vs/base/common/assert';
|
||||
import { readonly, illegalArgument } from 'vs/base/common/errors';
|
||||
import { readonly, illegalArgument, V8CallSite } from 'vs/base/common/errors';
|
||||
import { IdGenerator } from 'vs/base/common/idGenerator';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { ExtHostDocumentData } from 'vs/workbench/api/node/extHostDocumentData';
|
||||
import { Selection, Range, Position, EndOfLine, TextEditorRevealType, TextEditorLineNumbersStyle, SnippetString } from './extHostTypes';
|
||||
import { ISingleEditOperation } from 'vs/editor/common/editorCommon';
|
||||
import * as TypeConverters from './extHostTypeConverters';
|
||||
import { MainThreadEditorsShape, IResolvedTextEditorConfiguration, ITextEditorConfigurationUpdate } from './extHost.protocol';
|
||||
import { MainThreadEditorsShape, MainThreadTelemetryShape, IResolvedTextEditorConfiguration, ITextEditorConfigurationUpdate } from './extHost.protocol';
|
||||
import * as vscode from 'vscode';
|
||||
import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import { containsCommandLink } from 'vs/base/common/htmlContent';
|
||||
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
|
||||
|
||||
export class TextEditorDecorationType implements vscode.TextEditorDecorationType {
|
||||
|
||||
@@ -550,6 +552,70 @@ export class ExtHostTextEditor implements vscode.TextEditor {
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostTextEditor2 extends ExtHostTextEditor {
|
||||
|
||||
constructor(
|
||||
private readonly _extHostExtensions: ExtHostExtensionService,
|
||||
private readonly _mainThreadTelemetry: MainThreadTelemetryShape,
|
||||
proxy: MainThreadEditorsShape,
|
||||
id: string,
|
||||
document: ExtHostDocumentData,
|
||||
selections: Selection[],
|
||||
options: IResolvedTextEditorConfiguration,
|
||||
viewColumn: vscode.ViewColumn
|
||||
) {
|
||||
super(proxy, id, document, selections, options, viewColumn);
|
||||
}
|
||||
|
||||
setDecorations(decorationType: vscode.TextEditorDecorationType, rangesOrOptions: Range[] | vscode.DecorationOptions[]): void {
|
||||
// (1) find out if this decoration is important for us
|
||||
let usesCommandLink = false;
|
||||
outer: for (const rangeOrOption of rangesOrOptions) {
|
||||
if (Range.isRange(rangeOrOption)) {
|
||||
break;
|
||||
}
|
||||
if (typeof rangeOrOption.hoverMessage === 'string' && containsCommandLink(rangeOrOption.hoverMessage)) {
|
||||
usesCommandLink = true;
|
||||
break;
|
||||
} else if (Array.isArray(rangeOrOption.hoverMessage)) {
|
||||
for (const message of rangeOrOption.hoverMessage) {
|
||||
if (typeof message === 'string' && containsCommandLink(message)) {
|
||||
usesCommandLink = true;
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// (2) send event for important decorations
|
||||
if (usesCommandLink) {
|
||||
let tag = new Error();
|
||||
this._extHostExtensions.getExtensionPathIndex().then(index => {
|
||||
const oldHandler = (<any>Error).prepareStackTrace;
|
||||
(<any>Error).prepareStackTrace = (error: Error, stackTrace: V8CallSite[]) => {
|
||||
for (const call of stackTrace) {
|
||||
const extension = index.findSubstr(call.getFileName());
|
||||
if (extension) {
|
||||
this._mainThreadTelemetry.$publicLog('usesCommandLink', {
|
||||
extension: extension.id,
|
||||
from: 'decoration',
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
// it all happens here...
|
||||
// tslint:disable-next-line:no-unused-expression
|
||||
tag.stack;
|
||||
(<any>Error).prepareStackTrace = oldHandler;
|
||||
});
|
||||
}
|
||||
|
||||
// (3) do it
|
||||
super.setDecorations(decorationType, rangesOrOptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function warnOnError(promise: TPromise<any>): void {
|
||||
promise.then(null, (err) => {
|
||||
console.warn(err);
|
||||
|
||||
@@ -16,6 +16,7 @@ import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import { ISelection } from 'vs/editor/common/core/selection';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
|
||||
export interface PositionLike {
|
||||
line: number;
|
||||
@@ -143,12 +144,26 @@ function isDecorationOptionsArr(something: vscode.Range[] | vscode.DecorationOpt
|
||||
return isDecorationOptions(something[0]) ? true : false;
|
||||
}
|
||||
|
||||
export namespace MarkedString {
|
||||
export function from(markup: vscode.MarkedString): IMarkdownString {
|
||||
if (typeof markup === 'string' || !markup) {
|
||||
return { value: <string>markup || '', trusted: true };
|
||||
} else {
|
||||
const { language, value } = markup;
|
||||
return { value: '```' + language + '\n' + value + '\n```' };
|
||||
}
|
||||
}
|
||||
export function to(value: IMarkdownString): vscode.MarkedString {
|
||||
return value.value;
|
||||
}
|
||||
}
|
||||
|
||||
export function fromRangeOrRangeWithMessage(ranges: vscode.Range[] | vscode.DecorationOptions[]): IDecorationOptions[] {
|
||||
if (isDecorationOptionsArr(ranges)) {
|
||||
return ranges.map((r): IDecorationOptions => {
|
||||
return {
|
||||
range: fromRange(r.range),
|
||||
hoverMessage: r.hoverMessage,
|
||||
hoverMessage: Array.isArray(r.hoverMessage) ? r.hoverMessage.map(MarkedString.from) : MarkedString.from(r.hoverMessage),
|
||||
renderOptions: <any> /* URI vs Uri */r.renderOptions
|
||||
};
|
||||
});
|
||||
@@ -256,12 +271,12 @@ export const location = {
|
||||
export function fromHover(hover: vscode.Hover): modes.Hover {
|
||||
return <modes.Hover>{
|
||||
range: fromRange(hover.range),
|
||||
contents: hover.contents
|
||||
contents: hover.contents.map(MarkedString.from)
|
||||
};
|
||||
}
|
||||
|
||||
export function toHover(info: modes.Hover): types.Hover {
|
||||
return new types.Hover(info.contents, toRange(info.range));
|
||||
return new types.Hover(info.contents.map(MarkedString.to), toRange(info.range));
|
||||
}
|
||||
|
||||
export function toDocumentHighlight(occurrence: modes.DocumentHighlight): types.DocumentHighlight {
|
||||
|
||||
Reference in New Issue
Block a user