diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index ed9672fb778..ff210dad06d 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -531,7 +531,7 @@ export interface IOccurence { * Interface used to find occurrences of a symbol */ export interface IOccurrencesSupport { - findOccurrences(resource:URL, position:EditorCommon.IPosition, strict?:boolean):TPromise; + findOccurrences(resource:URI, position:EditorCommon.IPosition, strict?:boolean):TPromise; } diff --git a/src/vs/editor/contrib/codelens/browser/codelens.ts b/src/vs/editor/contrib/codelens/browser/codelens.ts index 9ec540a9476..b65a862004e 100644 --- a/src/vs/editor/contrib/codelens/browser/codelens.ts +++ b/src/vs/editor/contrib/codelens/browser/codelens.ts @@ -424,8 +424,7 @@ export class CodeLensContribution implements EditorCommon.IEditorContribution { this._currentFindCodeLensSymbolsPromise.cancel(); } - this._currentFindCodeLensSymbolsPromise = getCodeLensData(model.getAssociatedResource(), - model.getModeId()); + this._currentFindCodeLensSymbolsPromise = getCodeLensData(model); var counterValue = ++this._modelChangeCounter; this._currentFindCodeLensSymbolsPromise.then((result) => { diff --git a/src/vs/editor/contrib/codelens/common/codelens.ts b/src/vs/editor/contrib/codelens/common/codelens.ts index 0392ab6a924..cd2da755419 100644 --- a/src/vs/editor/contrib/codelens/common/codelens.ts +++ b/src/vs/editor/contrib/codelens/common/codelens.ts @@ -9,7 +9,7 @@ import {onUnexpectedError} from 'vs/base/common/errors'; import URI from 'vs/base/common/uri'; import {IAction, Action} from 'vs/base/common/actions'; import {TPromise} from 'vs/base/common/winjs.base'; -import {IRange, IPosition} from 'vs/editor/common/editorCommon'; +import {IModel, IRange, IPosition} from 'vs/editor/common/editorCommon'; import {Range} from 'vs/editor/common/core/range'; import {ICodeLensSupport, ICodeLensSymbol, ICommand} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; @@ -21,11 +21,11 @@ export interface ICodeLensData { support: ICodeLensSupport; } -export function getCodeLensData(resource: URI, modeId: string) { +export function getCodeLensData(model: IModel) { const symbols: ICodeLensData[] = []; - const promises = CodeLensRegistry.all({ uri: resource, language: modeId }).map(support => { - return support.findCodeLensSymbols(resource).then(result => { + const promises = CodeLensRegistry.all(model).map(support => { + return support.findCodeLensSymbols(model.getAssociatedResource()).then(result => { if (!Array.isArray(result)) { return; } diff --git a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts index e1665615a60..d31e219e1ee 100644 --- a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts @@ -173,7 +173,7 @@ export class GoToDeclarationAction extends GoToTypeAction { } protected _resolve(resource: URI, position: EditorCommon.IPosition): TPromise { - return getDeclarationsAtPosition(this.editor.getModel().getAssociatedResource(), this.editor.getModel().getModeId(), this.editor.getPosition()); + return getDeclarationsAtPosition(this.editor.getModel(), this.editor.getPosition()); } } @@ -437,7 +437,7 @@ class GotoDefinitionWithMouseEditorContribution implements EditorCommon.IEditorC return TPromise.as(null); } - return getDeclarationsAtPosition(this.editor.getModel().getAssociatedResource(), this.editor.getModel().getModeId(), target.position); + return getDeclarationsAtPosition(this.editor.getModel(), target.position); } private gotoDefinition(target:EditorBrowser.IMouseTarget, sideBySide:boolean):TPromise { diff --git a/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts index f704b82665b..dea603b4c2c 100644 --- a/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts @@ -8,17 +8,18 @@ import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; import {onUnexpectedError} from 'vs/base/common/errors'; -import {IPosition} from 'vs/editor/common/editorCommon'; +import {IModel, IPosition} from 'vs/editor/common/editorCommon'; import {IDeclarationSupport} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import {IReference} from 'vs/editor/common/modes'; export const DeclarationRegistry = new LanguageFeatureRegistry('declarationSupport'); -export function getDeclarationsAtPosition(resource: URI, modeId:string, position: IPosition): TPromise { +export function getDeclarationsAtPosition(model: IModel, position: IPosition): TPromise { const promises: TPromise[] = []; - const provider = DeclarationRegistry.ordered({ uri: resource, language: modeId }); + const resource = model.getAssociatedResource(); + const provider = DeclarationRegistry.ordered(model); const references: (IReference[]| IReference)[] = Array<(IReference[]| IReference)>(provider.length); // get results diff --git a/src/vs/editor/contrib/hover/browser/modesContentHover.ts b/src/vs/editor/contrib/hover/browser/modesContentHover.ts index 581eeb9287a..e0e92c72331 100644 --- a/src/vs/editor/contrib/hover/browser/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/browser/modesContentHover.ts @@ -46,8 +46,10 @@ class ModesContentComputer implements HoverOperation.IHoverComputer('extraInfoSupport'); -export function getExtraInfoAtPosition(resource: URI, modeId: string, position: IPosition): TPromise { +export function getExtraInfoAtPosition(model: IModel, position: IPosition): TPromise { - const supports = ExtraInfoRegistry.ordered({uri: resource, language: modeId }); + const resource = model.getAssociatedResource(); + const supports = ExtraInfoRegistry.ordered(model); const values: IComputeExtraInfoResult[] = []; const promises = supports.map((support, idx) => { diff --git a/src/vs/editor/contrib/quickOpen/common/quickOpen.ts b/src/vs/editor/contrib/quickOpen/common/quickOpen.ts index 5894c18e632..4b135a963da 100644 --- a/src/vs/editor/contrib/quickOpen/common/quickOpen.ts +++ b/src/vs/editor/contrib/quickOpen/common/quickOpen.ts @@ -11,7 +11,6 @@ import {Range} from 'vs/editor/common/core/range'; import {IModel} from 'vs/editor/common/editorCommon'; import {IOutlineEntry, IOutlineSupport} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; -import {ModelLike} from 'vs/editor/common/modes/languageSelector'; const OutlineRegistry = new LanguageFeatureRegistry('outlineSupport'); @@ -21,7 +20,7 @@ export { IOutlineSupport } -export function getOutlineEntries(model: ModelLike): TPromise<{ entries: IOutlineEntry[], outlineGroupLabel: { [n: string]: string;} }> { +export function getOutlineEntries(model: IModel): TPromise<{ entries: IOutlineEntry[], outlineGroupLabel: { [n: string]: string;} }> { let groupLabels: { [n: string]: string } = Object.create(null); let entries: IOutlineEntry[] = []; @@ -36,7 +35,7 @@ export function getOutlineEntries(model: ModelLike): TPromise<{ entries: IOutlin } } - return support.getOutline( model.uri).then(result => { + return support.getOutline(model.getAssociatedResource()).then(result => { if (Array.isArray(result)) { entries.push(...result); } diff --git a/src/vs/editor/contrib/wordHighlighter/common/wordHighlighter.ts b/src/vs/editor/contrib/wordHighlighter/common/wordHighlighter.ts index 3b66e3ef597..5d817a7ad28 100644 --- a/src/vs/editor/contrib/wordHighlighter/common/wordHighlighter.ts +++ b/src/vs/editor/contrib/wordHighlighter/common/wordHighlighter.ts @@ -5,6 +5,7 @@ 'use strict'; import {TPromise} from 'vs/base/common/winjs.base'; +import URI from 'vs/base/common/uri'; import * as EditorCommon from 'vs/editor/common/editorCommon'; import {IOccurrencesSupport, IOccurence} from 'vs/editor/common/modes'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; @@ -14,8 +15,34 @@ import {INullService} from 'vs/platform/instantiation/common/instantiation'; import {sequence} from 'vs/base/common/async'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; -const DocumentHighlighterRegistry = new LanguageFeatureRegistry('occurrencesSupport'); -export default DocumentHighlighterRegistry; +export const OccurrencesRegistry = new LanguageFeatureRegistry('occurrencesSupport'); + +export function getOccurrencesAtPosition(model: EditorCommon.IModel, position: EditorCommon.IPosition):TPromise { + + const resource = model.getAssociatedResource(); + const orderedByScore = OccurrencesRegistry.ordered(model); + let foundResult = false; + + // in order of score ask the occurrences provider + // until someone response with a good result + // (good = none empty array) + return sequence(orderedByScore.map(provider => { + return () => { + if (!foundResult) { + return provider.findOccurrences(resource, position).then(data => { + if (Array.isArray(data) && data.length > 0) { + foundResult = true; + return data; + } + }, err => { + onUnexpectedError(err); + }); + } + } + })).then(values => { + return values[0] + }); +} class WordHighlighter { @@ -99,7 +126,7 @@ class WordHighlighter { } // no providers for this model - if(!DocumentHighlighterRegistry.has(this.model)) { + if(!OccurrencesRegistry.has(this.model)) { this._stopAll(); return; } @@ -175,25 +202,7 @@ class WordHighlighter { var myRequestId = ++this.workerRequestTokenId; this.workerRequestCompleted = false; - let foundResult = false; - let orderedByScore = DocumentHighlighterRegistry.ordered(this.model); - let resource = this.model.getAssociatedResource(); - let position = this.editor.getPosition(); - - // in order of score ask the occurrences provider - // until someone response with a good result - // (good = none empty array) - this.workerRequest = sequence(orderedByScore.map(provider => { - return () => { - if (!foundResult) { - return provider.findOccurrences(resource, position).then(data => { - if (Array.isArray(data) && data.length > 0) { - return data; - } - }); - } - } - })).then(values => values[0]); + this.workerRequest = getOccurrencesAtPosition(this.model, this.editor.getPosition()); this.workerRequest.then(data => { if (myRequestId === this.workerRequestTokenId) { diff --git a/src/vs/workbench/api/browser/pluginHost.api.impl.ts b/src/vs/workbench/api/browser/pluginHost.api.impl.ts index 91b16d57765..93c40d6acc9 100644 --- a/src/vs/workbench/api/browser/pluginHost.api.impl.ts +++ b/src/vs/workbench/api/browser/pluginHost.api.impl.ts @@ -277,7 +277,7 @@ export class PluginHostAPIImplementation { 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); diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index bb762502983..65943d85924 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -25,7 +25,7 @@ import {IMarkerService, IMarker} from 'vs/platform/markers/common/markers'; import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; import {DeclarationRegistry} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; import {ExtraInfoRegistry} from 'vs/editor/contrib/hover/common/hover'; -import DocumentHighlighterRegistry from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; +import {OccurrencesRegistry} from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; import ReferenceSearchRegistry from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; import QuickFixRegistry from 'vs/editor/contrib/quickFix/common/quickFix'; import {OutlineRegistry, IOutlineEntry, IOutlineSupport} from 'vs/editor/contrib/quickOpen/common/quickOpen'; @@ -232,7 +232,37 @@ class ExtraInfoAdapter implements modes.IExtraInfoSupport { } } -type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | ExtraInfoAdapter; +class OccurrencesAdapter implements modes.IOccurrencesSupport { + + private _documents: PluginHostModelService; + private _provider: vscode.DocumentHighlightProvider; + + constructor(documents: PluginHostModelService, provider: vscode.DocumentHighlightProvider) { + this._documents = documents; + this._provider = provider; + } + + findOccurrences(resource: URI, position: IPosition): TPromise { + + let doc = this._documents.getDocument(resource); + let pos = TypeConverters.toPosition(position); + + return asWinJsPromise(token => this._provider.provideDocumentHighlights(doc, pos, token)).then(value => { + if (Array.isArray(value)) { + return value.map(OccurrencesAdapter._convertDocumentHighlight); + } + }); + } + + private static _convertDocumentHighlight(documentHighlight: vscode.DocumentHighlight): modes.IOccurence { + return { + range: TypeConverters.fromRange(documentHighlight.range), + kind: DocumentHighlightKind[documentHighlight.kind].toString().toLowerCase() + } + } +} + +type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | ExtraInfoAdapter | OccurrencesAdapter; @Remotable.PluginHostContext('ExtHostLanguageFeatures') export class ExtHostLanguageFeatures { @@ -322,6 +352,19 @@ export class ExtHostLanguageFeatures { $computeInfo(handle:number, resource: URI, position: IPosition): TPromise { return this._withAdapter(handle, ExtraInfoAdapter, adpater => adpater.computeInfo(resource, position)); } + + // --- occurrences adapter + + registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable { + const handle = this._nextHandle(); + this._adapter[handle] = new OccurrencesAdapter(this._documents, provider); + this._proxy.$registerOccurrencesSupport(handle, selector); + return this._createDisposable(handle); + } + + $findOccurrences(handle:number, resource: URI, position: IPosition): TPromise { + return this._withAdapter(handle, OccurrencesAdapter, adapter => adapter.findOccurrences(resource, position)); + } } @Remotable.MainContext('MainThreadLanguageFeatures') @@ -392,4 +435,15 @@ export class MainThreadLanguageFeatures { }); return undefined; } + + // --- occurrences + + $registerOccurrencesSupport(handle: number, selector: vscode.DocumentSelector): TPromise { + this._registrations[handle] = OccurrencesRegistry.register(selector, { + findOccurrences: (resource: URI, position: IPosition): TPromise => { + return this._proxy.$findOccurrences(handle, resource, position); + } + }); + return undefined; + } } \ No newline at end of file diff --git a/src/vs/workbench/api/common/languageFeatures.ts b/src/vs/workbench/api/common/languageFeatures.ts index 188b0dc377c..d8cb2762569 100644 --- a/src/vs/workbench/api/common/languageFeatures.ts +++ b/src/vs/workbench/api/common/languageFeatures.ts @@ -22,7 +22,6 @@ import {CancellationTokenSource} from 'vs/base/common/cancellation'; import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; import {IMarkerService, IMarker} from 'vs/platform/markers/common/markers'; import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; -import DocumentHighlighterRegistry from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; import ReferenceSearchRegistry from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; import QuickFixRegistry from 'vs/editor/contrib/quickFix/common/quickFix'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; @@ -133,62 +132,6 @@ export abstract class AbstractExtensionHostFeature { - - constructor(@IThreadService threadService: IThreadService) { - super(threadService.getRemotable(MainThreadOccurrencesFeature), threadService); - } - - _runAsCommand(resource: URI, position: IPosition): TPromise { - - let document = this._models.getDocument(resource); - let pos = TypeConverters.toPosition(position); - let highlights: vscode.DocumentHighlight[]; - - let factory = this._getOrderedFor(document).map(provider => { - return () => { - if (!highlights) { - return asWinJsPromise(token => provider.provideDocumentHighlights(document, pos, token)).then(result => { - if (Array.isArray(result) && result.length > 0) { - highlights = result; - } - }, err => { - console.error(err); - }); - } - } - }); - - return sequence(factory).then(() => { - if (highlights) { - return highlights.map(ExtensionHostOccurrencesFeature._convertDocumentHighlight); - } - }); - } - - private static _convertDocumentHighlight(documentHighlight: vscode.DocumentHighlight): modes.IOccurence { - return { - range: TypeConverters.fromRange(documentHighlight.range), - kind: DocumentHighlightKind[documentHighlight.kind].toString().toLowerCase() - } - } -} - -@Remotable.MainContext('MainThreadOccurrencesFeature') -export class MainThreadOccurrencesFeature extends AbstractMainThreadFeature { - - constructor(@IThreadService threadService: IThreadService) { - super('vscode.executeDocumentHighlights', DocumentHighlighterRegistry, threadService); - } - - findOccurrences(resource: URI, position: IPosition): TPromise { - return this._executeCommand(resource, position); - } -} - // --- reference search export class ExtensionHostReferenceSearch extends AbstractExtensionHostFeature { @@ -941,7 +884,6 @@ export class MainThreadWorkspaceSymbols implements INavigateTypesSupport { export namespace LanguageFeatures { export function createMainThreadInstances(threadService: IThreadService): void { - threadService.getRemotable(MainThreadOccurrencesFeature); threadService.getRemotable(MainThreadReferenceSearch); threadService.getRemotable(MainThreadCodeActions); threadService.getRemotable(MainThreadWorkspaceSymbols); @@ -955,7 +897,6 @@ export namespace LanguageFeatures { export function createExtensionHostInstances(threadService: IThreadService) { return { - documentHighlight: new ExtensionHostOccurrencesFeature(threadService), referenceSearch: new ExtensionHostReferenceSearch(threadService), codeActions: new ExtensionHostCodeActions(threadService), workspaceSymbols: new ExtensionHostWorkspaceSymbols(threadService), diff --git a/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts b/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts index a4f86a7bc11..aa7743ebfdb 100644 --- a/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts +++ b/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts @@ -527,10 +527,7 @@ export class GotoSymbolHandler extends QuickOpenHandler { return TPromise.as(this.outlineToModelCache[modelId]); } - return getOutlineEntries({ - uri: ( model).getAssociatedResource(), - language: (model).getModeId() - }).then(outline => { + return getOutlineEntries( model).then(outline => { let model = new OutlineModel(outline, this.toQuickOpenEntries(outline)); diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts index ce090215b97..b93fbe0cccf 100644 --- a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts @@ -9,11 +9,13 @@ 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 {ExtHostLanguageFeatures, MainThreadLanguageFeatures} from 'vs/workbench/api/common/extHostLanguageFeatures'; import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; @@ -24,8 +26,19 @@ import {OutlineRegistry, getOutlineEntries} from 'vs/editor/contrib/quickOpen/co 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'; + + +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 model: ModelLike; let extHost: ExtHostLanguageFeatures; let mainThread: MainThreadLanguageFeatures; let disposables: vscode.Disposable[] = []; @@ -38,27 +51,18 @@ suite('ExtHostLanguageFeatures', function() { originalErrorHandler = errorHandler.getUnexpectedErrorHandler(); setUnexpectedErrorHandler(() => { }); - model = { - language: 'far', - uri: URI.parse('far://testing/file.a') - }; - threadService.getRemotable(PluginHostModelService)._acceptModelAdd({ isDirty: false, - versionId: 1, - modeId: 'far', - url: model.uri, + versionId: model.getVersionId(), + modeId: model.getModeId(), + url: model.getAssociatedResource(), value: { - EOL: '\n', - lines: [ - 'This is the first line', - 'This is the second line', - 'This is the third line', - ], + EOL: model.getEOL(), + lines: model.getValue().split(model.getEOL()), BOM: '', length: -1 }, - }) + }); threadService.getRemotable(PluginHostCommands); threadService.getRemotable(MainThreadCommands); @@ -82,7 +86,7 @@ suite('ExtHostLanguageFeatures', function() { test('DocumentSymbols, register/deregister', function(done) { assert.equal(OutlineRegistry.all(model).length, 0); - let d1 = extHost.registerDocumentSymbolProvider('far', { + let d1 = extHost.registerDocumentSymbolProvider(defaultSelector, { provideDocumentSymbols() { return []; } @@ -99,12 +103,12 @@ suite('ExtHostLanguageFeatures', function() { }); test('DocumentSymbols, evil provider', function(done) { - disposables.push(extHost.registerDocumentSymbolProvider('far', { + disposables.push(extHost.registerDocumentSymbolProvider(defaultSelector, { provideDocumentSymbols(): any { throw new Error('evil document symbol provider'); } })); - disposables.push(extHost.registerDocumentSymbolProvider('far', { + disposables.push(extHost.registerDocumentSymbolProvider(defaultSelector, { provideDocumentSymbols(): any { return [new types.SymbolInformation('test', types.SymbolKind.Field, new types.Range(0, 0, 0, 0))]; } @@ -122,7 +126,7 @@ suite('ExtHostLanguageFeatures', function() { }); test('DocumentSymbols, data conversion', function(done) { - disposables.push(extHost.registerDocumentSymbolProvider('far', { + disposables.push(extHost.registerDocumentSymbolProvider(defaultSelector, { provideDocumentSymbols(): any { return [new types.SymbolInformation('test', types.SymbolKind.Field, new types.Range(0, 0, 0, 0))]; } @@ -148,19 +152,19 @@ suite('ExtHostLanguageFeatures', function() { test('CodeLens, evil provider', function(done) { - disposables.push(extHost.registerCodeLensProvider('far', { + disposables.push(extHost.registerCodeLensProvider(defaultSelector, { provideCodeLenses():any { throw new Error('evil') } })); - disposables.push(extHost.registerCodeLensProvider('far', { + disposables.push(extHost.registerCodeLensProvider(defaultSelector, { provideCodeLenses() { return [new types.CodeLens(new types.Range(0, 0, 0, 0))]; } })); threadService.sync().then(() => { - getCodeLensData(model.uri, model.language).then(value => { + getCodeLensData(model).then(value => { assert.equal(value.length, 1); done(); }); @@ -169,7 +173,7 @@ suite('ExtHostLanguageFeatures', function() { test('CodeLens, do not resolve a resolved lens', function(done) { - disposables.push(extHost.registerCodeLensProvider('far', { + disposables.push(extHost.registerCodeLensProvider(defaultSelector, { provideCodeLenses():any { return [new types.CodeLens( new types.Range(0, 0, 0, 0), @@ -182,11 +186,11 @@ suite('ExtHostLanguageFeatures', function() { threadService.sync().then(() => { - getCodeLensData(model.uri, model.language).then(value => { + getCodeLensData(model).then(value => { assert.equal(value.length, 1); let data = value[0]; - data.support.resolveCodeLensSymbol(model.uri, data.symbol).then(command => { + data.support.resolveCodeLensSymbol(model.getAssociatedResource(), data.symbol).then(command => { assert.equal(command.id, 'id'); assert.equal(command.title, 'Title'); done(); @@ -197,7 +201,7 @@ suite('ExtHostLanguageFeatures', function() { test('CodeLens, missing command', function(done) { - disposables.push(extHost.registerCodeLensProvider('far', { + disposables.push(extHost.registerCodeLensProvider(defaultSelector, { provideCodeLenses() { return [new types.CodeLens(new types.Range(0, 0, 0, 0))]; } @@ -205,11 +209,11 @@ suite('ExtHostLanguageFeatures', function() { threadService.sync().then(() => { - getCodeLensData(model.uri, model.language).then(value => { + getCodeLensData(model).then(value => { assert.equal(value.length, 1); let data = value[0]; - data.support.resolveCodeLensSymbol(model.uri, data.symbol).then(command => { + data.support.resolveCodeLensSymbol(model.getAssociatedResource(), data.symbol).then(command => { assert.equal(command.id, 'missing'); assert.equal(command.title, '<>'); @@ -223,19 +227,19 @@ suite('ExtHostLanguageFeatures', function() { test('Definition, data conversion', function(done) { - disposables.push(extHost.registerDefinitionProvider('far', { + disposables.push(extHost.registerDefinitionProvider(defaultSelector, { provideDefinition(): any { - return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))]; + return [new types.Location(model.getAssociatedResource(), new types.Range(1, 2, 3, 4))]; } })); threadService.sync().then(() => { - getDeclarationsAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + 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.uri.toString()); + assert.equal(entry.resource.toString(), model.getAssociatedResource().toString()); done(); }, err => { done(err); @@ -245,20 +249,20 @@ suite('ExtHostLanguageFeatures', function() { test('Definition, one or many', function(done) { - disposables.push(extHost.registerDefinitionProvider('far', { + disposables.push(extHost.registerDefinitionProvider(defaultSelector, { provideDefinition(): any { - return [new types.Location(model.uri, new types.Range(1, 1, 1, 1))]; + return [new types.Location(model.getAssociatedResource(), new types.Range(1, 1, 1, 1))]; } })); - disposables.push(extHost.registerDefinitionProvider('far', { + disposables.push(extHost.registerDefinitionProvider(defaultSelector, { provideDefinition(): any { - return new types.Location(model.uri, new types.Range(1, 1, 1, 1)); + return new types.Location(model.getAssociatedResource(), new types.Range(1, 1, 1, 1)); } })); threadService.sync().then(() => { - getDeclarationsAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + getDeclarationsAtPosition(model, { lineNumber: 1, column: 1 }).then(value => { assert.equal(value.length, 2); done(); }, err => { @@ -269,14 +273,14 @@ suite('ExtHostLanguageFeatures', function() { test('Definition, registration order', function(done) { - disposables.push(extHost.registerDefinitionProvider('far', { + disposables.push(extHost.registerDefinitionProvider(defaultSelector, { 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('far', { + disposables.push(extHost.registerDefinitionProvider(defaultSelector, { provideDefinition(): any { return new types.Location(URI.parse('far://second'), new types.Range(1, 2, 3, 4)); } @@ -284,7 +288,7 @@ suite('ExtHostLanguageFeatures', function() { threadService.sync().then(() => { - getDeclarationsAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + getDeclarationsAtPosition(model, { lineNumber: 1, column: 1 }).then(value => { assert.equal(value.length, 2); // let [first, second] = value; @@ -301,20 +305,20 @@ suite('ExtHostLanguageFeatures', function() { test('Definition, evil provider', function(done) { - disposables.push(extHost.registerDefinitionProvider('far', { + disposables.push(extHost.registerDefinitionProvider(defaultSelector, { provideDefinition(): any { throw new Error('evil provider') } })); - disposables.push(extHost.registerDefinitionProvider('far', { + disposables.push(extHost.registerDefinitionProvider(defaultSelector, { provideDefinition(): any { - return new types.Location(model.uri, new types.Range(1, 1, 1, 1)); + return new types.Location(model.getAssociatedResource(), new types.Range(1, 1, 1, 1)); } })); threadService.sync().then(() => { - getDeclarationsAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + getDeclarationsAtPosition(model, { lineNumber: 1, column: 1 }).then(value => { assert.equal(value.length, 1); done(); }, err => { @@ -327,7 +331,7 @@ suite('ExtHostLanguageFeatures', function() { test('ExtraInfo, word range at pos', function(done) { - disposables.push(extHost.registerHoverProvider('far', { + disposables.push(extHost.registerHoverProvider(defaultSelector, { provideHover(): any { return new types.Hover('Hello') } @@ -335,7 +339,7 @@ suite('ExtHostLanguageFeatures', function() { threadService.sync().then(() => { - getExtraInfoAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + getExtraInfoAtPosition(model, { lineNumber: 1, column: 1 }).then(value => { assert.equal(value.length, 1); let [entry] = value; @@ -347,7 +351,7 @@ suite('ExtHostLanguageFeatures', function() { test('ExtraInfo, given range', function(done) { - disposables.push(extHost.registerHoverProvider('far', { + disposables.push(extHost.registerHoverProvider(defaultSelector, { provideHover(): any { return new types.Hover('Hello', new types.Range(3, 0, 8, 7)); } @@ -355,7 +359,7 @@ suite('ExtHostLanguageFeatures', function() { threadService.sync().then(() => { - getExtraInfoAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + 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 }); @@ -366,14 +370,14 @@ suite('ExtHostLanguageFeatures', function() { test('ExtraInfo, registration order', function(done) { - disposables.push(extHost.registerHoverProvider('far', { + disposables.push(extHost.registerHoverProvider(defaultSelector, { provideHover(): any { return new types.Hover('registered first'); } })); setTimeout(function() { - disposables.push(extHost.registerHoverProvider('far', { + disposables.push(extHost.registerHoverProvider(defaultSelector, { provideHover(): any { return new types.Hover('registered second'); } @@ -381,7 +385,7 @@ suite('ExtHostLanguageFeatures', function() { threadService.sync().then(() => { - getExtraInfoAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + 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'); @@ -396,12 +400,12 @@ suite('ExtHostLanguageFeatures', function() { test('ExtraInfo, evil provider', function(done) { - disposables.push(extHost.registerHoverProvider('far', { + disposables.push(extHost.registerHoverProvider(defaultSelector, { provideHover(): any { throw new Error('evil') } })); - disposables.push(extHost.registerHoverProvider('far', { + disposables.push(extHost.registerHoverProvider(defaultSelector, { provideHover(): any { return new types.Hover('Hello') } @@ -409,12 +413,106 @@ suite('ExtHostLanguageFeatures', function() { threadService.sync().then(() => { - getExtraInfoAtPosition(model.uri, 'far', { lineNumber: 1, column: 1 }).then(value => { + 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, { + 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, { + provideDocumentHighlights(): any { + return [] + } + })); + disposables.push(extHost.registerDocumentHighlightProvider('*', { + 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, { + provideDocumentHighlights(): any { + return [new types.DocumentHighlight(new types.Range(0, 0, 0, 2))] + } + })); + disposables.push(extHost.registerDocumentHighlightProvider('*', { + 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, { + provideDocumentHighlights(): any { + throw new Error('evil'); + } + })); + + disposables.push(extHost.registerDocumentHighlightProvider(defaultSelector, { + 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(); + }); + }); }); }); \ No newline at end of file