mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-25 19:18:59 +01:00
Merge branch 'master' into ben/workspace-api
This commit is contained in:
@@ -55,8 +55,8 @@ import { ExtHostDecorations } from 'vs/workbench/api/node/extHostDecorations';
|
||||
import { toGlobPattern, toLanguageSelector } from 'vs/workbench/api/node/extHostTypeConverters';
|
||||
import { ExtensionActivatedByAPI } from 'vs/workbench/api/node/extHostExtensionActivator';
|
||||
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { OverviewRulerLane } from 'vs/editor/common/model';
|
||||
import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService';
|
||||
|
||||
export interface IExtensionApiFactory {
|
||||
(extension: IExtensionDescription): typeof vscode;
|
||||
@@ -89,18 +89,19 @@ export function createApiFactory(
|
||||
extHostWorkspace: ExtHostWorkspace,
|
||||
extHostConfiguration: ExtHostConfiguration,
|
||||
extensionService: ExtHostExtensionService,
|
||||
logService: ILogService
|
||||
extHostLogService: ExtHostLogService
|
||||
): IExtensionApiFactory {
|
||||
|
||||
// Addressable instances
|
||||
rpcProtocol.set(ExtHostContext.ExtHostLogService, extHostLogService);
|
||||
const extHostHeapService = rpcProtocol.set(ExtHostContext.ExtHostHeapService, new ExtHostHeapService());
|
||||
const extHostDecorations = rpcProtocol.set(ExtHostContext.ExtHostDecorations, new ExtHostDecorations(rpcProtocol));
|
||||
const extHostDocumentsAndEditors = rpcProtocol.set(ExtHostContext.ExtHostDocumentsAndEditors, new ExtHostDocumentsAndEditors(rpcProtocol));
|
||||
const extHostDocuments = rpcProtocol.set(ExtHostContext.ExtHostDocuments, new ExtHostDocuments(rpcProtocol, extHostDocumentsAndEditors));
|
||||
const extHostDocumentContentProviders = rpcProtocol.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(rpcProtocol, extHostDocumentsAndEditors));
|
||||
const extHostDocumentSaveParticipant = rpcProtocol.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(logService, extHostDocuments, rpcProtocol.getProxy(MainContext.MainThreadEditors)));
|
||||
const extHostDocumentSaveParticipant = rpcProtocol.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(extHostLogService, extHostDocuments, rpcProtocol.getProxy(MainContext.MainThreadEditors)));
|
||||
const extHostEditors = rpcProtocol.set(ExtHostContext.ExtHostEditors, new ExtHostEditors(rpcProtocol, extHostDocumentsAndEditors));
|
||||
const extHostCommands = rpcProtocol.set(ExtHostContext.ExtHostCommands, new ExtHostCommands(rpcProtocol, extHostHeapService, logService));
|
||||
const extHostCommands = rpcProtocol.set(ExtHostContext.ExtHostCommands, new ExtHostCommands(rpcProtocol, extHostHeapService, extHostLogService));
|
||||
const extHostTreeViews = rpcProtocol.set(ExtHostContext.ExtHostTreeViews, new ExtHostTreeViews(rpcProtocol.getProxy(MainContext.MainThreadTreeViews), extHostCommands));
|
||||
rpcProtocol.set(ExtHostContext.ExtHostWorkspace, extHostWorkspace);
|
||||
const extHostDebugService = rpcProtocol.set(ExtHostContext.ExtHostDebugService, new ExtHostDebugService(rpcProtocol, extHostWorkspace));
|
||||
@@ -111,7 +112,7 @@ export function createApiFactory(
|
||||
const extHostFileSystemEvent = rpcProtocol.set(ExtHostContext.ExtHostFileSystemEventService, new ExtHostFileSystemEventService());
|
||||
const extHostQuickOpen = rpcProtocol.set(ExtHostContext.ExtHostQuickOpen, new ExtHostQuickOpen(rpcProtocol, extHostWorkspace, extHostCommands));
|
||||
const extHostTerminalService = rpcProtocol.set(ExtHostContext.ExtHostTerminalService, new ExtHostTerminalService(rpcProtocol));
|
||||
const extHostSCM = rpcProtocol.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(rpcProtocol, extHostCommands, logService));
|
||||
const extHostSCM = rpcProtocol.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(rpcProtocol, extHostCommands, extHostLogService));
|
||||
const extHostTask = rpcProtocol.set(ExtHostContext.ExtHostTask, new ExtHostTask(rpcProtocol, extHostWorkspace));
|
||||
const extHostWindow = rpcProtocol.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(rpcProtocol));
|
||||
rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService);
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import { UriComponents } from 'vs/base/common/uri';
|
||||
import URI, { UriComponents } from 'vs/base/common/uri';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
|
||||
@@ -52,8 +52,9 @@ import { IStat, FileChangeType } from 'vs/platform/files/common/files';
|
||||
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { ParsedArgs } from 'vs/platform/environment/common/environment';
|
||||
import { CommentRule, CharacterPair, EnterAction } from 'vs/editor/common/modes/languageConfiguration';
|
||||
import { EndOfLineSequence, ISingleEditOperation } from 'vs/editor/common/model';
|
||||
import { ISingleEditOperation } from 'vs/editor/common/model';
|
||||
import { ILineMatch, IPatternInfo } from 'vs/platform/search/common/search';
|
||||
import { LogLevel } from 'vs/platform/log/common/log';
|
||||
|
||||
export interface IEnvironment {
|
||||
isExtensionDevelopmentDebug: boolean;
|
||||
@@ -71,6 +72,7 @@ export interface IWorkspaceData {
|
||||
id: string;
|
||||
name: string;
|
||||
folders: { uri: UriComponents, name: string, index: number }[];
|
||||
configuration?: UriComponents;
|
||||
}
|
||||
|
||||
export interface IInitData {
|
||||
@@ -83,6 +85,7 @@ export interface IInitData {
|
||||
windowId: number;
|
||||
args: ParsedArgs;
|
||||
execPath: string;
|
||||
logLevel: LogLevel;
|
||||
}
|
||||
|
||||
export interface IConfigurationInitData extends IConfigurationData {
|
||||
@@ -192,8 +195,6 @@ export interface IApplyEditsOptions extends IUndoStopOptions {
|
||||
setEndOfLine: EndOfLine;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export interface ITextDocumentShowOptions {
|
||||
position?: EditorPosition;
|
||||
preserveFocus?: boolean;
|
||||
@@ -201,16 +202,6 @@ export interface ITextDocumentShowOptions {
|
||||
selection?: IRange;
|
||||
}
|
||||
|
||||
export interface IWorkspaceResourceEdit {
|
||||
resource: UriComponents;
|
||||
modelVersionId?: number;
|
||||
edits: {
|
||||
range?: IRange;
|
||||
newText: string;
|
||||
newEol?: EndOfLineSequence;
|
||||
}[];
|
||||
}
|
||||
|
||||
export interface MainThreadEditorsShape extends IDisposable {
|
||||
$tryShowTextDocument(resource: UriComponents, options: ITextDocumentShowOptions): TPromise<string>;
|
||||
$registerTextEditorDecorationType(key: string, options: editorCommon.IDecorationRenderOptions): void;
|
||||
@@ -223,7 +214,7 @@ export interface MainThreadEditorsShape extends IDisposable {
|
||||
$tryRevealRange(id: string, range: IRange, revealType: TextEditorRevealType): TPromise<void>;
|
||||
$trySetSelections(id: string, selections: ISelection[]): TPromise<void>;
|
||||
$tryApplyEdits(id: string, modelVersionId: number, edits: ISingleEditOperation[], opts: IApplyEditsOptions): TPromise<boolean>;
|
||||
$tryApplyWorkspaceEdit(workspaceResourceEdits: IWorkspaceResourceEdit[]): TPromise<boolean>;
|
||||
$tryApplyWorkspaceEdit(workspaceEditDto: WorkspaceEditDto): TPromise<boolean>;
|
||||
$tryInsertSnippet(id: string, template: string, selections: IRange[], opts: IUndoStopOptions): TPromise<boolean>;
|
||||
$getDiffInformation(id: string): TPromise<editorCommon.ILineChange[]>;
|
||||
}
|
||||
@@ -624,23 +615,44 @@ export interface WorkspaceSymbolsDto extends IdObject {
|
||||
symbols: SymbolInformationDto[];
|
||||
}
|
||||
|
||||
export interface ResourceEditDto {
|
||||
export interface ResourceFileEditDto {
|
||||
oldUri: UriComponents;
|
||||
newUri: UriComponents;
|
||||
}
|
||||
|
||||
export interface ResourceTextEditDto {
|
||||
resource: UriComponents;
|
||||
range: IRange;
|
||||
newText: string;
|
||||
modelVersionId?: number;
|
||||
edits: modes.TextEdit[];
|
||||
}
|
||||
|
||||
export interface WorkspaceEditDto {
|
||||
edits: ResourceEditDto[];
|
||||
edits: (ResourceFileEditDto | ResourceTextEditDto)[];
|
||||
|
||||
// todo@joh reject should go into rename
|
||||
rejectReason?: string;
|
||||
}
|
||||
|
||||
export function reviveWorkspaceEditDto(data: WorkspaceEditDto): modes.WorkspaceEdit {
|
||||
if (data && data.edits) {
|
||||
for (const edit of data.edits) {
|
||||
if (typeof (<ResourceTextEditDto>edit).resource === 'object') {
|
||||
(<ResourceTextEditDto>edit).resource = URI.revive((<ResourceTextEditDto>edit).resource);
|
||||
} else {
|
||||
(<ResourceFileEditDto>edit).newUri = URI.revive((<ResourceFileEditDto>edit).newUri);
|
||||
(<ResourceFileEditDto>edit).oldUri = URI.revive((<ResourceFileEditDto>edit).oldUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
return <modes.WorkspaceEdit>data;
|
||||
}
|
||||
|
||||
export interface CodeActionDto {
|
||||
title: string;
|
||||
edit?: WorkspaceEditDto;
|
||||
diagnostics?: IMarkerData[];
|
||||
command?: modes.Command;
|
||||
scope?: string;
|
||||
kind?: string;
|
||||
}
|
||||
|
||||
export interface ExtHostLanguageFeaturesShape {
|
||||
@@ -745,6 +757,10 @@ export interface ExtHostWindowShape {
|
||||
$onDidChangeWindowFocus(value: boolean): void;
|
||||
}
|
||||
|
||||
export interface ExtHostLogServiceShape {
|
||||
$setLevel(level: LogLevel);
|
||||
}
|
||||
|
||||
// --- proxy identifiers
|
||||
|
||||
export const MainContext = {
|
||||
@@ -795,7 +811,7 @@ export const ExtHostContext = {
|
||||
ExtHostLanguageFeatures: createExtId<ExtHostLanguageFeaturesShape>('ExtHostLanguageFeatures'),
|
||||
ExtHostQuickOpen: createExtId<ExtHostQuickOpenShape>('ExtHostQuickOpen'),
|
||||
ExtHostExtensionService: createExtId<ExtHostExtensionServiceShape>('ExtHostExtensionService'),
|
||||
// ExtHostLogService: createExtId<ExtHostLogServiceShape>('ExtHostLogService'),
|
||||
ExtHostLogService: createExtId<ExtHostLogServiceShape>('ExtHostLogService'),
|
||||
ExtHostTerminalService: createExtId<ExtHostTerminalServiceShape>('ExtHostTerminalService'),
|
||||
ExtHostSCM: createExtId<ExtHostSCMShape>('ExtHostSCM'),
|
||||
ExtHostTask: createExtId<ExtHostTaskShape>('ExtHostTask', ProxyType.CustomMarshaller),
|
||||
|
||||
@@ -353,11 +353,7 @@ export class ExtHostApiCommands {
|
||||
if (value.rejectReason) {
|
||||
return TPromise.wrapError<types.WorkspaceEdit>(new Error(value.rejectReason));
|
||||
}
|
||||
let workspaceEdit = new types.WorkspaceEdit();
|
||||
for (let edit of value.edits) {
|
||||
workspaceEdit.replace(edit.resource, typeConverters.toRange(edit.range), edit.newText);
|
||||
}
|
||||
return workspaceEdit;
|
||||
return typeConverters.WorkspaceEdit.to(value);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import Event from 'vs/base/common/event';
|
||||
import URI, { UriComponents } from 'vs/base/common/uri';
|
||||
import { sequence, always } from 'vs/base/common/async';
|
||||
import { illegalState } from 'vs/base/common/errors';
|
||||
import { ExtHostDocumentSaveParticipantShape, MainThreadEditorsShape, IWorkspaceResourceEdit } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import { ExtHostDocumentSaveParticipantShape, MainThreadEditorsShape, ResourceTextEditDto } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import { TextEdit } from 'vs/workbench/api/node/extHostTypes';
|
||||
import { fromRange, TextDocumentSaveReason, EndOfLine } from 'vs/workbench/api/node/extHostTypeConverters';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
|
||||
@@ -142,7 +142,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
|
||||
|
||||
}).then(values => {
|
||||
|
||||
let workspaceResourceEdit: IWorkspaceResourceEdit = {
|
||||
const resourceEdit: ResourceTextEditDto = {
|
||||
resource: document.uri,
|
||||
edits: []
|
||||
};
|
||||
@@ -150,10 +150,10 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
|
||||
for (const value of values) {
|
||||
if (Array.isArray(value) && (<vscode.TextEdit[]>value).every(e => e instanceof TextEdit)) {
|
||||
for (const { newText, newEol, range } of value) {
|
||||
workspaceResourceEdit.edits.push({
|
||||
resourceEdit.edits.push({
|
||||
range: range && fromRange(range),
|
||||
newText,
|
||||
newEol: EndOfLine.from(newEol)
|
||||
text: newText,
|
||||
eol: EndOfLine.from(newEol)
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -161,12 +161,12 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
|
||||
|
||||
// apply edits if any and if document
|
||||
// didn't change somehow in the meantime
|
||||
if (workspaceResourceEdit.edits.length === 0) {
|
||||
if (resourceEdit.edits.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (version === document.version) {
|
||||
return this._mainThreadEditors.$tryApplyWorkspaceEdit([workspaceResourceEdit]);
|
||||
return this._mainThreadEditors.$tryApplyWorkspaceEdit({ edits: [resourceEdit] });
|
||||
}
|
||||
|
||||
// TODO@joh bubble this to listener?
|
||||
|
||||
@@ -22,6 +22,7 @@ import { Barrier } from 'vs/base/common/async';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService';
|
||||
import URI from 'vs/base/common/uri';
|
||||
|
||||
class ExtensionMemento implements IExtensionMemento {
|
||||
|
||||
@@ -108,6 +109,7 @@ class ExtensionStoragePath {
|
||||
join(storagePath, 'meta.json'),
|
||||
JSON.stringify({
|
||||
id: this._workspace.id,
|
||||
configuration: this._workspace.configuration && URI.revive(this._workspace.configuration).toString(),
|
||||
name: this._workspace.name
|
||||
}, undefined, 2)
|
||||
);
|
||||
@@ -128,7 +130,6 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
private readonly _storage: ExtHostStorage;
|
||||
private readonly _storagePath: ExtensionStoragePath;
|
||||
private readonly _proxy: MainThreadExtensionServiceShape;
|
||||
private readonly _logService: ILogService;
|
||||
private readonly _extHostLogService: ExtHostLogService;
|
||||
private _activator: ExtensionsActivator;
|
||||
private _extensionPathIndex: TPromise<TernarySearchTree<IExtensionDescription>>;
|
||||
@@ -139,21 +140,20 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
extHostContext: IExtHostContext,
|
||||
extHostWorkspace: ExtHostWorkspace,
|
||||
extHostConfiguration: ExtHostConfiguration,
|
||||
logService: ILogService,
|
||||
extHostLogService: ExtHostLogService,
|
||||
environmentService: IEnvironmentService
|
||||
) {
|
||||
this._barrier = new Barrier();
|
||||
this._registry = new ExtensionDescriptionRegistry(initData.extensions);
|
||||
this._logService = logService;
|
||||
this._extHostLogService = extHostLogService;
|
||||
this._mainThreadTelemetry = extHostContext.getProxy(MainContext.MainThreadTelemetry);
|
||||
this._storage = new ExtHostStorage(extHostContext);
|
||||
this._storagePath = new ExtensionStoragePath(initData.workspace, initData.environment);
|
||||
this._proxy = extHostContext.getProxy(MainContext.MainThreadExtensionService);
|
||||
this._activator = null;
|
||||
this._extHostLogService = new ExtHostLogService(environmentService);
|
||||
|
||||
// initialize API first (i.e. do not release barrier until the API is initialized)
|
||||
const apiFactory = createApiFactory(initData, extHostContext, extHostWorkspace, extHostConfiguration, this, logService);
|
||||
const apiFactory = createApiFactory(initData, extHostContext, extHostWorkspace, extHostConfiguration, this, this._extHostLogService);
|
||||
|
||||
initializeExtensionApi(this, apiFactory).then(() => {
|
||||
|
||||
@@ -314,14 +314,14 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
return TPromise.as(new EmptyExtension(ExtensionActivationTimes.NONE));
|
||||
}
|
||||
|
||||
this._logService.info(`ExtensionService#_doActivateExtension ${extensionDescription.id} ${JSON.stringify(reason)}`);
|
||||
this._extHostLogService.info(`ExtensionService#_doActivateExtension ${extensionDescription.id} ${JSON.stringify(reason)}`);
|
||||
|
||||
const activationTimesBuilder = new ExtensionActivationTimesBuilder(reason.startup);
|
||||
return TPromise.join<any>([
|
||||
loadCommonJSModule(this._logService, extensionDescription.main, activationTimesBuilder),
|
||||
loadCommonJSModule(this._extHostLogService, extensionDescription.main, activationTimesBuilder),
|
||||
this._loadExtensionContext(extensionDescription)
|
||||
]).then(values => {
|
||||
return ExtHostExtensionService._callActivate(this._logService, extensionDescription.id, <IExtensionModule>values[0], <IExtensionContext>values[1], activationTimesBuilder);
|
||||
return ExtHostExtensionService._callActivate(this._extHostLogService, extensionDescription.id, <IExtensionModule>values[0], <IExtensionContext>values[1], activationTimesBuilder);
|
||||
}, (errors: any[]) => {
|
||||
// Avoid failing with an array of errors, fail with a single error
|
||||
if (errors[0]) {
|
||||
@@ -339,7 +339,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
let globalState = new ExtensionMemento(extensionDescription.id, true, this._storage);
|
||||
let workspaceState = new ExtensionMemento(extensionDescription.id, false, this._storage);
|
||||
|
||||
this._logService.trace(`ExtensionService#loadExtensionContext ${extensionDescription.id}`);
|
||||
this._extHostLogService.trace(`ExtensionService#loadExtensionContext ${extensionDescription.id}`);
|
||||
return TPromise.join([
|
||||
globalState.whenReady,
|
||||
workspaceState.whenReady,
|
||||
|
||||
@@ -17,7 +17,7 @@ import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
|
||||
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
|
||||
import { ExtHostDiagnostics, DiagnosticCollection } from 'vs/workbench/api/node/extHostDiagnostics';
|
||||
import { asWinJsPromise } from 'vs/base/common/async';
|
||||
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, SymbolInformationDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto } from './extHost.protocol';
|
||||
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, SymbolInformationDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto, CodeActionDto } from './extHost.protocol';
|
||||
import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
@@ -255,7 +255,7 @@ class ReferenceAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
export interface CustomCodeAction extends modes.CodeAction {
|
||||
export interface CustomCodeAction extends CodeActionDto {
|
||||
_isSynthetic?: boolean;
|
||||
}
|
||||
|
||||
@@ -273,7 +273,8 @@ class CodeActionAdapter {
|
||||
this._provider = provider;
|
||||
}
|
||||
|
||||
provideCodeActions(resource: URI, range: IRange, context: modes.CodeActionContext): TPromise<modes.CodeAction[]> {
|
||||
|
||||
provideCodeActions(resource: URI, range: IRange, context: modes.CodeActionContext): TPromise<CodeActionDto[]> {
|
||||
|
||||
const doc = this._documents.getDocumentData(resource).document;
|
||||
const ran = <vscode.Range>TypeConverters.toRange(range);
|
||||
@@ -948,7 +949,8 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideCodeActions(handle: number, resource: UriComponents, range: IRange, context: modes.CodeActionContext): TPromise<modes.CodeAction[]> {
|
||||
|
||||
$provideCodeActions(handle: number, resource: UriComponents, range: IRange, context: modes.CodeActionContext): TPromise<CodeActionDto[]> {
|
||||
return this._withAdapter(handle, CodeActionAdapter, adapter => adapter.provideCodeActions(URI.revive(resource), range, context));
|
||||
}
|
||||
|
||||
|
||||
@@ -8,47 +8,61 @@ import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { mkdirp, dirExists } from 'vs/base/node/pfs';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import Event from 'vs/base/common/event';
|
||||
import { LogLevel } from 'vs/workbench/api/node/extHostTypes';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ILogService, DelegatedLogService } from 'vs/platform/log/common/log';
|
||||
import { createSpdLogService } from 'vs/platform/log/node/spdlogService';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
import { ExtHostLogServiceShape } from 'vs/workbench/api/node/extHost.protocol';
|
||||
|
||||
|
||||
export class ExtHostLogService extends DelegatedLogService implements ILogService, ExtHostLogServiceShape {
|
||||
|
||||
export class ExtHostLogService {
|
||||
private _loggers: Map<string, ExtHostLogger> = new Map();
|
||||
|
||||
constructor(private _environmentService: IEnvironmentService) {
|
||||
constructor(
|
||||
windowId: number,
|
||||
logLevel: LogLevel,
|
||||
private _environmentService: IEnvironmentService
|
||||
) {
|
||||
super(createSpdLogService(`exthost${windowId}`, logLevel, _environmentService.logsPath));
|
||||
}
|
||||
|
||||
$setLevel(level: LogLevel): void {
|
||||
this.setLevel(level);
|
||||
}
|
||||
|
||||
getExtLogger(extensionID: string): ExtHostLogger {
|
||||
if (!this._loggers.has(extensionID)) {
|
||||
const logService = createSpdLogService(extensionID, this._environmentService, extensionID);
|
||||
const logsDirPath = path.join(this._environmentService.logsPath, extensionID);
|
||||
this._loggers.set(extensionID, new ExtHostLogger(logService, logsDirPath));
|
||||
let logger = this._loggers.get(extensionID);
|
||||
if (!logger) {
|
||||
logger = this.createLogger(extensionID);
|
||||
this._loggers.set(extensionID, logger);
|
||||
}
|
||||
return logger;
|
||||
}
|
||||
|
||||
return this._loggers.get(extensionID);
|
||||
private createLogger(extensionID: string): ExtHostLogger {
|
||||
const logService = createSpdLogService(extensionID, this.getLevel(), this._environmentService.logsPath, extensionID);
|
||||
const logsDirPath = path.join(this._environmentService.logsPath, extensionID);
|
||||
this._register(this.onDidChangeLogLevel(level => logService.setLevel(level)));
|
||||
return new ExtHostLogger(logService, logsDirPath);
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostLogger implements vscode.Logger {
|
||||
private _currentLevel: LogLevel;
|
||||
private _onDidChangeLogLevel: Emitter<LogLevel>;
|
||||
|
||||
constructor(
|
||||
private readonly _logService: ILogService,
|
||||
private readonly _logDirectory: string
|
||||
) {
|
||||
this._currentLevel = this._logService.getLevel();
|
||||
this._onDidChangeLogLevel = new Emitter<LogLevel>();
|
||||
this.onDidChangeLogLevel = this._onDidChangeLogLevel.event;
|
||||
}
|
||||
|
||||
// TODO
|
||||
readonly onDidChangeLogLevel: Event<LogLevel>;
|
||||
get onDidChangeLogLevel(): Event<LogLevel> {
|
||||
return this._logService.onDidChangeLogLevel;
|
||||
}
|
||||
|
||||
get currentLevel(): LogLevel { return this._currentLevel; }
|
||||
get currentLevel(): LogLevel { return this._logService.getLevel(); }
|
||||
|
||||
@memoize
|
||||
get logDirectory(): TPromise<string> {
|
||||
|
||||
@@ -12,7 +12,7 @@ import * as TypeConverters from './extHostTypeConverters';
|
||||
import { TextEditorDecorationType, ExtHostTextEditor } from './extHostTextEditor';
|
||||
import { ExtHostDocumentsAndEditors } from './extHostDocumentsAndEditors';
|
||||
import { Position as EditorPosition } from 'vs/platform/editor/common/editor';
|
||||
import { MainContext, MainThreadEditorsShape, ExtHostEditorsShape, ITextDocumentShowOptions, ITextEditorPositionData, IResolvedTextEditorConfiguration, ISelectionChangeEvent, IMainContext, IWorkspaceResourceEdit } from './extHost.protocol';
|
||||
import { MainContext, MainThreadEditorsShape, ExtHostEditorsShape, ITextDocumentShowOptions, ITextEditorPositionData, IResolvedTextEditorConfiguration, ISelectionChangeEvent, IMainContext, WorkspaceEditDto } from './extHost.protocol';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export class ExtHostEditors implements ExtHostEditorsShape {
|
||||
@@ -92,36 +92,23 @@ export class ExtHostEditors implements ExtHostEditorsShape {
|
||||
|
||||
applyWorkspaceEdit(edit: vscode.WorkspaceEdit): TPromise<boolean> {
|
||||
|
||||
let workspaceResourceEdits: IWorkspaceResourceEdit[] = [];
|
||||
const dto: WorkspaceEditDto = { edits: [] };
|
||||
|
||||
let entries = edit.entries();
|
||||
for (let entry of entries) {
|
||||
let [uri, edits] = entry;
|
||||
|
||||
let doc = this._extHostDocumentsAndEditors.getDocument(uri.toString());
|
||||
let docVersion: number = undefined;
|
||||
if (doc) {
|
||||
docVersion = doc.version;
|
||||
}
|
||||
|
||||
let workspaceResourceEdit: IWorkspaceResourceEdit = {
|
||||
resource: uri,
|
||||
modelVersionId: docVersion,
|
||||
edits: []
|
||||
};
|
||||
|
||||
for (let edit of edits) {
|
||||
workspaceResourceEdit.edits.push({
|
||||
newText: edit.newText,
|
||||
newEol: TypeConverters.EndOfLine.from(edit.newEol),
|
||||
range: edit.range && TypeConverters.fromRange(edit.range)
|
||||
for (let entry of edit.allEntries()) {
|
||||
let [uri, uriOrEdits] = entry;
|
||||
if (Array.isArray(uriOrEdits)) {
|
||||
let doc = this._extHostDocumentsAndEditors.getDocument(uri.toString());
|
||||
dto.edits.push({
|
||||
resource: uri,
|
||||
modelVersionId: doc && doc.version,
|
||||
edits: uriOrEdits.map(TypeConverters.TextEdit.from)
|
||||
});
|
||||
} else {
|
||||
dto.edits.push({ oldUri: uri, newUri: uriOrEdits });
|
||||
}
|
||||
|
||||
workspaceResourceEdits.push(workspaceResourceEdit);
|
||||
}
|
||||
|
||||
return this._proxy.$tryApplyWorkspaceEdit(workspaceResourceEdits);
|
||||
return this._proxy.$tryApplyWorkspaceEdit(dto);
|
||||
}
|
||||
|
||||
// --- called from main thread
|
||||
|
||||
@@ -20,6 +20,7 @@ import { ISelection } from 'vs/editor/common/core/selection';
|
||||
import * as htmlContent from 'vs/base/common/htmlContent';
|
||||
import { IRelativePattern } from 'vs/base/common/glob';
|
||||
import { LanguageSelector, LanguageFilter } from 'vs/editor/common/modes/languageSelector';
|
||||
import { WorkspaceEditDto, ResourceTextEditDto, ResourceFileEditDto } from 'vs/workbench/api/node/extHost.protocol';
|
||||
|
||||
export interface PositionLike {
|
||||
line: number;
|
||||
@@ -228,24 +229,36 @@ export const TextEdit = {
|
||||
|
||||
export namespace WorkspaceEdit {
|
||||
export function from(value: vscode.WorkspaceEdit): modes.WorkspaceEdit {
|
||||
const result: modes.WorkspaceEdit = { edits: [] };
|
||||
for (let entry of value.entries()) {
|
||||
let [uri, textEdits] = entry;
|
||||
for (let textEdit of textEdits) {
|
||||
result.edits.push({
|
||||
resource: uri,
|
||||
newText: textEdit.newText,
|
||||
range: fromRange(textEdit.range)
|
||||
});
|
||||
const result: modes.WorkspaceEdit = {
|
||||
edits: []
|
||||
};
|
||||
for (const entry of value.allEntries()) {
|
||||
const [uri, uriOrEdits] = entry;
|
||||
if (Array.isArray(uriOrEdits)) {
|
||||
// text edits
|
||||
result.edits.push({ resource: uri, edits: uriOrEdits.map(TextEdit.from) });
|
||||
} else {
|
||||
// resource edits
|
||||
result.edits.push({ oldUri: uri, newUri: uriOrEdits });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function to(value: modes.WorkspaceEdit) {
|
||||
export function to(value: WorkspaceEditDto) {
|
||||
const result = new types.WorkspaceEdit();
|
||||
for (const edit of value.edits) {
|
||||
result.replace(edit.resource, toRange(edit.range), edit.newText);
|
||||
if (Array.isArray((<ResourceTextEditDto>edit).edits)) {
|
||||
result.set(
|
||||
URI.revive((<ResourceTextEditDto>edit).resource),
|
||||
<types.TextEdit[]>(<ResourceTextEditDto>edit).edits.map(TextEdit.to)
|
||||
);
|
||||
} else {
|
||||
result.renameResource(
|
||||
URI.revive((<ResourceFileEditDto>edit).oldUri),
|
||||
URI.revive((<ResourceFileEditDto>edit).newUri)
|
||||
);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -492,10 +492,28 @@ export class TextEdit {
|
||||
}
|
||||
}
|
||||
|
||||
export class WorkspaceEdit {
|
||||
export class WorkspaceEdit implements vscode.WorkspaceEdit {
|
||||
|
||||
private _values: [URI, TextEdit[]][] = [];
|
||||
private _index = new Map<string, number>();
|
||||
private _seqPool: number = 0;
|
||||
|
||||
private _resourceEdits: { seq: number, from: URI, to: URI }[] = [];
|
||||
private _textEdits = new Map<string, { seq: number, uri: URI, edits: TextEdit[] }>();
|
||||
|
||||
createResource(uri: vscode.Uri): void {
|
||||
this.renameResource(undefined, uri);
|
||||
}
|
||||
|
||||
deleteResource(uri: vscode.Uri): void {
|
||||
this.renameResource(uri, undefined);
|
||||
}
|
||||
|
||||
renameResource(from: vscode.Uri, to: vscode.Uri): void {
|
||||
this._resourceEdits.push({ seq: this._seqPool++, from, to });
|
||||
}
|
||||
|
||||
resourceEdits(): [vscode.Uri, vscode.Uri][] {
|
||||
return this._resourceEdits.map(({ from, to }) => (<[vscode.Uri, vscode.Uri]>[from, to]));
|
||||
}
|
||||
|
||||
replace(uri: URI, range: Range, newText: string): void {
|
||||
let edit = new TextEdit(range, newText);
|
||||
@@ -503,8 +521,9 @@ export class WorkspaceEdit {
|
||||
if (array) {
|
||||
array.push(edit);
|
||||
} else {
|
||||
this.set(uri, [edit]);
|
||||
array = [edit];
|
||||
}
|
||||
this.set(uri, array);
|
||||
}
|
||||
|
||||
insert(resource: URI, position: Position, newText: string): void {
|
||||
@@ -516,34 +535,58 @@ export class WorkspaceEdit {
|
||||
}
|
||||
|
||||
has(uri: URI): boolean {
|
||||
return this._index.has(uri.toString());
|
||||
return this._textEdits.has(uri.toString());
|
||||
}
|
||||
|
||||
set(uri: URI, edits: TextEdit[]): void {
|
||||
const idx = this._index.get(uri.toString());
|
||||
if (typeof idx === 'undefined') {
|
||||
let newLen = this._values.push([uri, edits]);
|
||||
this._index.set(uri.toString(), newLen - 1);
|
||||
let data = this._textEdits.get(uri.toString());
|
||||
if (!data) {
|
||||
data = { seq: this._seqPool++, uri, edits: [] };
|
||||
this._textEdits.set(uri.toString(), data);
|
||||
}
|
||||
if (!edits) {
|
||||
data.edits = undefined;
|
||||
} else {
|
||||
this._values[idx][1] = edits;
|
||||
data.edits = edits.slice(0);
|
||||
}
|
||||
}
|
||||
|
||||
get(uri: URI): TextEdit[] {
|
||||
let idx = this._index.get(uri.toString());
|
||||
return typeof idx !== 'undefined' && this._values[idx][1];
|
||||
if (!this._textEdits.has(uri.toString())) {
|
||||
return undefined;
|
||||
}
|
||||
const { edits } = this._textEdits.get(uri.toString());
|
||||
return edits ? edits.slice() : undefined;
|
||||
}
|
||||
|
||||
entries(): [URI, TextEdit[]][] {
|
||||
return this._values;
|
||||
const res: [URI, TextEdit[]][] = [];
|
||||
this._textEdits.forEach(value => res.push([value.uri, value.edits]));
|
||||
return res.slice();
|
||||
}
|
||||
|
||||
allEntries(): ([URI, TextEdit[]] | [URI, URI])[] {
|
||||
// use the 'seq' the we have assigned when inserting
|
||||
// the operation and use that order in the resulting
|
||||
// array
|
||||
const res: ([URI, TextEdit[]] | [URI, URI])[] = [];
|
||||
this._textEdits.forEach(value => {
|
||||
const { seq, uri, edits } = value;
|
||||
res[seq] = [uri, edits];
|
||||
});
|
||||
this._resourceEdits.forEach(value => {
|
||||
const { seq, from, to } = value;
|
||||
res[seq] = [from, to];
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
get size(): number {
|
||||
return this._values.length;
|
||||
return this._textEdits.size + this._resourceEdits.length;
|
||||
}
|
||||
|
||||
toJSON(): any {
|
||||
return this._values;
|
||||
return this.entries();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user