mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-04 15:25:47 +01:00
Merge pull request #620 from Microsoft/joh/fixLanguageFeatures
Joh/fix language features
This commit is contained in:
@@ -17,11 +17,11 @@ import {PluginHostQuickOpen} from 'vs/workbench/api/browser/pluginHostQuickOpen'
|
||||
import {PluginHostStatusBar} from 'vs/workbench/api/browser/pluginHostStatusBar';
|
||||
import {PluginHostCommands} from 'vs/workbench/api/common/pluginHostCommands';
|
||||
import {ExtHostOutputService} from 'vs/workbench/api/browser/extHostOutputService';
|
||||
import {LanguageFeatures} from 'vs/workbench/api/common/languageFeatures';
|
||||
import {PluginHostMessageService} from 'vs/workbench/api/common/pluginHostMessageService';
|
||||
import {PluginHostTelemetryService} from 'vs/workbench/api/common/pluginHostTelemetry';
|
||||
import {PluginHostEditors} from 'vs/workbench/api/common/pluginHostEditors';
|
||||
import {ExtHostLanguages} from 'vs/workbench/api/common/extHostLanguages';
|
||||
import {ExtHostLanguageFeatures} from 'vs/workbench/api/common/extHostLanguageFeatures';
|
||||
import * as extHostTypes from 'vs/workbench/api/common/pluginHostTypes';
|
||||
import 'vs/workbench/api/common/pluginHostTypes.marshalling';
|
||||
import {wrapAsWinJSPromise} from 'vs/base/common/async';
|
||||
@@ -250,7 +250,7 @@ export class PluginHostAPIImplementation {
|
||||
//
|
||||
const languages = new ExtHostLanguages(this._threadService);
|
||||
const pluginHostDiagnostics = new PluginHostDiagnostics(this._threadService);
|
||||
const features = LanguageFeatures.createExtensionHostInstances(this._threadService);
|
||||
const languageFeatures = threadService.getRemotable(ExtHostLanguageFeatures);
|
||||
|
||||
this.languages = {
|
||||
createDiagnosticCollection(name?: string): vscode.DiagnosticCollection {
|
||||
@@ -263,46 +263,46 @@ export class PluginHostAPIImplementation {
|
||||
return score(selector, { uri: <any> document.uri, language: document.languageId });
|
||||
},
|
||||
registerCodeActionsProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable {
|
||||
return features.codeActions.register(selector, provider);
|
||||
return languageFeatures.registerCodeActionProvider(selector, provider);
|
||||
},
|
||||
registerCodeLensProvider(selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable {
|
||||
return features.codeLens.register(selector, provider);
|
||||
return languageFeatures.registerCodeLensProvider(selector, provider);
|
||||
},
|
||||
registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable {
|
||||
return features.definition.register(selector, provider);
|
||||
return languageFeatures.registerDefinitionProvider(selector, provider);
|
||||
},
|
||||
registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable {
|
||||
return features.hover.register(selector, provider);
|
||||
return languageFeatures.registerHoverProvider(selector, provider);
|
||||
},
|
||||
registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {
|
||||
return features.documentHighlight.register(selector, provider);
|
||||
return languageFeatures.registerDocumentHighlightProvider(selector, provider);
|
||||
},
|
||||
registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable {
|
||||
return features.referenceSearch.register(selector, provider);
|
||||
return languageFeatures.registerReferenceProvider(selector, provider);
|
||||
},
|
||||
registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable {
|
||||
return features.rename.register(selector, provider);
|
||||
return languageFeatures.registerRenameProvider(selector, provider);
|
||||
},
|
||||
registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable {
|
||||
return features.documentSymbols.register(selector, provider);
|
||||
return languageFeatures.registerDocumentSymbolProvider(selector, provider);
|
||||
},
|
||||
registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable {
|
||||
return features.workspaceSymbols.register(provider);
|
||||
return languageFeatures.registerWorkspaceSymbolProvider(provider);
|
||||
},
|
||||
registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable {
|
||||
return features.formatDocument.register(selector, provider);
|
||||
return languageFeatures.registerDocumentFormattingEditProvider(selector, provider);
|
||||
},
|
||||
registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable {
|
||||
return features.formatRange.register(selector, provider);
|
||||
return languageFeatures.registerDocumentRangeFormattingEditProvider(selector, provider);
|
||||
},
|
||||
registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, firstTriggerCharacter: string, ...moreTriggerCharacters: string[]): vscode.Disposable {
|
||||
return features.formatOnType.register(selector, { triggerCharacters: [firstTriggerCharacter].concat(moreTriggerCharacters), provider });
|
||||
return languageFeatures.registerOnTypeFormattingEditProvider(selector, provider, [firstTriggerCharacter].concat(moreTriggerCharacters));
|
||||
},
|
||||
registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, ...triggerCharacters: string[]): vscode.Disposable {
|
||||
return features.signatureHelp.register(selector, { triggerCharacters, provider });
|
||||
return languageFeatures.registerSignatureHelpProvider(selector, provider, triggerCharacters);
|
||||
},
|
||||
registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, ...triggerCharacters: string[]): vscode.Disposable {
|
||||
return features.completions.register(selector, { triggerCharacters, provider });
|
||||
return languageFeatures.registerCompletionItemProvider(selector, provider, triggerCharacters);
|
||||
},
|
||||
setLanguageConfiguration: (language: string, configuration: vscode.LanguageConfiguration):vscode.Disposable => {
|
||||
return this._setLanguageConfiguration(language, configuration);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ import Severity from 'vs/base/common/severity';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import {Position as EditorPosition} from 'vs/platform/editor/common/editor';
|
||||
import {Selection, Range, Position, SymbolKind, DiagnosticSeverity, ViewColumn} from './pluginHostTypes';
|
||||
import {IPosition, ISelection, IRange, IRangeWithMessage} from 'vs/editor/common/editorCommon';
|
||||
import {IPosition, ISelection, IRange, IRangeWithMessage, ISingleEditOperation} from 'vs/editor/common/editorCommon';
|
||||
import {IHTMLContentElement} from 'vs/base/common/htmlContent';
|
||||
|
||||
export interface PositionLike {
|
||||
@@ -189,3 +189,10 @@ export function fromRangeOrRangeWithMessage(ranges:vscode.Range[]|vscode.Decorat
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function fromTextEdit(edit: vscode.TextEdit) {
|
||||
return <ISingleEditOperation>{
|
||||
text: edit.newText,
|
||||
range: fromRange(edit.range)
|
||||
}
|
||||
}
|
||||
@@ -509,7 +509,7 @@ export class CodeLens {
|
||||
|
||||
constructor(range: Range, command?: vscode.Command) {
|
||||
this.range = range;
|
||||
this.command;
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
get isResolved(): boolean {
|
||||
|
||||
@@ -68,7 +68,7 @@ import {MainThreadLanguages} from 'vs/workbench/api/common/extHostLanguages';
|
||||
import {MainThreadEditors} from 'vs/workbench/api/common/pluginHostEditors';
|
||||
import {MainThreadWorkspace} from 'vs/workbench/api/browser/pluginHostWorkspace';
|
||||
import {MainThreadConfiguration} from 'vs/workbench/api/common/pluginHostConfiguration';
|
||||
import {LanguageFeatures} from 'vs/workbench/api/common/languageFeatures';
|
||||
import {MainThreadLanguageFeatures} from 'vs/workbench/api/common/extHostLanguageFeatures';
|
||||
import {EventService} from 'vs/platform/event/common/eventService';
|
||||
import {IOptions} from 'vs/workbench/common/options';
|
||||
import themes = require('vs/platform/theme/common/themes');
|
||||
@@ -367,7 +367,7 @@ export class WorkbenchShell {
|
||||
this.threadService.getRemotable(MainThreadWorkspace);
|
||||
this.threadService.getRemotable(MainThreadEditors);
|
||||
this.threadService.getRemotable(MainThreadStorage);
|
||||
LanguageFeatures.createMainThreadInstances(this.threadService);
|
||||
this.threadService.getRemotable(MainThreadLanguageFeatures);
|
||||
}
|
||||
|
||||
public open(): void {
|
||||
|
||||
@@ -31,7 +31,7 @@ import {IQuickOpenService} from 'vs/workbench/services/quickopen/browser/quickOp
|
||||
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
|
||||
import {Position} from 'vs/platform/editor/common/editor';
|
||||
import {KeyMod, KeyCode} from 'vs/base/common/keyCodes';
|
||||
import QuickOpenRegistry from 'vs/editor/contrib/quickOpen/common/quickOpen';
|
||||
import {OutlineRegistry, getOutlineEntries} from 'vs/editor/contrib/quickOpen/common/quickOpen';
|
||||
|
||||
const ACTION_ID = 'workbench.action.gotoSymbol';
|
||||
const ACTION_LABEL = nls.localize('gotoSymbol', "Go to Symbol...");
|
||||
@@ -432,7 +432,7 @@ export class GotoSymbolHandler extends QuickOpenHandler {
|
||||
|
||||
|
||||
if (model && types.isFunction((<ITokenizedModel>model).getMode)) {
|
||||
canRun = QuickOpenRegistry.has(<IModel> model);
|
||||
canRun = OutlineRegistry.has(<IModel> model);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,34 +527,7 @@ export class GotoSymbolHandler extends QuickOpenHandler {
|
||||
return TPromise.as(this.outlineToModelCache[modelId]);
|
||||
}
|
||||
|
||||
let groupLabels: { [n: string]: string } = Object.create(null);
|
||||
let entries: IOutlineEntry[] = [];
|
||||
let resource = (<IModel>model).getAssociatedResource();
|
||||
let promises = QuickOpenRegistry.all(<IModel>model).map(support => {
|
||||
|
||||
if (support.outlineGroupLabel) {
|
||||
for (var key in support.outlineGroupLabel) {
|
||||
if (Object.prototype.hasOwnProperty.call(support.outlineGroupLabel, key)) {
|
||||
groupLabels[key] = support.outlineGroupLabel[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return support.getOutline(resource).then(result => {
|
||||
if (Array.isArray(result)) {
|
||||
entries.push(...result);
|
||||
}
|
||||
}, err => {
|
||||
errors.onUnexpectedError(err);
|
||||
});
|
||||
});
|
||||
|
||||
return TPromise.join(promises).then(() => {
|
||||
|
||||
let outline = {
|
||||
entries,
|
||||
outlineGroupLabel: groupLabels
|
||||
};
|
||||
return getOutlineEntries(<IModel> model).then(outline => {
|
||||
|
||||
let model = new OutlineModel(outline, this.toQuickOpenEntries(outline));
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import {IWorkbenchEditorService, IFileInput} from 'vs/workbench/services/editor/
|
||||
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
|
||||
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
|
||||
import {IModeService} from 'vs/editor/common/services/modeService';
|
||||
import {NavigateTypesSupportRegistry, ITypeBearing} from '../common/search';
|
||||
import {NavigateTypesSupportRegistry, ITypeBearing, getNavigateToItems} from '../common/search';
|
||||
|
||||
class SymbolEntry extends EditorQuickOpenEntry {
|
||||
private name: string;
|
||||
@@ -135,21 +135,7 @@ export class OpenSymbolHandler extends QuickOpenHandler {
|
||||
|
||||
private doGetResults(searchValue: string): TPromise<QuickOpenEntry[]> {
|
||||
|
||||
let registry = <IEditorModesRegistry>Registry.as(Extensions.EditorModes);
|
||||
|
||||
// Find Types (and ignore error)
|
||||
let bearings: ITypeBearing[] = [];
|
||||
let promises = NavigateTypesSupportRegistry.getAll().map(support => {
|
||||
return support.getNavigateToItems(searchValue).then(result => {
|
||||
if (Array.isArray(result)) {
|
||||
bearings.push(...result);
|
||||
}
|
||||
}, err => {
|
||||
errors.onUnexpectedError(err);
|
||||
});
|
||||
});
|
||||
|
||||
return TPromise.join(promises).then(() => {
|
||||
return getNavigateToItems(searchValue).then(bearings => {
|
||||
return this.toQuickOpenEntries(bearings, searchValue);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
'use strict';
|
||||
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import {onUnexpectedError} from 'vs/base/common/errors';
|
||||
import {IDisposable} from 'vs/base/common/lifecycle';
|
||||
import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry';
|
||||
import {IRange} from 'vs/editor/common/editorCommon';
|
||||
@@ -51,11 +52,24 @@ export namespace NavigateTypesSupportRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
// export function has(): boolean {
|
||||
// return _supports.length > 0;
|
||||
// }
|
||||
|
||||
export function getAll(): INavigateTypesSupport[] {
|
||||
export function all(): INavigateTypesSupport[] {
|
||||
return _supports.slice(0);
|
||||
}
|
||||
}
|
||||
|
||||
export function getNavigateToItems(query: string): TPromise<ITypeBearing[]> {
|
||||
|
||||
const promises = NavigateTypesSupportRegistry.all().map(support => {
|
||||
return support.getNavigateToItems(query).then(value => value, onUnexpectedError);
|
||||
});
|
||||
|
||||
return TPromise.join(promises).then(all => {
|
||||
const result: ITypeBearing[] = [];
|
||||
for (let bearings of all) {
|
||||
if (Array.isArray(bearings)) {
|
||||
result.push(...bearings);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,804 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import {setUnexpectedErrorHandler, errorHandler} from 'vs/base/common/errors';
|
||||
import {create} from 'vs/base/common/types';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import {URL} from 'vs/base/common/network';
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import {PluginHostDocument} from 'vs/workbench/api/common/pluginHostDocuments';
|
||||
import * as types from 'vs/workbench/api/common/pluginHostTypes';
|
||||
import {Range as CodeEditorRange} from 'vs/editor/common/core/range';
|
||||
import * as EditorCommon from 'vs/editor/common/editorCommon';
|
||||
import {Model as EditorModel} from 'vs/editor/common/model/model';
|
||||
import threadService from './testThreadService'
|
||||
import {create as createInstantiationService} from 'vs/platform/instantiation/common/instantiationService';
|
||||
import {MarkerService} from 'vs/platform/markers/common/markerService';
|
||||
import {IMarkerService} from 'vs/platform/markers/common/markers';
|
||||
import {IThreadService} from 'vs/platform/thread/common/thread';
|
||||
import {ExtHostLanguageFeatures, MainThreadLanguageFeatures} from 'vs/workbench/api/common/extHostLanguageFeatures';
|
||||
import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands';
|
||||
import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments';
|
||||
import {SyncDescriptor0} from 'vs/platform/instantiation/common/descriptors';
|
||||
import {LanguageSelector, ModelLike} from 'vs/editor/common/modes/languageSelector';
|
||||
import {OutlineRegistry, getOutlineEntries} from 'vs/editor/contrib/quickOpen/common/quickOpen';
|
||||
import {CodeLensRegistry, getCodeLensData} from 'vs/editor/contrib/codelens/common/codelens';
|
||||
import {DeclarationRegistry, getDeclarationsAtPosition} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration';
|
||||
import {ExtraInfoRegistry, getExtraInfoAtPosition} from 'vs/editor/contrib/hover/common/hover';
|
||||
import {OccurrencesRegistry, getOccurrencesAtPosition} from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter';
|
||||
import {ReferenceRegistry, findReferences} from 'vs/editor/contrib/referenceSearch/common/referenceSearch';
|
||||
import {getQuickFixes} from 'vs/editor/contrib/quickFix/common/quickFix';
|
||||
import {getNavigateToItems} from 'vs/workbench/parts/search/common/search';
|
||||
import {rename} from 'vs/editor/contrib/rename/common/rename';
|
||||
import {getParameterHints} from 'vs/editor/contrib/parameterHints/common/parameterHints';
|
||||
|
||||
const defaultSelector = { scheme: 'far' };
|
||||
const model: EditorCommon.IModel = new EditorModel(
|
||||
[
|
||||
'This is the first line',
|
||||
'This is the second line',
|
||||
'This is the third line',
|
||||
].join('\n'),
|
||||
undefined,
|
||||
URL.fromUri(URI.parse('far://testing/file.a')));
|
||||
|
||||
let extHost: ExtHostLanguageFeatures;
|
||||
let mainThread: MainThreadLanguageFeatures;
|
||||
let disposables: vscode.Disposable[] = [];
|
||||
let originalErrorHandler: (e: any) => any;
|
||||
|
||||
suite('ExtHostLanguageFeatures', function() {
|
||||
|
||||
suiteSetup(() => {
|
||||
|
||||
let instantiationService = createInstantiationService();
|
||||
threadService.setInstantiationService(instantiationService);
|
||||
instantiationService.addSingleton(IMarkerService, new MarkerService(threadService));
|
||||
instantiationService.addSingleton(IThreadService, threadService);
|
||||
|
||||
originalErrorHandler = errorHandler.getUnexpectedErrorHandler();
|
||||
setUnexpectedErrorHandler(() => { });
|
||||
|
||||
threadService.getRemotable(PluginHostModelService)._acceptModelAdd({
|
||||
isDirty: false,
|
||||
versionId: model.getVersionId(),
|
||||
modeId: model.getModeId(),
|
||||
url: model.getAssociatedResource(),
|
||||
value: {
|
||||
EOL: model.getEOL(),
|
||||
lines: model.getValue().split(model.getEOL()),
|
||||
BOM: '',
|
||||
length: -1
|
||||
},
|
||||
});
|
||||
|
||||
threadService.getRemotable(PluginHostCommands);
|
||||
threadService.getRemotable(MainThreadCommands);
|
||||
mainThread = threadService.getRemotable(MainThreadLanguageFeatures);
|
||||
extHost = threadService.getRemotable(ExtHostLanguageFeatures);
|
||||
});
|
||||
|
||||
suiteTeardown(() => {
|
||||
setUnexpectedErrorHandler(originalErrorHandler);
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
while (disposables.length) {
|
||||
disposables.pop().dispose();
|
||||
}
|
||||
threadService.sync()
|
||||
.then(() => done(), err => done(err));
|
||||
});
|
||||
|
||||
// --- outline
|
||||
|
||||
test('DocumentSymbols, register/deregister', function(done) {
|
||||
assert.equal(OutlineRegistry.all(model).length, 0);
|
||||
let d1 = extHost.registerDocumentSymbolProvider(defaultSelector, <vscode.DocumentSymbolProvider>{
|
||||
provideDocumentSymbols() {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
threadService.sync().then(() => {
|
||||
assert.equal(OutlineRegistry.all(model).length, 1);
|
||||
d1.dispose();
|
||||
threadService.sync().then(() => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test('DocumentSymbols, evil provider', function(done) {
|
||||
disposables.push(extHost.registerDocumentSymbolProvider(defaultSelector, <vscode.DocumentSymbolProvider>{
|
||||
provideDocumentSymbols(): any {
|
||||
throw new Error('evil document symbol provider');
|
||||
}
|
||||
}));
|
||||
disposables.push(extHost.registerDocumentSymbolProvider(defaultSelector, <vscode.DocumentSymbolProvider>{
|
||||
provideDocumentSymbols(): any {
|
||||
return [new types.SymbolInformation('test', types.SymbolKind.Field, new types.Range(0, 0, 0, 0))];
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
getOutlineEntries(model).then(value => {
|
||||
assert.equal(value.entries.length, 1);
|
||||
done();
|
||||
}, err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('DocumentSymbols, data conversion', function(done) {
|
||||
disposables.push(extHost.registerDocumentSymbolProvider(defaultSelector, <vscode.DocumentSymbolProvider>{
|
||||
provideDocumentSymbols(): any {
|
||||
return [new types.SymbolInformation('test', types.SymbolKind.Field, new types.Range(0, 0, 0, 0))];
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
getOutlineEntries(model).then(value => {
|
||||
assert.equal(value.entries.length, 1);
|
||||
|
||||
let entry = value.entries[0];
|
||||
assert.equal(entry.label, 'test');
|
||||
assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 });
|
||||
done();
|
||||
|
||||
}, err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// --- code lens
|
||||
|
||||
test('CodeLens, evil provider', function(done) {
|
||||
|
||||
disposables.push(extHost.registerCodeLensProvider(defaultSelector, <vscode.CodeLensProvider>{
|
||||
provideCodeLenses():any {
|
||||
throw new Error('evil')
|
||||
}
|
||||
}));
|
||||
disposables.push(extHost.registerCodeLensProvider(defaultSelector, <vscode.CodeLensProvider>{
|
||||
provideCodeLenses() {
|
||||
return [new types.CodeLens(new types.Range(0, 0, 0, 0))];
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
getCodeLensData(model).then(value => {
|
||||
assert.equal(value.length, 1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('CodeLens, do not resolve a resolved lens', function(done) {
|
||||
|
||||
disposables.push(extHost.registerCodeLensProvider(defaultSelector, <vscode.CodeLensProvider>{
|
||||
provideCodeLenses():any {
|
||||
return [new types.CodeLens(
|
||||
new types.Range(0, 0, 0, 0),
|
||||
{ command: 'id', title: 'Title' })];
|
||||
},
|
||||
resolveCodeLens():any {
|
||||
assert.ok(false, 'do not resolve');
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
getCodeLensData(model).then(value => {
|
||||
assert.equal(value.length, 1);
|
||||
let data = value[0];
|
||||
|
||||
data.support.resolveCodeLensSymbol(model.getAssociatedResource(), data.symbol).then(command => {
|
||||
assert.equal(command.id, 'id');
|
||||
assert.equal(command.title, 'Title');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('CodeLens, missing command', function(done) {
|
||||
|
||||
disposables.push(extHost.registerCodeLensProvider(defaultSelector, <vscode.CodeLensProvider>{
|
||||
provideCodeLenses() {
|
||||
return [new types.CodeLens(new types.Range(0, 0, 0, 0))];
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
getCodeLensData(model).then(value => {
|
||||
assert.equal(value.length, 1);
|
||||
|
||||
let data = value[0];
|
||||
data.support.resolveCodeLensSymbol(model.getAssociatedResource(), data.symbol).then(command => {
|
||||
|
||||
assert.equal(command.id, 'missing');
|
||||
assert.equal(command.title, '<<MISSING COMMAND>>');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// --- definition
|
||||
|
||||
test('Definition, data conversion', function(done) {
|
||||
|
||||
disposables.push(extHost.registerDefinitionProvider(defaultSelector, <vscode.DefinitionProvider>{
|
||||
provideDefinition(): any {
|
||||
return [new types.Location(model.getAssociatedResource(), new types.Range(1, 2, 3, 4))];
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
getDeclarationsAtPosition(model, { lineNumber: 1, column: 1 }).then(value => {
|
||||
assert.equal(value.length, 1);
|
||||
let [entry] = value;
|
||||
assert.deepEqual(entry.range, { startLineNumber: 2, startColumn: 3, endLineNumber: 4, endColumn: 5 });
|
||||
assert.equal(entry.resource.toString(), model.getAssociatedResource().toString());
|
||||
done();
|
||||
}, err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Definition, one or many', function(done) {
|
||||
|
||||
disposables.push(extHost.registerDefinitionProvider(defaultSelector, <vscode.DefinitionProvider>{
|
||||
provideDefinition(): any {
|
||||
return [new types.Location(model.getAssociatedResource(), new types.Range(1, 1, 1, 1))];
|
||||
}
|
||||
}));
|
||||
disposables.push(extHost.registerDefinitionProvider(defaultSelector, <vscode.DefinitionProvider>{
|
||||
provideDefinition(): any {
|
||||
return new types.Location(model.getAssociatedResource(), new types.Range(1, 1, 1, 1));
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
getDeclarationsAtPosition(model, { lineNumber: 1, column: 1 }).then(value => {
|
||||
assert.equal(value.length, 2);
|
||||
done();
|
||||
}, err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Definition, registration order', function(done) {
|
||||
|
||||
disposables.push(extHost.registerDefinitionProvider(defaultSelector, <vscode.DefinitionProvider>{
|
||||
provideDefinition(): any {
|
||||
return [new types.Location(URI.parse('far://first'), new types.Range(2, 3, 4, 5))];
|
||||
}
|
||||
}));
|
||||
|
||||
setTimeout(function() { // registration time matters
|
||||
disposables.push(extHost.registerDefinitionProvider(defaultSelector, <vscode.DefinitionProvider>{
|
||||
provideDefinition(): any {
|
||||
return new types.Location(URI.parse('far://second'), new types.Range(1, 2, 3, 4));
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
getDeclarationsAtPosition(model, { lineNumber: 1, column: 1 }).then(value => {
|
||||
assert.equal(value.length, 2);
|
||||
// let [first, second] = value;
|
||||
|
||||
assert.equal(value[0].resource.authority, 'second');
|
||||
assert.equal(value[1].resource.authority, 'first');
|
||||
done();
|
||||
|
||||
}, err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
}, 5);
|
||||
});
|
||||
|
||||
test('Definition, evil provider', function(done) {
|
||||
|
||||
disposables.push(extHost.registerDefinitionProvider(defaultSelector, <vscode.DefinitionProvider>{
|
||||
provideDefinition(): any {
|
||||
throw new Error('evil provider')
|
||||
}
|
||||
}));
|
||||
disposables.push(extHost.registerDefinitionProvider(defaultSelector, <vscode.DefinitionProvider>{
|
||||
provideDefinition(): any {
|
||||
return new types.Location(model.getAssociatedResource(), new types.Range(1, 1, 1, 1));
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
getDeclarationsAtPosition(model, { lineNumber: 1, column: 1 }).then(value => {
|
||||
assert.equal(value.length, 1);
|
||||
done();
|
||||
}, err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// --- extra info
|
||||
|
||||
test('ExtraInfo, word range at pos', function(done) {
|
||||
|
||||
disposables.push(extHost.registerHoverProvider(defaultSelector, <vscode.HoverProvider>{
|
||||
provideHover(): any {
|
||||
return new types.Hover('Hello')
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
getExtraInfoAtPosition(model, { lineNumber: 1, column: 1 }).then(value => {
|
||||
|
||||
assert.equal(value.length, 1);
|
||||
let [entry] = value;
|
||||
assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 5 });
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('ExtraInfo, given range', function(done) {
|
||||
|
||||
disposables.push(extHost.registerHoverProvider(defaultSelector, <vscode.HoverProvider>{
|
||||
provideHover(): any {
|
||||
return new types.Hover('Hello', new types.Range(3, 0, 8, 7));
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
getExtraInfoAtPosition(model, { lineNumber: 1, column: 1 }).then(value => {
|
||||
assert.equal(value.length, 1);
|
||||
let [entry] = value;
|
||||
assert.deepEqual(entry.range, { startLineNumber: 4, startColumn: 1, endLineNumber: 9, endColumn: 8 });
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('ExtraInfo, registration order', function(done) {
|
||||
|
||||
disposables.push(extHost.registerHoverProvider(defaultSelector, <vscode.HoverProvider>{
|
||||
provideHover(): any {
|
||||
return new types.Hover('registered first');
|
||||
}
|
||||
}));
|
||||
|
||||
setTimeout(function() {
|
||||
disposables.push(extHost.registerHoverProvider(defaultSelector, <vscode.HoverProvider>{
|
||||
provideHover(): any {
|
||||
return new types.Hover('registered second');
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
getExtraInfoAtPosition(model, { lineNumber: 1, column: 1 }).then(value => {
|
||||
assert.equal(value.length, 2);
|
||||
let [first, second] = value;
|
||||
assert.equal(first.htmlContent[0].formattedText, 'registered second');
|
||||
assert.equal(second.htmlContent[0].formattedText, 'registered first');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
}, 5);
|
||||
|
||||
});
|
||||
|
||||
test('ExtraInfo, evil provider', function(done) {
|
||||
|
||||
disposables.push(extHost.registerHoverProvider(defaultSelector, <vscode.HoverProvider>{
|
||||
provideHover(): any {
|
||||
throw new Error('evil')
|
||||
}
|
||||
}));
|
||||
disposables.push(extHost.registerHoverProvider(defaultSelector, <vscode.HoverProvider>{
|
||||
provideHover(): any {
|
||||
return new types.Hover('Hello')
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
getExtraInfoAtPosition(model, { lineNumber: 1, column: 1 }).then(value => {
|
||||
|
||||
assert.equal(value.length, 1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// --- occurrences
|
||||
|
||||
test('Occurrences, data conversion', function(done) {
|
||||
|
||||
disposables.push(extHost.registerDocumentHighlightProvider(defaultSelector, <vscode.DocumentHighlightProvider>{
|
||||
provideDocumentHighlights(): any {
|
||||
return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))]
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
getOccurrencesAtPosition(model, { lineNumber: 1, column: 2 }).then(value => {
|
||||
assert.equal(value.length, 1);
|
||||
let [entry] = value;
|
||||
assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 5 });
|
||||
assert.equal(entry.kind, 'text');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Occurrences, order 1/2', function(done) {
|
||||
|
||||
disposables.push(extHost.registerDocumentHighlightProvider(defaultSelector, <vscode.DocumentHighlightProvider>{
|
||||
provideDocumentHighlights(): any {
|
||||
return []
|
||||
}
|
||||
}));
|
||||
disposables.push(extHost.registerDocumentHighlightProvider('*', <vscode.DocumentHighlightProvider>{
|
||||
provideDocumentHighlights(): any {
|
||||
return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))]
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
getOccurrencesAtPosition(model, { lineNumber: 1, column: 2 }).then(value => {
|
||||
assert.equal(value.length, 1);
|
||||
let [entry] = value;
|
||||
assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 5 });
|
||||
assert.equal(entry.kind, 'text');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Occurrences, order 2/2', function(done) {
|
||||
|
||||
disposables.push(extHost.registerDocumentHighlightProvider(defaultSelector, <vscode.DocumentHighlightProvider>{
|
||||
provideDocumentHighlights(): any {
|
||||
return [new types.DocumentHighlight(new types.Range(0, 0, 0, 2))]
|
||||
}
|
||||
}));
|
||||
disposables.push(extHost.registerDocumentHighlightProvider('*', <vscode.DocumentHighlightProvider>{
|
||||
provideDocumentHighlights(): any {
|
||||
return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))]
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
getOccurrencesAtPosition(model, { lineNumber: 1, column: 2 }).then(value => {
|
||||
assert.equal(value.length, 1);
|
||||
let [entry] = value;
|
||||
assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 3 });
|
||||
assert.equal(entry.kind, 'text');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Occurrences, evil provider', function(done) {
|
||||
|
||||
disposables.push(extHost.registerDocumentHighlightProvider(defaultSelector, <vscode.DocumentHighlightProvider>{
|
||||
provideDocumentHighlights(): any {
|
||||
throw new Error('evil');
|
||||
}
|
||||
}));
|
||||
|
||||
disposables.push(extHost.registerDocumentHighlightProvider(defaultSelector, <vscode.DocumentHighlightProvider>{
|
||||
provideDocumentHighlights(): any {
|
||||
return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))]
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
getOccurrencesAtPosition(model, { lineNumber: 1, column: 2 }).then(value => {
|
||||
assert.equal(value.length, 1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// --- references
|
||||
|
||||
test('References, registration order', function(done) {
|
||||
|
||||
disposables.push(extHost.registerReferenceProvider(defaultSelector, <vscode.ReferenceProvider>{
|
||||
provideReferences(): any {
|
||||
return [new types.Location(URI.parse('far://register/first'), new types.Range(0, 0, 0, 0))];
|
||||
}
|
||||
}));
|
||||
|
||||
setTimeout(function() {
|
||||
disposables.push(extHost.registerReferenceProvider(defaultSelector, <vscode.ReferenceProvider>{
|
||||
provideReferences(): any {
|
||||
return [new types.Location(URI.parse('far://register/second'), new types.Range(0, 0, 0, 0))];
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
findReferences(model, { lineNumber: 1, column: 2 }).then(value => {
|
||||
assert.equal(value.length, 2);
|
||||
|
||||
let [first, second] = value;
|
||||
assert.equal(first.resource.path, '/second');
|
||||
assert.equal(second.resource.path, '/first');
|
||||
done();
|
||||
});
|
||||
});
|
||||
}, 5);
|
||||
});
|
||||
|
||||
test('References, data conversion', function(done) {
|
||||
|
||||
disposables.push(extHost.registerReferenceProvider(defaultSelector, <vscode.ReferenceProvider>{
|
||||
provideReferences(): any {
|
||||
return [new types.Location(model.getAssociatedResource(), new types.Position(0, 0))];
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
findReferences(model, { lineNumber: 1, column: 2 }).then(value => {
|
||||
assert.equal(value.length, 1);
|
||||
|
||||
let [item] = value;
|
||||
assert.deepEqual(item.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 });
|
||||
assert.equal(item.resource.toString(), model.getAssociatedResource().toString());
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
test('References, evil provider', function(done) {
|
||||
|
||||
disposables.push(extHost.registerReferenceProvider(defaultSelector, <vscode.ReferenceProvider>{
|
||||
provideReferences(): any {
|
||||
throw new Error('evil');
|
||||
}
|
||||
}));
|
||||
disposables.push(extHost.registerReferenceProvider(defaultSelector, <vscode.ReferenceProvider>{
|
||||
provideReferences(): any {
|
||||
return [new types.Location(model.getAssociatedResource(), new types.Range(0, 0, 0, 0))];
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
findReferences(model, { lineNumber: 1, column: 2 }).then(value => {
|
||||
assert.equal(value.length, 1);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
// --- quick fix
|
||||
|
||||
test('Quick Fix, data conversion', function(done) {
|
||||
|
||||
disposables.push(extHost.registerCodeActionProvider(defaultSelector, <vscode.CodeActionProvider>{
|
||||
provideCodeActions(): any {
|
||||
return [
|
||||
<vscode.Command>{ command: 'test', title: 'Testing1' },
|
||||
<vscode.Command>{ command: 'test', title: 'Testing2' }
|
||||
];
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
getQuickFixes(model, model.getFullModelRange()).then(value => {
|
||||
assert.equal(value.length, 2);
|
||||
|
||||
let [first, second] = value;
|
||||
assert.equal(first.label, 'Testing1');
|
||||
assert.equal(first.id, String(0));
|
||||
assert.equal(second.label, 'Testing2');
|
||||
assert.equal(second.id, String(1));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Quick Fix, invoke command+args', function(done) {
|
||||
let actualArgs: any;
|
||||
let commands = threadService.getRemotable(PluginHostCommands);
|
||||
disposables.push(commands.registerCommand('test1', function(...args: any[]) {
|
||||
actualArgs = args;
|
||||
}));
|
||||
|
||||
disposables.push(extHost.registerCodeActionProvider(defaultSelector, <vscode.CodeActionProvider>{
|
||||
provideCodeActions(): any {
|
||||
return [<vscode.Command>{ command: 'test1', title: 'Testing', arguments: [true, 1, { bar: 'boo', foo: 'far' }, null] }];
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
getQuickFixes(model, model.getFullModelRange()).then(value => {
|
||||
assert.equal(value.length, 1);
|
||||
|
||||
let [entry] = value;
|
||||
entry.support.runQuickFixAction(model.getAssociatedResource(), model.getFullModelRange(), entry.id).then(value => {
|
||||
assert.equal(value, undefined);
|
||||
|
||||
assert.equal(actualArgs.length, 4);
|
||||
assert.equal(actualArgs[0], true)
|
||||
assert.equal(actualArgs[1], 1)
|
||||
assert.deepEqual(actualArgs[2], { bar: 'boo', foo: 'far' });
|
||||
assert.equal(actualArgs[3], null)
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Quick Fix, evil provider', function(done) {
|
||||
|
||||
disposables.push(extHost.registerCodeActionProvider(defaultSelector, <vscode.CodeActionProvider>{
|
||||
provideCodeActions(): any {
|
||||
throw new Error('evil');
|
||||
}
|
||||
}));
|
||||
disposables.push(extHost.registerCodeActionProvider(defaultSelector, <vscode.CodeActionProvider>{
|
||||
provideCodeActions(): any {
|
||||
return [<vscode.Command>{ command: 'test', title: 'Testing' }];
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
getQuickFixes(model, model.getFullModelRange()).then(value => {
|
||||
assert.equal(value.length, 1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// --- navigate types
|
||||
|
||||
test('Navigate types, evil provider', function(done) {
|
||||
|
||||
disposables.push(extHost.registerWorkspaceSymbolProvider(<vscode.WorkspaceSymbolProvider>{
|
||||
provideWorkspaceSymbols(): any {
|
||||
throw new Error('evil');
|
||||
}
|
||||
}));
|
||||
|
||||
disposables.push(extHost.registerWorkspaceSymbolProvider(<vscode.WorkspaceSymbolProvider>{
|
||||
provideWorkspaceSymbols(): any {
|
||||
return [new types.SymbolInformation('testing', types.SymbolKind.Array, new types.Range(0, 0, 1, 1))]
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
getNavigateToItems('').then(value => {
|
||||
assert.equal(value.length, 1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// --- rename
|
||||
|
||||
test('Rename, evil provider 1/2', function(done) {
|
||||
|
||||
disposables.push(extHost.registerRenameProvider(defaultSelector, <vscode.RenameProvider>{
|
||||
provideRenameEdits(): any {
|
||||
throw Error('evil');
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
rename(model, { lineNumber: 1, column: 1 }, 'newName').then(value => {
|
||||
done(new Error(''));
|
||||
}, err => {
|
||||
done(); // expected
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Rename, evil provider 2/2', function(done) {
|
||||
|
||||
disposables.push(extHost.registerRenameProvider('*', <vscode.RenameProvider>{
|
||||
provideRenameEdits(): any {
|
||||
throw Error('evil');
|
||||
}
|
||||
}));
|
||||
|
||||
disposables.push(extHost.registerRenameProvider(defaultSelector, <vscode.RenameProvider>{
|
||||
provideRenameEdits(): any {
|
||||
let edit = new types.WorkspaceEdit();
|
||||
edit.replace(model.getAssociatedResource(), new types.Range(0, 0, 0, 0), 'testing');
|
||||
return edit;
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
rename(model, { lineNumber: 1, column: 1 }, 'newName').then(value => {
|
||||
assert.equal(value.edits.length, 1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Rename, ordering', function(done) {
|
||||
|
||||
disposables.push(extHost.registerRenameProvider('*', <vscode.RenameProvider>{
|
||||
provideRenameEdits(): any {
|
||||
let edit = new types.WorkspaceEdit();
|
||||
edit.replace(model.getAssociatedResource(), new types.Range(0, 0, 0, 0), 'testing');
|
||||
edit.replace(model.getAssociatedResource(), new types.Range(1, 0, 1, 0), 'testing');
|
||||
return edit;
|
||||
}
|
||||
}));
|
||||
|
||||
disposables.push(extHost.registerRenameProvider(defaultSelector, <vscode.RenameProvider>{
|
||||
provideRenameEdits(): any {
|
||||
return;
|
||||
}
|
||||
}));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
rename(model, { lineNumber: 1, column: 1 }, 'newName').then(value => {
|
||||
assert.equal(value.edits.length, 2); // least relevant renamer
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// --- parameter hints
|
||||
|
||||
test('Parameter Hints, evil provider', function(done) {
|
||||
|
||||
disposables.push(extHost.registerSignatureHelpProvider(defaultSelector, <vscode.SignatureHelpProvider>{
|
||||
provideSignatureHelp(): any {
|
||||
throw new Error('evil');
|
||||
}
|
||||
}, []));
|
||||
|
||||
threadService.sync().then(() => {
|
||||
|
||||
getParameterHints(model, { lineNumber: 1, column: 1 }, '(').then(value => {
|
||||
done(new Error('error expeted'));
|
||||
}, err => {
|
||||
assert.equal(err.message, 'evil');
|
||||
done();
|
||||
})
|
||||
});
|
||||
})
|
||||
});
|
||||
@@ -1,177 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import {create} from 'vs/base/common/types';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import {PluginHostDocument} from 'vs/workbench/api/common/pluginHostDocuments';
|
||||
import * as phTypes from 'vs/workbench/api/common/pluginHostTypes';
|
||||
import {Range as CodeEditorRange} from 'vs/editor/common/core/range';
|
||||
import * as EditorCommon from 'vs/editor/common/editorCommon';
|
||||
import {NullThreadService} from 'vs/platform/test/common/nullThreadService'
|
||||
import * as LF from 'vs/workbench/api/common/languageFeatures';
|
||||
import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands';
|
||||
import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments';
|
||||
import {SyncDescriptor0} from 'vs/platform/instantiation/common/descriptors';
|
||||
import QuickOutlineRegistry from 'vs/editor/contrib/quickOpen/common/quickOpen';
|
||||
import {LanguageSelector, ModelLike} from 'vs/editor/common/modes/languageSelector';
|
||||
|
||||
class ThreadService extends NullThreadService {
|
||||
|
||||
protected _registerAndInstantiateMainProcessActor<T>(id: string, descriptor: SyncDescriptor0<T>): T {
|
||||
|
||||
let instance: any;
|
||||
|
||||
return this._getOrCreateProxyInstance({
|
||||
callOnRemote: (proxyId: string, path: string, args: any[]): TPromise<any> => {
|
||||
if (!instance) {
|
||||
instance = create(descriptor.ctor, this);
|
||||
}
|
||||
try {
|
||||
let result = (<Function>instance[path]).apply(instance, args);
|
||||
return TPromise.is(result) ? result : TPromise.as(result);
|
||||
} catch (err) {
|
||||
return TPromise.wrapError(err);
|
||||
}
|
||||
}
|
||||
}, id, descriptor)
|
||||
}
|
||||
|
||||
protected _registerAndInstantiatePluginHostActor<T>(id: string, descriptor: SyncDescriptor0<T>): T {
|
||||
return this._getOrCreateLocalInstance(id, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
let threadService: ThreadService;
|
||||
let model: ModelLike = { language: 'far', uri: URI.parse('far://testing/file.a') };
|
||||
|
||||
let extHost: LF.ExtensionHostDocumentSymbols;
|
||||
let mainHost: LF.MainThreadDocumentSymbols;
|
||||
|
||||
suite('ExtHostLanguageFeatures', function() {
|
||||
|
||||
suiteSetup(() => {
|
||||
threadService = new ThreadService();
|
||||
let documents = threadService.getRemotable(PluginHostModelService);
|
||||
documents._acceptModelAdd({
|
||||
isDirty: false,
|
||||
versionId: 1,
|
||||
modeId: 'far',
|
||||
url: model.uri,
|
||||
value: {
|
||||
EOL: '\n',
|
||||
lines: [
|
||||
'This is the first line',
|
||||
'This is the second line',
|
||||
'This is the third line',
|
||||
],
|
||||
BOM: '',
|
||||
length: -1
|
||||
},
|
||||
})
|
||||
threadService.getRemotable(PluginHostCommands);
|
||||
threadService.getRemotable(MainThreadCommands);
|
||||
threadService.getRemotable(LF.MainThreadDocumentSymbols);
|
||||
extHost = new LF.ExtensionHostDocumentSymbols(threadService);
|
||||
mainHost = threadService.getRemotable(LF.MainThreadDocumentSymbols);
|
||||
});
|
||||
|
||||
test('DocumentSymbols, register/deregister', function() {
|
||||
|
||||
|
||||
// register
|
||||
assert.equal(QuickOutlineRegistry.all(model).length, 0);
|
||||
let disposable = extHost.register('far', {
|
||||
provideDocumentSymbols() {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
assert.equal(QuickOutlineRegistry.all(model).length, 1);
|
||||
|
||||
// deregister
|
||||
disposable.dispose();
|
||||
assert.equal(QuickOutlineRegistry.all(model).length, 0);
|
||||
|
||||
// all extension host provider appear as one
|
||||
disposable = extHost.register('far', {
|
||||
provideDocumentSymbols() {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
let disposable2 = extHost.register('far', {
|
||||
provideDocumentSymbols() {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
assert.equal(QuickOutlineRegistry.all(model).length, 1);
|
||||
|
||||
disposable.dispose();
|
||||
assert.equal(QuickOutlineRegistry.all(model).length, 1);
|
||||
disposable2.dispose();
|
||||
assert.equal(QuickOutlineRegistry.all(model).length, 0);
|
||||
});
|
||||
|
||||
test('DocumentSymbols, evil provider', function(done) {
|
||||
|
||||
|
||||
let disposable = extHost.register('far', {
|
||||
provideDocumentSymbols():any {
|
||||
throw new Error('ddd');
|
||||
}
|
||||
});
|
||||
let disposable2 = extHost.register('far', {
|
||||
provideDocumentSymbols():any {
|
||||
return [
|
||||
new phTypes.SymbolInformation('boo', phTypes.SymbolKind.Field, new phTypes.Range(0, 0, 0, 0))
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
mainHost.getOutline(model.uri).then(result => {
|
||||
assert.equal(result.length, 1);
|
||||
done();
|
||||
|
||||
disposable.dispose();
|
||||
disposable2.dispose();
|
||||
|
||||
}, err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('DocumentSymbols, data conversion', function(done) {
|
||||
|
||||
let d = extHost.register('far', {
|
||||
provideDocumentSymbols():any {
|
||||
return [
|
||||
new phTypes.SymbolInformation('boo',
|
||||
phTypes.SymbolKind.Field,
|
||||
new phTypes.Range(0, 0, 0, 0),
|
||||
model.uri,
|
||||
'far')
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
mainHost.getOutline(model.uri).then(result => {
|
||||
assert.equal(result.length, 1);
|
||||
let entry = result[0];
|
||||
|
||||
assert.equal(entry.label, 'boo');
|
||||
assert.equal(entry.containerLabel, 'far');
|
||||
assert.equal(entry.children, undefined);
|
||||
assert.deepEqual(entry.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 });
|
||||
d.dispose();
|
||||
done();
|
||||
|
||||
}, err => {
|
||||
done(err);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,90 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 {NullThreadService} from 'vs/platform/test/common/nullThreadService';
|
||||
import {create} from 'vs/base/common/types';
|
||||
import {SyncDescriptor0} from 'vs/platform/instantiation/common/descriptors';
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export class TestThreadService extends NullThreadService {
|
||||
|
||||
private _callCountValue: number = 0;
|
||||
private _idle: TPromise<any>;
|
||||
private _completeIdle: Function;
|
||||
|
||||
private get _callCount(): number {
|
||||
return this._callCountValue;
|
||||
}
|
||||
|
||||
private set _callCount(value:number) {
|
||||
this._callCountValue = value;
|
||||
if (this._callCountValue === 0) {
|
||||
this._completeIdle();
|
||||
this._idle = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
sync(): TPromise<any> {
|
||||
if (this._callCount === 0) {
|
||||
return TPromise.as(undefined);
|
||||
}
|
||||
if (!this._idle) {
|
||||
this._idle = new TPromise<any>((c, e) => {
|
||||
this._completeIdle = c;
|
||||
}, function() {
|
||||
// no cancel
|
||||
});
|
||||
}
|
||||
return this._idle;
|
||||
}
|
||||
|
||||
protected _registerAndInstantiateMainProcessActor<T>(id: string, descriptor: SyncDescriptor0<T>): T {
|
||||
|
||||
let _calls:{path: string; args: any[] }[] = [];
|
||||
let _instance: any;
|
||||
|
||||
return this._getOrCreateProxyInstance({
|
||||
|
||||
|
||||
callOnRemote: (proxyId: string, path: string, args: any[]): TPromise<any> => {
|
||||
|
||||
this._callCount++;
|
||||
_calls.push({path, args});
|
||||
|
||||
return TPromise.timeout(0).then(() => {
|
||||
if (!_instance) {
|
||||
_instance = this._instantiationService.createInstance(descriptor.ctor);
|
||||
}
|
||||
let p: TPromise<any>;
|
||||
try {
|
||||
let {path, args} = _calls.shift();
|
||||
let result = (<Function>_instance[path]).apply(_instance, args);
|
||||
p = TPromise.is(result) ? result : TPromise.as(result);
|
||||
} catch (err) {
|
||||
p = TPromise.wrapError(err);
|
||||
}
|
||||
|
||||
return p.then(result => {
|
||||
this._callCount--;
|
||||
return result;
|
||||
}, err => {
|
||||
this._callCount--;
|
||||
return TPromise.wrapError(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
}, id, descriptor)
|
||||
}
|
||||
|
||||
protected _registerAndInstantiatePluginHostActor<T>(id: string, descriptor: SyncDescriptor0<T>): T {
|
||||
return this._getOrCreateLocalInstance(id, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
const Instance = new TestThreadService();
|
||||
export default Instance;
|
||||
Reference in New Issue
Block a user