Merge remote-tracking branch 'origin/master' into bug46075

This commit is contained in:
Alex Dima
2018-03-28 18:29:10 +02:00
631 changed files with 12425 additions and 9510 deletions

View File

@@ -29,6 +29,15 @@ export class MainThreadDiagnostics implements MainThreadDiagnosticsShape {
$changeMany(owner: string, entries: [UriComponents, IMarkerData[]][]): void {
for (let entry of entries) {
let [uri, markers] = entry;
if (markers) {
for (const marker of markers) {
if (marker.relatedInformation) {
for (const relatedInformation of marker.relatedInformation) {
relatedInformation.resource = URI.revive(relatedInformation.resource);
}
}
}
}
this._markerService.changeOne(owner, URI.revive(uri), markers);
}
this._activeOwners.add(owner);

View File

@@ -6,7 +6,7 @@
import URI, { UriComponents } from 'vs/base/common/uri';
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModelService, shouldSynchronizeModel } from 'vs/editor/common/services/modelService';
import { IDisposable, dispose, IReference } from 'vs/base/common/lifecycle';
import { TextFileModelChangeEvent, ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { TPromise } from 'vs/base/common/winjs.base';
@@ -132,12 +132,12 @@ export class MainThreadDocuments implements MainThreadDocumentsShape {
private _shouldHandleFileEvent(e: TextFileModelChangeEvent): boolean {
const model = this._modelService.getModel(e.resource);
return model && !model.isTooLargeForHavingARichMode();
return model && shouldSynchronizeModel(model);
}
private _onModelAdded(model: ITextModel): void {
// Same filter as in mainThreadEditorsTracker
if (model.isTooLargeForHavingARichMode()) {
if (!shouldSynchronizeModel(model)) {
// don't synchronize too large models
return null;
}

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModelService, shouldSynchronizeModel } from 'vs/editor/common/services/modelService';
import { ITextModel } from 'vs/editor/common/model';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
@@ -192,7 +192,7 @@ class MainThreadDocumentAndEditorStateComputer {
}
private _updateStateOnModelAdd(model: ITextModel): void {
if (model.isTooLargeForHavingARichMode()) {
if (!shouldSynchronizeModel(model)) {
// ignore
return;
}
@@ -222,7 +222,7 @@ class MainThreadDocumentAndEditorStateComputer {
// models: ignore too large models
const models = new Set<ITextModel>();
for (const model of this._modelService.getModels()) {
if (!model.isTooLargeForHavingARichMode()) {
if (shouldSynchronizeModel(model)) {
models.add(model);
}
}
@@ -233,8 +233,11 @@ class MainThreadDocumentAndEditorStateComputer {
let activeEditor: string = null;
for (const editor of this._codeEditorService.listCodeEditors()) {
if (editor.isSimpleWidget) {
continue;
}
const model = editor.getModel();
if (model && !model.isTooLargeForHavingARichMode()
if (model && shouldSynchronizeModel(model)
&& !model.isDisposed() // model disposed
&& Boolean(this._modelService.getModel(model.uri)) // model disposing, the flag didn't flip yet but the model service already removed it
) {

View File

@@ -322,7 +322,7 @@ export class MainThreadTextEditor {
if (newConfiguration.tabSize === 'auto' || newConfiguration.insertSpaces === 'auto') {
// one of the options was set to 'auto' => detect indentation
let creationOpts = this._modelService.getCreationOptions(this._model.getLanguageIdentifier().language, this._model.uri);
let creationOpts = this._modelService.getCreationOptions(this._model.getLanguageIdentifier().language, this._model.uri, this._model.isForSimpleWidget);
let insertSpaces = creationOpts.insertSpaces;
let tabSize = creationOpts.tabSize;

View File

@@ -13,8 +13,6 @@ import { Event, Emitter } from 'vs/base/common/event';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { IProgress } from 'vs/platform/progress/common/progress';
import { ISearchResultProvider, ISearchQuery, ISearchComplete, ISearchProgressItem, QueryType, IFileMatch, ISearchService, ILineMatch } from 'vs/platform/search/common/search';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
import { onUnexpectedError } from 'vs/base/common/errors';
import { values } from 'vs/base/common/map';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
@@ -22,47 +20,50 @@ import { isFalsyOrEmpty } from 'vs/base/common/arrays';
export class MainThreadFileSystem implements MainThreadFileSystemShape {
private readonly _proxy: ExtHostFileSystemShape;
private readonly _provider = new Map<number, RemoteFileSystemProvider>();
private readonly _fileProvider = new Map<number, RemoteFileSystemProvider>();
private readonly _searchProvider = new Map<number, RemoteSearchProvider>();
constructor(
extHostContext: IExtHostContext,
@IFileService private readonly _fileService: IFileService,
@ISearchService private readonly _searchService: ISearchService,
@IWorkspaceEditingService private readonly _workspaceEditingService: IWorkspaceEditingService
@ISearchService private readonly _searchService: ISearchService
) {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostFileSystem);
}
dispose(): void {
this._provider.forEach(value => dispose());
this._provider.clear();
this._fileProvider.forEach(value => dispose());
this._fileProvider.clear();
}
$registerFileSystemProvider(handle: number, scheme: string): void {
this._provider.set(handle, new RemoteFileSystemProvider(this._fileService, this._searchService, scheme, handle, this._proxy));
this._fileProvider.set(handle, new RemoteFileSystemProvider(this._fileService, scheme, handle, this._proxy));
}
$unregisterFileSystemProvider(handle: number): void {
dispose(this._provider.get(handle));
this._provider.delete(handle);
$registerSearchProvider(handle: number, scheme: string): void {
this._searchProvider.set(handle, new RemoteSearchProvider(this._searchService, scheme, handle, this._proxy));
}
$onDidAddFileSystemRoot(data: UriComponents): void {
this._workspaceEditingService.addFolders([{ uri: URI.revive(data) }], true).done(null, onUnexpectedError);
$unregisterProvider(handle: number): void {
dispose(this._fileProvider.get(handle));
this._fileProvider.delete(handle);
dispose(this._searchProvider.get(handle));
this._searchProvider.delete(handle);
}
$onFileSystemChange(handle: number, changes: IFileChangeDto[]): void {
this._provider.get(handle).$onFileSystemChange(changes);
this._fileProvider.get(handle).$onFileSystemChange(changes);
}
$reportFileChunk(handle: number, session: number, chunk: number[]): void {
this._provider.get(handle).reportFileChunk(session, chunk);
this._fileProvider.get(handle).reportFileChunk(session, chunk);
}
// --- search
$handleFindMatch(handle: number, session, data: UriComponents | [UriComponents, ILineMatch]): void {
this._provider.get(handle).handleFindMatch(session, data);
this._searchProvider.get(handle).handleFindMatch(session, data);
}
}
@@ -78,40 +79,22 @@ class FileReadOperation {
}
}
class SearchOperation {
private static _idPool = 0;
constructor(
readonly progress: (match: IFileMatch) => any,
readonly id: number = ++SearchOperation._idPool,
readonly matches = new Map<string, IFileMatch>()
) {
//
}
}
class RemoteFileSystemProvider implements IFileSystemProvider, ISearchResultProvider {
class RemoteFileSystemProvider implements IFileSystemProvider {
private readonly _onDidChange = new Emitter<IFileChange[]>();
private readonly _registrations: IDisposable[];
private readonly _reads = new Map<number, FileReadOperation>();
private readonly _searches = new Map<number, SearchOperation>();
readonly onDidChange: Event<IFileChange[]> = this._onDidChange.event;
constructor(
fileService: IFileService,
searchService: ISearchService,
private readonly _scheme: string,
scheme: string,
private readonly _handle: number,
private readonly _proxy: ExtHostFileSystemShape
) {
this._registrations = [
fileService.registerProvider(_scheme, this),
searchService.registerSearchResultProvider(this),
];
this._registrations = [fileService.registerProvider(scheme, this)];
}
dispose(): void {
@@ -166,8 +149,49 @@ class RemoteFileSystemProvider implements IFileSystemProvider, ISearchResultProv
rmdir(resource: URI): TPromise<void, any> {
return this._proxy.$rmdir(this._handle, resource);
}
}
// --- search
class SearchOperation {
private static _idPool = 0;
constructor(
readonly progress: (match: IFileMatch) => any,
readonly id: number = ++SearchOperation._idPool,
readonly matches = new Map<string, IFileMatch>()
) {
//
}
addMatch(resource: URI, match: ILineMatch): void {
if (!this.matches.has(resource.toString())) {
this.matches.set(resource.toString(), { resource, lineMatches: [] });
}
if (match) {
this.matches.get(resource.toString()).lineMatches.push(match);
}
this.progress(this.matches.get(resource.toString()));
}
}
class RemoteSearchProvider implements ISearchResultProvider {
private readonly _registrations: IDisposable[];
private readonly _searches = new Map<number, SearchOperation>();
constructor(
searchService: ISearchService,
private readonly _scheme: string,
private readonly _handle: number,
private readonly _proxy: ExtHostFileSystemShape
) {
this._registrations = [searchService.registerSearchResultProvider(this)];
}
dispose(): void {
dispose(this._registrations);
}
search(query: ISearchQuery): PPromise<ISearchComplete, ISearchProgressItem> {
@@ -185,26 +209,36 @@ class RemoteFileSystemProvider implements IFileSystemProvider, ISearchResultProv
}
}
let outer: TPromise;
return new PPromise((resolve, reject, report) => {
const search = new SearchOperation(report);
this._searches.set(search.id, search);
const promise = query.type === QueryType.File
? this._proxy.$findFiles(this._handle, search.id, query.filePattern)
outer = query.type === QueryType.File
? this._proxy.$provideFileSearchResults(this._handle, search.id, query.filePattern)
: this._proxy.$provideTextSearchResults(this._handle, search.id, query.contentPattern, { excludes: Object.keys(excludes), includes: Object.keys(includes) });
promise.then(() => {
outer.then(() => {
this._searches.delete(search.id);
resolve(({ results: values(search.matches), stats: undefined }));
}, err => {
this._searches.delete(search.id);
reject(err);
});
}, () => {
if (outer) {
outer.cancel();
}
});
}
handleFindMatch(session: number, dataOrUri: UriComponents | [UriComponents, ILineMatch]): void {
if (!this._searches.has(session)) {
// ignore...
return;
}
let resource: URI;
let match: ILineMatch;
@@ -215,12 +249,6 @@ class RemoteFileSystemProvider implements IFileSystemProvider, ISearchResultProv
resource = URI.revive(dataOrUri);
}
const { matches } = this._searches.get(session);
if (!matches.has(resource.toString())) {
matches.set(resource.toString(), { resource, lineMatches: [] });
}
if (match) {
matches.get(resource.toString()).lineMatches.push(match);
}
this._searches.get(session).addMatch(resource, match);
}
}

View File

@@ -7,15 +7,14 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { IDisposable } from 'vs/base/common/lifecycle';
import { Emitter } from 'vs/base/common/event';
import * as vscode from 'vscode';
import { ITextModel, ISingleEditOperation } from 'vs/editor/common/model';
import * as modes from 'vs/editor/common/modes';
import { WorkspaceSymbolProviderRegistry, IWorkspaceSymbolProvider } 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, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ISerializedLanguageConfiguration, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, LocationDto, SymbolInformationDto, CodeActionDto, reviveWorkspaceEditDto } from '../node/extHost.protocol';
import { Range as EditorRange, IRange } from 'vs/editor/common/core/range';
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ISerializedLanguageConfiguration, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, LocationDto, SymbolInformationDto, CodeActionDto, reviveWorkspaceEditDto, ISerializedDocumentFilter } from '../node/extHost.protocol';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { LanguageConfiguration, IndentationRule, OnEnterRule } from 'vs/editor/common/modes/languageConfiguration';
import { IHeapService } from './mainThreadHeapService';
@@ -97,7 +96,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- outline
$registerOutlineSupport(handle: number, selector: vscode.DocumentSelector): void {
$registerOutlineSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.DocumentSymbolProviderRegistry.register(toLanguageSelector(selector), <modes.DocumentSymbolProvider>{
provideDocumentSymbols: (model: ITextModel, token: CancellationToken): Thenable<modes.SymbolInformation[]> => {
return wireCancellationToken(token, this._proxy.$provideDocumentSymbols(handle, model.uri)).then(MainThreadLanguageFeatures._reviveSymbolInformationDto);
@@ -107,7 +106,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- code lens
$registerCodeLensSupport(handle: number, selector: vscode.DocumentSelector, eventHandle: number): void {
$registerCodeLensSupport(handle: number, selector: ISerializedDocumentFilter[], eventHandle: number): void {
const provider = <modes.CodeLensProvider>{
provideCodeLenses: (model: ITextModel, token: CancellationToken): modes.ICodeLensSymbol[] | Thenable<modes.ICodeLensSymbol[]> => {
@@ -136,7 +135,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- declaration
$registerDeclaractionSupport(handle: number, selector: vscode.DocumentSelector): void {
$registerDeclaractionSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.DefinitionProviderRegistry.register(toLanguageSelector(selector), <modes.DefinitionProvider>{
provideDefinition: (model, position, token): Thenable<modes.Definition> => {
return wireCancellationToken(token, this._proxy.$provideDefinition(handle, model.uri, position)).then(MainThreadLanguageFeatures._reviveLocationDto);
@@ -144,7 +143,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
});
}
$registerImplementationSupport(handle: number, selector: vscode.DocumentSelector): void {
$registerImplementationSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.ImplementationProviderRegistry.register(toLanguageSelector(selector), <modes.ImplementationProvider>{
provideImplementation: (model, position, token): Thenable<modes.Definition> => {
return wireCancellationToken(token, this._proxy.$provideImplementation(handle, model.uri, position)).then(MainThreadLanguageFeatures._reviveLocationDto);
@@ -152,7 +151,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
});
}
$registerTypeDefinitionSupport(handle: number, selector: vscode.DocumentSelector): void {
$registerTypeDefinitionSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.TypeDefinitionProviderRegistry.register(toLanguageSelector(selector), <modes.TypeDefinitionProvider>{
provideTypeDefinition: (model, position, token): Thenable<modes.Definition> => {
return wireCancellationToken(token, this._proxy.$provideTypeDefinition(handle, model.uri, position)).then(MainThreadLanguageFeatures._reviveLocationDto);
@@ -162,7 +161,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- extra info
$registerHoverProvider(handle: number, selector: vscode.DocumentSelector): void {
$registerHoverProvider(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.HoverProviderRegistry.register(toLanguageSelector(selector), <modes.HoverProvider>{
provideHover: (model: ITextModel, position: EditorPosition, token: CancellationToken): Thenable<modes.Hover> => {
return wireCancellationToken(token, this._proxy.$provideHover(handle, model.uri, position));
@@ -172,7 +171,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- occurrences
$registerDocumentHighlightProvider(handle: number, selector: vscode.DocumentSelector): void {
$registerDocumentHighlightProvider(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.DocumentHighlightProviderRegistry.register(toLanguageSelector(selector), <modes.DocumentHighlightProvider>{
provideDocumentHighlights: (model: ITextModel, position: EditorPosition, token: CancellationToken): Thenable<modes.DocumentHighlight[]> => {
return wireCancellationToken(token, this._proxy.$provideDocumentHighlights(handle, model.uri, position));
@@ -182,7 +181,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- references
$registerReferenceSupport(handle: number, selector: vscode.DocumentSelector): void {
$registerReferenceSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.ReferenceProviderRegistry.register(toLanguageSelector(selector), <modes.ReferenceProvider>{
provideReferences: (model: ITextModel, position: EditorPosition, context: modes.ReferenceContext, token: CancellationToken): Thenable<modes.Location[]> => {
return wireCancellationToken(token, this._proxy.$provideReferences(handle, model.uri, position, context)).then(MainThreadLanguageFeatures._reviveLocationDto);
@@ -192,7 +191,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- quick fix
$registerQuickFixSupport(handle: number, selector: vscode.DocumentSelector): void {
$registerQuickFixSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.CodeActionProviderRegistry.register(toLanguageSelector(selector), <modes.CodeActionProvider>{
provideCodeActions: (model: ITextModel, range: EditorRange, context: modes.CodeActionContext, token: CancellationToken): Thenable<modes.CodeAction[]> => {
return this._heapService.trackRecursive(wireCancellationToken(token, this._proxy.$provideCodeActions(handle, model.uri, range, context))).then(MainThreadLanguageFeatures._reviveCodeActionDto);
@@ -202,7 +201,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- formatting
$registerDocumentFormattingSupport(handle: number, selector: vscode.DocumentSelector): void {
$registerDocumentFormattingSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.DocumentFormattingEditProviderRegistry.register(toLanguageSelector(selector), <modes.DocumentFormattingEditProvider>{
provideDocumentFormattingEdits: (model: ITextModel, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> => {
return wireCancellationToken(token, this._proxy.$provideDocumentFormattingEdits(handle, model.uri, options));
@@ -210,7 +209,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
});
}
$registerRangeFormattingSupport(handle: number, selector: vscode.DocumentSelector): void {
$registerRangeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.DocumentRangeFormattingEditProviderRegistry.register(toLanguageSelector(selector), <modes.DocumentRangeFormattingEditProvider>{
provideDocumentRangeFormattingEdits: (model: ITextModel, range: EditorRange, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> => {
return wireCancellationToken(token, this._proxy.$provideDocumentRangeFormattingEdits(handle, model.uri, range, options));
@@ -218,7 +217,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
});
}
$registerOnTypeFormattingSupport(handle: number, selector: vscode.DocumentSelector, autoFormatTriggerCharacters: string[]): void {
$registerOnTypeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[], autoFormatTriggerCharacters: string[]): void {
this._registrations[handle] = modes.OnTypeFormattingEditProviderRegistry.register(toLanguageSelector(selector), <modes.OnTypeFormattingEditProvider>{
autoFormatTriggerCharacters,
@@ -251,20 +250,21 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- rename
$registerRenameSupport(handle: number, selector: vscode.DocumentSelector, supportsResolveInitialValues: boolean): void {
$registerRenameSupport(handle: number, selector: ISerializedDocumentFilter[], supportResolveLocation: boolean): void {
this._registrations[handle] = modes.RenameProviderRegistry.register(toLanguageSelector(selector), <modes.RenameProvider>{
provideRenameEdits: (model: ITextModel, position: EditorPosition, newName: string, token: CancellationToken): Thenable<modes.WorkspaceEdit> => {
return wireCancellationToken(token, this._proxy.$provideRenameEdits(handle, model.uri, position, newName)).then(reviveWorkspaceEditDto);
},
resolveRenameContext: supportsResolveInitialValues
? (model: ITextModel, position: EditorPosition, token: CancellationToken): Thenable<modes.RenameContext> => wireCancellationToken(token, this._proxy.$resolveRenameContext(handle, model.uri, position))
resolveRenameLocation: supportResolveLocation
? (model: ITextModel, position: EditorPosition, token: CancellationToken): Thenable<IRange> => wireCancellationToken(token, this._proxy.$resolveRenameLocation(handle, model.uri, position))
: undefined
});
}
// --- suggest
$registerSuggestSupport(handle: number, selector: vscode.DocumentSelector, triggerCharacters: string[], supportsResolveDetails: boolean): void {
$registerSuggestSupport(handle: number, selector: ISerializedDocumentFilter[], triggerCharacters: string[], supportsResolveDetails: boolean): void {
this._registrations[handle] = modes.SuggestRegistry.register(toLanguageSelector(selector), <modes.ISuggestSupport>{
triggerCharacters,
provideCompletionItems: (model: ITextModel, position: EditorPosition, context: modes.SuggestContext, token: CancellationToken): Thenable<modes.ISuggestResult> => {
@@ -287,7 +287,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- parameter hints
$registerSignatureHelpProvider(handle: number, selector: vscode.DocumentSelector, triggerCharacter: string[]): void {
$registerSignatureHelpProvider(handle: number, selector: ISerializedDocumentFilter[], triggerCharacter: string[]): void {
this._registrations[handle] = modes.SignatureHelpProviderRegistry.register(toLanguageSelector(selector), <modes.SignatureHelpProvider>{
signatureHelpTriggerCharacters: triggerCharacter,
@@ -301,7 +301,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- links
$registerDocumentLinkProvider(handle: number, selector: vscode.DocumentSelector): void {
$registerDocumentLinkProvider(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.LinkProviderRegistry.register(toLanguageSelector(selector), <modes.LinkProvider>{
provideLinks: (model, token) => {
return this._heapService.trackRecursive(wireCancellationToken(token, this._proxy.$provideDocumentLinks(handle, model.uri)));
@@ -314,7 +314,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- colors
$registerDocumentColorProvider(handle: number, selector: vscode.DocumentSelector): void {
$registerDocumentColorProvider(handle: number, selector: ISerializedDocumentFilter[]): void {
const proxy = this._proxy;
this._registrations[handle] = modes.ColorProviderRegistry.register(toLanguageSelector(selector), <modes.DocumentColorProvider>{
provideDocumentColors: (model, token) => {
@@ -348,7 +348,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- folding
$registerFoldingProvider(handle: number, selector: vscode.DocumentSelector): void {
$registerFoldingProvider(handle: number, selector: ISerializedDocumentFilter[]): void {
const proxy = this._proxy;
this._registrations[handle] = modes.FoldingProviderRegistry.register(toLanguageSelector(selector), <modes.FoldingProvider>{
provideFoldingRanges: (model, context, token) => {

View File

@@ -5,7 +5,7 @@
'use strict';
import { IProgressService2, IProgress, IProgressOptions, IProgressStep } from 'vs/platform/progress/common/progress';
import { MainThreadProgressShape, MainContext, IExtHostContext } from '../node/extHost.protocol';
import { MainThreadProgressShape, MainContext, IExtHostContext, ExtHostProgressShape, ExtHostContext } from '../node/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
@extHostNamedCustomer(MainContext.MainThreadProgress)
@@ -13,11 +13,13 @@ export class MainThreadProgress implements MainThreadProgressShape {
private _progressService: IProgressService2;
private _progress = new Map<number, { resolve: Function, progress: IProgress<IProgressStep> }>();
private _proxy: ExtHostProgressShape;
constructor(
extHostContext: IExtHostContext,
@IProgressService2 progressService: IProgressService2
) {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostProgress);
this._progressService = progressService;
}
@@ -28,7 +30,8 @@ export class MainThreadProgress implements MainThreadProgressShape {
$startProgress(handle: number, options: IProgressOptions): void {
const task = this._createTask(handle);
this._progressService.withProgress(options, task);
this._progressService.withProgress(options, task, () => this._proxy.$acceptProgressCanceled(handle));
}
$progressReport(handle: number, message: IProgressStep): void {

View File

@@ -7,6 +7,7 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { asWinJsPromise } from 'vs/base/common/async';
import { IQuickOpenService, IPickOptions, IInputOptions } from 'vs/platform/quickOpen/common/quickOpen';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { InputBoxOptions } from 'vscode';
import { ExtHostContext, MainThreadQuickOpenShape, ExtHostQuickOpenShape, MyQuickPickItems, MainContext, IExtHostContext } from '../node/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
@@ -16,6 +17,7 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
private _proxy: ExtHostQuickOpenShape;
private _quickOpenService: IQuickOpenService;
private _quickInputService: IQuickInputService;
private _doSetItems: (items: MyQuickPickItems[]) => any;
private _doSetError: (error: Error) => any;
private _contents: TPromise<MyQuickPickItems[]>;
@@ -23,16 +25,18 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
constructor(
extHostContext: IExtHostContext,
@IQuickOpenService quickOpenService: IQuickOpenService
@IQuickOpenService quickOpenService: IQuickOpenService,
@IQuickInputService quickInputService: IQuickInputService
) {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostQuickOpen);
this._quickOpenService = quickOpenService;
this._quickInputService = quickInputService;
}
public dispose(): void {
}
$show(options: IPickOptions): TPromise<number> {
$show(options: IPickOptions): TPromise<number | number[]> {
const myToken = ++this._token;
@@ -50,16 +54,29 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
};
});
return asWinJsPromise(token => this._quickOpenService.pick(this._contents, options, token)).then(item => {
if (item) {
return item.handle;
}
return undefined;
}, undefined, progress => {
if (progress) {
this._proxy.$onItemSelected((<MyQuickPickItems>progress).handle);
}
});
if (options.canSelectMany) {
return asWinJsPromise(token => this._quickInputService.pick(this._contents, options, token)).then(items => {
if (items) {
return items.map(item => item.handle);
}
return undefined;
}, undefined, progress => {
if (progress) {
this._proxy.$onItemSelected((<MyQuickPickItems>progress).handle);
}
});
} else {
return asWinJsPromise(token => this._quickOpenService.pick(this._contents, options, token)).then(item => {
if (item) {
return item.handle;
}
return undefined;
}, undefined, progress => {
if (progress) {
this._proxy.$onItemSelected((<MyQuickPickItems>progress).handle);
}
});
}
}
$setItems(items: MyQuickPickItems[]): TPromise<any> {

View File

@@ -28,6 +28,7 @@ import { IProgressService2, ProgressLocation } from 'vs/platform/progress/common
import { localize } from 'vs/nls';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { ILogService } from 'vs/platform/log/common/log';
import { shouldSynchronizeModel } from 'vs/editor/common/services/modelService';
export interface ISaveParticipantParticipant extends ISaveParticipant {
// progressMessage: string;
@@ -49,7 +50,7 @@ class TrimWhitespaceParticipant implements ISaveParticipantParticipant {
}
private doTrimTrailingWhitespace(model: ITextModel, isAutoSaved: boolean): void {
let prevSelection: Selection[] = [new Selection(1, 1, 1, 1)];
let prevSelection: Selection[] = [];
const cursors: Position[] = [];
let editor = findEditor(model, this.codeEditorService);
@@ -113,7 +114,7 @@ export class FinalNewLineParticipant implements ISaveParticipantParticipant {
return;
}
let prevSelection: Selection[] = [new Selection(1, 1, 1, 1)];
let prevSelection: Selection[] = [];
const editor = findEditor(model, this.codeEditorService);
if (editor) {
prevSelection = editor.getSelections();
@@ -150,7 +151,7 @@ export class TrimFinalNewLinesParticipant implements ISaveParticipantParticipant
return;
}
let prevSelection: Selection[] = [new Selection(1, 1, 1, 1)];
let prevSelection: Selection[] = [];
const editor = findEditor(model, this.codeEditorService);
if (editor) {
prevSelection = editor.getSelections();
@@ -200,7 +201,7 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant {
const timeout = this._configurationService.getValue('editor.formatOnSaveTimeout', { overrideIdentifier: model.getLanguageIdentifier().language, resource: editorModel.getResource() });
return new Promise<ISingleEditOperation[]>((resolve, reject) => {
setTimeout(reject, timeout);
setTimeout(() => reject(localize('timeout.formatOnSave', "Aborted format on save after {0}ms", timeout)), timeout);
getDocumentFormattingEdits(model, { tabSize, insertSpaces })
.then(edits => this._editorWorkerService.computeMoreMinimalEdits(model.uri, edits))
.then(resolve, err => {
@@ -224,7 +225,7 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant {
}
private _editsWithEditor(editor: ICodeEditor, edits: ISingleEditOperation[]): void {
EditOperationsCommand.execute(editor, edits, false);
EditOperationsCommand.execute(editor, edits);
}
private _editWithModel(model: ITextModel, edits: ISingleEditOperation[]): void {
@@ -261,14 +262,14 @@ class ExtHostSaveParticipant implements ISaveParticipantParticipant {
participate(editorModel: ITextFileEditorModel, env: { reason: SaveReason }): Promise<void> {
if (editorModel.textEditorModel.isTooLargeForHavingARichMode()) {
if (!shouldSynchronizeModel(editorModel.textEditorModel)) {
// the model never made it to the extension
// host meaning we cannot participate in its save
return undefined;
}
return new Promise<any>((resolve, reject) => {
setTimeout(reject, 1750);
setTimeout(() => reject(localize('timeout.onWillSave', "Aborted onWillSaveTextDocument-event after 1750ms")), 1750);
this._proxy.$participateInSave(editorModel.getResource(), env.reason).then(values => {
for (const success of values) {
if (!success) {
@@ -314,7 +315,7 @@ export class SaveParticipant implements ISaveParticipant {
const promiseFactory = this._saveParticipants.map(p => () => {
return Promise.resolve(p.participate(model, env));
});
return sequence(promiseFactory).then(() => { }, err => this._logService.error(err));
return sequence(promiseFactory).then(() => { }, err => this._logService.warn(err));
});
}
}

View File

@@ -4,16 +4,331 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as crypto from 'crypto';
import * as nls from 'vs/nls';
import URI from 'vs/base/common/uri';
import * as Objects from 'vs/base/common/objects';
import { TPromise } from 'vs/base/common/winjs.base';
import * as Types from 'vs/base/common/types';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { ContributedTask, ExtensionTaskSourceTransfer } from 'vs/workbench/parts/tasks/common/tasks';
import {
ContributedTask, ExtensionTaskSourceTransfer, TaskIdentifier, TaskExecution, Task, TaskEvent, TaskEventKind,
PresentationOptions, CommandOptions, CommandConfiguration, RuntimeType, CustomTask, TaskScope, TaskSource, TaskSourceKind, ExtensionTaskSource, RevealKind, PanelKind
} from 'vs/workbench/parts/tasks/common/tasks';
import { ITaskService } from 'vs/workbench/parts/tasks/common/taskService';
import { ExtHostContext, MainThreadTaskShape, ExtHostTaskShape, MainContext, IExtHostContext } from '../node/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import URI from 'vs/base/common/uri';
import { ExtHostContext, MainThreadTaskShape, ExtHostTaskShape, MainContext, IExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
import {
TaskDefinitionDTO, TaskExecutionDTO, ProcessExecutionOptionsDTO, TaskPresentationOptionsDTO,
ProcessExecutionDTO, ShellExecutionDTO, ShellExecutionOptionsDTO, TaskDTO, TaskSourceDTO, TaskHandleDTO
} from 'vs/workbench/api/shared/tasks';
export { TaskDTO, TaskHandleDTO, TaskExecutionDTO };
namespace TaskExecutionDTO {
export function from(value: TaskExecution): TaskExecutionDTO {
return {
id: value.id,
task: TaskDTO.from(value.task)
};
}
export function to(value: TaskExecutionDTO, workspace: IWorkspaceContextService): TaskExecution {
return {
id: value.id,
task: TaskDTO.to(value.task, workspace)
};
}
}
namespace TaskDefinitionDTO {
export function from(value: TaskIdentifier): TaskDefinitionDTO {
let result = Objects.assign(Object.create(null), value);
delete result._key;
return result;
}
export function to(value: TaskDefinitionDTO): TaskIdentifier {
const hash = crypto.createHash('md5');
hash.update(JSON.stringify(value));
let result = Objects.assign(Object.create(null), value);
result._key = hash.digest('hex');
return result;
}
}
namespace TaskPresentationOptionsDTO {
export function from(value: PresentationOptions): TaskPresentationOptionsDTO {
if (value === void 0 || value === null) {
return undefined;
}
return Objects.assign(Object.create(null), value);
}
export function to(value: TaskPresentationOptionsDTO): PresentationOptions {
if (value === void 0 || value === null) {
return undefined;
}
return Objects.assign(Object.create(null), value);
}
}
namespace ProcessExecutionOptionsDTO {
export function from(value: CommandOptions): ProcessExecutionOptionsDTO {
if (value === void 0 || value === null) {
return undefined;
}
return {
cwd: value.cwd,
env: value.env
};
}
export function to(value: ProcessExecutionOptionsDTO): CommandOptions {
if (value === void 0 || value === null) {
return undefined;
}
return {
cwd: value.cwd,
env: value.env
};
}
}
namespace ProcessExecutionDTO {
export function is(value: ShellExecutionDTO | ProcessExecutionDTO): value is ProcessExecutionDTO {
let candidate = value as ProcessExecutionDTO;
return candidate && !!candidate.process;
}
export function from(value: CommandConfiguration): ProcessExecutionDTO {
let process: string = Types.isString(value.name) ? value.name : value.name.value;
let args: string[] = value.args ? value.args.map(value => Types.isString(value) ? value : value.value) : [];
let result: ProcessExecutionDTO = {
process: process,
args: args
};
if (value.options) {
result.options = ProcessExecutionOptionsDTO.from(value.options);
}
return result;
}
export function to(value: ProcessExecutionDTO): CommandConfiguration {
let result: CommandConfiguration = {
runtime: RuntimeType.Process,
name: value.process,
args: value.args,
presentation: undefined
};
if (value.options) {
result.options = ProcessExecutionOptionsDTO.to(value.options);
}
return result;
}
}
namespace ShellExecutionOptionsDTO {
export function from(value: CommandOptions): ShellExecutionOptionsDTO {
if (value === void 0 || value === null) {
return undefined;
}
let result: ShellExecutionOptionsDTO = {
cwd: value.cwd,
env: value.env
};
if (value.shell) {
result.executable = value.shell.executable;
result.shellArgs = value.shell.args;
result.shellQuoting = value.shell.quoting;
}
return result;
}
export function to(value: ShellExecutionOptionsDTO): CommandOptions {
if (value === void 0 || value === null) {
return undefined;
}
let result: CommandOptions = {
cwd: value.cwd,
env: value.env
};
if (value.executable) {
result.shell = {
executable: value.executable
};
if (value.shellArgs) {
result.shell.args = value.shellArgs;
}
if (value.shellQuoting) {
result.shell.quoting = value.shellQuoting;
}
}
return result;
}
}
namespace ShellExecutionDTO {
export function is(value: ShellExecutionDTO | ProcessExecutionDTO): value is ShellExecutionDTO {
let candidate = value as ShellExecutionDTO;
return candidate && (!!candidate.commandLine || !!candidate.command);
}
export function from(value: CommandConfiguration): ShellExecutionDTO {
let result: ShellExecutionDTO = {};
if (value.name && Types.isString(value.name) && (value.args === void 0 || value.args === null || value.args.length === 0)) {
result.commandLine = value.name;
} else {
result.command = value.name;
result.args = value.args;
}
if (value.options) {
result.options = ShellExecutionOptionsDTO.from(value.options);
}
return result;
}
export function to(value: ShellExecutionDTO): CommandConfiguration {
let result: CommandConfiguration = {
runtime: RuntimeType.Shell,
name: value.commandLine ? value.commandLine : value.command,
args: value.args,
presentation: undefined
};
if (value.options) {
result.options = ShellExecutionOptionsDTO.to(value.options);
}
return result;
}
}
namespace TaskSourceDTO {
export function from(value: TaskSource): TaskSourceDTO {
let result: TaskSourceDTO = {
label: value.label
};
if (value.kind === TaskSourceKind.Extension) {
result.extensionId = value.extension;
if (value.workspaceFolder) {
result.scope = value.workspaceFolder.uri;
} else {
result.scope = value.scope;
}
} else if (value.kind === TaskSourceKind.Workspace) {
result.extensionId = '$core';
result.scope = value.config.workspaceFolder.uri;
}
return result;
}
export function to(value: TaskSourceDTO, workspace: IWorkspaceContextService): ExtensionTaskSource {
let scope: TaskScope;
let workspaceFolder: IWorkspaceFolder;
if (value.scope === void 0) {
if (workspace.getWorkspace().folders.length === 0) {
scope = TaskScope.Global;
workspaceFolder = undefined;
} else {
scope = TaskScope.Folder;
workspaceFolder = workspace.getWorkspace().folders[0];
}
} else if (typeof value.scope === 'number') {
scope = value.scope;
} else {
scope = TaskScope.Folder;
workspaceFolder = workspace.getWorkspaceFolder(URI.revive(value.scope));
}
let result: ExtensionTaskSource = {
kind: TaskSourceKind.Extension,
label: value.label,
extension: value.extensionId,
scope,
workspaceFolder
};
return result;
}
}
namespace TaskHandleDTO {
export function is(value: any): value is TaskHandleDTO {
let candidate: TaskHandleDTO = value;
return candidate && Types.isString(candidate.id) && !!candidate.workspaceFolder;
}
}
namespace TaskDTO {
export function from(task: Task): TaskDTO {
if (task === void 0 || task === null || (!CustomTask.is(task) && !ContributedTask.is(task))) {
return undefined;
}
let result: TaskDTO = {
_id: task._id,
name: task.name,
definition: TaskDefinitionDTO.from(Task.getTaskDefinition(task)),
source: TaskSourceDTO.from(task._source),
execution: undefined,
presentationOptions: task.command ? TaskPresentationOptionsDTO.from(task.command.presentation) : undefined,
isBackground: task.isBackground,
problemMatchers: [],
hasDefinedMatchers: ContributedTask.is(task) ? task.hasDefinedMatchers : false
};
if (task.group) {
result.group = task.group;
}
if (task.command) {
if (task.command.runtime === RuntimeType.Process) {
result.execution = ProcessExecutionDTO.from(task.command);
} else if (task.command.runtime === RuntimeType.Shell) {
result.execution = ShellExecutionDTO.from(task.command);
}
}
if (task.problemMatchers) {
for (let matcher of task.problemMatchers) {
if (Types.isString(matcher)) {
result.problemMatchers.push(matcher);
}
}
}
if (!result.execution) {
return undefined;
}
return result;
}
export function to(task: TaskDTO, workspace: IWorkspaceContextService): Task {
if (typeof task.name !== 'string') {
return undefined;
}
let command: CommandConfiguration;
if (ShellExecutionDTO.is(task.execution)) {
command = ShellExecutionDTO.to(task.execution);
} else if (ProcessExecutionDTO.is(task.execution)) {
command = ProcessExecutionDTO.to(task.execution);
}
if (!command) {
return undefined;
}
command.presentation = TaskPresentationOptionsDTO.to(task.presentationOptions);
command.presentation = Objects.assign(command.presentation || {}, { echo: true, reveal: RevealKind.Always, focus: false, panel: PanelKind.Shared });
let source = TaskSourceDTO.to(task.source, workspace);
let label = nls.localize('task.label', '{0}: {1}', source.label, task.name);
let definition = TaskDefinitionDTO.to(task.definition);
let id = `${task.source.extensionId}.${definition._key}`;
let result: ContributedTask = {
_id: id, // uuidMap.getUUID(identifier),
_source: source,
_label: label,
type: definition.type,
defines: definition,
name: task.name,
identifier: label,
group: task.group,
command: command,
isBackground: !!task.isBackground,
problemMatchers: task.problemMatchers.slice(),
hasDefinedMatchers: task.hasDefinedMatchers
};
return result;
}
}
@extHostNamedCustomer(MainContext.MainThreadTask)
export class MainThreadTask implements MainThreadTaskShape {
@@ -28,6 +343,14 @@ export class MainThreadTask implements MainThreadTaskShape {
) {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTask);
this._activeHandles = Object.create(null);
this._taskService.onDidStateChange((event: TaskEvent) => {
let task = event.__task;
if (event.kind === TaskEventKind.Start) {
this._proxy.$taskStarted(TaskExecutionDTO.from(Task.getTaskExecution(task)));
} else if (event.kind === TaskEventKind.End) {
this._proxy.$taskEnded(TaskExecutionDTO.from(Task.getTaskExecution(task)));
}
});
}
public dispose(): void {
@@ -63,4 +386,61 @@ export class MainThreadTask implements MainThreadTaskShape {
delete this._activeHandles[handle];
return TPromise.wrap<void>(undefined);
}
public $executeTaskProvider(): TPromise<TaskDTO[]> {
return this._taskService.tasks().then((tasks) => {
let result: TaskDTO[] = [];
for (let task of tasks) {
let item = TaskDTO.from(task);
if (item) {
result.push(item);
}
}
return result;
});
}
public $executeTask(value: TaskHandleDTO | TaskDTO): TPromise<TaskExecutionDTO> {
return new TPromise<TaskExecutionDTO>((resolve, reject) => {
if (TaskHandleDTO.is(value)) {
let workspaceFolder = this._workspaceContextServer.getWorkspaceFolder(URI.revive(value.workspaceFolder));
this._taskService.getTask(workspaceFolder, value.id, true).then((task: Task) => {
this._taskService.run(task);
let result: TaskExecutionDTO = {
id: value.id,
task: TaskDTO.from(task)
};
resolve(result);
}, (error) => {
reject(new Error('Task not found'));
});
} else {
let task = TaskDTO.to(value, this._workspaceContextServer);
this._taskService.run(task);
let result: TaskExecutionDTO = {
id: task._id,
task: TaskDTO.from(task)
};
resolve(result);
}
});
}
public $terminateTask(id: string): TPromise<void> {
return new TPromise<void>((resolve, reject) => {
this._taskService.getActiveTasks().then((tasks) => {
for (let task of tasks) {
if (id === task._id) {
this._taskService.terminate(task).then((value) => {
resolve(undefined);
}, (error) => {
reject(undefined);
});
return;
}
}
reject(new Error('Task to terminate not found'));
});
});
}
}

View File

@@ -31,7 +31,12 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
$registerTreeViewDataProvider(treeViewId: string): void {
const dataProvider = this._register(new TreeViewDataProvider(treeViewId, this._proxy, this.notificationService));
this._dataProviders.set(treeViewId, dataProvider);
this.viewsService.getTreeViewer(treeViewId).dataProvider = dataProvider;
const treeViewer = this.viewsService.getTreeViewer(treeViewId);
if (treeViewer) {
treeViewer.dataProvider = dataProvider;
} else {
this.notificationService.error('No view is registered with id: ' + treeViewId);
}
}
$reveal(treeViewId: string, item: ITreeItem, parentChain: ITreeItem[], options?: { select?: boolean }): TPromise<void> {

View File

@@ -46,8 +46,15 @@ export class MainThreadWebviews implements MainThreadWebviewsShape {
this._toDispose = dispose(this._toDispose);
}
$createWebview(handle: WebviewHandle, uri: URI, title: string, column: Position, options: vscode.WebviewOptions, extensionFolderPath: string): void {
const webviewInput = new WebviewInput(URI.revive(uri), title, options, '', {
$createWebview(
handle: WebviewHandle,
viewType: string,
title: string,
column: Position,
options: vscode.WebviewOptions,
extensionFolderPath: string
): void {
const webviewInput = new WebviewInput(title, options, '', {
onMessage: message => this._proxy.$onMessage(handle, message),
onDidChangePosition: position => this._proxy.$onDidChangePosition(handle, position),
onDispose: () => {
@@ -80,7 +87,7 @@ export class MainThreadWebviews implements MainThreadWebviewsShape {
webview.setHtml(value);
}
$show(handle: WebviewHandle, column: Position): void {
$reveal(handle: WebviewHandle, column: Position): void {
const webviewInput = this.getWebview(handle);
if (webviewInput.position === column) {
this._editorService.openEditor(webviewInput, { preserveFocus: true }, column);

View File

@@ -9,6 +9,7 @@ import { IWindowService } from 'vs/platform/windows/common/windows';
import { MainThreadWindowShape, ExtHostWindowShape, ExtHostContext, MainContext, IExtHostContext } from '../node/extHost.protocol';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { latch } from 'vs/base/common/event';
@extHostNamedCustomer(MainContext.MainThreadWindow)
export class MainThreadWindow implements MainThreadWindowShape {
@@ -22,7 +23,8 @@ export class MainThreadWindow implements MainThreadWindowShape {
) {
this.proxy = extHostContext.getProxy(ExtHostContext.ExtHostWindow);
windowService.onDidChangeFocus(this.proxy.$onDidChangeWindowFocus, this.proxy, this.disposables);
latch(windowService.onDidChangeFocus)
(this.proxy.$onDidChangeWindowFocus, this.proxy, this.disposables);
}
$getWindowVisibility(): TPromise<boolean> {

View File

@@ -98,7 +98,7 @@ export function createApiFactory(
const extHostHeapService = rpcProtocol.set(ExtHostContext.ExtHostHeapService, new ExtHostHeapService());
const extHostDecorations = rpcProtocol.set(ExtHostContext.ExtHostDecorations, new ExtHostDecorations(rpcProtocol));
const extHostWebviews = rpcProtocol.set(ExtHostContext.ExtHostWebviews, new ExtHostWebviews(rpcProtocol));
const extHostDocumentsAndEditors = rpcProtocol.set(ExtHostContext.ExtHostDocumentsAndEditors, new ExtHostDocumentsAndEditors(rpcProtocol, extHostWebviews));
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, extHostLogService));
const extHostDocumentSaveParticipant = rpcProtocol.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(extHostLogService, extHostDocuments, rpcProtocol.getProxy(MainContext.MainThreadTextEditors)));
@@ -118,6 +118,7 @@ export function createApiFactory(
const extHostTask = rpcProtocol.set(ExtHostContext.ExtHostTask, new ExtHostTask(rpcProtocol, extHostWorkspace));
const extHostWindow = rpcProtocol.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(rpcProtocol));
rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService);
const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress)));
// Check that no named customers are missing
const expected: ProxyIdentifier<any>[] = Object.keys(ExtHostContext).map((key) => ExtHostContext[key]);
@@ -127,12 +128,11 @@ export function createApiFactory(
const extHostMessageService = new ExtHostMessageService(rpcProtocol);
const extHostDialogs = new ExtHostDialogs(rpcProtocol);
const extHostStatusBar = new ExtHostStatusBar(rpcProtocol);
const extHostProgress = new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress));
const extHostOutputService = new ExtHostOutputService(rpcProtocol);
const extHostLanguages = new ExtHostLanguages(rpcProtocol);
// Register API-ish commands
ExtHostApiCommands.register(extHostCommands, extHostWorkspace);
ExtHostApiCommands.register(extHostCommands, extHostTask);
return function (extension: IExtensionDescription): typeof vscode {
@@ -161,10 +161,10 @@ export function createApiFactory(
// namespace: commands
const commands: typeof vscode.commands = {
registerCommand(id: string, command: <T>(...args: any[]) => T | Thenable<T>, thisArgs?: any): vscode.Disposable {
return extHostCommands.registerCommand(id, command, thisArgs);
return extHostCommands.registerCommand(true, id, command, thisArgs);
},
registerTextEditorCommand(id: string, callback: (textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit, ...args: any[]) => void, thisArg?: any): vscode.Disposable {
return extHostCommands.registerCommand(id, (...args: any[]): any => {
return extHostCommands.registerCommand(true, id, (...args: any[]): any => {
let activeTextEditor = extHostEditors.getActiveTextEditor();
if (!activeTextEditor) {
console.warn('Cannot execute ' + id + ' because there is no active text editor.');
@@ -185,7 +185,7 @@ export function createApiFactory(
});
},
registerDiffInformationCommand: proposedApiFunction(extension, (id: string, callback: (diff: vscode.LineChange[], ...args: any[]) => any, thisArg?: any): vscode.Disposable => {
return extHostCommands.registerCommand(id, async (...args: any[]) => {
return extHostCommands.registerCommand(true, id, async (...args: any[]) => {
let activeTextEditor = extHostEditors.getActiveTextEditor();
if (!activeTextEditor) {
console.warn('Cannot execute ' + id + ' because there is no active text editor.');
@@ -211,6 +211,7 @@ export function createApiFactory(
get language() { return Platform.language; },
get appName() { return product.nameLong; },
get appRoot() { return initData.environment.appRoot; },
get logLevel() { return extHostLogService.getLevel(); }
});
// namespace: extensions
@@ -243,7 +244,7 @@ export function createApiFactory(
return extHostLanguages.getLanguages();
},
match(selector: vscode.DocumentSelector, document: vscode.TextDocument): number {
return score(toLanguageSelector(selector), document.uri, document.languageId);
return score(toLanguageSelector(selector), document.uri, document.languageId, true);
},
registerCodeActionsProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable {
return extHostLanguageFeatures.registerCodeActionProvider(selector, provider);
@@ -341,9 +342,9 @@ export function createApiFactory(
onDidChangeTextEditorOptions(listener: (e: vscode.TextEditorOptionsChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) {
return extHostEditors.onDidChangeTextEditorOptions(listener, thisArgs, disposables);
},
onDidChangeTextEditorVisibleRanges: proposedApiFunction(extension, (listener: (e: vscode.TextEditorVisibleRangesChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => {
onDidChangeTextEditorVisibleRanges(listener: (e: vscode.TextEditorVisibleRangesChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) {
return extHostEditors.onDidChangeTextEditorVisibleRanges(listener, thisArgs, disposables);
}),
},
onDidChangeTextEditorViewColumn(listener, thisArg?, disposables?) {
return extHostEditors.onDidChangeTextEditorViewColumn(listener, thisArg, disposables);
},
@@ -365,7 +366,7 @@ export function createApiFactory(
showErrorMessage(message, first, ...rest) {
return extHostMessageService.showMessage(extension, Severity.Error, message, first, rest);
},
showQuickPick(items: any, options: vscode.QuickPickOptions, token?: vscode.CancellationToken) {
showQuickPick(items: any, options: vscode.QuickPickOptions, token?: vscode.CancellationToken): any {
return extHostQuickOpen.showQuickPick(items, options, token);
},
showWorkspaceFolderPick(options: vscode.WorkspaceFolderPickOptions) {
@@ -390,7 +391,7 @@ export function createApiFactory(
console.warn(`[Deprecation Warning] function 'withScmProgress' is deprecated and should no longer be used. Use 'withProgress' instead.`);
return extHostProgress.withProgress(extension, { location: extHostTypes.ProgressLocation.SourceControl }, (progress, token) => task({ report(n: number) { /*noop*/ } }));
},
withProgress<R>(options: vscode.ProgressOptions, task: (progress: vscode.Progress<{ message?: string; percentage?: number }>) => Thenable<R>) {
withProgress<R>(options: vscode.ProgressOptions, task: (progress: vscode.Progress<{ message?: string; worked?: number }>, token: vscode.CancellationToken) => Thenable<R>) {
return extHostProgress.withProgress(extension, options, task);
},
createOutputChannel(name: string): vscode.OutputChannel {
@@ -402,8 +403,11 @@ export function createApiFactory(
}
return extHostTerminalService.createTerminal(<string>nameOrOptions, shellPath, shellArgs);
},
registerTreeDataProvider(viewId: string, treeDataProvider: vscode.TreeDataProvider<any>): vscode.TreeView<any> {
return extHostTreeViews.registerTreeDataProvider(viewId, treeDataProvider, (fn) => proposedApiFunction(extension, fn));
registerTreeDataProvider(viewId: string, treeDataProvider: vscode.TreeDataProvider<any>): vscode.Disposable {
return extHostTreeViews.registerTreeDataProvider(viewId, treeDataProvider);
},
createTreeView(viewId: string, options: { treeDataProvider: vscode.TreeDataProvider<any> }): vscode.TreeView<any> {
return extHostTreeViews.createTreeView(viewId, options);
},
// proposed API
sampleFunction: proposedApiFunction(extension, () => {
@@ -412,11 +416,8 @@ export function createApiFactory(
registerDecorationProvider: proposedApiFunction(extension, (provider: vscode.DecorationProvider) => {
return extHostDecorations.registerDecorationProvider(provider, extension.id);
}),
createWebview: proposedApiFunction(extension, (uri: vscode.Uri, title: string, column: vscode.ViewColumn, options: vscode.WebviewOptions) => {
return extHostWebviews.createWebview(uri, title, column, options, extension.extensionFolderPath);
}),
onDidChangeActiveEditor: proposedApiFunction(extension, (listener, thisArg?, disposables?) => {
return extHostDocumentsAndEditors.onDidChangeActiveEditor(listener, thisArg, disposables);
createWebview: proposedApiFunction(extension, (viewType: string, title: string, column: vscode.ViewColumn, options: vscode.WebviewOptions) => {
return extHostWebviews.createWebview(viewType, title, column, options, extension.extensionFolderPath);
})
};
@@ -516,8 +517,29 @@ export function createApiFactory(
registerTaskProvider: (type: string, provider: vscode.TaskProvider) => {
return extHostTask.registerTaskProvider(extension, provider);
},
registerFileSystemProvider: proposedApiFunction(extension, (authority, provider) => {
return extHostFileSystem.registerFileSystemProvider(authority, provider);
// fetchTasks: proposedApiFunction(extension, (): Thenable<vscode.Task[]> => {
// return extHostTask.executeTaskProvider();
// }),
// executeTask: proposedApiFunction(extension, (task: vscode.Task): Thenable<vscode.TaskExecution> => {
// return extHostTask.executeTask(extension, task);
// }),
fetchTasks: (): Thenable<vscode.Task[]> => {
return extHostTask.executeTaskProvider();
},
executeTask: (task: vscode.Task): Thenable<vscode.TaskExecution> => {
return extHostTask.executeTask(extension, task);
},
onDidStartTask: (listeners, thisArgs?, disposables?) => {
return extHostTask.onDidStartTask(listeners, thisArgs, disposables);
},
onDidEndTask: (listeners, thisArgs?, disposables?) => {
return extHostTask.onDidEndTask(listeners, thisArgs, disposables);
},
registerFileSystemProvider: proposedApiFunction(extension, (scheme, provider) => {
return extHostFileSystem.registerFileSystemProvider(scheme, provider);
}),
registerSearchProvider: proposedApiFunction(extension, (scheme, provider) => {
return extHostFileSystem.registerSearchProvider(scheme, provider);
})
};
@@ -616,7 +638,6 @@ export function createApiFactory(
ParameterInformation: extHostTypes.ParameterInformation,
Position: extHostTypes.Position,
Range: extHostTypes.Range,
RenameContext: extHostTypes.RenameContext,
Selection: extHostTypes.Selection,
SignatureHelp: extHostTypes.SignatureHelp,
SignatureInformation: extHostTypes.SignatureInformation,

View File

@@ -44,11 +44,11 @@ import { IDisposable } from 'vs/base/common/lifecycle';
import { SerializedError } from 'vs/base/common/errors';
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 { ISingleEditOperation } from 'vs/editor/common/model';
import { ILineMatch, IPatternInfo } from 'vs/platform/search/common/search';
import { LogLevel } from 'vs/platform/log/common/log';
import { TaskExecutionDTO, TaskDTO, TaskHandleDTO } from 'vs/workbench/api/shared/tasks';
export interface IEnvironment {
isExtensionDevelopmentDebug: boolean;
@@ -57,7 +57,6 @@ export interface IEnvironment {
appRoot: string;
appSettingsHome: string;
disableExtensions: boolean;
userExtensionsHome: string;
extensionDevelopmentPath: string;
extensionTestsPath: string;
}
@@ -77,9 +76,8 @@ export interface IInitData {
configuration: IConfigurationInitData;
telemetryInfo: ITelemetryInfo;
windowId: number;
args: ParsedArgs;
execPath: string;
logLevel: LogLevel;
logsPath: string;
}
export interface IConfigurationInitData extends IConfigurationData {
@@ -257,28 +255,35 @@ export interface ISerializedLanguageConfiguration {
};
}
export interface ISerializedDocumentFilter {
$serialized: true;
language?: string;
scheme?: string;
pattern?: vscode.GlobPattern;
}
export interface MainThreadLanguageFeaturesShape extends IDisposable {
$unregister(handle: number): void;
$registerOutlineSupport(handle: number, selector: vscode.DocumentSelector): void;
$registerCodeLensSupport(handle: number, selector: vscode.DocumentSelector, eventHandle: number): void;
$registerOutlineSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerCodeLensSupport(handle: number, selector: ISerializedDocumentFilter[], eventHandle: number): void;
$emitCodeLensEvent(eventHandle: number, event?: any): void;
$registerDeclaractionSupport(handle: number, selector: vscode.DocumentSelector): void;
$registerImplementationSupport(handle: number, selector: vscode.DocumentSelector): void;
$registerTypeDefinitionSupport(handle: number, selector: vscode.DocumentSelector): void;
$registerHoverProvider(handle: number, selector: vscode.DocumentSelector): void;
$registerDocumentHighlightProvider(handle: number, selector: vscode.DocumentSelector): void;
$registerReferenceSupport(handle: number, selector: vscode.DocumentSelector): void;
$registerQuickFixSupport(handle: number, selector: vscode.DocumentSelector): void;
$registerDocumentFormattingSupport(handle: number, selector: vscode.DocumentSelector): void;
$registerRangeFormattingSupport(handle: number, selector: vscode.DocumentSelector): void;
$registerOnTypeFormattingSupport(handle: number, selector: vscode.DocumentSelector, autoFormatTriggerCharacters: string[]): void;
$registerDeclaractionSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerImplementationSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerTypeDefinitionSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerHoverProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerDocumentHighlightProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerReferenceSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerQuickFixSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerDocumentFormattingSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerRangeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerOnTypeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[], autoFormatTriggerCharacters: string[]): void;
$registerNavigateTypeSupport(handle: number): void;
$registerRenameSupport(handle: number, selector: vscode.DocumentSelector, supportsResolveInitialValues: boolean): void;
$registerSuggestSupport(handle: number, selector: vscode.DocumentSelector, triggerCharacters: string[], supportsResolveDetails: boolean): void;
$registerSignatureHelpProvider(handle: number, selector: vscode.DocumentSelector, triggerCharacter: string[]): void;
$registerDocumentLinkProvider(handle: number, selector: vscode.DocumentSelector): void;
$registerDocumentColorProvider(handle: number, selector: vscode.DocumentSelector): void;
$registerFoldingProvider(handle: number, selector: vscode.DocumentSelector): void;
$registerRenameSupport(handle: number, selector: ISerializedDocumentFilter[], supportsResolveInitialValues: boolean): void;
$registerSuggestSupport(handle: number, selector: ISerializedDocumentFilter[], triggerCharacters: string[], supportsResolveDetails: boolean): void;
$registerSignatureHelpProvider(handle: number, selector: ISerializedDocumentFilter[], triggerCharacter: string[]): void;
$registerDocumentLinkProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerDocumentColorProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerFoldingProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
$setLanguageConfiguration(handle: number, languageId: string, configuration: ISerializedLanguageConfiguration): void;
}
@@ -322,7 +327,7 @@ export interface MyQuickPickItems extends IPickOpenEntry {
handle: number;
}
export interface MainThreadQuickOpenShape extends IDisposable {
$show(options: IPickOptions): TPromise<number>;
$show(options: IPickOptions): TPromise<number | number[]>;
$setItems(items: MyQuickPickItems[]): TPromise<any>;
$setError(error: Error): TPromise<any>;
$input(options: vscode.InputBoxOptions, validateInput: boolean): TPromise<string>;
@@ -345,9 +350,9 @@ export interface MainThreadTelemetryShape extends IDisposable {
export type WebviewHandle = number;
export interface MainThreadWebviewsShape extends IDisposable {
$createWebview(handle: WebviewHandle, uri: URI, title: string, column: EditorPosition, options: vscode.WebviewOptions, extensionFolderPath: string): void;
$createWebview(handle: WebviewHandle, viewType: string, title: string, column: EditorPosition, options: vscode.WebviewOptions, extensionFolderPath: string): void;
$disposeWebview(handle: WebviewHandle): void;
$show(handle: WebviewHandle, column: EditorPosition): void;
$reveal(handle: WebviewHandle, column: EditorPosition): void;
$setTitle(handle: WebviewHandle, value: string): void;
$setHtml(handle: WebviewHandle, value: string): void;
$sendMessage(handle: WebviewHandle, value: any): Thenable<boolean>;
@@ -373,9 +378,9 @@ export interface IFileChangeDto {
export interface MainThreadFileSystemShape extends IDisposable {
$registerFileSystemProvider(handle: number, scheme: string): void;
$unregisterFileSystemProvider(handle: number): void;
$registerSearchProvider(handle: number, scheme: string): void;
$unregisterProvider(handle: number): void;
$onDidAddFileSystemRoot(root: UriComponents): void;
$onFileSystemChange(handle: number, resource: IFileChangeDto[]): void;
$reportFileChunk(handle: number, session: number, chunk: number[] | null): void;
@@ -384,6 +389,9 @@ export interface MainThreadFileSystemShape extends IDisposable {
export interface MainThreadTaskShape extends IDisposable {
$registerTaskProvider(handle: number): TPromise<void>;
$executeTaskProvider(): TPromise<TaskDTO[]>;
$executeTask(task: TaskHandleDTO | TaskDTO): TPromise<TaskExecutionDTO>;
$terminateTask(id: string): TPromise<void>;
$unregisterTaskProvider(handle: number): TPromise<void>;
}
@@ -559,7 +567,7 @@ export interface ExtHostFileSystemShape {
$mkdir(handle: number, resource: UriComponents): TPromise<IStat>;
$readdir(handle: number, resource: UriComponents): TPromise<[UriComponents, IStat][]>;
$rmdir(handle: number, resource: UriComponents): TPromise<void>;
$findFiles(handle: number, session: number, query: string): TPromise<void>;
$provideFileSearchResults(handle: number, session: number, query: string): TPromise<void>;
$provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, options: { includes: string[], excludes: string[] }): TPromise<void>;
}
@@ -692,7 +700,7 @@ export interface ExtHostLanguageFeaturesShape {
$resolveWorkspaceSymbol(handle: number, symbol: SymbolInformationDto): TPromise<SymbolInformationDto>;
$releaseWorkspaceSymbols(handle: number, id: number): void;
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string): TPromise<WorkspaceEditDto>;
$resolveRenameContext(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.RenameContext>;
$resolveRenameLocation(handle: number, resource: UriComponents, position: IPosition): TPromise<IRange>;
$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.SuggestContext): TPromise<SuggestResultDto>;
$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion>;
$releaseCompletionItems(handle: number, id: number): void;
@@ -723,6 +731,8 @@ export interface ExtHostSCMShape {
export interface ExtHostTaskShape {
$provideTasks(handle: number): TPromise<TaskSet>;
$taskStarted(execution: TaskExecutionDTO): void;
$taskEnded(execution: TaskExecutionDTO): void;
}
export interface IBreakpointDto {
@@ -799,6 +809,10 @@ export interface ExtHostLogServiceShape {
$setLevel(level: LogLevel);
}
export interface ExtHostProgressShape {
$acceptProgressCanceled(handle: number): void;
}
// --- proxy identifiers
export const MainContext = {
@@ -856,5 +870,6 @@ export const ExtHostContext = {
ExtHostTask: createExtId<ExtHostTaskShape>('ExtHostTask'),
ExtHostWorkspace: createExtId<ExtHostWorkspaceShape>('ExtHostWorkspace'),
ExtHostWindow: createExtId<ExtHostWindowShape>('ExtHostWindow'),
ExtHostWebviews: createExtId<ExtHostWebviewsShape>('ExtHostWebviews')
ExtHostWebviews: createExtId<ExtHostWebviewsShape>('ExtHostWebviews'),
ExtHostProgress: createMainId<ExtHostProgressShape>('ExtHostProgress')
};

View File

@@ -6,11 +6,12 @@
import URI from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import * as Objects from 'vs/base/common/objects';
import { IDisposable } from 'vs/base/common/lifecycle';
import * as vscode from 'vscode';
import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters';
import * as types from 'vs/workbench/api/node/extHostTypes';
import { IRawColorInfo } from 'vs/workbench/api/node/extHost.protocol';
import { ISingleEditOperation } from 'vs/editor/common/model';
import * as modes from 'vs/editor/common/modes';
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
@@ -18,22 +19,21 @@ import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import { IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search';
import { Position as EditorPosition, ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { CustomCodeAction } from 'vs/workbench/api/node/extHostLanguageFeatures';
import * as TaskSystem from 'vs/workbench/parts/tasks/common/tasks';
import { ExtHostWorkspace } from './extHostWorkspace';
import { ExtHostTask } from './extHostTask';
export class ExtHostApiCommands {
static register(commands: ExtHostCommands, workspace: ExtHostWorkspace) {
static register(commands: ExtHostCommands, workspace: ExtHostTask) {
return new ExtHostApiCommands(commands, workspace).registerCommands();
}
private _commands: ExtHostCommands;
private _workspace: ExtHostWorkspace;
private _tasks: ExtHostTask;
private _disposables: IDisposable[] = [];
private constructor(commands: ExtHostCommands, workspace: ExtHostWorkspace) {
private constructor(commands: ExtHostCommands, task: ExtHostTask) {
this._commands = commands;
this._workspace = workspace;
this._tasks = task;
}
registerCommands() {
@@ -179,7 +179,21 @@ export class ExtHostApiCommands {
args: [],
returns: 'An array of task handles'
});
this._register('vscode.executeDocumentColorProvider', this._executeDocumentColorProvider, {
description: 'Execute document color provider.',
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
],
returns: 'A promise that resolves to an array of ColorInformation objects.'
});
this._register('vscode.executeColorPresentationProvider', this._executeColorPresentationProvider, {
description: 'Execute color presentation provider.',
args: [
{ name: 'color', description: 'The color to show and insert', constraint: types.Color },
{ name: 'context', description: 'Context object with uri and range' }
],
returns: 'A promise that resolves to an array of ColorPresentation objects.'
});
this._register('vscode.previewHtml', (uri: URI, position?: vscode.ViewColumn, label?: string, options?: any) => {
return this._commands.executeCommand('_workbench.previewHtml',
uri,
@@ -271,7 +285,7 @@ export class ExtHostApiCommands {
// --- command impl
private _register(id: string, handler: (...args: any[]) => any, description?: ICommandHandlerDescription): void {
let disposable = this._commands.registerCommand(id, handler, this, description);
let disposable = this._commands.registerCommand(false, id, handler, this, description);
this._disposables.push(disposable);
}
@@ -393,6 +407,32 @@ export class ExtHostApiCommands {
});
}
private _executeDocumentColorProvider(resource: URI): Thenable<types.ColorInformation[]> {
const args = {
resource
};
return this._commands.executeCommand<IRawColorInfo[]>('_executeDocumentColorProvider', args).then(result => {
if (result) {
return result.map(ci => ({ range: typeConverters.toRange(ci.range), color: typeConverters.Color.to(ci.color) }));
}
return [];
});
}
private _executeColorPresentationProvider(color: types.Color, context: { uri: URI, range: types.Range }): Thenable<types.ColorPresentation[]> {
const args = {
resource: context.uri,
color: typeConverters.Color.from(color),
range: typeConverters.fromRange(context.range),
};
return this._commands.executeCommand<modes.IColorPresentation[]>('_executeColorPresentationProvider', args).then(result => {
if (result) {
return result.map(typeConverters.ColorPresentation.to);
}
return [];
});
}
private _executeDocumentSymbolProvider(resource: URI): Thenable<types.SymbolInformation[]> {
const args = {
resource
@@ -476,29 +516,8 @@ export class ExtHostApiCommands {
.then(tryMapWith(typeConverters.DocumentLink.to));
}
private _executeTaskProvider(): Thenable<vscode.TaskItem[]> {
return this._commands.executeCommand<TaskSystem.TaskItemTransfer[]>('_executeTaskProvider').then<vscode.TaskItem[]>((values) => {
let workspace = this._workspace;
return values.map(handle => {
let definition: vscode.TaskDefinition = Objects.assign(Object.create(null), handle.definition);
delete definition._key;
let uri = URI.revive(handle.workspaceFolderUri);
return new class {
get id(): string {
return handle.id;
}
get label(): string {
return handle.label;
}
get definition(): vscode.TaskDefinition {
return definition;
}
get workspaceFolder(): vscode.WorkspaceFolder {
return uri ? workspace.resolveWorkspaceFolder(uri) : undefined;
}
};
});
});
private _executeTaskProvider(): Thenable<vscode.Task[]> {
return this._tasks.executeTaskProvider();
}
}

View File

@@ -54,7 +54,7 @@ export class ExtHostCommands implements ExtHostCommandsShape {
this._argumentProcessors.push(processor);
}
registerCommand(id: string, callback: <T>(...args: any[]) => T | Thenable<T>, thisArg?: any, description?: ICommandHandlerDescription): extHostTypes.Disposable {
registerCommand(global: boolean, id: string, callback: <T>(...args: any[]) => T | Thenable<T>, thisArg?: any, description?: ICommandHandlerDescription): extHostTypes.Disposable {
this._logService.trace('ExtHostCommands#registerCommand', id);
if (!id.trim().length) {
@@ -66,11 +66,15 @@ export class ExtHostCommands implements ExtHostCommandsShape {
}
this._commands.set(id, { callback, thisArg, description });
this._proxy.$registerCommand(id);
if (global) {
this._proxy.$registerCommand(id);
}
return new extHostTypes.Disposable(() => {
if (this._commands.delete(id)) {
this._proxy.$unregisterCommand(id);
if (global) {
this._proxy.$unregisterCommand(id);
}
}
});
}
@@ -161,15 +165,16 @@ export class ExtHostCommands implements ExtHostCommandsShape {
export class CommandsConverter {
private readonly _delegatingCommandId: string;
private _commands: ExtHostCommands;
private _heap: ExtHostHeapService;
// --- conversion between internal and api commands
constructor(commands: ExtHostCommands, heap: ExtHostHeapService) {
this._delegatingCommandId = `_internal_command_delegation_${Date.now()}`;
this._commands = commands;
this._heap = heap;
this._commands.registerCommand('_internal_command_delegation', this._executeConvertedCommand, this);
this._commands.registerCommand(true, this._delegatingCommandId, this._executeConvertedCommand, this);
}
toInternal(command: vscode.Command): modes.Command {
@@ -190,7 +195,7 @@ export class CommandsConverter {
const id = this._heap.keep(command);
ObjectIdentifier.mixin(result, id);
result.id = '_internal_command_delegation';
result.id = this._delegatingCommandId;
result.arguments = [id];
}

View File

@@ -12,7 +12,6 @@ import { ExtHostTextEditor } from './extHostTextEditor';
import * as assert from 'assert';
import * as typeConverters from './extHostTypeConverters';
import URI from 'vs/base/common/uri';
import { ExtHostWebview, ExtHostWebviews } from './extHostWebview';
import { Disposable } from './extHostTypes';
export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsShape {
@@ -20,7 +19,6 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
private _disposables: Disposable[] = [];
private _activeEditorId: string;
private _activeWebview: ExtHostWebview;
private readonly _editors = new Map<string, ExtHostTextEditor>();
private readonly _documents = new Map<string, ExtHostDocumentData>();
@@ -29,31 +27,15 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
private readonly _onDidRemoveDocuments = new Emitter<ExtHostDocumentData[]>();
private readonly _onDidChangeVisibleTextEditors = new Emitter<ExtHostTextEditor[]>();
private readonly _onDidChangeActiveTextEditor = new Emitter<ExtHostTextEditor>();
private readonly _onDidChangeActiveEditor = new Emitter<ExtHostTextEditor | ExtHostWebview>();
readonly onDidAddDocuments: Event<ExtHostDocumentData[]> = this._onDidAddDocuments.event;
readonly onDidRemoveDocuments: Event<ExtHostDocumentData[]> = this._onDidRemoveDocuments.event;
readonly onDidChangeVisibleTextEditors: Event<ExtHostTextEditor[]> = this._onDidChangeVisibleTextEditors.event;
readonly onDidChangeActiveTextEditor: Event<ExtHostTextEditor> = this._onDidChangeActiveTextEditor.event;
readonly onDidChangeActiveEditor: Event<ExtHostTextEditor | ExtHostWebview> = this._onDidChangeActiveEditor.event;
constructor(
private readonly _mainContext: IMainContext,
_extHostWebviews?: ExtHostWebviews
) {
if (_extHostWebviews) {
_extHostWebviews.onDidChangeActiveWebview(webview => {
if (webview) {
if (webview !== this._activeWebview) {
this._onDidChangeActiveEditor.fire(webview);
this._activeWebview = webview;
}
} else {
this._activeWebview = webview;
}
}, this, this._disposables);
}
}
) { }
dispose() {
this._disposables = dispose(this._disposables);
@@ -143,9 +125,6 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
}
if (delta.newActiveEditor !== undefined) {
this._onDidChangeActiveTextEditor.fire(this.activeEditor());
const activeEditor = this.activeEditor();
this._onDidChangeActiveEditor.fire(activeEditor || this._activeWebview);
}
}

View File

@@ -20,7 +20,6 @@ import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { TernarySearchTree } from 'vs/base/common/map';
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';
@@ -140,8 +139,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
extHostContext: IExtHostContext,
extHostWorkspace: ExtHostWorkspace,
extHostConfiguration: ExtHostConfiguration,
extHostLogService: ExtHostLogService,
environmentService: IEnvironmentService
extHostLogService: ExtHostLogService
) {
this._barrier = new Barrier();
this._registry = new ExtensionDescriptionRegistry(initData.extensions);
@@ -426,6 +424,7 @@ function getTelemetryActivationEvent(extensionDescription: IExtensionDescription
"id": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
"name": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
"publisherDisplayName": { "classification": "PublicPersonalData", "purpose": "FeatureInsight" },
"galleryPublisherDisplayName": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
"activationEvents": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"isBuiltin": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
@@ -434,6 +433,7 @@ function getTelemetryActivationEvent(extensionDescription: IExtensionDescription
id: extensionDescription.id,
name: extensionDescription.name,
publisherDisplayName: extensionDescription.publisher,
galleryPublisherDisplayName: extensionDescription.publisher,
activationEvents: extensionDescription.activationEvents ? extensionDescription.activationEvents.join(',') : null,
isBuiltin: extensionDescription.isBuiltin
};

View File

@@ -58,7 +58,8 @@ class FsLinkProvider implements vscode.DocumentLinkProvider {
export class ExtHostFileSystem implements ExtHostFileSystemShape {
private readonly _proxy: MainThreadFileSystemShape;
private readonly _provider = new Map<number, vscode.FileSystemProvider>();
private readonly _fsProvider = new Map<number, vscode.FileSystemProvider>();
private readonly _searchProvider = new Map<number, vscode.SearchProvider>();
private readonly _linkProvider = new FsLinkProvider();
private _handlePool: number = 0;
@@ -71,12 +72,8 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
registerFileSystemProvider(scheme: string, provider: vscode.FileSystemProvider) {
const handle = this._handlePool++;
this._linkProvider.add(scheme);
this._provider.set(handle, provider);
this._fsProvider.set(handle, provider);
this._proxy.$registerFileSystemProvider(handle, scheme);
if (provider.root) {
// todo@remote
this._proxy.$onDidAddFileSystemRoot(provider.root);
}
let reg: IDisposable;
if (provider.onDidChange) {
reg = provider.onDidChange(event => this._proxy.$onFileSystemChange(handle, <any>event));
@@ -87,17 +84,29 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
reg.dispose();
}
this._linkProvider.delete(scheme);
this._provider.delete(handle);
this._proxy.$unregisterFileSystemProvider(handle);
this._fsProvider.delete(handle);
this._proxy.$unregisterProvider(handle);
}
};
}
registerSearchProvider(scheme: string, provider: vscode.SearchProvider) {
const handle = this._handlePool++;
this._searchProvider.set(handle, provider);
this._proxy.$registerSearchProvider(handle, scheme);
return {
dispose: () => {
this._searchProvider.delete(handle);
this._proxy.$unregisterProvider(handle);
}
};
}
$utimes(handle: number, resource: UriComponents, mtime: number, atime: number): TPromise<IStat, any> {
return asWinJsPromise(token => this._provider.get(handle).utimes(URI.revive(resource), mtime, atime));
return asWinJsPromise(token => this._fsProvider.get(handle).utimes(URI.revive(resource), mtime, atime));
}
$stat(handle: number, resource: UriComponents): TPromise<IStat, any> {
return asWinJsPromise(token => this._provider.get(handle).stat(URI.revive(resource)));
return asWinJsPromise(token => this._fsProvider.get(handle).stat(URI.revive(resource)));
}
$read(handle: number, session: number, offset: number, count: number, resource: UriComponents): TPromise<number> {
const progress = {
@@ -105,29 +114,29 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
this._proxy.$reportFileChunk(handle, session, [].slice.call(chunk));
}
};
return asWinJsPromise(token => this._provider.get(handle).read(URI.revive(resource), offset, count, progress));
return asWinJsPromise(token => this._fsProvider.get(handle).read(URI.revive(resource), offset, count, progress));
}
$write(handle: number, resource: UriComponents, content: number[]): TPromise<void, any> {
return asWinJsPromise(token => this._provider.get(handle).write(URI.revive(resource), Buffer.from(content)));
return asWinJsPromise(token => this._fsProvider.get(handle).write(URI.revive(resource), Buffer.from(content)));
}
$unlink(handle: number, resource: UriComponents): TPromise<void, any> {
return asWinJsPromise(token => this._provider.get(handle).unlink(URI.revive(resource)));
return asWinJsPromise(token => this._fsProvider.get(handle).unlink(URI.revive(resource)));
}
$move(handle: number, resource: UriComponents, target: UriComponents): TPromise<IStat, any> {
return asWinJsPromise(token => this._provider.get(handle).move(URI.revive(resource), URI.revive(target)));
return asWinJsPromise(token => this._fsProvider.get(handle).move(URI.revive(resource), URI.revive(target)));
}
$mkdir(handle: number, resource: UriComponents): TPromise<IStat, any> {
return asWinJsPromise(token => this._provider.get(handle).mkdir(URI.revive(resource)));
return asWinJsPromise(token => this._fsProvider.get(handle).mkdir(URI.revive(resource)));
}
$readdir(handle: number, resource: UriComponents): TPromise<[UriComponents, IStat][], any> {
return asWinJsPromise(token => this._provider.get(handle).readdir(URI.revive(resource)));
return asWinJsPromise(token => this._fsProvider.get(handle).readdir(URI.revive(resource)));
}
$rmdir(handle: number, resource: UriComponents): TPromise<void, any> {
return asWinJsPromise(token => this._provider.get(handle).rmdir(URI.revive(resource)));
return asWinJsPromise(token => this._fsProvider.get(handle).rmdir(URI.revive(resource)));
}
$findFiles(handle: number, session: number, query: string): TPromise<void> {
const provider = this._provider.get(handle);
if (!provider.findFiles) {
$provideFileSearchResults(handle: number, session: number, query: string): TPromise<void> {
const provider = this._searchProvider.get(handle);
if (!provider.provideFileSearchResults) {
return TPromise.as(undefined);
}
const progress = {
@@ -135,17 +144,17 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
this._proxy.$handleFindMatch(handle, session, uri);
}
};
return asWinJsPromise(token => provider.findFiles(query, progress, token));
return asWinJsPromise(token => provider.provideFileSearchResults(query, progress, token));
}
$provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, options: { includes: string[], excludes: string[] }): TPromise<void> {
const provider = this._provider.get(handle);
const provider = this._searchProvider.get(handle);
if (!provider.provideTextSearchResults) {
return TPromise.as(undefined);
}
const progress = {
report: (data: vscode.TextSearchResult) => {
this._proxy.$handleFindMatch(handle, session, [data.uri, {
lineNumber: 1 + data.range.start.line,
lineNumber: data.range.start.line,
preview: data.preview.leading + data.preview.matching + data.preview.trailing,
offsetAndLengths: [[data.preview.leading.length, data.preview.matching.length]]
}]);

View File

@@ -9,7 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { mixin } from 'vs/base/common/objects';
import * as vscode from 'vscode';
import * as TypeConverters from 'vs/workbench/api/node/extHostTypeConverters';
import { Range, Disposable, CompletionList, SnippetString, Color, CodeActionKind } from 'vs/workbench/api/node/extHostTypes';
import { Range, Disposable, CompletionList, SnippetString, CodeActionKind } from 'vs/workbench/api/node/extHostTypes';
import { ISingleEditOperation } from 'vs/editor/common/model';
import * as modes from 'vs/editor/common/modes';
import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
@@ -17,7 +17,7 @@ import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
import { ExtHostDiagnostics } 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, CodeActionDto } from './extHost.protocol';
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, SymbolInformationDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto, CodeActionDto, ISerializedDocumentFilter } 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';
@@ -467,7 +467,7 @@ class NavigateTypeAdapter {
class RenameAdapter {
static supportsResolving(provider: vscode.RenameProvider2): boolean {
return typeof provider.resolveRenameContext === 'function';
return typeof provider.resolveRenameLocation === 'function';
}
private _documents: ExtHostDocuments;
@@ -506,31 +506,27 @@ class RenameAdapter {
});
}
resolveRenameContext(resource: URI, position: IPosition): TPromise<modes.RenameContext> {
if (typeof this._provider.resolveRenameContext !== 'function') {
resolveRenameLocation(resource: URI, position: IPosition): TPromise<IRange> {
if (typeof this._provider.resolveRenameLocation !== 'function') {
return TPromise.as(undefined);
}
let doc = this._documents.getDocumentData(resource).document;
let pos = TypeConverters.toPosition(position);
return asWinJsPromise(token => this._provider.resolveRenameContext(doc, pos, token)).then(context => {
if (!context) {
return asWinJsPromise(token => this._provider.resolveRenameLocation(doc, pos, token)).then(range => {
if (!range) {
return undefined;
}
if (!context.range.contains(pos)) {
console.warn('INVALID rename information, must contain the request-position');
if (range && (!range.isSingleLine || range.start.line !== pos.line)) {
console.warn('INVALID rename context, range must be single line and on the same line');
return undefined;
}
return <modes.RenameContext>{
range: TypeConverters.fromRange(context.range),
text: context.newName || doc.getText(context.range)
};
return TypeConverters.fromRange(range);
});
}
}
class SuggestAdapter {
static supportsResolving(provider: vscode.CompletionItemProvider): boolean {
@@ -784,7 +780,7 @@ class ColorProviderAdapter {
const colorInfos: IRawColorInfo[] = colors.map(ci => {
return {
color: [ci.color.red, ci.color.green, ci.color.blue, ci.color.alpha] as [number, number, number, number],
color: TypeConverters.Color.from(ci.color),
range: TypeConverters.fromRange(ci.range)
};
});
@@ -796,7 +792,7 @@ class ColorProviderAdapter {
provideColorPresentations(resource: URI, raw: IRawColorInfo): TPromise<modes.IColorPresentation[]> {
const document = this._documents.getDocumentData(resource).document;
const range = TypeConverters.toRange(raw.range);
const color = new Color(raw.color[0], raw.color[1], raw.color[2], raw.color[3]);
const color = TypeConverters.Color.to(raw.color);
return asWinJsPromise(token => this._provider.provideColorPresentations(color, { document, range }, token)).then(value => {
return value.map(TypeConverters.ColorPresentation.from);
});
@@ -852,6 +848,38 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
this._diagnostics = diagnostics;
}
private _transformDocumentSelector(selector: vscode.DocumentSelector): ISerializedDocumentFilter[] {
if (Array.isArray(selector)) {
return selector.map(sel => this._doTransformDocumentSelector(sel));
}
return [this._doTransformDocumentSelector(selector)];
}
private _doTransformDocumentSelector(selector: string | vscode.DocumentFilter): ISerializedDocumentFilter {
if (typeof selector === 'string') {
return {
$serialized: true,
language: selector
};
}
if (selector) {
return {
$serialized: true,
language: selector.language,
scheme: this._transformScheme(selector.scheme),
pattern: selector.pattern
};
}
return undefined;
}
private _transformScheme(scheme: string): string {
return scheme;
}
private _createDisposable(handle: number): Disposable {
return new Disposable(() => {
this._adapter.delete(handle);
@@ -881,7 +909,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable {
const handle = this._addNewAdapter(new OutlineAdapter(this._documents, provider));
this._proxy.$registerOutlineSupport(handle, selector);
this._proxy.$registerOutlineSupport(handle, this._transformDocumentSelector(selector));
return this._createDisposable(handle);
}
@@ -896,7 +924,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
const eventHandle = typeof provider.onDidChangeCodeLenses === 'function' ? this._nextHandle() : undefined;
this._adapter.set(handle, new CodeLensAdapter(this._documents, this._commands.converter, this._heapService, provider));
this._proxy.$registerCodeLensSupport(handle, selector, eventHandle);
this._proxy.$registerCodeLensSupport(handle, this._transformDocumentSelector(selector), eventHandle);
let result = this._createDisposable(handle);
if (eventHandle !== undefined) {
@@ -919,7 +947,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable {
const handle = this._addNewAdapter(new DefinitionAdapter(this._documents, provider));
this._proxy.$registerDeclaractionSupport(handle, selector);
this._proxy.$registerDeclaractionSupport(handle, this._transformDocumentSelector(selector));
return this._createDisposable(handle);
}
@@ -929,7 +957,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerImplementationProvider(selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable {
const handle = this._addNewAdapter(new ImplementationAdapter(this._documents, provider));
this._proxy.$registerImplementationSupport(handle, selector);
this._proxy.$registerImplementationSupport(handle, this._transformDocumentSelector(selector));
return this._createDisposable(handle);
}
@@ -939,7 +967,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerTypeDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable {
const handle = this._addNewAdapter(new TypeDefinitionAdapter(this._documents, provider));
this._proxy.$registerTypeDefinitionSupport(handle, selector);
this._proxy.$registerTypeDefinitionSupport(handle, this._transformDocumentSelector(selector));
return this._createDisposable(handle);
}
@@ -951,7 +979,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider, extensionId?: string): vscode.Disposable {
const handle = this._addNewAdapter(new HoverAdapter(this._documents, provider));
this._proxy.$registerHoverProvider(handle, selector);
this._proxy.$registerHoverProvider(handle, this._transformDocumentSelector(selector));
return this._createDisposable(handle);
}
@@ -963,7 +991,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {
const handle = this._addNewAdapter(new DocumentHighlightAdapter(this._documents, provider));
this._proxy.$registerDocumentHighlightProvider(handle, selector);
this._proxy.$registerDocumentHighlightProvider(handle, this._transformDocumentSelector(selector));
return this._createDisposable(handle);
}
@@ -975,7 +1003,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable {
const handle = this._addNewAdapter(new ReferenceAdapter(this._documents, provider));
this._proxy.$registerReferenceSupport(handle, selector);
this._proxy.$registerReferenceSupport(handle, this._transformDocumentSelector(selector));
return this._createDisposable(handle);
}
@@ -987,7 +1015,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerCodeActionProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable {
const handle = this._addNewAdapter(new CodeActionAdapter(this._documents, this._commands.converter, this._diagnostics, provider));
this._proxy.$registerQuickFixSupport(handle, selector);
this._proxy.$registerQuickFixSupport(handle, this._transformDocumentSelector(selector));
return this._createDisposable(handle);
}
@@ -1000,7 +1028,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable {
const handle = this._addNewAdapter(new DocumentFormattingAdapter(this._documents, provider));
this._proxy.$registerDocumentFormattingSupport(handle, selector);
this._proxy.$registerDocumentFormattingSupport(handle, this._transformDocumentSelector(selector));
return this._createDisposable(handle);
}
@@ -1010,7 +1038,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable {
const handle = this._addNewAdapter(new RangeFormattingAdapter(this._documents, provider));
this._proxy.$registerRangeFormattingSupport(handle, selector);
this._proxy.$registerRangeFormattingSupport(handle, this._transformDocumentSelector(selector));
return this._createDisposable(handle);
}
@@ -1020,7 +1048,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, triggerCharacters: string[]): vscode.Disposable {
const handle = this._addNewAdapter(new OnTypeFormattingAdapter(this._documents, provider));
this._proxy.$registerOnTypeFormattingSupport(handle, selector, triggerCharacters);
this._proxy.$registerOnTypeFormattingSupport(handle, this._transformDocumentSelector(selector), triggerCharacters);
return this._createDisposable(handle);
}
@@ -1052,7 +1080,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider, canUseProposedApi = false): vscode.Disposable {
const handle = this._addNewAdapter(new RenameAdapter(this._documents, provider));
this._proxy.$registerRenameSupport(handle, selector, canUseProposedApi && RenameAdapter.supportsResolving(provider));
this._proxy.$registerRenameSupport(handle, this._transformDocumentSelector(selector), canUseProposedApi && RenameAdapter.supportsResolving(provider));
return this._createDisposable(handle);
}
@@ -1060,15 +1088,15 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._withAdapter(handle, RenameAdapter, adapter => adapter.provideRenameEdits(URI.revive(resource), position, newName));
}
$resolveRenameContext(handle: number, resource: URI, position: IPosition): TPromise<modes.RenameContext> {
return this._withAdapter(handle, RenameAdapter, adapter => adapter.resolveRenameContext(resource, position));
$resolveRenameLocation(handle: number, resource: URI, position: IPosition): TPromise<IRange> {
return this._withAdapter(handle, RenameAdapter, adapter => adapter.resolveRenameLocation(resource, position));
}
// --- suggestion
registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {
const handle = this._addNewAdapter(new SuggestAdapter(this._documents, this._commands.converter, provider));
this._proxy.$registerSuggestSupport(handle, selector, triggerCharacters, SuggestAdapter.supportsResolving(provider));
this._proxy.$registerSuggestSupport(handle, this._transformDocumentSelector(selector), triggerCharacters, SuggestAdapter.supportsResolving(provider));
return this._createDisposable(handle);
}
@@ -1088,7 +1116,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, triggerCharacters: string[]): vscode.Disposable {
const handle = this._addNewAdapter(new SignatureHelpAdapter(this._documents, provider));
this._proxy.$registerSignatureHelpProvider(handle, selector, triggerCharacters);
this._proxy.$registerSignatureHelpProvider(handle, this._transformDocumentSelector(selector), triggerCharacters);
return this._createDisposable(handle);
}
@@ -1100,7 +1128,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {
const handle = this._addNewAdapter(new LinkProviderAdapter(this._documents, this._heapService, provider));
this._proxy.$registerDocumentLinkProvider(handle, selector);
this._proxy.$registerDocumentLinkProvider(handle, this._transformDocumentSelector(selector));
return this._createDisposable(handle);
}
@@ -1114,7 +1142,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable {
const handle = this._addNewAdapter(new ColorProviderAdapter(this._documents, provider));
this._proxy.$registerDocumentColorProvider(handle, selector);
this._proxy.$registerDocumentColorProvider(handle, this._transformDocumentSelector(selector));
return this._createDisposable(handle);
}
@@ -1128,7 +1156,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerFoldingProvider(selector: vscode.DocumentSelector, provider: vscode.FoldingProvider): vscode.Disposable {
const handle = this._addNewAdapter(new FoldingProviderAdapter(this._documents, provider));
this._proxy.$registerFoldingProvider(handle, selector);
this._proxy.$registerFoldingProvider(handle, this._transformDocumentSelector(selector));
return this._createDisposable(handle);
}

View File

@@ -6,11 +6,9 @@
import * as vscode from 'vscode';
import { join } from 'vs/base/common/paths';
import { Event } from 'vs/base/common/event';
import { LogLevel } from 'vs/workbench/api/node/extHostTypes';
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 { ExtHostLogServiceShape } from 'vs/workbench/api/node/extHost.protocol';
@@ -21,9 +19,9 @@ export class ExtHostLogService extends DelegatedLogService implements ILogServic
constructor(
private _windowId: number,
logLevel: LogLevel,
private _environmentService: IEnvironmentService
private _logsPath: string
) {
super(createSpdLogService(`exthost${_windowId}`, logLevel, _environmentService.logsPath));
super(createSpdLogService(`exthost${_windowId}`, logLevel, _logsPath));
}
$setLevel(level: LogLevel): void {
@@ -40,7 +38,7 @@ export class ExtHostLogService extends DelegatedLogService implements ILogServic
}
getLogDirectory(extensionID: string): string {
return join(this._environmentService.logsPath, `${extensionID}_${this._windowId}`);
return join(this._logsPath, `${extensionID}_${this._windowId}`);
}
private createLogger(extensionID: string): ExtHostLogger {
@@ -57,12 +55,6 @@ export class ExtHostLogger implements vscode.Logger {
private readonly _logService: ILogService
) { }
get onDidChangeLogLevel(): Event<LogLevel> {
return this._logService.onDidChangeLogLevel;
}
get currentLevel(): LogLevel { return this._logService.getLevel(); }
trace(message: string, ...args: any[]): void {
return this._logService.trace(message, ...args);
}

View File

@@ -4,16 +4,20 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Progress, ProgressOptions, CancellationToken } from 'vscode';
import { MainThreadProgressShape } from './extHost.protocol';
import { ProgressOptions } from 'vscode';
import { MainThreadProgressShape, ExtHostProgressShape } from './extHost.protocol';
import { ProgressLocation } from './extHostTypeConverters';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { IProgressStep } from 'vs/platform/progress/common/progress';
import { IProgressStep, Progress } from 'vs/platform/progress/common/progress';
import { localize } from 'vs/nls';
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';
import { debounce } from 'vs/base/common/decorators';
export class ExtHostProgress {
export class ExtHostProgress implements ExtHostProgressShape {
private _proxy: MainThreadProgressShape;
private _handles: number = 0;
private _mapHandleToCancellationSource: Map<number, CancellationTokenSource> = new Map();
constructor(proxy: MainThreadProgressShape) {
this._proxy = proxy;
@@ -21,30 +25,66 @@ export class ExtHostProgress {
withProgress<R>(extension: IExtensionDescription, options: ProgressOptions, task: (progress: Progress<IProgressStep>, token: CancellationToken) => Thenable<R>): Thenable<R> {
const handle = this._handles++;
const { title, location } = options;
this._proxy.$startProgress(handle, { location: ProgressLocation.from(location), title, tooltip: extension.name });
return this._withProgress(handle, task);
const { title, location, cancellable } = options;
const source = localize('extensionSource', "{0} (Extension)", extension.displayName || extension.name);
this._proxy.$startProgress(handle, { location: ProgressLocation.from(location), title, source, cancellable });
return this._withProgress(handle, task, cancellable);
}
private _withProgress<R>(handle: number, task: (progress: Progress<IProgressStep>, token: CancellationToken) => Thenable<R>): Thenable<R> {
private _withProgress<R>(handle: number, task: (progress: Progress<IProgressStep>, token: CancellationToken) => Thenable<R>, cancellable: boolean): Thenable<R> {
let source: CancellationTokenSource;
if (cancellable) {
source = new CancellationTokenSource();
this._mapHandleToCancellationSource.set(handle, source);
}
const progress = {
report: (p: IProgressStep) => {
this._proxy.$progressReport(handle, p);
const progressEnd = (handle: number): void => {
this._proxy.$progressEnd(handle);
this._mapHandleToCancellationSource.delete(handle);
if (source) {
source.dispose();
}
};
let p: Thenable<R>;
try {
p = task(progress, null);
p = task(new ProgressCallback(this._proxy, handle), cancellable ? source.token : CancellationToken.None);
} catch (err) {
this._proxy.$progressEnd(handle);
progressEnd(handle);
throw err;
}
p.then(result => this._proxy.$progressEnd(handle), err => this._proxy.$progressEnd(handle));
p.then(result => progressEnd(handle), err => progressEnd(handle));
return p;
}
public $acceptProgressCanceled(handle: number): void {
const source = this._mapHandleToCancellationSource.get(handle);
if (source) {
source.cancel();
this._mapHandleToCancellationSource.delete(handle);
}
}
}
function mergeProgress(result: IProgressStep, currentValue: IProgressStep): IProgressStep {
result.message = currentValue.message;
if (typeof currentValue.increment === 'number' && typeof result.message === 'number') {
result.increment += currentValue.increment;
} else if (typeof currentValue.increment === 'number') {
result.increment = currentValue.increment;
}
return result;
}
class ProgressCallback extends Progress<IProgressStep> {
constructor(private _proxy: MainThreadProgressShape, private _handle: number) {
super(p => this.throttledReport(p));
}
@debounce(100, (result: IProgressStep, currentValue: IProgressStep) => mergeProgress(result, currentValue), () => Object.create(null))
throttledReport(p: IProgressStep): void {
this._proxy.$progressReport(this._handle, p);
}
}

View File

@@ -29,9 +29,10 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
this._commands = commands;
}
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Thenable<QuickPickItem[]>, options: QuickPickOptions & { canSelectMany: true; }, token?: CancellationToken): Thenable<QuickPickItem[] | undefined>;
showQuickPick(itemsOrItemsPromise: string[] | Thenable<string[]>, options?: QuickPickOptions, token?: CancellationToken): Thenable<string | undefined>;
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Thenable<QuickPickItem[]>, options?: QuickPickOptions, token?: CancellationToken): Thenable<QuickPickItem | undefined>;
showQuickPick(itemsOrItemsPromise: Item[] | Thenable<Item[]>, options?: QuickPickOptions, token: CancellationToken = CancellationToken.None): Thenable<Item | undefined> {
showQuickPick(itemsOrItemsPromise: Item[] | Thenable<Item[]>, options?: QuickPickOptions, token: CancellationToken = CancellationToken.None): Thenable<Item | Item[] | undefined> {
// clear state from last invocation
this._onDidSelectItem = undefined;
@@ -43,7 +44,8 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
placeHolder: options && options.placeHolder,
matchOnDescription: options && options.matchOnDescription,
matchOnDetail: options && options.matchOnDetail,
ignoreFocusLost: options && options.ignoreFocusOut
ignoreFocusLost: options && options.ignoreFocusOut,
canSelectMany: options && options.canPickMany
});
const promise = TPromise.any(<TPromise<number | Item[]>[]>[quickPickWidget, itemsPromise]).then(values => {
@@ -60,6 +62,7 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
let label: string;
let description: string;
let detail: string;
let picked: boolean;
if (typeof item === 'string') {
label = item;
@@ -67,12 +70,14 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
label = item.label;
description = item.description;
detail = item.detail;
picked = item.picked;
}
pickItems.push({
label,
description,
handle,
detail
detail,
picked
});
}
@@ -89,6 +94,8 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
return quickPickWidget.then(handle => {
if (typeof handle === 'number') {
return items[handle];
} else if (Array.isArray(handle)) {
return handle.map(h => items[h]);
}
return undefined;
});
@@ -98,7 +105,7 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
return TPromise.wrapError(err);
});
});
return wireCancellationToken<Item>(token, promise, true);
return wireCancellationToken<Item | Item[]>(token, promise, true);
}
$onItemSelected(handle: number): void {

View File

@@ -4,11 +4,12 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import URI from 'vs/base/common/uri';
import URI, { UriComponents } from 'vs/base/common/uri';
import * as nls from 'vs/nls';
import { TPromise } from 'vs/base/common/winjs.base';
import * as Objects from 'vs/base/common/objects';
import { asWinJsPromise } from 'vs/base/common/async';
import { Event, Emitter } from 'vs/base/common/event';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import * as TaskSystem from 'vs/workbench/parts/tasks/common/tasks';
@@ -18,7 +19,12 @@ import { MainContext, MainThreadTaskShape, ExtHostTaskShape, IMainContext } from
import * as types from 'vs/workbench/api/node/extHostTypes';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import * as vscode from 'vscode';
import {
TaskDefinitionDTO, TaskExecutionDTO, TaskPresentationOptionsDTO, ProcessExecutionOptionsDTO, ProcessExecutionDTO,
ShellExecutionOptionsDTO, ShellExecutionDTO, TaskDTO, TaskHandleDTO
} from '../shared/tasks';
export { TaskExecutionDTO };
/*
namespace ProblemPattern {
@@ -450,6 +456,250 @@ namespace Tasks {
}
}
namespace TaskDefinitionDTO {
export function from(value: vscode.TaskDefinition): TaskDefinitionDTO {
if (value === void 0 || value === null) {
return undefined;
}
return value;
}
export function to(value: TaskDefinitionDTO): vscode.TaskDefinition {
if (value === void 0 || value === null) {
return undefined;
}
return value;
}
}
namespace TaskPresentationOptionsDTO {
export function from(value: vscode.TaskPresentationOptions): TaskPresentationOptionsDTO {
if (value === void 0 || value === null) {
return undefined;
}
return value;
}
export function to(value: TaskPresentationOptionsDTO): vscode.TaskPresentationOptions {
if (value === void 0 || value === null) {
return undefined;
}
return value;
}
}
namespace ProcessExecutionOptionsDTO {
export function from(value: vscode.ProcessExecutionOptions): ProcessExecutionOptionsDTO {
if (value === void 0 || value === null) {
return undefined;
}
return value;
}
export function to(value: ProcessExecutionOptionsDTO): vscode.ProcessExecutionOptions {
if (value === void 0 || value === null) {
return undefined;
}
return value;
}
}
namespace ProcessExecutionDTO {
export function is(value: ShellExecutionDTO | ProcessExecutionDTO): value is ProcessExecutionDTO {
let candidate = value as ProcessExecutionDTO;
return candidate && !!candidate.process;
}
export function from(value: vscode.ProcessExecution): ProcessExecutionDTO {
if (value === void 0 || value === null) {
return undefined;
}
let result: ProcessExecutionDTO = {
process: value.process,
args: value.args
};
if (value.options) {
result.options = ProcessExecutionOptionsDTO.from(value.options);
}
return result;
}
export function to(value: ProcessExecutionDTO): types.ProcessExecution {
if (value === void 0 || value === null) {
return undefined;
}
return new types.ProcessExecution(value.process, value.args, value.options);
}
}
namespace ShellExecutionOptionsDTO {
export function from(value: vscode.ShellExecutionOptions): ShellExecutionOptionsDTO {
if (value === void 0 || value === null) {
return undefined;
}
return value;
}
export function to(value: ShellExecutionOptionsDTO): vscode.ShellExecutionOptions {
if (value === void 0 || value === null) {
return undefined;
}
return value;
}
}
namespace ShellExecutionDTO {
export function is(value: ShellExecutionDTO | ProcessExecutionDTO): value is ShellExecutionDTO {
let candidate = value as ShellExecutionDTO;
return candidate && (!!candidate.commandLine || !!candidate.command);
}
export function from(value: vscode.ShellExecution): ShellExecutionDTO {
if (value === void 0 || value === null) {
return undefined;
}
let result: ShellExecutionDTO = {
};
if (value.commandLine !== void 0) {
result.commandLine = value.commandLine;
} else {
result.command = value.command;
result.args = value.args;
}
if (value.options) {
result.options = ShellExecutionOptionsDTO.from(value.options);
}
return result;
}
export function to(value: ShellExecutionDTO): types.ShellExecution {
if (value === void 0 || value === null) {
return undefined;
}
if (value.commandLine) {
return new types.ShellExecution(value.commandLine, value.options);
} else {
return new types.ShellExecution(value.command, value.args ? value.args : [], value.options);
}
}
}
namespace TaskHandleDTO {
export function from(value: types.Task): TaskHandleDTO {
let folder: UriComponents;
if (value.scope !== void 0 && typeof value.scope !== 'number') {
folder = value.scope.uri;
}
return {
id: value._id,
workspaceFolder: folder
};
}
}
namespace TaskDTO {
export function from(value: vscode.Task, extension: IExtensionDescription): TaskDTO {
if (value === void 0 || value === null) {
return undefined;
}
let execution: ShellExecutionDTO | ProcessExecutionDTO;
if (value.execution instanceof types.ProcessExecution) {
execution = ProcessExecutionDTO.from(value.execution);
} else if (value.execution instanceof types.ShellExecution) {
execution = ShellExecutionDTO.from(value.execution);
}
let definition: TaskDefinitionDTO = TaskDefinitionDTO.from(value.definition);
let scope: number | UriComponents;
if (value.scope) {
if (typeof value.scope === 'number') {
scope = value.scope;
} else {
scope = value.scope.uri.toJSON();
}
}
if (!execution || !definition || !scope) {
return undefined;
}
let group = (value.group as types.TaskGroup) ? (value.group as types.TaskGroup).id : undefined;
let result: TaskDTO = {
_id: (value as types.Task)._id,
definition,
name: value.name,
source: {
extensionId: extension.id,
label: value.source,
scope: scope
},
execution,
isBackground: value.isBackground,
group: group,
presentationOptions: TaskPresentationOptionsDTO.from(value.presentationOptions),
problemMatchers: value.problemMatchers,
hasDefinedMatchers: (value as types.Task).hasDefinedMatchers
};
return result;
}
export function to(value: TaskDTO, workspace: ExtHostWorkspace): types.Task {
if (value === void 0 || value === null) {
return undefined;
}
let execution: types.ShellExecution | types.ProcessExecution;
if (ProcessExecutionDTO.is(value.execution)) {
execution = ProcessExecutionDTO.to(value.execution);
} else if (ShellExecutionDTO.is(value.execution)) {
execution = ShellExecutionDTO.to(value.execution);
}
let definition: vscode.TaskDefinition = TaskDefinitionDTO.to(value.definition);
let scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder;
if (value.source) {
if (value.source.scope !== void 0) {
if (typeof value.source.scope === 'number') {
scope = value.source.scope;
} else {
scope = workspace.resolveWorkspaceFolder(URI.revive(value.source.scope));
}
} else {
scope = types.TaskScope.Workspace;
}
}
if (!execution || !definition || !scope) {
return undefined;
}
let result = new types.Task(definition, scope, value.name, value.source.label, execution, value.problemMatchers);
if (value.isBackground !== void 0) {
result.isBackground = value.isBackground;
}
if (value.group !== void 0) {
result.group = types.TaskGroup.from(value.group);
}
if (value.presentationOptions) {
result.presentationOptions = TaskPresentationOptionsDTO.to(value.presentationOptions);
}
if (value._id) {
result._id = value._id;
}
return result;
}
}
class TaskExecutionImpl implements vscode.TaskExecution {
constructor(readonly _id: string, private readonly _task: vscode.Task, private readonly _tasks: ExtHostTask) {
}
get task(): vscode.Task {
return this._task;
}
public terminate(): void {
this._tasks.terminateTask(this);
}
}
namespace TaskExecutionDTO {
export function to(value: TaskExecutionDTO, tasks: ExtHostTask): vscode.TaskExecution {
return new TaskExecutionImpl(value.id, TaskDTO.to(value.task, tasks.extHostWorkspace), tasks);
}
export function from(value: vscode.TaskExecution): TaskExecutionDTO {
return {
id: (value as TaskExecutionImpl)._id,
task: undefined
};
}
}
interface HandlerData {
provider: vscode.TaskProvider;
extension: IExtensionDescription;
@@ -462,6 +712,9 @@ export class ExtHostTask implements ExtHostTaskShape {
private _handleCounter: number;
private _handlers: Map<number, HandlerData>;
private readonly _onDidExecuteTask: Emitter<vscode.TaskStartEvent> = new Emitter<vscode.TaskStartEvent>();
private readonly _onDidTerminateTask: Emitter<vscode.TaskEndEvent> = new Emitter<vscode.TaskEndEvent>();
constructor(mainContext: IMainContext, extHostWorkspace: ExtHostWorkspace) {
this._proxy = mainContext.getProxy(MainContext.MainThreadTask);
this._extHostWorkspace = extHostWorkspace;
@@ -469,6 +722,10 @@ export class ExtHostTask implements ExtHostTaskShape {
this._handlers = new Map<number, HandlerData>();
}
public get extHostWorkspace(): ExtHostWorkspace {
return this._extHostWorkspace;
}
public registerTaskProvider(extension: IExtensionDescription, provider: vscode.TaskProvider): vscode.Disposable {
if (!provider) {
return new types.Disposable(() => { });
@@ -482,6 +739,60 @@ export class ExtHostTask implements ExtHostTaskShape {
});
}
public executeTaskProvider(): Thenable<vscode.Task[]> {
return this._proxy.$executeTaskProvider().then((values) => {
let result: vscode.Task[] = [];
for (let value of values) {
let task = TaskDTO.to(value, this._extHostWorkspace);
if (task) {
result.push(task);
}
}
return result;
});
}
public executeTask(extension: IExtensionDescription, task: vscode.Task): Thenable<vscode.TaskExecution> {
let tTask = (task as types.Task);
// We have a preserved ID. So the task didn't change.
if (tTask._id !== void 0) {
return this._proxy.$executeTask(TaskHandleDTO.from(tTask)).then(value => new TaskExecutionImpl(value.id, task, this));
} else {
let dto = TaskDTO.from(task, extension);
if (dto === void 0) {
return Promise.reject(new Error('Task is not valid'));
}
return this._proxy.$executeTask(dto).then(value => new TaskExecutionImpl(value.id, task, this));
}
}
public $taskStarted(execution: TaskExecutionDTO): void {
this._onDidExecuteTask.fire({
execution: TaskExecutionDTO.to(execution, this)
});
}
get onDidStartTask(): Event<vscode.TaskStartEvent> {
return this._onDidExecuteTask.event;
}
public terminateTask(execution: vscode.TaskExecution): TPromise<void> {
if (!(execution instanceof TaskExecutionImpl)) {
throw new Error('No valid task execution provided');
}
return this._proxy.$terminateTask((execution as TaskExecutionImpl)._id);
}
public $taskEnded(execution: TaskExecutionDTO): void {
this._onDidTerminateTask.fire({
execution: TaskExecutionDTO.to(execution, this)
});
}
get onDidEndTask(): Event<vscode.TaskEndEvent> {
return this._onDidTerminateTask.event;
}
public $provideTasks(handle: number): TPromise<TaskSystem.TaskSet> {
let handler = this._handlers.get(handle);
if (!handler) {

View File

@@ -313,8 +313,6 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
export class ExtHostTextEditor implements vscode.TextEditor {
public readonly editorType = 'texteditor';
private readonly _proxy: MainThreadTextEditorsShape;
private readonly _id: string;
private readonly _documentData: ExtHostDocumentData;

View File

@@ -38,14 +38,22 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
});
}
registerTreeDataProvider<T>(id: string, dataProvider: vscode.TreeDataProvider<T>, proposedApiFunction: <U>(fn: U) => U): vscode.TreeView<T> {
const treeView = this.createExtHostTreeViewer(id, dataProvider);
registerTreeDataProvider<T>(id: string, treeDataProvider: vscode.TreeDataProvider<T>): vscode.Disposable {
const treeView = this.createTreeView(id, { treeDataProvider });
return { dispose: () => treeView.dispose() };
}
createTreeView<T>(viewId: string, options: { treeDataProvider: vscode.TreeDataProvider<T> }): vscode.TreeView<T> {
if (!options || !options.treeDataProvider) {
throw new Error('Options with treeDataProvider is mandatory');
}
const treeView = this.createExtHostTreeViewer(viewId, options.treeDataProvider);
return {
reveal: proposedApiFunction((element: T, options?: { select?: boolean }): Thenable<void> => {
reveal: (element: T, options?: { select?: boolean }): Thenable<void> => {
return treeView.reveal(element, options);
}),
},
dispose: () => {
this.treeViews.delete(id);
this.treeViews.delete(viewId);
treeView.dispose();
}
};

View File

@@ -83,7 +83,6 @@ export function fromPosition(position: types.Position): IPosition {
return { lineNumber: position.line + 1, column: position.character + 1 };
}
export function fromDiagnostic(value: vscode.Diagnostic): IMarkerData {
return {
...fromRange(value.range),
@@ -245,7 +244,7 @@ export const TextEdit = {
range: fromRange(edit.range)
};
},
to(edit: modes.TextEdit): vscode.TextEdit {
to(edit: modes.TextEdit): types.TextEdit {
let result = new types.TextEdit(toRange(edit.range), edit.text);
result.newEol = EndOfLine.to(edit.eol);
return result;
@@ -547,12 +546,15 @@ export namespace DocumentLink {
}
export namespace ColorPresentation {
export function to(colorPresentation: modes.IColorPresentation): vscode.ColorPresentation {
return {
label: colorPresentation.label,
textEdit: colorPresentation.textEdit ? TextEdit.to(colorPresentation.textEdit) : undefined,
additionalTextEdits: colorPresentation.additionalTextEdits ? colorPresentation.additionalTextEdits.map(value => TextEdit.to(value)) : undefined
};
export function to(colorPresentation: modes.IColorPresentation): types.ColorPresentation {
let cp = new types.ColorPresentation(colorPresentation.label);
if (colorPresentation.textEdit) {
cp.textEdit = TextEdit.to(colorPresentation.textEdit);
}
if (colorPresentation.additionalTextEdits) {
cp.additionalTextEdits = colorPresentation.additionalTextEdits.map(value => TextEdit.to(value));
}
return cp;
}
export function from(colorPresentation: vscode.ColorPresentation): modes.IColorPresentation {
@@ -564,6 +566,15 @@ export namespace ColorPresentation {
}
}
export namespace Color {
export function to(c: [number, number, number, number]): types.Color {
return new types.Color(c[0], c[1], c[2], c[3]);
}
export function from(color: types.Color): [number, number, number, number] {
return [color.red, color.green, color.blue, color.alpha];
}
}
export namespace TextDocumentSaveReason {
export function to(reason: SaveReason): vscode.TextDocumentSaveReason {
@@ -606,6 +617,7 @@ export namespace ProgressLocation {
switch (loc) {
case types.ProgressLocation.SourceControl: return MainProgressLocation.Scm;
case types.ProgressLocation.Window: return MainProgressLocation.Window;
case types.ProgressLocation.Notification: return MainProgressLocation.Notification;
}
return undefined;
}

View File

@@ -591,16 +591,6 @@ export class WorkspaceEdit implements vscode.WorkspaceEdit {
}
}
export class RenameContext {
range: Range;
newName?: string;
constructor(range: Range, newName?: string) {
this.range = range;
this.newName = newName;
}
}
export class SnippetString {
static isSnippetString(thing: any): thing is SnippetString {
@@ -1267,6 +1257,21 @@ export class TaskGroup implements vscode.TaskGroup {
public static Test: TaskGroup = new TaskGroup('test', 'Test');
public static from(value: string) {
switch (value) {
case 'clean':
return TaskGroup.Clean;
case 'build':
return TaskGroup.Build;
case 'rebuild':
return TaskGroup.Rebuild;
case 'test':
return TaskGroup.Test;
default:
return undefined;
}
}
constructor(id: string, _label: string) {
if (typeof id !== 'string') {
throw illegalArgument('name');
@@ -1338,6 +1343,20 @@ export class ProcessExecution implements vscode.ProcessExecution {
set options(value: vscode.ProcessExecutionOptions) {
this._options = value;
}
public computeId(): string {
const hash = crypto.createHash('md5');
hash.update('process');
if (this._process !== void 0) {
hash.update(this._process);
}
if (this._args && this._args.length > 0) {
for (let arg of this._args) {
hash.update(arg);
}
}
return hash.digest('hex');
}
}
export class ShellExecution implements vscode.ShellExecution {
@@ -1406,6 +1425,23 @@ export class ShellExecution implements vscode.ShellExecution {
set options(value: vscode.ShellExecutionOptions) {
this._options = value;
}
public computeId(): string {
const hash = crypto.createHash('md5');
hash.update('shell');
if (this._commandLine !== void 0) {
hash.update(this._commandLine);
}
if (this._command !== void 0) {
hash.update(typeof this._command === 'string' ? this._command : this._command.value);
}
if (this._args && this._args.length > 0) {
for (let arg of this._args) {
hash.update(typeof arg === 'string' ? arg : arg.value);
}
}
return hash.digest('hex');
}
}
export enum ShellQuoting {
@@ -1421,6 +1457,8 @@ export enum TaskScope {
export class Task implements vscode.Task {
private __id: string;
private _definition: vscode.TaskDefinition;
private _definitionKey: string;
private _scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder;
@@ -1469,6 +1507,35 @@ export class Task implements vscode.Task {
this._isBackground = false;
}
get _id(): string {
return this.__id;
}
set _id(value: string) {
this.__id = value;
}
private clear(): void {
if (this.__id === void 0) {
return;
}
this.__id = undefined;
this._scope = undefined;
this._definitionKey = undefined;
this._definition = undefined;
if (this._execution instanceof ProcessExecution) {
this._definition = {
type: 'process',
id: this._execution.computeId()
};
} else if (this._execution instanceof ShellExecution) {
this._definition = {
type: 'shell',
id: this._execution.computeId()
};
}
}
get definition(): vscode.TaskDefinition {
return this._definition;
}
@@ -1477,6 +1544,7 @@ export class Task implements vscode.Task {
if (value === void 0 || value === null) {
throw illegalArgument('Kind can\'t be undefined or null');
}
this.clear();
this._definitionKey = undefined;
this._definition = value;
}
@@ -1495,6 +1563,7 @@ export class Task implements vscode.Task {
}
set target(value: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder) {
this.clear();
this._scope = value;
}
@@ -1506,6 +1575,7 @@ export class Task implements vscode.Task {
if (typeof value !== 'string') {
throw illegalArgument('name');
}
this.clear();
this._name = value;
}
@@ -1517,6 +1587,7 @@ export class Task implements vscode.Task {
if (value === null) {
value = undefined;
}
this.clear();
this._execution = value;
}
@@ -1530,6 +1601,7 @@ export class Task implements vscode.Task {
this._hasDefinedMatchers = false;
return;
}
this.clear();
this._problemMatchers = value;
this._hasDefinedMatchers = true;
}
@@ -1546,6 +1618,7 @@ export class Task implements vscode.Task {
if (value !== true && value !== false) {
value = false;
}
this.clear();
this._isBackground = value;
}
@@ -1557,6 +1630,7 @@ export class Task implements vscode.Task {
if (typeof value !== 'string' || value.length === 0) {
throw illegalArgument('source must be a string of length > 0');
}
this.clear();
this._source = value;
}
@@ -1569,6 +1643,7 @@ export class Task implements vscode.Task {
this._group = undefined;
return;
}
this.clear();
this._group = value;
}
@@ -1580,6 +1655,7 @@ export class Task implements vscode.Task {
if (value === null) {
value = undefined;
}
this.clear();
this._presentationOptions = value;
}
}
@@ -1588,6 +1664,7 @@ export class Task implements vscode.Task {
export enum ProgressLocation {
SourceControl = 1,
Window = 10,
Notification = 15
}
export class TreeItem {

View File

@@ -11,13 +11,14 @@ import { Position } from 'vs/platform/editor/common/editor';
import { TPromise } from 'vs/base/common/winjs.base';
export class ExtHostWebview implements vscode.Webview {
public readonly editorType = 'webview';
private readonly _viewType: string;
private _title: string;
private _html: string;
private _options: vscode.WebviewOptions;
private _isDisposed: boolean = false;
private _viewColumn: vscode.ViewColumn;
private _active: boolean;
public readonly onMessageEmitter = new Emitter<any>();
public readonly onDidReceiveMessage: Event<any> = this.onMessageEmitter.event;
@@ -25,16 +26,17 @@ export class ExtHostWebview implements vscode.Webview {
public readonly onDisposeEmitter = new Emitter<void>();
public readonly onDidDispose: Event<void> = this.onDisposeEmitter.event;
public readonly onDidChangeViewColumnEmitter = new Emitter<vscode.ViewColumn>();
public readonly onDidChangeViewColumn: Event<vscode.ViewColumn> = this.onDidChangeViewColumnEmitter.event;
public readonly onDidChangeViewStateEmitter = new Emitter<vscode.WebViewOnDidChangeViewStateEvent>();
public readonly onDidChangeViewState: Event<vscode.WebViewOnDidChangeViewStateEvent> = this.onDidChangeViewStateEmitter.event;
constructor(
private readonly _handle: WebviewHandle,
private readonly _proxy: MainThreadWebviewsShape,
private readonly _uri: vscode.Uri,
viewType: string,
viewColumn: vscode.ViewColumn,
options: vscode.WebviewOptions
) {
this._viewType = viewType;
this._viewColumn = viewColumn;
this._options = options;
}
@@ -49,12 +51,12 @@ export class ExtHostWebview implements vscode.Webview {
this.onDisposeEmitter.dispose();
this.onMessageEmitter.dispose();
this.onDidChangeViewColumnEmitter.dispose();
this.onDidChangeViewStateEmitter.dispose();
}
get uri(): vscode.Uri {
get viewType(): string {
this.assertNotDisposed();
return this._uri;
return this._viewType;
}
get title(): string {
@@ -93,19 +95,29 @@ export class ExtHostWebview implements vscode.Webview {
return this._viewColumn;
}
get active(): boolean {
this.assertNotDisposed();
return this._active;
}
set viewColumn(value: vscode.ViewColumn) {
this.assertNotDisposed();
this._viewColumn = value;
}
set active(value: boolean) {
this.assertNotDisposed();
this._active = value;
}
public postMessage(message: any): Thenable<boolean> {
this.assertNotDisposed();
return this._proxy.$sendMessage(this._handle, message);
}
public show(viewColumn: vscode.ViewColumn): void {
public reveal(viewColumn: vscode.ViewColumn): void {
this.assertNotDisposed();
this._proxy.$show(this._handle, typeConverters.fromViewColumn(viewColumn));
this._proxy.$reveal(this._handle, typeConverters.fromViewColumn(viewColumn));
}
private assertNotDisposed() {
@@ -116,12 +128,14 @@ export class ExtHostWebview implements vscode.Webview {
}
export class ExtHostWebviews implements ExtHostWebviewsShape {
private static handlePool = 0;
private static handlePool = 1;
private readonly _proxy: MainThreadWebviewsShape;
private readonly _webviews = new Map<WebviewHandle, ExtHostWebview>();
private _activeWebview: ExtHostWebview | undefined;
constructor(
mainContext: IMainContext
) {
@@ -129,16 +143,16 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
}
createWebview(
uri: vscode.Uri,
viewType: string,
title: string,
viewColumn: vscode.ViewColumn,
options: vscode.WebviewOptions,
extensionFolderPath: string
): vscode.Webview {
const handle = ExtHostWebviews.handlePool++;
this._proxy.$createWebview(handle, uri, title, typeConverters.fromViewColumn(viewColumn), options, extensionFolderPath);
this._proxy.$createWebview(handle, viewType, title, typeConverters.fromViewColumn(viewColumn), options, extensionFolderPath);
const webview = new ExtHostWebview(handle, this._proxy, uri, viewColumn, options);
const webview = new ExtHostWebview(handle, this._proxy, viewType, viewColumn, options);
this._webviews.set(handle, webview);
return webview;
}
@@ -151,7 +165,22 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
}
$onDidChangeActiveWeview(handle: WebviewHandle | undefined): void {
this._onDidChangeActiveWebview.fire(this.getWebview(handle));
if (handle) {
const webview = this.getWebview(handle);
if (webview) {
if (webview !== this._activeWebview) {
this._activeWebview = webview;
webview.active = true;
webview.onDidChangeViewStateEmitter.fire({ viewColumn: webview.viewColumn, active: true });
}
}
} else {
if (this._activeWebview) {
this._activeWebview.active = false;
this._activeWebview.onDidChangeViewStateEmitter.fire({ viewColumn: this._activeWebview.viewColumn, active: false });
this._activeWebview = undefined;
}
}
}
$onDidDisposeWeview(handle: WebviewHandle): Thenable<void> {
@@ -159,6 +188,9 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
if (webview) {
webview.onDisposeEmitter.fire();
this._webviews.delete(handle);
if (this._activeWebview === webview) {
this._activeWebview = undefined;
}
}
return TPromise.as(void 0);
}
@@ -169,7 +201,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
const newViewColumn = typeConverters.toViewColumn(newPosition);
if (webview.viewColumn !== newViewColumn) {
webview.viewColumn = newViewColumn;
webview.onDidChangeViewColumnEmitter.fire(newViewColumn);
webview.onDidChangeViewStateEmitter.fire({ viewColumn: newViewColumn, active: webview.active });
}
}
}

View File

@@ -0,0 +1,89 @@
/*---------------------------------------------------------------------------------------------
* 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 { UriComponents } from 'vs/base/common/uri';
export interface TaskDefinitionDTO {
type: string;
[name: string]: any;
}
export interface TaskPresentationOptionsDTO {
reveal?: number;
echo?: boolean;
focus?: boolean;
panel?: number;
}
export interface ExecutionOptionsDTO {
cwd?: string;
env?: { [key: string]: string };
}
export interface ProcessExecutionOptionsDTO extends ExecutionOptionsDTO {
}
export interface ProcessExecutionDTO {
process: string;
args: string[];
options?: ProcessExecutionOptionsDTO;
}
export interface ShellQuotingOptionsDTO {
escape?: string | {
escapeChar: string;
charsToEscape: string;
};
strong?: string;
weak?: string;
}
export interface ShellExecutionOptionsDTO extends ExecutionOptionsDTO {
executable?: string;
shellArgs?: string[];
shellQuoting?: ShellQuotingOptionsDTO;
}
export interface ShellQuotedStringDTO {
value: string;
quoting: number;
}
export interface ShellExecutionDTO {
commandLine?: string;
command?: string | ShellQuotedStringDTO;
args?: (string | ShellQuotedStringDTO)[];
options?: ShellExecutionOptionsDTO;
}
export interface TaskSourceDTO {
label: string;
extensionId?: string;
scope?: number | UriComponents;
}
export interface TaskHandleDTO {
id: string;
workspaceFolder: UriComponents;
}
export interface TaskDTO {
_id: string;
name: string;
execution: ProcessExecutionDTO | ShellExecutionDTO;
definition: TaskDefinitionDTO;
isBackground: boolean;
source: TaskSourceDTO;
group?: string;
presentationOptions: TaskPresentationOptionsDTO;
problemMatchers: string[];
hasDefinedMatchers: boolean;
}
export interface TaskExecutionDTO {
id: string;
task: TaskDTO;
}