提交 d285fe05 编写于 作者: A Alex Dima

Split up ext host <-> main thread communication to separate files

上级 fa9d7071
......@@ -7,11 +7,10 @@
import {Emitter} from 'vs/base/common/event';
import {score} from 'vs/editor/common/modes/languageSelector';
import * as Platform from 'vs/base/common/platform';
import {regExpLeadsToEndlessLoop} from 'vs/base/common/strings';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import * as errors from 'vs/base/common/errors';
import {ExtHostFileSystemEventService} from 'vs/workbench/api/node/extHostFileSystemEventService';
import {ExtHostModelService, setWordDefinitionFor} from 'vs/workbench/api/node/extHostDocuments';
import {ExtHostDocuments} from 'vs/workbench/api/node/extHostDocuments';
import {ExtHostConfiguration} from 'vs/workbench/api/node/extHostConfiguration';
import {ExtHostDiagnostics} from 'vs/workbench/api/node/extHostDiagnostics';
import {ExtHostWorkspace} from 'vs/workbench/api/node/extHostWorkspace';
......@@ -27,22 +26,18 @@ import * as ExtHostTypeConverters from 'vs/workbench/api/node/extHostTypeConvert
import {registerApiCommands} from 'vs/workbench/api/node/extHostApiCommands';
import * as extHostTypes from 'vs/workbench/api/node/extHostTypes';
import Modes = require('vs/editor/common/modes');
import {IModeService} from 'vs/editor/common/services/modeService';
import URI from 'vs/base/common/uri';
import Severity from 'vs/base/common/severity';
import {IDisposable} from 'vs/base/common/lifecycle';
import EditorCommon = require('vs/editor/common/editorCommon');
import {IExtensionDescription} from 'vs/platform/extensions/common/extensions';
import {ExtHostExtensionService} from 'vs/workbench/api/node/nativeExtensionService';
import {ExtHostExtensionService} from 'vs/workbench/api/node/extHostExtensionService';
import {ExtensionsRegistry} from 'vs/platform/extensions/common/extensionsRegistry';
import {TPromise} from 'vs/base/common/winjs.base';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {CancellationTokenSource} from 'vs/base/common/cancellation';
import vscode = require('vscode');
import {TextEditorRevealType} from 'vs/workbench/api/node/mainThreadEditors';
import * as paths from 'vs/base/common/paths';
import {ITelemetryService, ITelemetryInfo} from 'vs/platform/telemetry/common/telemetry';
import {LanguageConfigurationRegistry} from 'vs/editor/common/modes/languageConfigurationRegistry';
import {MainContext, ExtHostContext, InstanceCollection} from './extHostProtocol';
/**
......@@ -51,13 +46,6 @@ import {MainContext, ExtHostContext, InstanceCollection} from './extHostProtocol
*/
export class ExtHostAPIImplementation {
private static _LAST_REGISTER_TOKEN = 0;
private static generateDisposeToken(): string {
return String(++ExtHostAPIImplementation._LAST_REGISTER_TOKEN);
}
private _proxy: MainProcessVSCodeAPIHelper;
version: typeof vscode.version;
env: typeof vscode.env;
Uri: typeof vscode.Uri;
......@@ -106,7 +94,7 @@ export class ExtHostAPIImplementation {
// Addressable instances
const col = new InstanceCollection();
const extHostDocuments = col.define(ExtHostContext.ExtHostModelService).set(new ExtHostModelService(threadService));
const extHostDocuments = col.define(ExtHostContext.ExtHostDocuments).set(new ExtHostDocuments(threadService));
const extHostEditors = col.define(ExtHostContext.ExtHostEditors).set(new ExtHostEditors(threadService, extHostDocuments));
const extHostCommands = col.define(ExtHostContext.ExtHostCommands).set(new ExtHostCommands(threadService, extHostEditors));
const extHostConfiguration = col.define(ExtHostContext.ExtHostConfiguration).set(new ExtHostConfiguration());
......@@ -118,11 +106,10 @@ export class ExtHostAPIImplementation {
col.finish(false, threadService);
// Others
this._proxy = threadService.get(MainContext.MainProcessVSCodeAPIHelper);
const mainThreadErrors = threadService.get(MainContext.MainThreadErrors);
errors.setUnexpectedErrorHandler((err) => {
this._proxy.onUnexpectedExtHostError(errors.transformErrorForSerialization(err));
mainThreadErrors.onUnexpectedExtHostError(errors.transformErrorForSerialization(err));
});
const extHostMessageService = new ExtHostMessageService(threadService);
......@@ -167,7 +154,7 @@ export class ExtHostAPIImplementation {
this.StatusBarAlignment = extHostTypes.StatusBarAlignment;
this.IndentAction = Modes.IndentAction;
this.OverviewRulerLane = EditorCommon.OverviewRulerLane;
this.TextEditorRevealType = TextEditorRevealType;
this.TextEditorRevealType = extHostTypes.TextEditorRevealType;
this.EndOfLine = extHostTypes.EndOfLine;
this.TextEditorCursorStyle = EditorCommon.TextEditorCursorStyle;
......@@ -383,7 +370,7 @@ export class ExtHostAPIImplementation {
return languageFeatures.registerCompletionItemProvider(selector, provider, triggerCharacters);
},
setLanguageConfiguration: (language: string, configuration: vscode.LanguageConfiguration):vscode.Disposable => {
return this._setLanguageConfiguration(language, configuration);
return languageFeatures.setLanguageConfiguration(language, configuration);
}
};
......@@ -399,41 +386,6 @@ export class ExtHostAPIImplementation {
}
};
}
private _disposableFromToken(disposeToken:string): IDisposable {
return new extHostTypes.Disposable(() => this._proxy.disposeByToken(disposeToken));
}
private _setLanguageConfiguration(modeId: string, configuration: vscode.LanguageConfiguration): vscode.Disposable {
let {wordPattern} = configuration;
// check for a valid word pattern
if (wordPattern && regExpLeadsToEndlessLoop(wordPattern)) {
throw new Error(`Invalid language configuration: wordPattern '${wordPattern}' is not allowed to match the empty string.`);
}
// word definition
if (wordPattern) {
setWordDefinitionFor(modeId, wordPattern);
} else {
setWordDefinitionFor(modeId, null);
}
// backward compatibility, migrate deprecated setting
if (configuration.__characterPairSupport && !configuration.autoClosingPairs) {
configuration.autoClosingPairs = configuration.__characterPairSupport.autoClosingPairs;
delete configuration.__characterPairSupport;
}
return this.Modes_RichEditSupport_register(modeId, configuration);
}
private Modes_RichEditSupport_register(modeId: string, configuration:vscode.LanguageConfiguration): IDisposable {
let disposeToken = ExtHostAPIImplementation.generateDisposeToken();
this._proxy.Modes_RichEditSupport_register(disposeToken, modeId, configuration);
return this._disposableFromToken(disposeToken);
}
}
class Extension<T> implements vscode.Extension<T> {
......@@ -475,32 +427,3 @@ export function defineAPI(impl: typeof vscode) {
};
define('vscode', [], impl);
}
export class MainProcessVSCodeAPIHelper {
protected _modeService: IModeService;
private _token2Dispose: {
[token:string]: IDisposable;
};
constructor(
@IModeService modeService: IModeService
) {
this._modeService = modeService;
this._token2Dispose = {};
}
public onUnexpectedExtHostError(err: any): void {
errors.onUnexpectedError(err);
}
public disposeByToken(disposeToken:string): void {
if (this._token2Dispose[disposeToken]) {
this._token2Dispose[disposeToken].dispose();
delete this._token2Dispose[disposeToken];
}
}
public Modes_RichEditSupport_register(disposeToken:string, modeId: string, configuration:vscode.LanguageConfiguration): void {
this._token2Dispose[disposeToken] = LanguageConfigurationRegistry.register(modeId, configuration);
}
}
\ No newline at end of file
......@@ -10,29 +10,33 @@ import {Registry} from 'vs/platform/platform';
import {IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions} from 'vs/workbench/common/contributions';
import {IInstantiationService, IConstructorSignature0} from 'vs/platform/instantiation/common/instantiation';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {MainThreadDocuments} from 'vs/workbench/api/node/extHostDocuments';
import {MainContext, InstanceCollection} from './extHostProtocol';
import {IExtensionService} from 'vs/platform/extensions/common/extensions';
// --- addressable
import {MainThreadCommands} from './mainThreadCommands';
import {MainThreadConfiguration} from './mainThreadConfiguration';
import {MainThreadDiagnostics} from './mainThreadDiagnostics';
import {MainThreadDocuments} from './mainThreadDocuments';
import {MainThreadEditors} from './mainThreadEditors';
import {MainThreadErrors} from './mainThreadErrors';
import {MainThreadLanguageFeatures} from './mainThreadLanguageFeatures';
import {MainThreadLanguages} from './mainThreadLanguages';
import {MainThreadMessageService} from './mainThreadMessageService';
import {MainThreadOutputService} from './mainThreadOutputService';
import {MainThreadQuickOpen} from './mainThreadQuickOpen';
import {MainThreadStatusBar} from './mainThreadStatusBar';
import {MainThreadStorage} from './mainThreadStorage';
import {MainThreadTelemetry} from './mainThreadTelemetry';
import {MainThreadWorkspace} from './mainThreadWorkspace';
import {MainProcessExtensionService} from './mainThreadExtensionService';
import {MainThreadFileSystemEventService} from './mainThreadFileSystemEventService';
// --- other interested parties
import {MainProcessTextMateSyntax} from 'vs/editor/node/textMate/TMSyntax';
import {MainProcessTextMateSnippet} from 'vs/editor/node/textMate/TMSnippets';
import {JSONValidationExtensionPoint} from 'vs/platform/jsonschemas/common/jsonValidationExtensionPoint';
import {LanguageConfigurationFileHandler} from 'vs/editor/node/languageConfiguration';
import {MainThreadFileSystemEventService} from 'vs/workbench/api/node/extHostFileSystemEventService';
import {MainThreadQuickOpen} from 'vs/workbench/api/node/extHostQuickOpen';
import {MainThreadStatusBar} from 'vs/workbench/api/node/extHostStatusBar';
import {MainThreadCommands} from 'vs/workbench/api/node/extHostCommands';
import {MainThreadTelemetry} from 'vs/workbench/api/node/extHostTelemetry';
import {MainThreadDiagnostics} from 'vs/workbench/api/node/extHostDiagnostics';
import {MainThreadOutputService} from 'vs/workbench/api/node/extHostOutputService';
import {MainThreadMessageService} from 'vs/workbench/api/node/extHostMessageService';
import {MainThreadLanguages} from 'vs/workbench/api/node/extHostLanguages';
import {MainThreadEditors} from 'vs/workbench/api/node/extHostEditors';
import {MainThreadWorkspace} from 'vs/workbench/api/node/extHostWorkspace';
import {MainThreadConfiguration} from 'vs/workbench/api/node/extHostConfiguration';
import {MainThreadLanguageFeatures} from 'vs/workbench/api/node/extHostLanguageFeatures';
import {MainThreadStorage} from 'vs/workbench/api/node/extHostStorage';
import {MainProcessVSCodeAPIHelper} from 'vs/workbench/api/node/extHost.api.impl';
import {MainContext, InstanceCollection} from './extHostProtocol';
import {IExtensionService} from 'vs/platform/extensions/common/extensions';
import {MainProcessExtensionService} from './nativeExtensionService';
export class ExtHostContribution implements IWorkbenchContribution {
......@@ -55,12 +59,12 @@ export class ExtHostContribution implements IWorkbenchContribution {
// Addressable instances
const col = new InstanceCollection();
col.define(MainContext.MainProcessVSCodeAPIHelper).set(create(MainProcessVSCodeAPIHelper));
col.define(MainContext.MainThreadCommands).set(create(MainThreadCommands));
col.define(MainContext.MainThreadConfiguration).set(create(MainThreadConfiguration));
col.define(MainContext.MainThreadDiagnostics).set(create(MainThreadDiagnostics));
col.define(MainContext.MainThreadDocuments).set(create(MainThreadDocuments));
col.define(MainContext.MainThreadEditors).set(create(MainThreadEditors));
col.define(MainContext.MainThreadErrors).set(create(MainThreadErrors));
col.define(MainContext.MainThreadLanguageFeatures).set(create(MainThreadLanguageFeatures));
col.define(MainContext.MainThreadLanguages).set(create(MainThreadLanguages));
col.define(MainContext.MainThreadMessageService).set(create(MainThreadMessageService));
......
......@@ -6,14 +6,14 @@
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {validateConstraint} from 'vs/base/common/types';
import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry';
import {IKeybindingService, ICommandHandlerDescription} from 'vs/platform/keybinding/common/keybindingService';
import {ICommandHandlerDescription} from 'vs/platform/keybinding/common/keybindingService';
import {TPromise} from 'vs/base/common/winjs.base';
import {ExtHostEditors} from 'vs/workbench/api/node/extHostEditors';
import * as extHostTypes from 'vs/workbench/api/node/extHostTypes';
import * as extHostTypeConverter from 'vs/workbench/api/node/extHostTypeConverters';
import {cloneAndChange} from 'vs/base/common/objects';
import {MainContext, ExtHostContext} from './extHostProtocol';
import {MainContext} from './extHostProtocol';
import {MainThreadCommands} from './mainThreadCommands';
interface CommandHandler {
callback: Function;
......@@ -126,95 +126,3 @@ export class ExtHostCommands {
return TPromise.as(result);
}
}
export class MainThreadCommands {
private _threadService: IThreadService;
private _keybindingService: IKeybindingService;
private _proxy: ExtHostCommands;
constructor(
@IThreadService threadService: IThreadService,
@IKeybindingService keybindingService: IKeybindingService
) {
this._threadService = threadService;
this._keybindingService = keybindingService;
this._proxy = this._threadService.get(ExtHostContext.ExtHostCommands);
}
$registerCommand(id: string): TPromise<any> {
KeybindingsRegistry.registerCommandDesc({
id,
handler: (serviceAccessor, ...args: any[]) => {
return this._proxy.$executeContributedCommand(id, ...args);
},
weight: undefined,
when: undefined,
win: undefined,
mac: undefined,
linux: undefined,
primary: undefined,
secondary: undefined
});
return undefined;
}
$executeCommand<T>(id: string, args: any[]): Thenable<T> {
return this._keybindingService.executeCommand(id, ...args);
}
$getCommands(): Thenable<string[]> {
return TPromise.as(Object.keys(KeybindingsRegistry.getCommands()));
}
}
// --- command doc
KeybindingsRegistry.registerCommandDesc({
id: '_generateCommandsDocumentation',
handler: function(accessor) {
return accessor.get(IThreadService).get(ExtHostContext.ExtHostCommands).$getContributedCommandHandlerDescriptions().then(result => {
// add local commands
const commands = KeybindingsRegistry.getCommands();
for (let id in commands) {
let {description} = commands[id];
if (description) {
result[id] = description;
}
}
// print all as markdown
const all: string[] = [];
for (let id in result) {
all.push('`' + id + '` - ' + _generateMarkdown(result[id]));
}
console.log(all.join('\n'));
});
},
when: undefined,
weight: KeybindingsRegistry.WEIGHT.builtinExtension(0),
primary: undefined
});
function _generateMarkdown(description: string | ICommandHandlerDescription): string {
if (typeof description === 'string') {
return description;
} else {
let parts = [description.description];
parts.push('\n\n');
if (description.args) {
for (let arg of description.args) {
parts.push(`* _${arg.name}_ ${arg.description || ''}\n`);
}
}
if (description.returns) {
parts.push(`* _(returns)_ ${description.returns}`);
}
parts.push('\n\n');
return parts.join('');
}
}
......@@ -6,12 +6,8 @@
import {clone} from 'vs/base/common/objects';
import {illegalState} from 'vs/base/common/errors';
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
import Event, {Emitter} from 'vs/base/common/event';
import {WorkspaceConfiguration} from 'vscode';
import {ExtHostContext} from './extHostProtocol';
export class ExtHostConfiguration {
......@@ -76,24 +72,3 @@ export class ExtHostConfiguration {
return node;
}
}
export class MainThreadConfiguration {
private _configurationService: IConfigurationService;
private _toDispose: IDisposable;
private _proxy: ExtHostConfiguration;
constructor(@IConfigurationService configurationService: IConfigurationService,
@IThreadService threadService: IThreadService) {
this._configurationService = configurationService;
this._proxy = threadService.get(ExtHostContext.ExtHostConfiguration);
this._toDispose = this._configurationService.onDidUpdateConfiguration(event => this._proxy.$acceptConfigurationChanged(event.config));
this._proxy.$acceptConfigurationChanged(this._configurationService.getConfiguration());
}
public dispose(): void {
this._toDispose = dispose(this._toDispose);
}
}
\ No newline at end of file
......@@ -5,12 +5,12 @@
'use strict';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {IMarkerService, IMarkerData} from 'vs/platform/markers/common/markers';
import {IMarkerData} from 'vs/platform/markers/common/markers';
import URI from 'vs/base/common/uri';
import {TPromise} from 'vs/base/common/winjs.base';
import Severity from 'vs/base/common/severity';
import * as vscode from 'vscode';
import {MainContext} from './extHostProtocol';
import {MainThreadDiagnostics} from './mainThreadDiagnostics';
export class DiagnosticCollection implements vscode.DiagnosticCollection {
......@@ -216,24 +216,3 @@ export class ExtHostDiagnostics {
}
}
export class MainThreadDiagnostics {
private _markerService: IMarkerService;
constructor(@IMarkerService markerService: IMarkerService) {
this._markerService = markerService;
}
$changeMany(owner: string, entries: [URI, IMarkerData[]][]): TPromise<any> {
for (let entry of entries) {
let [uri, markers] = entry;
this._markerService.changeOne(owner, uri, markers);
}
return undefined;
}
$clear(owner: string): TPromise<any> {
this._markerService.changeAll(owner, undefined);
return undefined;
}
}
......@@ -4,34 +4,26 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import {toErrorMessage, onUnexpectedError} from 'vs/base/common/errors';
import {EmitterEvent} from 'vs/base/common/eventEmitter';
import {IModelService} from 'vs/editor/common/services/modelService';
import * as EditorCommon from 'vs/editor/common/editorCommon';
import {onUnexpectedError} from 'vs/base/common/errors';
import * as editorCommon from 'vs/editor/common/editorCommon';
import {MirrorModel2} from 'vs/editor/common/model/mirrorModel2';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import Event, {Emitter} from 'vs/base/common/event';
import URI from 'vs/base/common/uri';
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
import {IDisposable} from 'vs/base/common/lifecycle';
import {Range, Position, Disposable} from 'vs/workbench/api/node/extHostTypes';
import {IEventService} from 'vs/platform/event/common/event';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {EventType as FileEventType, TextFileChangeEvent, ITextFileService} from 'vs/workbench/parts/files/common/files';
import * as TypeConverters from './extHostTypeConverters';
import {TPromise} from 'vs/base/common/winjs.base';
import * as vscode from 'vscode';
import {IFileService} from 'vs/platform/files/common/files';
import {IModeService} from 'vs/editor/common/services/modeService';
import {IUntitledEditorService} from 'vs/workbench/services/untitled/common/untitledEditorService';
import {ResourceEditorInput} from 'vs/workbench/common/editor/resourceEditorInput';
import {asWinJsPromise} from 'vs/base/common/async';
import {getWordAtText, ensureValidWordDefinition} from 'vs/editor/common/model/wordHelper';
import {MainContext, ExtHostContext} from './extHostProtocol';
import {MainContext} from './extHostProtocol';
import {MainThreadDocuments} from './mainThreadDocuments';
export interface IModelAddedData {
url: URI;
versionId: number;
value: EditorCommon.IRawText;
value: editorCommon.IRawText;
modeId: string;
isDirty: boolean;
}
......@@ -40,15 +32,15 @@ const _modeId2WordDefinition: {
[modeId: string]: RegExp;
} = Object.create(null);
export function setWordDefinitionFor(modeId: string, wordDefinition: RegExp): void {
function setWordDefinitionFor(modeId: string, wordDefinition: RegExp): void {
_modeId2WordDefinition[modeId] = wordDefinition;
}
export function getWordDefinitionFor(modeId: string): RegExp {
function getWordDefinitionFor(modeId: string): RegExp {
return _modeId2WordDefinition[modeId];
}
export class ExtHostModelService {
export class ExtHostDocuments {
private static _handlePool: number = 0;
......@@ -135,7 +127,7 @@ export class ExtHostModelService {
throw new Error(`scheme '${scheme}' already registered`);
}
const handle = ExtHostModelService._handlePool++;
const handle = ExtHostDocuments._handlePool++;
this._documentContentProviders[handle] = provider;
this._proxy.$registerTextContentProvider(handle, scheme);
......@@ -215,7 +207,7 @@ export class ExtHostModelService {
data.dispose();
}
public _acceptModelChanged(strURL: string, events: EditorCommon.IModelContentChangedEvent2[]): void {
public _acceptModelChanged(strURL: string, events: editorCommon.IModelContentChangedEvent2[]): void {
let data = this._documentData[strURL];
data.onEvents(events);
this._onDidChangeDocumentEventEmitter.fire({
......@@ -229,6 +221,10 @@ export class ExtHostModelService {
})
});
}
setWordDefinitionFor(modeId: string, wordDefinition: RegExp): void {
setWordDefinitionFor(modeId, wordDefinition);
}
}
export class ExtHostDocumentData extends MirrorModel2 {
......@@ -436,242 +432,3 @@ export class ExtHostDocumentData extends MirrorModel2 {
}
}
}
export class MainThreadDocuments {
private _modelService: IModelService;
private _modeService: IModeService;
private _textFileService: ITextFileService;
private _editorService: IWorkbenchEditorService;
private _fileService: IFileService;
private _untitledEditorService: IUntitledEditorService;
private _toDispose: IDisposable[];
private _modelToDisposeMap: { [modelUrl: string]: IDisposable; };
private _proxy: ExtHostModelService;
private _modelIsSynced: { [modelId: string]: boolean; };
private _resourceContentProvider: { [handle: number]: IDisposable };
private _virtualDocumentSet: { [resource: string]: boolean };
constructor(
@IThreadService threadService: IThreadService,
@IModelService modelService: IModelService,
@IModeService modeService: IModeService,
@IEventService eventService: IEventService,
@ITextFileService textFileService: ITextFileService,
@IWorkbenchEditorService editorService: IWorkbenchEditorService,
@IFileService fileService: IFileService,
@IUntitledEditorService untitledEditorService: IUntitledEditorService
) {
this._modelService = modelService;
this._modeService = modeService;
this._textFileService = textFileService;
this._editorService = editorService;
this._fileService = fileService;
this._untitledEditorService = untitledEditorService;
this._proxy = threadService.get(ExtHostContext.ExtHostModelService);
this._modelIsSynced = {};
this._toDispose = [];
modelService.onModelAdded(this._onModelAdded, this, this._toDispose);
modelService.onModelRemoved(this._onModelRemoved, this, this._toDispose);
modelService.onModelModeChanged(this._onModelModeChanged, this, this._toDispose);
this._toDispose.push(eventService.addListener2(FileEventType.FILE_SAVED, (e: TextFileChangeEvent) => {
if (this._shouldHandleFileEvent(e)) {
this._proxy._acceptModelSaved(e.resource.toString());
}
}));
this._toDispose.push(eventService.addListener2(FileEventType.FILE_REVERTED, (e: TextFileChangeEvent) => {
if (this._shouldHandleFileEvent(e)) {
this._proxy._acceptModelReverted(e.resource.toString());
}
}));
this._toDispose.push(eventService.addListener2(FileEventType.FILE_DIRTY, (e: TextFileChangeEvent) => {
if (this._shouldHandleFileEvent(e)) {
this._proxy._acceptModelDirty(e.resource.toString());
}
}));
const handle = setInterval(() => this._runDocumentCleanup(), 1000 * 60 * 3);
this._toDispose.push({ dispose() { clearInterval(handle); } });
this._modelToDisposeMap = Object.create(null);
this._resourceContentProvider = Object.create(null);
this._virtualDocumentSet = Object.create(null);
}
public dispose(): void {
Object.keys(this._modelToDisposeMap).forEach((modelUrl) => {
this._modelToDisposeMap[modelUrl].dispose();
});
this._modelToDisposeMap = Object.create(null);
this._toDispose = dispose(this._toDispose);
}
private _shouldHandleFileEvent(e: TextFileChangeEvent): boolean {
const model = this._modelService.getModel(e.resource);
return model && !model.isTooLargeForHavingARichMode();
}
private _onModelAdded(model: EditorCommon.IModel): void {
// Same filter as in mainThreadEditors
if (model.isTooLargeForHavingARichMode()) {
// don't synchronize too large models
return null;
}
let modelUrl = model.uri;
this._modelIsSynced[modelUrl.toString()] = true;
this._modelToDisposeMap[modelUrl.toString()] = model.addBulkListener((events) => this._onModelEvents(modelUrl, events));
this._proxy._acceptModelAdd({
url: model.uri,
versionId: model.getVersionId(),
value: model.toRawText(),
modeId: model.getMode().getId(),
isDirty: this._textFileService.isDirty(modelUrl)
});
}
private _onModelModeChanged(event: { model: EditorCommon.IModel; oldModeId: string; }): void {
let {model, oldModeId} = event;
let modelUrl = model.uri;
if (!this._modelIsSynced[modelUrl.toString()]) {
return;
}
this._proxy._acceptModelModeChanged(model.uri.toString(), oldModeId, model.getMode().getId());
}
private _onModelRemoved(model: EditorCommon.IModel): void {
let modelUrl = model.uri;
if (!this._modelIsSynced[modelUrl.toString()]) {
return;
}
delete this._modelIsSynced[modelUrl.toString()];
this._modelToDisposeMap[modelUrl.toString()].dispose();
delete this._modelToDisposeMap[modelUrl.toString()];
this._proxy._acceptModelRemoved(modelUrl.toString());
}
private _onModelEvents(modelUrl: URI, events: EmitterEvent[]): void {
let changedEvents: EditorCommon.IModelContentChangedEvent2[] = [];
for (let i = 0, len = events.length; i < len; i++) {
let e = events[i];
switch (e.getType()) {
case EditorCommon.EventType.ModelContentChanged2:
changedEvents.push(<EditorCommon.IModelContentChangedEvent2>e.getData());
break;
}
}
if (changedEvents.length > 0) {
this._proxy._acceptModelChanged(modelUrl.toString(), changedEvents);
}
}
// --- from extension host process
_trySaveDocument(uri: URI): TPromise<boolean> {
return this._textFileService.save(uri);
}
_tryOpenDocument(uri: URI): TPromise<any> {
if (!uri.scheme || !(uri.fsPath || uri.authority)) {
return TPromise.wrapError(`Invalid uri. Scheme and authority or path must be set.`);
}
let promise: TPromise<boolean>;
switch (uri.scheme) {
case 'untitled':
promise = this._handleUnititledScheme(uri);
break;
case 'file':
default:
promise = this._handleAsResourceInput(uri);
break;
}
return promise.then(success => {
if (!success) {
return TPromise.wrapError('cannot open ' + uri.toString());
}
}, err => {
return TPromise.wrapError('cannot open ' + uri.toString() + '. Detail: ' + toErrorMessage(err));
});
}
private _handleAsResourceInput(uri: URI): TPromise<boolean> {
return this._editorService.resolveEditorModel({ resource: uri }).then(model => {
return !!model;
});
}
private _handleUnititledScheme(uri: URI): TPromise<boolean> {
let asFileUri = URI.file(uri.fsPath);
return this._fileService.resolveFile(asFileUri).then(stats => {
// don't create a new file ontop of an existing file
return TPromise.wrapError<boolean>('file already exists on disk');
}, err => {
let input = this._untitledEditorService.createOrGet(asFileUri); // using file-uri makes it show in 'Working Files' section
return input.resolve(true).then(model => {
if (input.getResource().toString() !== uri.toString()) {
throw new Error(`expected URI ${uri.toString() } BUT GOT ${input.getResource().toString() }`);
}
if (!this._modelIsSynced[uri.toString()]) {
throw new Error(`expected URI ${uri.toString()} to have come to LIFE`);
}
return this._proxy._acceptModelDirty(uri.toString()); // mark as dirty
}).then(() => {
return true;
});
});
}
// --- virtual document logic
$registerTextContentProvider(handle:number, scheme: string): void {
this._resourceContentProvider[handle] = ResourceEditorInput.registerResourceContentProvider(scheme, {
provideTextContent: (uri: URI): TPromise<EditorCommon.IModel> => {
return this._proxy.$provideTextDocumentContent(handle, uri).then(value => {
if (typeof value === 'string') {
this._virtualDocumentSet[uri.toString()] = true;
const firstLineText = value.substr(0, 1 + value.search(/\r?\n/));
const mode = this._modeService.getOrCreateModeByFilenameOrFirstLine(uri.fsPath, firstLineText);
return this._modelService.createModel(value, mode, uri);
}
});
}
});
}
$unregisterTextContentProvider(handle: number): void {
const registration = this._resourceContentProvider[handle];
if (registration) {
registration.dispose();
delete this._resourceContentProvider[handle];
}
}
$onVirtualDocumentChange(uri: URI, value: string): void {
const model = this._modelService.getModel(uri);
if (model) {
model.setValue(value);
}
}
private _runDocumentCleanup(): void {
const toBeDisposed: URI[] = [];
TPromise.join(Object.keys(this._virtualDocumentSet).map(key => {
let resource = URI.parse(key);
return this._editorService.createInput({ resource }).then(input => {
if (!this._editorService.isVisible(input, true)) {
toBeDisposed.push(resource);
}
});
})).then(() => {
for (let resource of toBeDisposed) {
this._modelService.destroyModel(resource);
delete this._virtualDocumentSet[resource.toString()];
}
}, onUnexpectedError);
}
}
......@@ -8,25 +8,17 @@ import URI from 'vs/base/common/uri';
import {readonly, illegalArgument} from 'vs/base/common/errors';
import {IdGenerator} from 'vs/base/common/idGenerator';
import Event, {Emitter} from 'vs/base/common/event';
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
import {TPromise} from 'vs/base/common/winjs.base';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {ExtHostModelService, ExtHostDocumentData} from 'vs/workbench/api/node/extHostDocuments';
import {Selection, Range, Position, EditorOptions, EndOfLine} from './extHostTypes';
import {ISingleEditOperation, ISelection, IRange, IEditor, EditorType, ICommonCodeEditor, ICommonDiffEditor, IDecorationRenderOptions, IDecorationOptions} from 'vs/editor/common/editorCommon';
import {ICodeEditorService} from 'vs/editor/common/services/codeEditorService';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {IEditorGroupService} from 'vs/workbench/services/group/common/groupService';
import {ExtHostDocuments, ExtHostDocumentData} from 'vs/workbench/api/node/extHostDocuments';
import {Selection, Range, Position, EditorOptions, EndOfLine, TextEditorRevealType} from './extHostTypes';
import {ISingleEditOperation, ISelection} from 'vs/editor/common/editorCommon';
import {Position as EditorPosition} from 'vs/platform/editor/common/editor';
import {IModelService} from 'vs/editor/common/services/modelService';
import {MainThreadEditorsTracker, TextEditorRevealType, MainThreadTextEditor, ITextEditorConfigurationUpdate, IResolvedTextEditorConfiguration} from 'vs/workbench/api/node/mainThreadEditors';
import {IResolvedTextEditorConfiguration} from 'vs/workbench/api/node/mainThreadEditorsTracker';
import * as TypeConverters from './extHostTypeConverters';
import {TextDocument, TextEditorSelectionChangeEvent, TextEditorOptionsChangeEvent, TextEditorOptions, TextEditorViewColumnChangeEvent, ViewColumn} from 'vscode';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {IEventService} from 'vs/platform/event/common/event';
import {equals as arrayEquals} from 'vs/base/common/arrays';
import {equals as objectEquals} from 'vs/base/common/objects';
import {MainContext, ExtHostContext} from './extHostProtocol';
import {MainContext} from './extHostProtocol';
import {MainThreadEditors} from './mainThreadEditors';
export interface ITextEditorAddData {
id: string;
......@@ -54,13 +46,13 @@ export class ExtHostEditors {
private _editors: { [id: string]: ExtHostTextEditor };
private _proxy: MainThreadEditors;
private _onDidChangeActiveTextEditor: Emitter<vscode.TextEditor>;
private _modelService: ExtHostModelService;
private _extHostDocuments: ExtHostDocuments;
private _activeEditorId: string;
private _visibleEditorIds: string[];
constructor(
threadService: IThreadService,
modelService: ExtHostModelService
extHostDocuments: ExtHostDocuments
) {
this._onDidChangeTextEditorSelection = new Emitter<TextEditorSelectionChangeEvent>();
this.onDidChangeTextEditorSelection = this._onDidChangeTextEditorSelection.event;
......@@ -71,7 +63,7 @@ export class ExtHostEditors {
this._onDidChangeTextEditorViewColumn = new Emitter<TextEditorViewColumnChangeEvent>();
this.onDidChangeTextEditorViewColumn = this._onDidChangeTextEditorViewColumn.event;
this._modelService = modelService;
this._extHostDocuments = extHostDocuments;
this._proxy = threadService.get(MainContext.MainThreadEditors);
this._onDidChangeActiveTextEditor = new Emitter<vscode.TextEditor>();
this._editors = Object.create(null);
......@@ -109,7 +101,7 @@ export class ExtHostEditors {
// --- called from main thread
_acceptTextEditorAdd(data: ITextEditorAddData): void {
let document = this._modelService.getDocumentData(data.document);
let document = this._extHostDocuments.getDocumentData(data.document);
let newEditor = new ExtHostTextEditor(this._proxy, data.id, document, data.selections.map(TypeConverters.toSelection), data.options, TypeConverters.toViewColumn(data.editorPosition));
this._editors[data.id] = newEditor;
}
......@@ -404,7 +396,7 @@ class ExtHostTextEditor implements vscode.TextEditor {
() => this._proxy._tryRevealRange(
this._id,
TypeConverters.fromRange(range),
(<TextEditorRevealType><any>revealType) || TextEditorRevealType.Default
revealType || TextEditorRevealType.Default
),
true
);
......@@ -453,278 +445,3 @@ class ExtHostTextEditor implements vscode.TextEditor {
});
}
}
export class MainThreadEditors {
private _proxy: ExtHostEditors;
private _workbenchEditorService: IWorkbenchEditorService;
private _telemetryService: ITelemetryService;
private _editorTracker: MainThreadEditorsTracker;
private _toDispose: IDisposable[];
private _textEditorsListenersMap: { [editorId: string]: IDisposable[]; };
private _textEditorsMap: { [editorId: string]: MainThreadTextEditor; };
private _activeTextEditor: string;
private _visibleEditors: string[];
private _editorPositionData: ITextEditorPositionData;
constructor(
@IThreadService threadService: IThreadService,
@IWorkbenchEditorService workbenchEditorService: IWorkbenchEditorService,
@IEditorGroupService editorGroupService: IEditorGroupService,
@ITelemetryService telemetryService: ITelemetryService,
@ICodeEditorService editorService: ICodeEditorService,
@IEventService eventService: IEventService,
@IModelService modelService: IModelService
) {
this._proxy = threadService.get(ExtHostContext.ExtHostEditors);
this._workbenchEditorService = workbenchEditorService;
this._telemetryService = telemetryService;
this._toDispose = [];
this._textEditorsListenersMap = Object.create(null);
this._textEditorsMap = Object.create(null);
this._activeTextEditor = null;
this._visibleEditors = [];
this._editorPositionData = null;
this._editorTracker = new MainThreadEditorsTracker(editorService, modelService);
this._toDispose.push(this._editorTracker);
this._toDispose.push(this._editorTracker.onTextEditorAdd((textEditor) => this._onTextEditorAdd(textEditor)));
this._toDispose.push(this._editorTracker.onTextEditorRemove((textEditor) => this._onTextEditorRemove(textEditor)));
this._toDispose.push(this._editorTracker.onDidUpdateTextEditors(() => this._updateActiveAndVisibleTextEditors()));
this._toDispose.push(this._editorTracker.onChangedFocusedTextEditor((focusedTextEditorId) => this._updateActiveAndVisibleTextEditors()));
this._toDispose.push(editorGroupService.onEditorsChanged(() => this._updateActiveAndVisibleTextEditors()));
this._toDispose.push(editorGroupService.onEditorsMoved(() => this._updateActiveAndVisibleTextEditors()));
}
public dispose(): void {
Object.keys(this._textEditorsListenersMap).forEach((editorId) => {
dispose(this._textEditorsListenersMap[editorId]);
});
this._textEditorsListenersMap = Object.create(null);
this._toDispose = dispose(this._toDispose);
}
private _onTextEditorAdd(textEditor: MainThreadTextEditor): void {
let id = textEditor.getId();
let toDispose: IDisposable[] = [];
toDispose.push(textEditor.onConfigurationChanged((opts) => {
this._proxy._acceptOptionsChanged(id, opts);
}));
toDispose.push(textEditor.onSelectionChanged((selection) => {
this._proxy._acceptSelectionsChanged(id, selection);
}));
this._proxy._acceptTextEditorAdd({
id: id,
document: textEditor.getModel().uri,
options: textEditor.getConfiguration(),
selections: textEditor.getSelections(),
editorPosition: this._findEditorPosition(textEditor)
});
this._textEditorsListenersMap[id] = toDispose;
this._textEditorsMap[id] = textEditor;
}
private _onTextEditorRemove(textEditor: MainThreadTextEditor): void {
let id = textEditor.getId();
dispose(this._textEditorsListenersMap[id]);
delete this._textEditorsListenersMap[id];
delete this._textEditorsMap[id];
this._proxy._acceptTextEditorRemove(id);
}
private _updateActiveAndVisibleTextEditors(): void {
// active and visible editors
let visibleEditors = this._editorTracker.getVisibleTextEditorIds();
let activeEditor = this._findActiveTextEditorId();
if (activeEditor !== this._activeTextEditor || !arrayEquals(this._visibleEditors, visibleEditors, (a, b) => a === b)) {
this._activeTextEditor = activeEditor;
this._visibleEditors = visibleEditors;
this._proxy._acceptActiveEditorAndVisibleEditors(this._activeTextEditor, this._visibleEditors);
}
// editor columns
let editorPositionData = this._getTextEditorPositionData();
if (!objectEquals(this._editorPositionData, editorPositionData)) {
this._editorPositionData = editorPositionData;
this._proxy._acceptEditorPositionData(this._editorPositionData);
}
}
private _findActiveTextEditorId(): string {
let focusedTextEditorId = this._editorTracker.getFocusedTextEditorId();
if (focusedTextEditorId) {
return focusedTextEditorId;
}
let activeEditor = this._workbenchEditorService.getActiveEditor();
if (!activeEditor) {
return null;
}
let editor = <IEditor>activeEditor.getControl();
// Substitute for (editor instanceof ICodeEditor)
if (!editor || typeof editor.getEditorType !== 'function') {
// Not a text editor...
return null;
}
if (editor.getEditorType() === EditorType.ICodeEditor) {
return this._editorTracker.findTextEditorIdFor(<ICommonCodeEditor>editor);
}
// Must be a diff editor => use the modified side
return this._editorTracker.findTextEditorIdFor((<ICommonDiffEditor>editor).getModifiedEditor());
}
private _findEditorPosition(editor: MainThreadTextEditor): EditorPosition {
for (let workbenchEditor of this._workbenchEditorService.getVisibleEditors()) {
if (editor.matches(workbenchEditor)) {
return workbenchEditor.position;
}
}
}
private _getTextEditorPositionData(): ITextEditorPositionData {
let result: ITextEditorPositionData = Object.create(null);
for (let workbenchEditor of this._workbenchEditorService.getVisibleEditors()) {
let editor = <IEditor>workbenchEditor.getControl();
// Substitute for (editor instanceof ICodeEditor)
if (!editor || typeof editor.getEditorType !== 'function') {
// Not a text editor...
continue;
}
if (editor.getEditorType() === EditorType.ICodeEditor) {
let id = this._editorTracker.findTextEditorIdFor(<ICommonCodeEditor>editor);
if (id) {
result[id] = workbenchEditor.position;
}
}
}
return result;
}
// --- from extension host process
_tryShowTextDocument(resource: URI, position: EditorPosition, preserveFocus: boolean): TPromise<string> {
const input = {
resource,
options: { preserveFocus }
};
return this._workbenchEditorService.openEditor(input, position).then(editor => {
if (!editor) {
return;
}
return new TPromise<void>(c => {
// not very nice but the way it is: changes to the editor state aren't
// send to the ext host as they happen but stuff is delayed a little. in
// order to provide the real editor on #openTextEditor we need to sync on
// that update
let subscription: IDisposable;
let handle: number;
function contd() {
subscription.dispose();
clearTimeout(handle);
c(undefined);
}
subscription = this._editorTracker.onDidUpdateTextEditors(() => {
contd();
});
handle = setTimeout(() => {
contd();
}, 1000);
}).then(() => {
// find the editor we have just opened and return the
// id we have assigned to it.
for (let id in this._textEditorsMap) {
if (this._textEditorsMap[id].matches(editor)) {
return id;
}
}
});
});
}
_tryShowEditor(id: string, position: EditorPosition): TPromise<void> {
// check how often this is used
this._telemetryService.publicLog('api.deprecated', { function: 'TextEditor.show' });
let mainThreadEditor = this._textEditorsMap[id];
if (mainThreadEditor) {
let model = mainThreadEditor.getModel();
return this._workbenchEditorService.openEditor({
resource: model.uri,
options: { preserveFocus: false }
}, position).then(() => { return; });
}
}
_tryHideEditor(id: string): TPromise<void> {
// check how often this is used
this._telemetryService.publicLog('api.deprecated', { function: 'TextEditor.hide' });
let mainThreadEditor = this._textEditorsMap[id];
if (mainThreadEditor) {
let editors = this._workbenchEditorService.getVisibleEditors();
for (let editor of editors) {
if (mainThreadEditor.matches(editor)) {
return this._workbenchEditorService.closeEditor(editor.position, editor.input).then(() => { return; });
}
}
}
}
_trySetSelections(id: string, selections: ISelection[]): TPromise<any> {
if (!this._textEditorsMap[id]) {
return TPromise.wrapError('TextEditor disposed');
}
this._textEditorsMap[id].setSelections(selections);
return TPromise.as(null);
}
_trySetDecorations(id: string, key: string, ranges: IDecorationOptions[]): TPromise<any> {
if (!this._textEditorsMap[id]) {
return TPromise.wrapError('TextEditor disposed');
}
this._textEditorsMap[id].setDecorations(key, ranges);
return TPromise.as(null);
}
_tryRevealRange(id: string, range: IRange, revealType: TextEditorRevealType): TPromise<any> {
if (!this._textEditorsMap[id]) {
return TPromise.wrapError('TextEditor disposed');
}
this._textEditorsMap[id].revealRange(range, revealType);
}
_trySetOptions(id: string, options: ITextEditorConfigurationUpdate): TPromise<any> {
if (!this._textEditorsMap[id]) {
return TPromise.wrapError('TextEditor disposed');
}
this._textEditorsMap[id].setConfiguration(options);
return TPromise.as(null);
}
_tryApplyEdits(id: string, modelVersionId: number, edits: ISingleEditOperation[], setEndOfLine:EndOfLine): TPromise<boolean> {
if (!this._textEditorsMap[id]) {
return TPromise.wrapError('TextEditor disposed');
}
return TPromise.as(this._textEditorsMap[id].applyEdits(modelVersionId, edits, setEndOfLine));
}
_registerTextEditorDecorationType(key: string, options: IDecorationRenderOptions): void {
this._editorTracker.registerTextEditorDecorationType(key, options);
}
_removeTextEditorDecorationType(key: string): void {
this._editorTracker.removeTextEditorDecorationType(key);
}
}
......@@ -10,144 +10,16 @@ import * as paths from 'vs/base/common/paths';
import Severity from 'vs/base/common/severity';
import {TPromise} from 'vs/base/common/winjs.base';
import {AbstractExtensionService, ActivatedExtension} from 'vs/platform/extensions/common/abstractExtensionService';
import {IMessage, IExtensionDescription, IExtensionsStatus} from 'vs/platform/extensions/common/extensions';
import {IMessage, IExtensionDescription} from 'vs/platform/extensions/common/extensions';
import {ExtensionsRegistry} from 'vs/platform/extensions/common/extensionsRegistry';
import {IMessageService} from 'vs/platform/message/common/message';
import {ExtHostStorage} from 'vs/workbench/api/node/extHostStorage';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {MainContext, ExtHostContext} from './extHostProtocol';
import {MainContext} from './extHostProtocol';
import {MainProcessExtensionService} from './mainThreadExtensionService';
const hasOwnProperty = Object.hasOwnProperty;
/**
* Represents a failed extension in the ext host.
*/
class MainProcessFailedExtension extends ActivatedExtension {
constructor() {
super(true);
}
}
/**
* Represents an extension that was successfully loaded or an
* empty extension in the ext host.
*/
class MainProcessSuccessExtension extends ActivatedExtension {
constructor() {
super(false);
}
}
function messageWithSource(msg:IMessage): string {
return (msg.source ? '[' + msg.source + ']: ' : '') + msg.message;
}
export class MainProcessExtensionService extends AbstractExtensionService<ActivatedExtension> {
private _threadService: IThreadService;
private _messageService: IMessageService;
private _proxy: ExtHostExtensionService;
private _isDev: boolean;
private _extensionsStatus: { [id: string]: IExtensionsStatus };
/**
* This class is constructed manually because it is a service, so it doesn't use any ctor injection
*/
constructor(
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IThreadService threadService: IThreadService,
@IMessageService messageService: IMessageService
) {
super(false);
let config = contextService.getConfiguration();
this._isDev = !config.env.isBuilt || !!config.env.extensionDevelopmentPath;
this._messageService = messageService;
this._threadService = threadService;
this._proxy = this._threadService.get(ExtHostContext.ExtHostExtensionService);
this._extensionsStatus = {};
ExtensionsRegistry.handleExtensionPoints((msg) => this._handleMessage(msg));
}
private _handleMessage(msg: IMessage) {
this._showMessage(msg.type, messageWithSource(msg));
if (!this._extensionsStatus[msg.source]) {
this._extensionsStatus[msg.source] = { messages: [] };
}
this._extensionsStatus[msg.source].messages.push(msg);
}
public $localShowMessage(severity: Severity, msg: string): void {
let messageShown = false;
if (severity === Severity.Error || severity === Severity.Warning) {
if (this._isDev) {
// Only show nasty intrusive messages if doing extension development.
this._messageService.show(severity, msg);
messageShown = true;
}
}
if (!messageShown) {
switch (severity) {
case Severity.Error:
console.error(msg);
break;
case Severity.Warning:
console.warn(msg);
break;
default:
console.log(msg);
}
}
}
// -- overwriting AbstractExtensionService
public getExtensionsStatus(): { [id: string]: IExtensionsStatus } {
return this._extensionsStatus;
}
protected _showMessage(severity: Severity, msg: string): void {
this._proxy.$localShowMessage(severity, msg);
this.$localShowMessage(severity, msg);
}
protected _createFailedExtension(): ActivatedExtension {
return new MainProcessFailedExtension();
}
protected _actualActivateExtension(extensionDescription: IExtensionDescription): TPromise<ActivatedExtension> {
// redirect extension activation to the extension host
return this._proxy.$activateExtension(extensionDescription).then(_ => {
// the extension host calls $onExtensionActivated, where we write to `_activatedExtensions`
return this._activatedExtensions[extensionDescription.id];
});
}
// -- called by extension host
public $onExtensionHostReady(extensionDescriptions: IExtensionDescription[], messages: IMessage[]): TPromise<void> {
ExtensionsRegistry.registerExtensions(extensionDescriptions);
messages.forEach((entry) => this._handleMessage(entry));
this._triggerOnReady();
return;
}
public $onExtensionActivated(extensionId: string): void {
this._activatedExtensions[extensionId] = new MainProcessSuccessExtension();
}
public $onExtensionActivationFailed(extensionId: string): void {
this._activatedExtensions[extensionId] = new MainProcessFailedExtension();
}
}
/**
* Represents the source code (module) of an extension.
*/
......@@ -444,4 +316,4 @@ function getTelemetryActivationEvent(extensionDescription: IExtensionDescription
}
return event;
}
\ No newline at end of file
}
......@@ -4,16 +4,11 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import {FileChangesEvent, FileChangeType} from 'vs/platform/files/common/files';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import Event, {Emitter} from 'vs/base/common/event';
import {Disposable} from './extHostTypes';
import {IEventService} from 'vs/platform/event/common/event';
import {RunOnceScheduler} from 'vs/base/common/async';
import URI from 'vs/base/common/uri';
import {match} from 'vs/base/common/glob';
import {Uri, FileSystemWatcher as _FileSystemWatcher} from 'vscode';
import {ExtHostContext} from './extHostProtocol';
export interface FileSystemEvents {
created: URI[];
......@@ -113,40 +108,3 @@ export class ExtHostFileSystemEventService {
this._emitter.fire(events);
}
}
export class MainThreadFileSystemEventService {
constructor( @IEventService eventService: IEventService, @IThreadService threadService: IThreadService) {
const proxy = threadService.get(ExtHostContext.ExtHostFileSystemEventService);
const events: FileSystemEvents = {
created: [],
changed: [],
deleted: []
};
const scheduler = new RunOnceScheduler(() => {
proxy._onFileEvent(events);
events.created.length = 0;
events.changed.length = 0;
events.deleted.length = 0;
}, 100);
eventService.addListener2('files:fileChanges', (event: FileChangesEvent) => {
for (let change of event.changes) {
switch (change.type) {
case FileChangeType.ADDED:
events.created.push(change.resource);
break;
case FileChangeType.UPDATED:
events.changed.push(change.resource);
break;
case FileChangeType.DELETED:
events.deleted.push(change.resource);
break;
}
}
scheduler.schedule();
});
}
}
......@@ -11,26 +11,25 @@ import {IThreadService} from 'vs/workbench/services/thread/common/threadService'
import * as vscode from 'vscode';
import * as TypeConverters from 'vs/workbench/api/node/extHostTypeConverters';
import {Range, Disposable, SignatureHelp, CompletionList} from 'vs/workbench/api/node/extHostTypes';
import {IReadOnlyModel, IPosition, IRange, ISingleEditOperation} from 'vs/editor/common/editorCommon';
import {IPosition, IRange, ISingleEditOperation} from 'vs/editor/common/editorCommon';
import * as modes from 'vs/editor/common/modes';
import {ExtHostModelService} from 'vs/workbench/api/node/extHostDocuments';
import {ExtHostDocuments} from 'vs/workbench/api/node/extHostDocuments';
import {ExtHostCommands} from 'vs/workbench/api/node/extHostCommands';
import {ExtHostDiagnostics} from 'vs/workbench/api/node/extHostDiagnostics';
import {NavigateTypesSupportRegistry, INavigateTypesSupport, ITypeBearing} from 'vs/workbench/parts/search/common/search';
import {asWinJsPromise, ShallowCancelThenPromise, wireCancellationToken} from 'vs/base/common/async';
import {CancellationToken} from 'vs/base/common/cancellation';
import {Position as EditorPosition} from 'vs/editor/common/core/position';
import {Range as EditorRange} from 'vs/editor/common/core/range';
import {MainContext, ExtHostContext} from './extHostProtocol';
import {INavigateTypesSupport, ITypeBearing} from 'vs/workbench/parts/search/common/search';
import {asWinJsPromise, ShallowCancelThenPromise} from 'vs/base/common/async';
import {MainContext} from './extHostProtocol';
import {MainThreadLanguageFeatures} from './mainThreadLanguageFeatures';
import {regExpLeadsToEndlessLoop} from 'vs/base/common/strings';
// --- adapter
class OutlineAdapter {
private _documents: ExtHostModelService;
private _documents: ExtHostDocuments;
private _provider: vscode.DocumentSymbolProvider;
constructor(documents: ExtHostModelService, provider: vscode.DocumentSymbolProvider) {
constructor(documents: ExtHostDocuments, provider: vscode.DocumentSymbolProvider) {
this._documents = documents;
this._provider = provider;
}
......@@ -53,13 +52,13 @@ interface CachedCodeLens {
class CodeLensAdapter {
private _documents: ExtHostModelService;
private _documents: ExtHostDocuments;
private _commands: ExtHostCommands;
private _provider: vscode.CodeLensProvider;
private _cache: { [uri: string]: { version: number; data: TPromise<CachedCodeLens>; } } = Object.create(null);
constructor(documents: ExtHostModelService, commands: ExtHostCommands, provider: vscode.CodeLensProvider) {
constructor(documents: ExtHostDocuments, commands: ExtHostCommands, provider: vscode.CodeLensProvider) {
this._documents = documents;
this._commands = commands;
this._provider = provider;
......@@ -157,10 +156,10 @@ class CodeLensAdapter {
class DefinitionAdapter {
private _documents: ExtHostModelService;
private _documents: ExtHostDocuments;
private _provider: vscode.DefinitionProvider;
constructor(documents: ExtHostModelService, provider: vscode.DefinitionProvider) {
constructor(documents: ExtHostDocuments, provider: vscode.DefinitionProvider) {
this._documents = documents;
this._provider = provider;
}
......@@ -190,10 +189,10 @@ class DefinitionAdapter {
class HoverAdapter {
private _documents: ExtHostModelService;
private _documents: ExtHostDocuments;
private _provider: vscode.HoverProvider;
constructor(documents: ExtHostModelService, provider: vscode.HoverProvider) {
constructor(documents: ExtHostDocuments, provider: vscode.HoverProvider) {
this._documents = documents;
this._provider = provider;
}
......@@ -221,10 +220,10 @@ class HoverAdapter {
class DocumentHighlightAdapter {
private _documents: ExtHostModelService;
private _documents: ExtHostDocuments;
private _provider: vscode.DocumentHighlightProvider;
constructor(documents: ExtHostModelService, provider: vscode.DocumentHighlightProvider) {
constructor(documents: ExtHostDocuments, provider: vscode.DocumentHighlightProvider) {
this._documents = documents;
this._provider = provider;
}
......@@ -251,10 +250,10 @@ class DocumentHighlightAdapter {
class ReferenceAdapter {
private _documents: ExtHostModelService;
private _documents: ExtHostDocuments;
private _provider: vscode.ReferenceProvider;
constructor(documents: ExtHostModelService, provider: vscode.ReferenceProvider) {
constructor(documents: ExtHostDocuments, provider: vscode.ReferenceProvider) {
this._documents = documents;
this._provider = provider;
}
......@@ -280,14 +279,14 @@ class ReferenceAdapter {
class QuickFixAdapter {
private _documents: ExtHostModelService;
private _documents: ExtHostDocuments;
private _commands: ExtHostCommands;
private _diagnostics: ExtHostDiagnostics;
private _provider: vscode.CodeActionProvider;
private _cachedCommands: IDisposable[] = [];
constructor(documents: ExtHostModelService, commands: ExtHostCommands, diagnostics: ExtHostDiagnostics, provider: vscode.CodeActionProvider) {
constructor(documents: ExtHostDocuments, commands: ExtHostCommands, diagnostics: ExtHostDiagnostics, provider: vscode.CodeActionProvider) {
this._documents = documents;
this._commands = commands;
this._diagnostics = diagnostics;
......@@ -328,10 +327,10 @@ class QuickFixAdapter {
class DocumentFormattingAdapter {
private _documents: ExtHostModelService;
private _documents: ExtHostDocuments;
private _provider: vscode.DocumentFormattingEditProvider;
constructor(documents: ExtHostModelService, provider: vscode.DocumentFormattingEditProvider) {
constructor(documents: ExtHostDocuments, provider: vscode.DocumentFormattingEditProvider) {
this._documents = documents;
this._provider = provider;
}
......@@ -350,10 +349,10 @@ class DocumentFormattingAdapter {
class RangeFormattingAdapter {
private _documents: ExtHostModelService;
private _documents: ExtHostDocuments;
private _provider: vscode.DocumentRangeFormattingEditProvider;
constructor(documents: ExtHostModelService, provider: vscode.DocumentRangeFormattingEditProvider) {
constructor(documents: ExtHostDocuments, provider: vscode.DocumentRangeFormattingEditProvider) {
this._documents = documents;
this._provider = provider;
}
......@@ -373,10 +372,10 @@ class RangeFormattingAdapter {
class OnTypeFormattingAdapter {
private _documents: ExtHostModelService;
private _documents: ExtHostDocuments;
private _provider: vscode.OnTypeFormattingEditProvider;
constructor(documents: ExtHostModelService, provider: vscode.OnTypeFormattingEditProvider) {
constructor(documents: ExtHostDocuments, provider: vscode.OnTypeFormattingEditProvider) {
this._documents = documents;
this._provider = provider;
}
......@@ -415,10 +414,10 @@ class NavigateTypeAdapter implements INavigateTypesSupport {
class RenameAdapter {
private _documents: ExtHostModelService;
private _documents: ExtHostDocuments;
private _provider: vscode.RenameProvider;
constructor(documents: ExtHostModelService, provider: vscode.RenameProvider) {
constructor(documents: ExtHostDocuments, provider: vscode.RenameProvider) {
this._documents = documents;
this._provider = provider;
}
......@@ -467,11 +466,11 @@ interface ISuggestion2 extends modes.ISuggestion {
class SuggestAdapter {
private _documents: ExtHostModelService;
private _documents: ExtHostDocuments;
private _provider: vscode.CompletionItemProvider;
private _cache: { [key: string]: CompletionList } = Object.create(null);
constructor(documents: ExtHostModelService, provider: vscode.CompletionItemProvider) {
constructor(documents: ExtHostDocuments, provider: vscode.CompletionItemProvider) {
this._documents = documents;
this._provider = provider;
}
......@@ -569,10 +568,10 @@ class SuggestAdapter {
class SignatureHelpAdapter {
private _documents: ExtHostModelService;
private _documents: ExtHostDocuments;
private _provider: vscode.SignatureHelpProvider;
constructor(documents: ExtHostModelService, provider: vscode.SignatureHelpProvider) {
constructor(documents: ExtHostDocuments, provider: vscode.SignatureHelpProvider) {
this._documents = documents;
this._provider = provider;
}
......@@ -600,14 +599,14 @@ export class ExtHostLanguageFeatures {
private static _handlePool: number = 0;
private _proxy: MainThreadLanguageFeatures;
private _documents: ExtHostModelService;
private _documents: ExtHostDocuments;
private _commands: ExtHostCommands;
private _diagnostics: ExtHostDiagnostics;
private _adapter: { [handle: number]: Adapter } = Object.create(null);
constructor(
threadService: IThreadService,
documents: ExtHostModelService,
documents: ExtHostDocuments,
commands: ExtHostCommands,
diagnostics: ExtHostDiagnostics
) {
......@@ -821,188 +820,32 @@ export class ExtHostLanguageFeatures {
$provideSignatureHelp(handle: number, resource: URI, position: IPosition): TPromise<modes.SignatureHelp> {
return this._withAdapter(handle, SignatureHelpAdapter, adapter => adapter.provideSignatureHelp(resource, position));
}
}
export class MainThreadLanguageFeatures {
private _proxy: ExtHostLanguageFeatures;
private _registrations: { [handle: number]: IDisposable; } = Object.create(null);
// --- configuration
constructor( @IThreadService threadService: IThreadService) {
this._proxy = threadService.get(ExtHostContext.ExtHostLanguageFeatures);
}
setLanguageConfiguration(languageId:string, configuration: vscode.LanguageConfiguration): vscode.Disposable {
let {wordPattern} = configuration;
$unregister(handle: number): TPromise<any> {
let registration = this._registrations[handle];
if (registration) {
registration.dispose();
delete this._registrations[handle];
// check for a valid word pattern
if (wordPattern && regExpLeadsToEndlessLoop(wordPattern)) {
throw new Error(`Invalid language configuration: wordPattern '${wordPattern}' is not allowed to match the empty string.`);
}
return undefined;
}
// --- outline
$registerOutlineSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.DocumentSymbolProviderRegistry.register(selector, <modes.DocumentSymbolProvider>{
provideDocumentSymbols: (model:IReadOnlyModel, token: CancellationToken): Thenable<modes.SymbolInformation[]> => {
return wireCancellationToken(token, this._proxy.$provideDocumentSymbols(handle, model.uri));
}
});
return undefined;
}
// --- code lens
$registerCodeLensSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.CodeLensProviderRegistry.register(selector, <modes.CodeLensProvider>{
provideCodeLenses: (model:IReadOnlyModel, token: CancellationToken): modes.ICodeLensSymbol[] | Thenable<modes.ICodeLensSymbol[]> => {
return wireCancellationToken(token, this._proxy.$provideCodeLenses(handle, model.uri));
},
resolveCodeLens: (model:IReadOnlyModel, codeLens: modes.ICodeLensSymbol, token: CancellationToken): modes.ICodeLensSymbol | Thenable<modes.ICodeLensSymbol> => {
return wireCancellationToken(token, this._proxy.$resolveCodeLens(handle, model.uri, codeLens));
}
});
return undefined;
}
// --- declaration
$registerDeclaractionSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.DefinitionProviderRegistry.register(selector, <modes.DefinitionProvider>{
provideDefinition: (model, position, token): Thenable<modes.Definition> => {
return wireCancellationToken(token, this._proxy.$provideDefinition(handle, model.uri, position));
}
});
return undefined;
}
// --- extra info
$registerHoverProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.HoverProviderRegistry.register(selector, <modes.HoverProvider>{
provideHover: (model:IReadOnlyModel, position:EditorPosition, token:CancellationToken): Thenable<modes.Hover> => {
return wireCancellationToken(token, this._proxy.$provideHover(handle, model.uri, position));
}
});
return undefined;
}
// --- occurrences
$registerDocumentHighlightProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.DocumentHighlightProviderRegistry.register(selector, <modes.DocumentHighlightProvider>{
provideDocumentHighlights: (model: IReadOnlyModel, position: EditorPosition, token: CancellationToken): Thenable<modes.DocumentHighlight[]> => {
return wireCancellationToken(token, this._proxy.$provideDocumentHighlights(handle, model.uri, position));
}
});
return undefined;
}
// --- references
$registerReferenceSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.ReferenceProviderRegistry.register(selector, <modes.ReferenceProvider>{
provideReferences: (model:IReadOnlyModel, position:EditorPosition, context: modes.ReferenceContext, token: CancellationToken): Thenable<modes.Location[]> => {
return wireCancellationToken(token, this._proxy.$provideReferences(handle, model.uri, position, context));
}
});
return undefined;
}
// --- quick fix
$registerQuickFixSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.CodeActionProviderRegistry.register(selector, <modes.CodeActionProvider>{
provideCodeActions: (model:IReadOnlyModel, range:EditorRange, token: CancellationToken): Thenable<modes.CodeAction[]> => {
return wireCancellationToken(token, this._proxy.$provideCodeActions(handle, model.uri, range));
}
});
return undefined;
}
// --- formatting
$registerDocumentFormattingSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.DocumentFormattingEditProviderRegistry.register(selector, <modes.DocumentFormattingEditProvider>{
provideDocumentFormattingEdits: (model: IReadOnlyModel, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> => {
return wireCancellationToken(token, this._proxy.$provideDocumentFormattingEdits(handle, model.uri, options));
}
});
return undefined;
}
$registerRangeFormattingSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.DocumentRangeFormattingEditProviderRegistry.register(selector, <modes.DocumentRangeFormattingEditProvider>{
provideDocumentRangeFormattingEdits: (model: IReadOnlyModel, range: EditorRange, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> => {
return wireCancellationToken(token, this._proxy.$provideDocumentRangeFormattingEdits(handle, model.uri, range, options));
}
});
return undefined;
}
$registerOnTypeFormattingSupport(handle: number, selector: vscode.DocumentSelector, autoFormatTriggerCharacters: string[]): TPromise<any> {
this._registrations[handle] = modes.OnTypeFormattingEditProviderRegistry.register(selector, <modes.OnTypeFormattingEditProvider>{
autoFormatTriggerCharacters,
provideOnTypeFormattingEdits: (model: IReadOnlyModel, position: EditorPosition, ch: string, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> => {
return wireCancellationToken(token, this._proxy.$provideOnTypeFormattingEdits(handle, model.uri, position, ch, options));
}
});
return undefined;
}
// --- navigate type
$registerNavigateTypeSupport(handle: number): TPromise<any> {
this._registrations[handle] = NavigateTypesSupportRegistry.register(<INavigateTypesSupport>{
getNavigateToItems: (search: string): TPromise<ITypeBearing[]> => {
return this._proxy.$getNavigateToItems(handle, search);
}
});
return undefined;
}
// --- rename
$registerRenameSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.RenameProviderRegistry.register(selector, <modes.RenameProvider>{
provideRenameEdits: (model:IReadOnlyModel, position:EditorPosition, newName: string, token: CancellationToken): Thenable<modes.WorkspaceEdit> => {
return wireCancellationToken(token, this._proxy.$provideRenameEdits(handle, model.uri, position, newName));
}
});
return undefined;
}
// --- suggest
$registerSuggestSupport(handle: number, selector: vscode.DocumentSelector, triggerCharacters: string[]): TPromise<any> {
this._registrations[handle] = modes.SuggestRegistry.register(selector, <modes.ISuggestSupport>{
triggerCharacters: triggerCharacters,
shouldAutotriggerSuggest: true,
provideCompletionItems: (model:IReadOnlyModel, position:EditorPosition, token:CancellationToken): Thenable<modes.ISuggestResult[]> => {
return wireCancellationToken(token, this._proxy.$provideCompletionItems(handle, model.uri, position));
},
resolveCompletionItem: (model:IReadOnlyModel, position:EditorPosition, suggestion: modes.ISuggestion, token: CancellationToken): Thenable<modes.ISuggestion> => {
return wireCancellationToken(token, this._proxy.$resolveCompletionItem(handle, model.uri, position, suggestion));
}
});
return undefined;
}
// --- parameter hints
$registerSignatureHelpProvider(handle: number, selector: vscode.DocumentSelector, triggerCharacter: string[]): TPromise<any> {
this._registrations[handle] = modes.SignatureHelpProviderRegistry.register(selector, <modes.SignatureHelpProvider>{
signatureHelpTriggerCharacters: triggerCharacter,
// word definition
if (wordPattern) {
this._documents.setWordDefinitionFor(languageId, wordPattern);
} else {
this._documents.setWordDefinitionFor(languageId, null);
}
provideSignatureHelp: (model:IReadOnlyModel, position:EditorPosition, token:CancellationToken): Thenable<modes.SignatureHelp> => {
return wireCancellationToken(token, this._proxy.$provideSignatureHelp(handle, model.uri, position));
}
// backward compatibility, migrate deprecated setting
if (configuration.__characterPairSupport && !configuration.autoClosingPairs) {
configuration.autoClosingPairs = configuration.__characterPairSupport.autoClosingPairs;
delete configuration.__characterPairSupport;
}
});
return undefined;
const handle = this._nextHandle();
this._proxy.$setLanguageConfiguration(handle, languageId, configuration);
return this._createDisposable(handle);
}
}
......@@ -6,8 +6,8 @@
import {TPromise} from 'vs/base/common/winjs.base';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {IModeService} from 'vs/editor/common/services/modeService';
import {MainContext} from './extHostProtocol';
import {MainThreadLanguages} from './mainThreadLanguages';
export class ExtHostLanguages {
......@@ -24,17 +24,3 @@ export class ExtHostLanguages {
}
}
export class MainThreadLanguages {
private _modeService: IModeService;
constructor(
@IModeService modeService: IModeService
) {
this._modeService = modeService;
}
_getLanguages(): TPromise<string[]> {
return TPromise.as(this._modeService.getRegisteredModes());
}
}
......@@ -4,14 +4,11 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import nls = require('vs/nls');
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {IMessageService} from 'vs/platform/message/common/message';
import Severity from 'vs/base/common/severity';
import {Action} from 'vs/base/common/actions';
import {TPromise as Promise} from 'vs/base/common/winjs.base';
import vscode = require('vscode');
import {MainContext} from './extHostProtocol';
import {MainThreadMessageService} from './mainThreadMessageService';
export class ExtHostMessageService {
......@@ -44,51 +41,3 @@ export class ExtHostMessageService {
});
}
}
export class MainThreadMessageService {
private _messageService: IMessageService;
constructor(@IMessageService messageService:IMessageService) {
this._messageService = messageService;
}
$showMessage(severity: Severity, message: string, commands: { title: string; isCloseAffordance: boolean; handle: number; }[]): Thenable<number> {
return new Promise<number>(resolve => {
let messageHide: Function;
let actions: MessageItemAction[] = [];
let hasCloseAffordance = false;
class MessageItemAction extends Action {
constructor(id: string, label: string, handle: number) {
super(id, label, undefined, true, () => {
resolve(handle);
messageHide(); // triggers dispose! make sure promise is already resolved
return undefined;
});
}
dispose(): void {
resolve(undefined);
}
}
commands.forEach(command => {
if (command.isCloseAffordance === true) {
hasCloseAffordance = true;
}
actions.push(new MessageItemAction('_extension_message_handle_' + command.handle, command.title, command.handle));
});
if (!hasCloseAffordance) {
actions.unshift(new MessageItemAction('__close', nls.localize('close', "Close"), undefined));
}
messageHide = this._messageService.show(severity, {
message,
actions
});
});
}
}
......@@ -4,13 +4,9 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import {TPromise} from 'vs/base/common/winjs.base';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {Registry} from 'vs/platform/platform';
import {IOutputService, IOutputChannel, OUTPUT_PANEL_ID, Extensions, IOutputChannelRegistry} from 'vs/workbench/parts/output/common/output';
import {IPartService} from 'vs/workbench/services/part/common/partService';
import {IPanelService} from 'vs/workbench/services/panel/common/panelService';
import {MainContext} from './extHostProtocol';
import {MainThreadOutputService} from './mainThreadOutputService';
export class ExtHostOutputChannel implements vscode.OutputChannel {
......@@ -81,51 +77,3 @@ export class ExtHostOutputService {
}
}
}
export class MainThreadOutputService {
private _outputService: IOutputService;
private _partService: IPartService;
private _panelService: IPanelService;
constructor(@IOutputService outputService: IOutputService,
@IPartService partService: IPartService,
@IPanelService panelService: IPanelService
) {
this._outputService = outputService;
this._partService = partService;
this._panelService = panelService;
}
public append(channelId: string, label: string, value: string): TPromise<void> {
this._getChannel(channelId, label).append(value);
return undefined;
}
public clear(channelId: string, label: string): TPromise<void> {
this._getChannel(channelId, label).clear();
return undefined;
}
public reveal(channelId: string, label: string, preserveFocus: boolean): TPromise<void> {
this._getChannel(channelId, label).show(preserveFocus);
return undefined;
}
private _getChannel(channelId: string, label: string): IOutputChannel {
if (Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).getChannels().every(channel => channel.id !== channelId)) {
Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).registerChannel(channelId, label);
}
return this._outputService.getChannel(channelId);
}
public close(channelId: string): TPromise<void> {
const panel = this._panelService.getActivePanel();
if (panel && panel.getId() === OUTPUT_PANEL_ID && channelId === this._outputService.getActiveChannel().id ) {
this._partService.setPanelHidden(true);
}
return undefined;
}
}
......@@ -9,32 +9,43 @@ import {
createExtHostContextProxyIdentifier as createExtId,
ProxyIdentifier, IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {MainProcessVSCodeAPIHelper} from './extHost.api.impl';
import {ExtHostCommands, MainThreadCommands} from './extHostCommands';
import {ExtHostConfiguration, MainThreadConfiguration} from './extHostConfiguration';
import {ExtHostDiagnostics, MainThreadDiagnostics} from './extHostDiagnostics';
import {ExtHostModelService, MainThreadDocuments} from './extHostDocuments';
import {ExtHostEditors, MainThreadEditors} from './extHostEditors';
// --- main thread addressable
import {MainThreadCommands} from './mainThreadCommands';
import {MainThreadConfiguration} from './mainThreadConfiguration';
import {MainThreadDiagnostics} from './mainThreadDiagnostics';
import {MainThreadDocuments} from './mainThreadDocuments';
import {MainThreadEditors} from './mainThreadEditors';
import {MainThreadErrors} from './mainThreadErrors';
import {MainThreadLanguageFeatures} from './mainThreadLanguageFeatures';
import {MainThreadLanguages} from './mainThreadLanguages';
import {MainThreadMessageService} from './mainThreadMessageService';
import {MainThreadOutputService} from './mainThreadOutputService';
import {MainThreadQuickOpen} from './mainThreadQuickOpen';
import {MainThreadStatusBar} from './mainThreadStatusBar';
import {MainThreadStorage} from './mainThreadStorage';
import {MainThreadTelemetry} from './mainThreadTelemetry';
import {MainThreadWorkspace} from './mainThreadWorkspace';
import {MainProcessExtensionService} from './mainThreadExtensionService';
// --- ext host addressable
import {ExtHostCommands} from './extHostCommands';
import {ExtHostConfiguration} from './extHostConfiguration';
import {ExtHostDiagnostics} from './extHostDiagnostics';
import {ExtHostDocuments} from './extHostDocuments';
import {ExtHostEditors} from './extHostEditors';
import {ExtHostFileSystemEventService} from './extHostFileSystemEventService';
import {ExtHostLanguageFeatures, MainThreadLanguageFeatures} from './extHostLanguageFeatures';
import {MainThreadLanguages} from './extHostLanguages';
import {MainThreadMessageService} from './extHostMessageService';
import {MainThreadOutputService} from './extHostOutputService';
import {ExtHostQuickOpen, MainThreadQuickOpen} from './extHostQuickOpen';
import {MainThreadStatusBar} from './extHostStatusBar';
import {MainThreadStorage} from './extHostStorage';
import {MainThreadTelemetry} from './extHostTelemetry';
import {MainThreadWorkspace} from './extHostWorkspace';
import {ExtHostExtensionService, MainProcessExtensionService} from './nativeExtensionService';
import {ExtHostLanguageFeatures} from './extHostLanguageFeatures';
import {ExtHostQuickOpen} from './extHostQuickOpen';
import {ExtHostExtensionService} from './extHostExtensionService';
let mainCounter = 0;
export const MainContext = {
MainProcessVSCodeAPIHelper: createMainId<MainProcessVSCodeAPIHelper>(++mainCounter),
MainThreadCommands: createMainId<MainThreadCommands>(++mainCounter),
MainThreadConfiguration: createMainId<MainThreadConfiguration>(++mainCounter),
MainThreadDiagnostics: createMainId<MainThreadDiagnostics>(++mainCounter),
MainThreadDocuments: createMainId<MainThreadDocuments>(++mainCounter),
MainThreadEditors: createMainId<MainThreadEditors>(++mainCounter),
MainThreadErrors: createMainId<MainThreadErrors>(++mainCounter),
MainThreadLanguageFeatures: createMainId<MainThreadLanguageFeatures>(++mainCounter),
MainThreadLanguages: createMainId<MainThreadLanguages>(++mainCounter),
MainThreadMessageService: createMainId<MainThreadMessageService>(++mainCounter),
......@@ -52,7 +63,7 @@ export const ExtHostContext = {
ExtHostCommands: createExtId<ExtHostCommands>(++extCounter),
ExtHostConfiguration: createExtId<ExtHostConfiguration>(++extCounter),
ExtHostDiagnostics: createExtId<ExtHostDiagnostics>(++extCounter),
ExtHostModelService: createExtId<ExtHostModelService>(++extCounter),
ExtHostDocuments: createExtId<ExtHostDocuments>(++extCounter),
ExtHostEditors: createExtId<ExtHostEditors>(++extCounter),
ExtHostFileSystemEventService: createExtId<ExtHostFileSystemEventService>(++extCounter),
ExtHostLanguageFeatures: createExtId<ExtHostLanguageFeatures>(++extCounter),
......
......@@ -6,9 +6,10 @@
import {TPromise} from 'vs/base/common/winjs.base';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {IQuickOpenService, IPickOpenEntry, IPickOptions, IInputOptions} from 'vs/workbench/services/quickopen/common/quickOpenService';
import {IPickOpenEntry} from 'vs/workbench/services/quickopen/common/quickOpenService';
import {QuickPickOptions, QuickPickItem, InputBoxOptions} from 'vscode';
import {MainContext, ExtHostContext} from './extHostProtocol';
import {MainContext} from './extHostProtocol';
import {MainThreadQuickOpen} from './mainThreadQuickOpen';
export interface MyQuickPickItems extends IPickOpenEntry {
handle: number;
......@@ -111,83 +112,3 @@ export class ExtHostQuickOpen {
}
}
}
export class MainThreadQuickOpen {
private _proxy: ExtHostQuickOpen;
private _quickOpenService: IQuickOpenService;
private _doSetItems: (items: MyQuickPickItems[]) => any;
private _doSetError: (error: Error) => any;
private _contents: TPromise<MyQuickPickItems[]>;
private _token: number = 0;
constructor( @IThreadService threadService: IThreadService, @IQuickOpenService quickOpenService: IQuickOpenService) {
this._proxy = threadService.get(ExtHostContext.ExtHostQuickOpen);
this._quickOpenService = quickOpenService;
}
$show(options: IPickOptions): Thenable<number> {
const myToken = ++this._token;
this._contents = new TPromise((c, e) => {
this._doSetItems = (items) => {
if (myToken === this._token) {
c(items);
}
};
this._doSetError = (error) => {
if (myToken === this._token) {
e(error);
}
};
});
return this._quickOpenService.pick(this._contents, options).then(item => {
if (item) {
return item.handle;
}
}, undefined, progress => {
if (progress) {
this._proxy.$onItemSelected((<MyQuickPickItems>progress).handle);
}
});
}
$setItems(items: MyQuickPickItems[]): Thenable<any> {
if (this._doSetItems) {
this._doSetItems(items);
return;
}
}
$setError(error: Error): Thenable<any> {
if (this._doSetError) {
this._doSetError(error);
return;
}
}
// ---- input
$input(options: InputBoxOptions, validateInput: boolean): Thenable<string> {
const inputOptions: IInputOptions = Object.create(null);
if (options) {
inputOptions.password = options.password;
inputOptions.placeHolder = options.placeHolder;
inputOptions.prompt = options.prompt;
inputOptions.value = options.value;
}
if (validateInput) {
inputOptions.validateInput = (value) => {
return this._proxy.$validateInput(value);
};
}
return this._quickOpenService.input(inputOptions);
}
}
......@@ -5,11 +5,11 @@
'use strict';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {IStatusbarService, StatusbarAlignment as MainThreadStatusBarAlignment} from 'vs/platform/statusbar/common/statusbar';
import {IDisposable} from 'vs/base/common/lifecycle';
import {StatusbarAlignment as MainThreadStatusBarAlignment} from 'vs/platform/statusbar/common/statusbar';
import {StatusBarAlignment as ExtHostStatusBarAlignment, Disposable} from './extHostTypes';
import {StatusBarItem, StatusBarAlignment} from 'vscode';
import {MainContext} from './extHostProtocol';
import {MainThreadStatusBar} from './mainThreadStatusBar';
export class ExtHostStatusBarEntry implements StatusBarItem {
private static ID_GEN = 0;
......@@ -188,32 +188,3 @@ export class ExtHostStatusBar {
});
}
}
export class MainThreadStatusBar {
private mapIdToDisposable: { [id: number]: IDisposable };
constructor(
@IStatusbarService private statusbarService: IStatusbarService
) {
this.mapIdToDisposable = Object.create(null);
}
setEntry(id: number, text: string, tooltip: string, command: string, color: string, alignment: MainThreadStatusBarAlignment, priority: number): void {
// Dispose any old
this.dispose(id);
// Add new
let disposeable = this.statusbarService.addEntry({ text, tooltip, command, color }, alignment, priority);
this.mapIdToDisposable[id] = disposeable;
}
dispose(id: number) {
let disposeable = this.mapIdToDisposable[id];
if (disposeable) {
disposeable.dispose();
}
delete this.mapIdToDisposable[id];
}
}
\ No newline at end of file
......@@ -6,41 +6,8 @@
import {TPromise} from 'vs/base/common/winjs.base';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage';
import {MainContext} from './extHostProtocol';
export class MainThreadStorage {
private _storageService: IStorageService;
constructor( @IStorageService storageService: IStorageService) {
this._storageService = storageService;
}
getValue<T>(shared: boolean, key: string): TPromise<T> {
let jsonValue = this._storageService.get(key, shared ? StorageScope.GLOBAL : StorageScope.WORKSPACE);
if (!jsonValue) {
return TPromise.as(undefined);
}
let value: T;
try {
value = JSON.parse(jsonValue);
return TPromise.as(value);
} catch (err) {
return TPromise.wrapError(err);
}
}
setValue(shared: boolean, key: string, value: any): TPromise<any> {
let jsonValue: any;
try {
jsonValue = JSON.stringify(value);
this._storageService.store(key, jsonValue, shared ? StorageScope.GLOBAL : StorageScope.WORKSPACE);
} catch (err) {
return TPromise.wrapError(err);
}
}
}
import {MainThreadStorage} from './mainThreadStorage';
export class ExtHostStorage {
......
......@@ -9,26 +9,7 @@ import {TPromise} from 'vs/base/common/winjs.base';
import {ITelemetryService, ITelemetryInfo} from 'vs/platform/telemetry/common/telemetry';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {MainContext} from './extHostProtocol';
/**
* Helper always instantiated in the main process to receive telemetry events from remote telemetry services
*/
export class MainThreadTelemetry {
private _telemetryService: ITelemetryService;
constructor( @ITelemetryService telemetryService: ITelemetryService) {
this._telemetryService = telemetryService;
}
public $publicLog(eventName: string, data?: any): void {
this._telemetryService.publicLog(eventName, data);
}
public $getTelemetryInfo(): TPromise<ITelemetryInfo> {
return this._telemetryService.getTelemetryInfo();
}
}
import {MainThreadTelemetry} from './mainThreadTelemetry';
export class RemoteTelemetryService implements ITelemetryService {
......
......@@ -764,3 +764,8 @@ export enum EndOfLine {
CRLF = 2
}
export enum TextEditorRevealType {
Default = 0,
InCenter = 1,
InCenterIfOutsideViewport = 2
}
......@@ -4,20 +4,14 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import {isPromiseCanceledError} from 'vs/base/common/errors';
import URI from 'vs/base/common/uri';
import {ISearchService, QueryType} from 'vs/platform/search/common/search';
import {IWorkspaceContextService, IWorkspace} from 'vs/platform/workspace/common/workspace';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {IEventService} from 'vs/platform/event/common/event';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {ITextFileService} from 'vs/workbench/parts/files/common/files';
import {ICommonCodeEditor} from 'vs/editor/common/editorCommon';
import {bulkEdit, IResourceEdit} from 'vs/editor/common/services/bulkEdit';
import {IResourceEdit} from 'vs/editor/common/services/bulkEdit';
import {TPromise} from 'vs/base/common/winjs.base';
import {fromRange} from 'vs/workbench/api/node/extHostTypeConverters';
import {Uri, CancellationToken} from 'vscode';
import {MainContext} from './extHostProtocol';
import {MainThreadWorkspace} from './mainThreadWorkspace';
export class ExtHostWorkspace {
......@@ -85,84 +79,3 @@ export class ExtHostWorkspace {
return this._proxy.$applyWorkspaceEdit(resourceEdits);
}
}
export class MainThreadWorkspace {
private _activeSearches: { [id: number]: TPromise<Uri[]> } = Object.create(null);
private _searchService: ISearchService;
private _workspace: IWorkspace;
private _textFileService: ITextFileService;
private _editorService:IWorkbenchEditorService;
private _eventService:IEventService;
constructor( @ISearchService searchService: ISearchService,
@IWorkspaceContextService contextService: IWorkspaceContextService,
@ITextFileService textFileService,
@IWorkbenchEditorService editorService,
@IEventService eventService) {
this._searchService = searchService;
this._workspace = contextService.getWorkspace();
this._textFileService = textFileService;
this._editorService = editorService;
this._eventService = eventService;
}
$startSearch(include: string, exclude: string, maxResults: number, requestId: number): Thenable<Uri[]> {
if (!this._workspace) {
return;
}
const search = this._searchService.search({
folderResources: [this._workspace.resource],
type: QueryType.File,
maxResults,
includePattern: { [include]: true },
excludePattern: { [exclude]: true },
}).then(result => {
return result.results.map(m => m.resource);
}, err => {
if (!isPromiseCanceledError(err)) {
return TPromise.wrapError(err);
}
});
this._activeSearches[requestId] = search;
const onDone = () => delete this._activeSearches[requestId];
search.done(onDone, onDone);
return search;
}
$cancelSearch(requestId: number): Thenable<boolean> {
const search = this._activeSearches[requestId];
if (search) {
delete this._activeSearches[requestId];
search.cancel();
return TPromise.as(true);
}
}
$saveAll(includeUntitled?: boolean): Thenable<boolean> {
return this._textFileService.saveAll(includeUntitled).then(result => {
return result.results.every(each => each.success === true);
});
}
$applyWorkspaceEdit(edits: IResourceEdit[]): TPromise<boolean> {
let codeEditor: ICommonCodeEditor;
let editor = this._editorService.getActiveEditor();
if (editor) {
let candidate = <ICommonCodeEditor> editor.getControl();
if (typeof candidate.getEditorType === 'function') {
// enough proof
codeEditor = candidate;
}
}
return bulkEdit(this._eventService, this._editorService, codeEditor, edits)
.then(() => true);
}
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* 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 {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry';
import {IKeybindingService, ICommandHandlerDescription} from 'vs/platform/keybinding/common/keybindingService';
import {TPromise} from 'vs/base/common/winjs.base';
import {ExtHostContext} from './extHostProtocol';
import {ExtHostCommands} from './extHostCommands';
export class MainThreadCommands {
private _threadService: IThreadService;
private _keybindingService: IKeybindingService;
private _proxy: ExtHostCommands;
constructor(
@IThreadService threadService: IThreadService,
@IKeybindingService keybindingService: IKeybindingService
) {
this._threadService = threadService;
this._keybindingService = keybindingService;
this._proxy = this._threadService.get(ExtHostContext.ExtHostCommands);
}
$registerCommand(id: string): TPromise<any> {
KeybindingsRegistry.registerCommandDesc({
id,
handler: (serviceAccessor, ...args: any[]) => {
return this._proxy.$executeContributedCommand(id, ...args);
},
weight: undefined,
when: undefined,
win: undefined,
mac: undefined,
linux: undefined,
primary: undefined,
secondary: undefined
});
return undefined;
}
$executeCommand<T>(id: string, args: any[]): Thenable<T> {
return this._keybindingService.executeCommand(id, ...args);
}
$getCommands(): Thenable<string[]> {
return TPromise.as(Object.keys(KeybindingsRegistry.getCommands()));
}
}
// --- command doc
KeybindingsRegistry.registerCommandDesc({
id: '_generateCommandsDocumentation',
handler: function(accessor) {
return accessor.get(IThreadService).get(ExtHostContext.ExtHostCommands).$getContributedCommandHandlerDescriptions().then(result => {
// add local commands
const commands = KeybindingsRegistry.getCommands();
for (let id in commands) {
let {description} = commands[id];
if (description) {
result[id] = description;
}
}
// print all as markdown
const all: string[] = [];
for (let id in result) {
all.push('`' + id + '` - ' + _generateMarkdown(result[id]));
}
console.log(all.join('\n'));
});
},
when: undefined,
weight: KeybindingsRegistry.WEIGHT.builtinExtension(0),
primary: undefined
});
function _generateMarkdown(description: string | ICommandHandlerDescription): string {
if (typeof description === 'string') {
return description;
} else {
let parts = [description.description];
parts.push('\n\n');
if (description.args) {
for (let arg of description.args) {
parts.push(`* _${arg.name}_ ${arg.description || ''}\n`);
}
}
if (description.returns) {
parts.push(`* _(returns)_ ${description.returns}`);
}
parts.push('\n\n');
return parts.join('');
}
}
/*---------------------------------------------------------------------------------------------
* 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 {IDisposable, dispose} from 'vs/base/common/lifecycle';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
import {ExtHostContext} from './extHostProtocol';
import {ExtHostConfiguration} from './extHostConfiguration';
export class MainThreadConfiguration {
private _configurationService: IConfigurationService;
private _toDispose: IDisposable;
private _proxy: ExtHostConfiguration;
constructor(@IConfigurationService configurationService: IConfigurationService,
@IThreadService threadService: IThreadService) {
this._configurationService = configurationService;
this._proxy = threadService.get(ExtHostContext.ExtHostConfiguration);
this._toDispose = this._configurationService.onDidUpdateConfiguration(event => this._proxy.$acceptConfigurationChanged(event.config));
this._proxy.$acceptConfigurationChanged(this._configurationService.getConfiguration());
}
public dispose(): void {
this._toDispose = dispose(this._toDispose);
}
}
/*---------------------------------------------------------------------------------------------
* 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 {IMarkerService, IMarkerData} from 'vs/platform/markers/common/markers';
import URI from 'vs/base/common/uri';
import {TPromise} from 'vs/base/common/winjs.base';
export class MainThreadDiagnostics {
private _markerService: IMarkerService;
constructor(@IMarkerService markerService: IMarkerService) {
this._markerService = markerService;
}
$changeMany(owner: string, entries: [URI, IMarkerData[]][]): TPromise<any> {
for (let entry of entries) {
let [uri, markers] = entry;
this._markerService.changeOne(owner, uri, markers);
}
return undefined;
}
$clear(owner: string): TPromise<any> {
this._markerService.changeAll(owner, undefined);
return undefined;
}
}
/*---------------------------------------------------------------------------------------------
* 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 {toErrorMessage, onUnexpectedError} from 'vs/base/common/errors';
import {EmitterEvent} from 'vs/base/common/eventEmitter';
import {IModelService} from 'vs/editor/common/services/modelService';
import * as editorCommon from 'vs/editor/common/editorCommon';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import URI from 'vs/base/common/uri';
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
import {IEventService} from 'vs/platform/event/common/event';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {EventType as FileEventType, TextFileChangeEvent, ITextFileService} from 'vs/workbench/parts/files/common/files';
import {TPromise} from 'vs/base/common/winjs.base';
import {IFileService} from 'vs/platform/files/common/files';
import {IModeService} from 'vs/editor/common/services/modeService';
import {IUntitledEditorService} from 'vs/workbench/services/untitled/common/untitledEditorService';
import {ResourceEditorInput} from 'vs/workbench/common/editor/resourceEditorInput';
import {ExtHostContext} from './extHostProtocol';
import {ExtHostDocuments} from './extHostDocuments';
export class MainThreadDocuments {
private _modelService: IModelService;
private _modeService: IModeService;
private _textFileService: ITextFileService;
private _editorService: IWorkbenchEditorService;
private _fileService: IFileService;
private _untitledEditorService: IUntitledEditorService;
private _toDispose: IDisposable[];
private _modelToDisposeMap: { [modelUrl: string]: IDisposable; };
private _proxy: ExtHostDocuments;
private _modelIsSynced: { [modelId: string]: boolean; };
private _resourceContentProvider: { [handle: number]: IDisposable };
private _virtualDocumentSet: { [resource: string]: boolean };
constructor(
@IThreadService threadService: IThreadService,
@IModelService modelService: IModelService,
@IModeService modeService: IModeService,
@IEventService eventService: IEventService,
@ITextFileService textFileService: ITextFileService,
@IWorkbenchEditorService editorService: IWorkbenchEditorService,
@IFileService fileService: IFileService,
@IUntitledEditorService untitledEditorService: IUntitledEditorService
) {
this._modelService = modelService;
this._modeService = modeService;
this._textFileService = textFileService;
this._editorService = editorService;
this._fileService = fileService;
this._untitledEditorService = untitledEditorService;
this._proxy = threadService.get(ExtHostContext.ExtHostDocuments);
this._modelIsSynced = {};
this._toDispose = [];
modelService.onModelAdded(this._onModelAdded, this, this._toDispose);
modelService.onModelRemoved(this._onModelRemoved, this, this._toDispose);
modelService.onModelModeChanged(this._onModelModeChanged, this, this._toDispose);
this._toDispose.push(eventService.addListener2(FileEventType.FILE_SAVED, (e: TextFileChangeEvent) => {
if (this._shouldHandleFileEvent(e)) {
this._proxy._acceptModelSaved(e.resource.toString());
}
}));
this._toDispose.push(eventService.addListener2(FileEventType.FILE_REVERTED, (e: TextFileChangeEvent) => {
if (this._shouldHandleFileEvent(e)) {
this._proxy._acceptModelReverted(e.resource.toString());
}
}));
this._toDispose.push(eventService.addListener2(FileEventType.FILE_DIRTY, (e: TextFileChangeEvent) => {
if (this._shouldHandleFileEvent(e)) {
this._proxy._acceptModelDirty(e.resource.toString());
}
}));
const handle = setInterval(() => this._runDocumentCleanup(), 1000 * 60 * 3);
this._toDispose.push({ dispose() { clearInterval(handle); } });
this._modelToDisposeMap = Object.create(null);
this._resourceContentProvider = Object.create(null);
this._virtualDocumentSet = Object.create(null);
}
public dispose(): void {
Object.keys(this._modelToDisposeMap).forEach((modelUrl) => {
this._modelToDisposeMap[modelUrl].dispose();
});
this._modelToDisposeMap = Object.create(null);
this._toDispose = dispose(this._toDispose);
}
private _shouldHandleFileEvent(e: TextFileChangeEvent): boolean {
const model = this._modelService.getModel(e.resource);
return model && !model.isTooLargeForHavingARichMode();
}
private _onModelAdded(model: editorCommon.IModel): void {
// Same filter as in mainThreadEditorsTracker
if (model.isTooLargeForHavingARichMode()) {
// don't synchronize too large models
return null;
}
let modelUrl = model.uri;
this._modelIsSynced[modelUrl.toString()] = true;
this._modelToDisposeMap[modelUrl.toString()] = model.addBulkListener((events) => this._onModelEvents(modelUrl, events));
this._proxy._acceptModelAdd({
url: model.uri,
versionId: model.getVersionId(),
value: model.toRawText(),
modeId: model.getMode().getId(),
isDirty: this._textFileService.isDirty(modelUrl)
});
}
private _onModelModeChanged(event: { model: editorCommon.IModel; oldModeId: string; }): void {
let {model, oldModeId} = event;
let modelUrl = model.uri;
if (!this._modelIsSynced[modelUrl.toString()]) {
return;
}
this._proxy._acceptModelModeChanged(model.uri.toString(), oldModeId, model.getMode().getId());
}
private _onModelRemoved(model: editorCommon.IModel): void {
let modelUrl = model.uri;
if (!this._modelIsSynced[modelUrl.toString()]) {
return;
}
delete this._modelIsSynced[modelUrl.toString()];
this._modelToDisposeMap[modelUrl.toString()].dispose();
delete this._modelToDisposeMap[modelUrl.toString()];
this._proxy._acceptModelRemoved(modelUrl.toString());
}
private _onModelEvents(modelUrl: URI, events: EmitterEvent[]): void {
let changedEvents: editorCommon.IModelContentChangedEvent2[] = [];
for (let i = 0, len = events.length; i < len; i++) {
let e = events[i];
switch (e.getType()) {
case editorCommon.EventType.ModelContentChanged2:
changedEvents.push(<editorCommon.IModelContentChangedEvent2>e.getData());
break;
}
}
if (changedEvents.length > 0) {
this._proxy._acceptModelChanged(modelUrl.toString(), changedEvents);
}
}
// --- from extension host process
_trySaveDocument(uri: URI): TPromise<boolean> {
return this._textFileService.save(uri);
}
_tryOpenDocument(uri: URI): TPromise<any> {
if (!uri.scheme || !(uri.fsPath || uri.authority)) {
return TPromise.wrapError(`Invalid uri. Scheme and authority or path must be set.`);
}
let promise: TPromise<boolean>;
switch (uri.scheme) {
case 'untitled':
promise = this._handleUnititledScheme(uri);
break;
case 'file':
default:
promise = this._handleAsResourceInput(uri);
break;
}
return promise.then(success => {
if (!success) {
return TPromise.wrapError('cannot open ' + uri.toString());
}
}, err => {
return TPromise.wrapError('cannot open ' + uri.toString() + '. Detail: ' + toErrorMessage(err));
});
}
private _handleAsResourceInput(uri: URI): TPromise<boolean> {
return this._editorService.resolveEditorModel({ resource: uri }).then(model => {
return !!model;
});
}
private _handleUnititledScheme(uri: URI): TPromise<boolean> {
let asFileUri = URI.file(uri.fsPath);
return this._fileService.resolveFile(asFileUri).then(stats => {
// don't create a new file ontop of an existing file
return TPromise.wrapError<boolean>('file already exists on disk');
}, err => {
let input = this._untitledEditorService.createOrGet(asFileUri); // using file-uri makes it show in 'Working Files' section
return input.resolve(true).then(model => {
if (input.getResource().toString() !== uri.toString()) {
throw new Error(`expected URI ${uri.toString() } BUT GOT ${input.getResource().toString() }`);
}
if (!this._modelIsSynced[uri.toString()]) {
throw new Error(`expected URI ${uri.toString()} to have come to LIFE`);
}
return this._proxy._acceptModelDirty(uri.toString()); // mark as dirty
}).then(() => {
return true;
});
});
}
// --- virtual document logic
$registerTextContentProvider(handle:number, scheme: string): void {
this._resourceContentProvider[handle] = ResourceEditorInput.registerResourceContentProvider(scheme, {
provideTextContent: (uri: URI): TPromise<editorCommon.IModel> => {
return this._proxy.$provideTextDocumentContent(handle, uri).then(value => {
if (typeof value === 'string') {
this._virtualDocumentSet[uri.toString()] = true;
const firstLineText = value.substr(0, 1 + value.search(/\r?\n/));
const mode = this._modeService.getOrCreateModeByFilenameOrFirstLine(uri.fsPath, firstLineText);
return this._modelService.createModel(value, mode, uri);
}
});
}
});
}
$unregisterTextContentProvider(handle: number): void {
const registration = this._resourceContentProvider[handle];
if (registration) {
registration.dispose();
delete this._resourceContentProvider[handle];
}
}
$onVirtualDocumentChange(uri: URI, value: string): void {
const model = this._modelService.getModel(uri);
if (model) {
model.setValue(value);
}
}
private _runDocumentCleanup(): void {
const toBeDisposed: URI[] = [];
TPromise.join(Object.keys(this._virtualDocumentSet).map(key => {
let resource = URI.parse(key);
return this._editorService.createInput({ resource }).then(input => {
if (!this._editorService.isVisible(input, true)) {
toBeDisposed.push(resource);
}
});
})).then(() => {
for (let resource of toBeDisposed) {
this._modelService.destroyModel(resource);
delete this._virtualDocumentSet[resource.toString()];
}
}, onUnexpectedError);
}
}
此差异已折叠。
/*---------------------------------------------------------------------------------------------
* 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 * as errors from 'vs/base/common/errors';
export class MainThreadErrors {
public onUnexpectedExtHostError(err: any): void {
errors.onUnexpectedError(err);
}
}
/*---------------------------------------------------------------------------------------------
* 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 Severity from 'vs/base/common/severity';
import {TPromise} from 'vs/base/common/winjs.base';
import {AbstractExtensionService, ActivatedExtension} from 'vs/platform/extensions/common/abstractExtensionService';
import {IMessage, IExtensionDescription, IExtensionsStatus} from 'vs/platform/extensions/common/extensions';
import {ExtensionsRegistry} from 'vs/platform/extensions/common/extensionsRegistry';
import {IMessageService} from 'vs/platform/message/common/message';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {ExtHostContext} from './extHostProtocol';
import {ExtHostExtensionService} from './extHostExtensionService';
/**
* Represents a failed extension in the ext host.
*/
class MainProcessFailedExtension extends ActivatedExtension {
constructor() {
super(true);
}
}
/**
* Represents an extension that was successfully loaded or an
* empty extension in the ext host.
*/
class MainProcessSuccessExtension extends ActivatedExtension {
constructor() {
super(false);
}
}
function messageWithSource(msg:IMessage): string {
return (msg.source ? '[' + msg.source + ']: ' : '') + msg.message;
}
export class MainProcessExtensionService extends AbstractExtensionService<ActivatedExtension> {
private _threadService: IThreadService;
private _messageService: IMessageService;
private _proxy: ExtHostExtensionService;
private _isDev: boolean;
private _extensionsStatus: { [id: string]: IExtensionsStatus };
/**
* This class is constructed manually because it is a service, so it doesn't use any ctor injection
*/
constructor(
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IThreadService threadService: IThreadService,
@IMessageService messageService: IMessageService
) {
super(false);
let config = contextService.getConfiguration();
this._isDev = !config.env.isBuilt || !!config.env.extensionDevelopmentPath;
this._messageService = messageService;
this._threadService = threadService;
this._proxy = this._threadService.get(ExtHostContext.ExtHostExtensionService);
this._extensionsStatus = {};
ExtensionsRegistry.handleExtensionPoints((msg) => this._handleMessage(msg));
}
private _handleMessage(msg: IMessage) {
this._showMessage(msg.type, messageWithSource(msg));
if (!this._extensionsStatus[msg.source]) {
this._extensionsStatus[msg.source] = { messages: [] };
}
this._extensionsStatus[msg.source].messages.push(msg);
}
public $localShowMessage(severity: Severity, msg: string): void {
let messageShown = false;
if (severity === Severity.Error || severity === Severity.Warning) {
if (this._isDev) {
// Only show nasty intrusive messages if doing extension development.
this._messageService.show(severity, msg);
messageShown = true;
}
}
if (!messageShown) {
switch (severity) {
case Severity.Error:
console.error(msg);
break;
case Severity.Warning:
console.warn(msg);
break;
default:
console.log(msg);
}
}
}
// -- overwriting AbstractExtensionService
public getExtensionsStatus(): { [id: string]: IExtensionsStatus } {
return this._extensionsStatus;
}
protected _showMessage(severity: Severity, msg: string): void {
this._proxy.$localShowMessage(severity, msg);
this.$localShowMessage(severity, msg);
}
protected _createFailedExtension(): ActivatedExtension {
return new MainProcessFailedExtension();
}
protected _actualActivateExtension(extensionDescription: IExtensionDescription): TPromise<ActivatedExtension> {
// redirect extension activation to the extension host
return this._proxy.$activateExtension(extensionDescription).then(_ => {
// the extension host calls $onExtensionActivated, where we write to `_activatedExtensions`
return this._activatedExtensions[extensionDescription.id];
});
}
// -- called by extension host
public $onExtensionHostReady(extensionDescriptions: IExtensionDescription[], messages: IMessage[]): TPromise<void> {
ExtensionsRegistry.registerExtensions(extensionDescriptions);
messages.forEach((entry) => this._handleMessage(entry));
this._triggerOnReady();
return;
}
public $onExtensionActivated(extensionId: string): void {
this._activatedExtensions[extensionId] = new MainProcessSuccessExtension();
}
public $onExtensionActivationFailed(extensionId: string): void {
this._activatedExtensions[extensionId] = new MainProcessFailedExtension();
}
}
/*---------------------------------------------------------------------------------------------
* 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 {FileChangesEvent, FileChangeType} from 'vs/platform/files/common/files';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {IEventService} from 'vs/platform/event/common/event';
import {RunOnceScheduler} from 'vs/base/common/async';
import {ExtHostContext} from './extHostProtocol';
import {FileSystemEvents} from './extHostFileSystemEventService';
export class MainThreadFileSystemEventService {
constructor( @IEventService eventService: IEventService, @IThreadService threadService: IThreadService) {
const proxy = threadService.get(ExtHostContext.ExtHostFileSystemEventService);
const events: FileSystemEvents = {
created: [],
changed: [],
deleted: []
};
const scheduler = new RunOnceScheduler(() => {
proxy._onFileEvent(events);
events.created.length = 0;
events.changed.length = 0;
events.deleted.length = 0;
}, 100);
eventService.addListener2('files:fileChanges', (event: FileChangesEvent) => {
for (let change of event.changes) {
switch (change.type) {
case FileChangeType.ADDED:
events.created.push(change.resource);
break;
case FileChangeType.UPDATED:
events.changed.push(change.resource);
break;
case FileChangeType.DELETED:
events.deleted.push(change.resource);
break;
}
}
scheduler.schedule();
});
}
}
/*---------------------------------------------------------------------------------------------
* 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 {TPromise} from 'vs/base/common/winjs.base';
import {IDisposable} from 'vs/base/common/lifecycle';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import * as vscode from 'vscode';
import {IReadOnlyModel, ISingleEditOperation} from 'vs/editor/common/editorCommon';
import * as modes from 'vs/editor/common/modes';
import {NavigateTypesSupportRegistry, INavigateTypesSupport, ITypeBearing} from 'vs/workbench/parts/search/common/search';
import {wireCancellationToken} from 'vs/base/common/async';
import {CancellationToken} from 'vs/base/common/cancellation';
import {Position as EditorPosition} from 'vs/editor/common/core/position';
import {Range as EditorRange} from 'vs/editor/common/core/range';
import {ExtHostContext} from './extHostProtocol';
import {ExtHostLanguageFeatures} from './extHostLanguageFeatures';
import {LanguageConfigurationRegistry} from 'vs/editor/common/modes/languageConfigurationRegistry';
export class MainThreadLanguageFeatures {
private _proxy: ExtHostLanguageFeatures;
private _registrations: { [handle: number]: IDisposable; } = Object.create(null);
constructor( @IThreadService threadService: IThreadService) {
this._proxy = threadService.get(ExtHostContext.ExtHostLanguageFeatures);
}
$unregister(handle: number): TPromise<any> {
let registration = this._registrations[handle];
if (registration) {
registration.dispose();
delete this._registrations[handle];
}
return undefined;
}
// --- outline
$registerOutlineSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.DocumentSymbolProviderRegistry.register(selector, <modes.DocumentSymbolProvider>{
provideDocumentSymbols: (model:IReadOnlyModel, token: CancellationToken): Thenable<modes.SymbolInformation[]> => {
return wireCancellationToken(token, this._proxy.$provideDocumentSymbols(handle, model.uri));
}
});
return undefined;
}
// --- code lens
$registerCodeLensSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.CodeLensProviderRegistry.register(selector, <modes.CodeLensProvider>{
provideCodeLenses: (model:IReadOnlyModel, token: CancellationToken): modes.ICodeLensSymbol[] | Thenable<modes.ICodeLensSymbol[]> => {
return wireCancellationToken(token, this._proxy.$provideCodeLenses(handle, model.uri));
},
resolveCodeLens: (model:IReadOnlyModel, codeLens: modes.ICodeLensSymbol, token: CancellationToken): modes.ICodeLensSymbol | Thenable<modes.ICodeLensSymbol> => {
return wireCancellationToken(token, this._proxy.$resolveCodeLens(handle, model.uri, codeLens));
}
});
return undefined;
}
// --- declaration
$registerDeclaractionSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.DefinitionProviderRegistry.register(selector, <modes.DefinitionProvider>{
provideDefinition: (model, position, token): Thenable<modes.Definition> => {
return wireCancellationToken(token, this._proxy.$provideDefinition(handle, model.uri, position));
}
});
return undefined;
}
// --- extra info
$registerHoverProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.HoverProviderRegistry.register(selector, <modes.HoverProvider>{
provideHover: (model:IReadOnlyModel, position:EditorPosition, token:CancellationToken): Thenable<modes.Hover> => {
return wireCancellationToken(token, this._proxy.$provideHover(handle, model.uri, position));
}
});
return undefined;
}
// --- occurrences
$registerDocumentHighlightProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.DocumentHighlightProviderRegistry.register(selector, <modes.DocumentHighlightProvider>{
provideDocumentHighlights: (model: IReadOnlyModel, position: EditorPosition, token: CancellationToken): Thenable<modes.DocumentHighlight[]> => {
return wireCancellationToken(token, this._proxy.$provideDocumentHighlights(handle, model.uri, position));
}
});
return undefined;
}
// --- references
$registerReferenceSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.ReferenceProviderRegistry.register(selector, <modes.ReferenceProvider>{
provideReferences: (model:IReadOnlyModel, position:EditorPosition, context: modes.ReferenceContext, token: CancellationToken): Thenable<modes.Location[]> => {
return wireCancellationToken(token, this._proxy.$provideReferences(handle, model.uri, position, context));
}
});
return undefined;
}
// --- quick fix
$registerQuickFixSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.CodeActionProviderRegistry.register(selector, <modes.CodeActionProvider>{
provideCodeActions: (model:IReadOnlyModel, range:EditorRange, token: CancellationToken): Thenable<modes.CodeAction[]> => {
return wireCancellationToken(token, this._proxy.$provideCodeActions(handle, model.uri, range));
}
});
return undefined;
}
// --- formatting
$registerDocumentFormattingSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.DocumentFormattingEditProviderRegistry.register(selector, <modes.DocumentFormattingEditProvider>{
provideDocumentFormattingEdits: (model: IReadOnlyModel, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> => {
return wireCancellationToken(token, this._proxy.$provideDocumentFormattingEdits(handle, model.uri, options));
}
});
return undefined;
}
$registerRangeFormattingSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.DocumentRangeFormattingEditProviderRegistry.register(selector, <modes.DocumentRangeFormattingEditProvider>{
provideDocumentRangeFormattingEdits: (model: IReadOnlyModel, range: EditorRange, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> => {
return wireCancellationToken(token, this._proxy.$provideDocumentRangeFormattingEdits(handle, model.uri, range, options));
}
});
return undefined;
}
$registerOnTypeFormattingSupport(handle: number, selector: vscode.DocumentSelector, autoFormatTriggerCharacters: string[]): TPromise<any> {
this._registrations[handle] = modes.OnTypeFormattingEditProviderRegistry.register(selector, <modes.OnTypeFormattingEditProvider>{
autoFormatTriggerCharacters,
provideOnTypeFormattingEdits: (model: IReadOnlyModel, position: EditorPosition, ch: string, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> => {
return wireCancellationToken(token, this._proxy.$provideOnTypeFormattingEdits(handle, model.uri, position, ch, options));
}
});
return undefined;
}
// --- navigate type
$registerNavigateTypeSupport(handle: number): TPromise<any> {
this._registrations[handle] = NavigateTypesSupportRegistry.register(<INavigateTypesSupport>{
getNavigateToItems: (search: string): TPromise<ITypeBearing[]> => {
return this._proxy.$getNavigateToItems(handle, search);
}
});
return undefined;
}
// --- rename
$registerRenameSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.RenameProviderRegistry.register(selector, <modes.RenameProvider>{
provideRenameEdits: (model:IReadOnlyModel, position:EditorPosition, newName: string, token: CancellationToken): Thenable<modes.WorkspaceEdit> => {
return wireCancellationToken(token, this._proxy.$provideRenameEdits(handle, model.uri, position, newName));
}
});
return undefined;
}
// --- suggest
$registerSuggestSupport(handle: number, selector: vscode.DocumentSelector, triggerCharacters: string[]): TPromise<any> {
this._registrations[handle] = modes.SuggestRegistry.register(selector, <modes.ISuggestSupport>{
triggerCharacters: triggerCharacters,
shouldAutotriggerSuggest: true,
provideCompletionItems: (model:IReadOnlyModel, position:EditorPosition, token:CancellationToken): Thenable<modes.ISuggestResult[]> => {
return wireCancellationToken(token, this._proxy.$provideCompletionItems(handle, model.uri, position));
},
resolveCompletionItem: (model:IReadOnlyModel, position:EditorPosition, suggestion: modes.ISuggestion, token: CancellationToken): Thenable<modes.ISuggestion> => {
return wireCancellationToken(token, this._proxy.$resolveCompletionItem(handle, model.uri, position, suggestion));
}
});
return undefined;
}
// --- parameter hints
$registerSignatureHelpProvider(handle: number, selector: vscode.DocumentSelector, triggerCharacter: string[]): TPromise<any> {
this._registrations[handle] = modes.SignatureHelpProviderRegistry.register(selector, <modes.SignatureHelpProvider>{
signatureHelpTriggerCharacters: triggerCharacter,
provideSignatureHelp: (model:IReadOnlyModel, position:EditorPosition, token:CancellationToken): Thenable<modes.SignatureHelp> => {
return wireCancellationToken(token, this._proxy.$provideSignatureHelp(handle, model.uri, position));
}
});
return undefined;
}
// --- configuration
$setLanguageConfiguration(handle: number, languageId:string, configuration: vscode.LanguageConfiguration): TPromise<any> {
this._registrations[handle] = LanguageConfigurationRegistry.register(languageId, configuration);
return undefined;
}
}
/*---------------------------------------------------------------------------------------------
* 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 {TPromise} from 'vs/base/common/winjs.base';
import {IModeService} from 'vs/editor/common/services/modeService';
export class MainThreadLanguages {
private _modeService: IModeService;
constructor(
@IModeService modeService: IModeService
) {
this._modeService = modeService;
}
_getLanguages(): TPromise<string[]> {
return TPromise.as(this._modeService.getRegisteredModes());
}
}
/*---------------------------------------------------------------------------------------------
* 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 nls = require('vs/nls');
import {IMessageService} from 'vs/platform/message/common/message';
import Severity from 'vs/base/common/severity';
import {Action} from 'vs/base/common/actions';
import {TPromise as Promise} from 'vs/base/common/winjs.base';
export class MainThreadMessageService {
private _messageService: IMessageService;
constructor(@IMessageService messageService:IMessageService) {
this._messageService = messageService;
}
$showMessage(severity: Severity, message: string, commands: { title: string; isCloseAffordance: boolean; handle: number; }[]): Thenable<number> {
return new Promise<number>(resolve => {
let messageHide: Function;
let actions: MessageItemAction[] = [];
let hasCloseAffordance = false;
class MessageItemAction extends Action {
constructor(id: string, label: string, handle: number) {
super(id, label, undefined, true, () => {
resolve(handle);
messageHide(); // triggers dispose! make sure promise is already resolved
return undefined;
});
}
dispose(): void {
resolve(undefined);
}
}
commands.forEach(command => {
if (command.isCloseAffordance === true) {
hasCloseAffordance = true;
}
actions.push(new MessageItemAction('_extension_message_handle_' + command.handle, command.title, command.handle));
});
if (!hasCloseAffordance) {
actions.unshift(new MessageItemAction('__close', nls.localize('close', "Close"), undefined));
}
messageHide = this._messageService.show(severity, {
message,
actions
});
});
}
}
/*---------------------------------------------------------------------------------------------
* 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 {TPromise} from 'vs/base/common/winjs.base';
import {Registry} from 'vs/platform/platform';
import {IOutputService, IOutputChannel, OUTPUT_PANEL_ID, Extensions, IOutputChannelRegistry} from 'vs/workbench/parts/output/common/output';
import {IPartService} from 'vs/workbench/services/part/common/partService';
import {IPanelService} from 'vs/workbench/services/panel/common/panelService';
export class MainThreadOutputService {
private _outputService: IOutputService;
private _partService: IPartService;
private _panelService: IPanelService;
constructor(@IOutputService outputService: IOutputService,
@IPartService partService: IPartService,
@IPanelService panelService: IPanelService
) {
this._outputService = outputService;
this._partService = partService;
this._panelService = panelService;
}
public append(channelId: string, label: string, value: string): TPromise<void> {
this._getChannel(channelId, label).append(value);
return undefined;
}
public clear(channelId: string, label: string): TPromise<void> {
this._getChannel(channelId, label).clear();
return undefined;
}
public reveal(channelId: string, label: string, preserveFocus: boolean): TPromise<void> {
this._getChannel(channelId, label).show(preserveFocus);
return undefined;
}
private _getChannel(channelId: string, label: string): IOutputChannel {
if (Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).getChannels().every(channel => channel.id !== channelId)) {
Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).registerChannel(channelId, label);
}
return this._outputService.getChannel(channelId);
}
public close(channelId: string): TPromise<void> {
const panel = this._panelService.getActivePanel();
if (panel && panel.getId() === OUTPUT_PANEL_ID && channelId === this._outputService.getActiveChannel().id ) {
this._partService.setPanelHidden(true);
}
return undefined;
}
}
/*---------------------------------------------------------------------------------------------
* 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 {TPromise} from 'vs/base/common/winjs.base';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {IQuickOpenService, IPickOptions, IInputOptions} from 'vs/workbench/services/quickopen/common/quickOpenService';
import {InputBoxOptions} from 'vscode';
import {ExtHostContext} from './extHostProtocol';
import {ExtHostQuickOpen, MyQuickPickItems} from './extHostQuickOpen';
export class MainThreadQuickOpen {
private _proxy: ExtHostQuickOpen;
private _quickOpenService: IQuickOpenService;
private _doSetItems: (items: MyQuickPickItems[]) => any;
private _doSetError: (error: Error) => any;
private _contents: TPromise<MyQuickPickItems[]>;
private _token: number = 0;
constructor( @IThreadService threadService: IThreadService, @IQuickOpenService quickOpenService: IQuickOpenService) {
this._proxy = threadService.get(ExtHostContext.ExtHostQuickOpen);
this._quickOpenService = quickOpenService;
}
$show(options: IPickOptions): Thenable<number> {
const myToken = ++this._token;
this._contents = new TPromise((c, e) => {
this._doSetItems = (items) => {
if (myToken === this._token) {
c(items);
}
};
this._doSetError = (error) => {
if (myToken === this._token) {
e(error);
}
};
});
return this._quickOpenService.pick(this._contents, options).then(item => {
if (item) {
return item.handle;
}
}, undefined, progress => {
if (progress) {
this._proxy.$onItemSelected((<MyQuickPickItems>progress).handle);
}
});
}
$setItems(items: MyQuickPickItems[]): Thenable<any> {
if (this._doSetItems) {
this._doSetItems(items);
return;
}
}
$setError(error: Error): Thenable<any> {
if (this._doSetError) {
this._doSetError(error);
return;
}
}
// ---- input
$input(options: InputBoxOptions, validateInput: boolean): Thenable<string> {
const inputOptions: IInputOptions = Object.create(null);
if (options) {
inputOptions.password = options.password;
inputOptions.placeHolder = options.placeHolder;
inputOptions.prompt = options.prompt;
inputOptions.value = options.value;
}
if (validateInput) {
inputOptions.validateInput = (value) => {
return this._proxy.$validateInput(value);
};
}
return this._quickOpenService.input(inputOptions);
}
}
/*---------------------------------------------------------------------------------------------
* 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 {IStatusbarService, StatusbarAlignment as MainThreadStatusBarAlignment} from 'vs/platform/statusbar/common/statusbar';
import {IDisposable} from 'vs/base/common/lifecycle';
export class MainThreadStatusBar {
private mapIdToDisposable: { [id: number]: IDisposable };
constructor(
@IStatusbarService private statusbarService: IStatusbarService
) {
this.mapIdToDisposable = Object.create(null);
}
setEntry(id: number, text: string, tooltip: string, command: string, color: string, alignment: MainThreadStatusBarAlignment, priority: number): void {
// Dispose any old
this.dispose(id);
// Add new
let disposeable = this.statusbarService.addEntry({ text, tooltip, command, color }, alignment, priority);
this.mapIdToDisposable[id] = disposeable;
}
dispose(id: number) {
let disposeable = this.mapIdToDisposable[id];
if (disposeable) {
disposeable.dispose();
}
delete this.mapIdToDisposable[id];
}
}
/*---------------------------------------------------------------------------------------------
* 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 {TPromise} from 'vs/base/common/winjs.base';
import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage';
export class MainThreadStorage {
private _storageService: IStorageService;
constructor( @IStorageService storageService: IStorageService) {
this._storageService = storageService;
}
getValue<T>(shared: boolean, key: string): TPromise<T> {
let jsonValue = this._storageService.get(key, shared ? StorageScope.GLOBAL : StorageScope.WORKSPACE);
if (!jsonValue) {
return TPromise.as(undefined);
}
let value: T;
try {
value = JSON.parse(jsonValue);
return TPromise.as(value);
} catch (err) {
return TPromise.wrapError(err);
}
}
setValue(shared: boolean, key: string, value: any): TPromise<any> {
let jsonValue: any;
try {
jsonValue = JSON.stringify(value);
this._storageService.store(key, jsonValue, shared ? StorageScope.GLOBAL : StorageScope.WORKSPACE);
} catch (err) {
return TPromise.wrapError(err);
}
}
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* 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 {TPromise} from 'vs/base/common/winjs.base';
import {ITelemetryService, ITelemetryInfo} from 'vs/platform/telemetry/common/telemetry';
/**
* Helper always instantiated in the main process to receive telemetry events from remote telemetry services
*/
export class MainThreadTelemetry {
private _telemetryService: ITelemetryService;
constructor( @ITelemetryService telemetryService: ITelemetryService) {
this._telemetryService = telemetryService;
}
public $publicLog(eventName: string, data?: any): void {
this._telemetryService.publicLog(eventName, data);
}
public $getTelemetryInfo(): TPromise<ITelemetryInfo> {
return this._telemetryService.getTelemetryInfo();
}
}
此差异已折叠。
......@@ -45,7 +45,7 @@ import {CodeEditorServiceImpl} from 'vs/editor/browser/services/codeEditorServic
import {ICodeEditorService} from 'vs/editor/common/services/codeEditorService';
import {EditorWorkerServiceImpl} from 'vs/editor/common/services/editorWorkerServiceImpl';
import {IEditorWorkerService} from 'vs/editor/common/services/editorWorkerService';
import {MainProcessExtensionService} from 'vs/workbench/api/node/nativeExtensionService';
import {MainProcessExtensionService} from 'vs/workbench/api/node/mainThreadExtensionService';
import {IOptions} from 'vs/workbench/common/options';
import {IStorageService} from 'vs/platform/storage/common/storage';
import {ServiceCollection} from 'vs/platform/instantiation/common/serviceCollection';
......
......@@ -17,7 +17,7 @@ import {IExtensionDescription} from 'vs/platform/extensions/common/extensions';
import {ExtensionsRegistry} from 'vs/platform/extensions/common/extensionsRegistry';
import {ExtHostAPIImplementation, defineAPI} from 'vs/workbench/api/node/extHost.api.impl';
import {IMainProcessExtHostIPC} from 'vs/platform/extensions/common/ipcRemoteCom';
import {ExtHostExtensionService} from 'vs/workbench/api/node/nativeExtensionService';
import {ExtHostExtensionService} from 'vs/workbench/api/node/extHostExtensionService';
import {ExtHostThreadService} from 'vs/workbench/services/thread/common/extHostThreadService';
import {RemoteTelemetryService} from 'vs/workbench/api/node/extHostTelemetry';
import {BaseWorkspaceContextService} from 'vs/platform/workspace/common/baseWorkspaceContextService';
......
......@@ -7,7 +7,7 @@
import * as assert from 'assert';
import {Action} from 'vs/base/common/actions';
import {MainThreadMessageService} from 'vs/workbench/api/node/extHostMessageService';
import {MainThreadMessageService} from 'vs/workbench/api/node/mainThreadMessageService';
suite('ExtHostMessageService', function () {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册