diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index da41cfc9210..5ce81bc86da 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -1622,6 +1622,14 @@ export interface IReadOnlyModel extends ITextModel { * @return The word under or besides `position`. Might be null. */ getWordAtPosition(position:IPosition): IWordAtPosition; + + /** + * Get the word under or besides `position` trimmed to `position`.column + * @param position The position to look for a word. + * @param skipSyntaxTokens Ignore syntax tokens, as identified by the mode. + * @return The word under or besides `position`. Will never be null. + */ + getWordUntilPosition(position:IPosition): IWordAtPosition; } export interface IRichEditBracket { diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 1a5dba646b4..0e18df81adf 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -357,7 +357,7 @@ export interface ISuggestSupport { /** * Compute all completions for the given resource at the given position. */ - suggest(resource: URI, position: editorCommon.IPosition, triggerCharacter?: string): TPromise; + provideCompletionItems(model:editorCommon.IReadOnlyModel, position:editorCommon.IEditorPosition, cancellationToken:CancellationToken): ISuggestResult[] | Thenable; /** * Compute more details for the given suggestion. diff --git a/src/vs/editor/common/modes/supports/suggestSupport.ts b/src/vs/editor/common/modes/supports/suggestSupport.ts index 70d1fd9cffa..3ccfcf8d1f0 100644 --- a/src/vs/editor/common/modes/supports/suggestSupport.ts +++ b/src/vs/editor/common/modes/supports/suggestSupport.ts @@ -4,9 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import URI from 'vs/base/common/uri'; -import {TPromise} from 'vs/base/common/winjs.base'; -import {IPosition} from 'vs/editor/common/editorCommon'; +import {IReadOnlyModel, IEditorPosition} from 'vs/editor/common/editorCommon'; import {ISuggestResult, ISuggestSupport} from 'vs/editor/common/modes'; import {IFilter, matchesStrictPrefix, fuzzyContiguousFilter} from 'vs/base/common/filters'; import {IEditorWorkerService} from 'vs/editor/common/services/editorWorkerService'; @@ -14,6 +12,8 @@ import {IConfigurationService} from 'vs/platform/configuration/common/configurat import {IConfigurationRegistry, Extensions} from 'vs/platform/configuration/common/configurationRegistry'; import {Registry} from 'vs/platform/platform'; import {localize} from 'vs/nls'; +import {CancellationToken} from 'vs/base/common/cancellation'; +import {wireCancellationToken} from 'vs/base/common/async'; export class TextualSuggestSupport implements ISuggestSupport { @@ -52,11 +52,12 @@ export class TextualSuggestSupport implements ISuggestSupport { this._configurationService = configurationService; } - public suggest(resource: URI, position: IPosition, triggerCharacter?: string): TPromise { + public provideCompletionItems(model:IReadOnlyModel, position:IEditorPosition, cancellationToken:CancellationToken): ISuggestResult[] | Thenable { let config = this._configurationService.getConfiguration<{ wordBasedSuggestions: boolean }>('editor'); - return (!config || config.wordBasedSuggestions) - ? this._editorWorkerService.textualSuggest(resource, position) - : TPromise.as([]); + if (!config || config.wordBasedSuggestions) { + return wireCancellationToken(cancellationToken, this._editorWorkerService.textualSuggest(model.getAssociatedResource(), position)); + } + return []; } } diff --git a/src/vs/editor/contrib/hover/browser/hoverOperation.ts b/src/vs/editor/contrib/hover/browser/hoverOperation.ts index 155525863f8..47455bae5ae 100644 --- a/src/vs/editor/contrib/hover/browser/hoverOperation.ts +++ b/src/vs/editor/contrib/hover/browser/hoverOperation.ts @@ -6,7 +6,7 @@ import {RunOnceScheduler} from 'vs/base/common/async'; import {onUnexpectedError} from 'vs/base/common/errors'; -import {CancellationToken, CancellationTokenSource} from 'vs/base/common/cancellation'; +import {TPromise} from 'vs/base/common/winjs.base'; export interface IHoverComputer { @@ -18,7 +18,7 @@ export interface IHoverComputer { /** * This is called after half the hover time */ - computeAsync?: (cancellationToken:CancellationToken) => Thenable; + computeAsync?: () => TPromise; /** * This is called after all the hover time @@ -56,7 +56,7 @@ export class HoverOperation { private _firstWaitScheduler: RunOnceScheduler; private _secondWaitScheduler: RunOnceScheduler; private _loadingMessageScheduler: RunOnceScheduler; - private _asyncComputationCancellationTokenSource: CancellationTokenSource; + private _asyncComputationPromise: TPromise; private _asyncComputationPromiseDone:boolean; private _completeCallback:(r:Result)=>void; @@ -71,7 +71,7 @@ export class HoverOperation { this._secondWaitScheduler = new RunOnceScheduler(() => this._triggerSyncComputation(), this._getHoverTimeMillis() / 2); this._loadingMessageScheduler = new RunOnceScheduler(() => this._showLoadingMessage(), 3 * this._getHoverTimeMillis()); - this._asyncComputationCancellationTokenSource = new CancellationTokenSource(); + this._asyncComputationPromise = null; this._asyncComputationPromiseDone = false; this._completeCallback = success; @@ -96,12 +96,10 @@ export class HoverOperation { if (this._computer.computeAsync) { this._asyncComputationPromiseDone = false; - this._asyncComputationCancellationTokenSource.dispose(); - this._asyncComputationCancellationTokenSource = new CancellationTokenSource(); - this._computer.computeAsync(this._asyncComputationCancellationTokenSource.token).then((asyncResult: Result) => { + this._asyncComputationPromise = this._computer.computeAsync().then((asyncResult: Result) => { this._asyncComputationPromiseDone = true; this._withAsyncResult(asyncResult); - }).then(null, () => this._onError); + }, () => this._onError); } else { this._asyncComputationPromiseDone = true; } @@ -173,10 +171,16 @@ export class HoverOperation { } if (this._state === ComputeHoverOperationState.SECOND_WAIT) { this._secondWaitScheduler.cancel(); - this._asyncComputationCancellationTokenSource.cancel(); + if (this._asyncComputationPromise) { + this._asyncComputationPromise.cancel(); + this._asyncComputationPromise = null; + } } if (this._state === ComputeHoverOperationState.WAITING_FOR_ASYNC_COMPUTATION) { - this._asyncComputationCancellationTokenSource.cancel(); + if (this._asyncComputationPromise) { + this._asyncComputationPromise.cancel(); + this._asyncComputationPromise = null; + } } this._state = ComputeHoverOperationState.IDLE; } diff --git a/src/vs/editor/contrib/hover/browser/modesContentHover.ts b/src/vs/editor/contrib/hover/browser/modesContentHover.ts index 51be136a245..47ebde79a3f 100644 --- a/src/vs/editor/contrib/hover/browser/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/browser/modesContentHover.ts @@ -19,7 +19,6 @@ import {ICodeEditor} from 'vs/editor/browser/editorBrowser'; import {provideHover} from '../common/hover'; import {HoverOperation, IHoverComputer} from './hoverOperation'; import {ContentHoverWidget} from './hoverWidgets'; -import {CancellationToken} from 'vs/base/common/cancellation'; class ModesContentComputer implements IHoverComputer { @@ -41,7 +40,7 @@ class ModesContentComputer implements IHoverComputer { this._result = []; } - public computeAsync(cancellationToken:CancellationToken): Thenable { + public computeAsync(): TPromise { let model = this._editor.getModel(); if (!HoverProviderRegistry.has(model)) { @@ -51,7 +50,7 @@ class ModesContentComputer implements IHoverComputer { return provideHover(model, new Position( this._range.startLineNumber, this._range.startColumn - ), cancellationToken); + )); } public computeSync(): Hover[] { diff --git a/src/vs/editor/contrib/hover/common/hover.ts b/src/vs/editor/contrib/hover/common/hover.ts index dd465cf887c..073117e6393 100644 --- a/src/vs/editor/contrib/hover/common/hover.ts +++ b/src/vs/editor/contrib/hover/common/hover.ts @@ -11,16 +11,17 @@ import {TPromise} from 'vs/base/common/winjs.base'; import {IReadOnlyModel, IEditorPosition} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; import {Hover, HoverProviderRegistry} from 'vs/editor/common/modes'; -import {CancellationToken} from 'vs/base/common/cancellation'; -import {toThenable} from 'vs/base/common/async'; +import {asWinJsPromise} from 'vs/base/common/async'; -export function provideHover(model: IReadOnlyModel, position: IEditorPosition, cancellationToken = CancellationToken.None): Thenable { +export function provideHover(model: IReadOnlyModel, position: IEditorPosition): TPromise { const supports = HoverProviderRegistry.ordered(model); const values: Hover[] = []; const promises = supports.map((support, idx) => { - return toThenable(support.provideHover(model, position, cancellationToken)).then(result => { + return asWinJsPromise((token) => { + return support.provideHover(model, position, token); + }).then((result) => { if (result) { let hasRange = (typeof result.range !== 'undefined'); let hasHtmlContent = (typeof result.htmlContent !== 'undefined' && result.htmlContent && result.htmlContent.length > 0); diff --git a/src/vs/editor/contrib/parameterHints/common/parameterHints.ts b/src/vs/editor/contrib/parameterHints/common/parameterHints.ts index 42dea8aa2b4..da7a22a1fdb 100644 --- a/src/vs/editor/contrib/parameterHints/common/parameterHints.ts +++ b/src/vs/editor/contrib/parameterHints/common/parameterHints.ts @@ -9,17 +9,16 @@ import {TPromise} from 'vs/base/common/winjs.base'; import {IReadOnlyModel, IEditorPosition} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; import {SignatureHelp, SignatureHelpProviderRegistry} from 'vs/editor/common/modes'; -import {CancellationToken} from 'vs/base/common/cancellation'; -import {toThenable} from 'vs/base/common/async'; +import {asWinJsPromise} from 'vs/base/common/async'; -export function provideSignatureHelp(model:IReadOnlyModel, position:IEditorPosition, cancellationToken = CancellationToken.None): Thenable { +export function provideSignatureHelp(model:IReadOnlyModel, position:IEditorPosition): TPromise { let support = SignatureHelpProviderRegistry.ordered(model)[0]; if (!support) { return TPromise.as(undefined); } - return toThenable(support.provideSignatureHelp(model, position, cancellationToken)); + return asWinJsPromise((token) => support.provideSignatureHelp(model, position, token)); } CommonEditorRegistry.registerDefaultLanguageCommand('_executeSignatureHelpProvider', provideSignatureHelp); \ No newline at end of file diff --git a/src/vs/editor/contrib/suggest/browser/suggestModel.ts b/src/vs/editor/contrib/suggest/browser/suggestModel.ts index ed2c28a2e20..e9011d51b75 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestModel.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestModel.ts @@ -12,7 +12,7 @@ import {TPromise} from 'vs/base/common/winjs.base'; import {EventType, ICommonCodeEditor, ICursorSelectionChangedEvent, IPosition, CursorChangeReason} from 'vs/editor/common/editorCommon'; import {ISuggestSupport, ISuggestion, SuggestRegistry} from 'vs/editor/common/modes'; import {CodeSnippet} from 'vs/editor/contrib/snippet/common/snippet'; -import {ISuggestResult2, suggest} from '../common/suggest'; +import {ISuggestResult2, provideCompletionItems} from '../common/suggest'; import {CompletionModel} from './completionModel'; export interface ICancelEvent { @@ -323,7 +323,7 @@ export class SuggestModel implements IDisposable { const position = this.editor.getPosition(); - this.requestPromise = suggest(model, position, triggerCharacter, groups).then(all => { + this.requestPromise = provideCompletionItems(model, position, groups).then(all => { this.requestPromise = null; if (this.state === State.Idle) { diff --git a/src/vs/editor/contrib/suggest/common/suggest.ts b/src/vs/editor/contrib/suggest/common/suggest.ts index 677d861de09..3e84f975bc7 100644 --- a/src/vs/editor/contrib/suggest/common/suggest.ts +++ b/src/vs/editor/contrib/suggest/common/suggest.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {sequence} from 'vs/base/common/async'; +import {sequence, asWinJsPromise} from 'vs/base/common/async'; import {isFalsyOrEmpty} from 'vs/base/common/arrays'; -import {illegalArgument, onUnexpectedError} from 'vs/base/common/errors'; +import {onUnexpectedError} from 'vs/base/common/errors'; import {TPromise} from 'vs/base/common/winjs.base'; -import {IReadOnlyModel, IPosition} from 'vs/editor/common/editorCommon'; +import {IReadOnlyModel, IEditorPosition} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; import {ISuggestResult, ISuggestSupport, SuggestRegistry} from 'vs/editor/common/modes'; import {SnippetsRegistry} from 'vs/editor/common/modes/supports'; @@ -21,13 +21,12 @@ export interface ISuggestResult2 extends ISuggestResult { support?: ISuggestSupport; } -export function suggest(model: IReadOnlyModel, position: IPosition, triggerCharacter: string, groups?: ISuggestSupport[][]): TPromise { +export function provideCompletionItems(model: IReadOnlyModel, position: IEditorPosition, groups?: ISuggestSupport[][]): TPromise { if (!groups) { groups = SuggestRegistry.orderedGroups(model); } - const resource = model.getAssociatedResource(); const result: ISuggestResult2[] = []; const factory = groups.map((supports, index) => { @@ -40,7 +39,9 @@ export function suggest(model: IReadOnlyModel, position: IPosition, triggerChara // for each support in the group ask for suggestions return TPromise.join(supports.map(support => { - return support.suggest(resource, position, triggerCharacter).then(values => { + return asWinJsPromise((token) => { + return support.provideCompletionItems(model, position, token); + }).then(values => { if (!values) { return; @@ -74,11 +75,5 @@ export function suggest(model: IReadOnlyModel, position: IPosition, triggerChara } CommonEditorRegistry.registerDefaultLanguageCommand('_executeCompletionItemProvider', (model, position, args) => { - - let triggerCharacter = args['triggerCharacter']; - if (typeof triggerCharacter !== 'undefined' && typeof triggerCharacter !== 'string') { - throw illegalArgument('triggerCharacter'); - } - - return suggest(model, position, triggerCharacter); + return provideCompletionItems(model, position); }); diff --git a/src/vs/languages/css/common/css.ts b/src/vs/languages/css/common/css.ts index 98ef65db648..c2563485358 100644 --- a/src/vs/languages/css/common/css.ts +++ b/src/vs/languages/css/common/css.ts @@ -338,7 +338,7 @@ export class CSSMode extends AbstractMode { Modes.SuggestRegistry.register(this.getId(), { triggerCharacters: [' ', ':'], shouldAutotriggerSuggest: true, - suggest: (resource, position) => this.suggest(resource, position) + provideCompletionItems: (model, position, cancellationToken) => this.provideCompletionItems(model, position, cancellationToken) }); Modes.QuickFixRegistry.register(this.getId(), this); @@ -383,9 +383,13 @@ export class CSSMode extends AbstractMode { return this._worker((w) => w.findOccurrences(resource, position, strict)); } - static $suggest = OneWorkerAttr(CSSMode, CSSMode.prototype.suggest); - public suggest(resource:URI, position:EditorCommon.IPosition):WinJS.TPromise { - return this._worker((w) => w.suggest(resource, position)); + public provideCompletionItems(model:EditorCommon.IReadOnlyModel, position:EditorCommon.IEditorPosition, cancellationToken:CancellationToken): Thenable { + return wireCancellationToken(cancellationToken, this._provideCompletionItems(model.getAssociatedResource(), position)); + } + + static $_provideCompletionItems = OneWorkerAttr(CSSMode, CSSMode.prototype._provideCompletionItems); + private _provideCompletionItems(resource:URI, position:EditorCommon.IPosition):WinJS.TPromise { + return this._worker((w) => w.provideCompletionItems(resource, position)); } static $findDeclaration = OneWorkerAttr(CSSMode, CSSMode.prototype.findDeclaration); diff --git a/src/vs/languages/css/common/cssWorker.ts b/src/vs/languages/css/common/cssWorker.ts index a31ba6fff1e..299cda0fbeb 100644 --- a/src/vs/languages/css/common/cssWorker.ts +++ b/src/vs/languages/css/common/cssWorker.ts @@ -196,7 +196,7 @@ export class CSSWorker { return new cssIntellisense.CSSIntellisense(); } - public suggest(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { + public provideCompletionItems(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { return this.doSuggest(resource, position).then(value => filterSuggestions(value)); } diff --git a/src/vs/languages/css/test/common/css-worker.test.ts b/src/vs/languages/css/test/common/css-worker.test.ts index ee0d236575b..de41ec38fb1 100644 --- a/src/vs/languages/css/test/common/css-worker.test.ts +++ b/src/vs/languages/css/test/common/css-worker.test.ts @@ -74,7 +74,7 @@ suite('Validation - CSS', () => { var idx = stringBefore ? value.indexOf(stringBefore) + stringBefore.length : 0; var position = env.model.getPositionFromOffset(idx); - return env.worker.suggest(url, position).then(result => result[0]); + return env.worker.provideCompletionItems(url, position).then(result => result[0]); }; var testValueSetFor = function(value:string, selection:string, selectionLength: number, up: boolean):WinJS.TPromise { diff --git a/src/vs/languages/handlebars/common/handlebars.ts b/src/vs/languages/handlebars/common/handlebars.ts index 12dc9bba816..7f1ed2a9360 100644 --- a/src/vs/languages/handlebars/common/handlebars.ts +++ b/src/vs/languages/handlebars/common/handlebars.ts @@ -121,7 +121,7 @@ export class HandlebarsMode extends htmlMode.HTMLMode { Modes.SuggestRegistry.register(this.getId(), { triggerCharacters: ['.', ':', '<', '"', '=', '/'], shouldAutotriggerSuggest: true, - suggest: (resource, position) => this.suggest(resource, position) + provideCompletionItems: (model, position, cancellationToken) => this.provideCompletionItems(model, position, cancellationToken) }); Modes.OccurrencesRegistry.register(this.getId(), this); } diff --git a/src/vs/languages/html/common/html.ts b/src/vs/languages/html/common/html.ts index 9a95d054d16..3e29b78ac89 100644 --- a/src/vs/languages/html/common/html.ts +++ b/src/vs/languages/html/common/html.ts @@ -333,7 +333,7 @@ export class HTMLMode extends AbstractMode impl Modes.SuggestRegistry.register(this.getId(), { triggerCharacters: ['.', ':', '<', '"', '=', '/'], shouldAutotriggerSuggest: true, - suggest: (resource, position) => this.suggest(resource, position) + provideCompletionItems: (model, position, cancellationToken) => this.provideCompletionItems(model, position, cancellationToken) }); Modes.OccurrencesRegistry.register(this.getId(), this); Modes.FormatRegistry.register(this.getId(), this); @@ -479,7 +479,7 @@ export class HTMLMode extends AbstractMode impl } static $_provideHover = OneWorkerAttr(HTMLMode, HTMLMode.prototype._provideHover); - public _provideHover(resource:URI, position:EditorCommon.IPosition): winjs.TPromise { + private _provideHover(resource:URI, position:EditorCommon.IPosition): winjs.TPromise { return this._worker((w) => w.provideHover(resource, position)); } @@ -493,9 +493,13 @@ export class HTMLMode extends AbstractMode impl return this._worker((w) => w.findOccurrences(resource, position, strict)); } - static $suggest = OneWorkerAttr(HTMLMode, HTMLMode.prototype.suggest); - public suggest(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { - return this._worker((w) => w.suggest(resource, position)); + public provideCompletionItems(model:EditorCommon.IReadOnlyModel, position:EditorCommon.IEditorPosition, cancellationToken:CancellationToken): Thenable { + return wireCancellationToken(cancellationToken, this._provideCompletionItems(model.getAssociatedResource(), position)); + } + + static $_provideCompletionItems = OneWorkerAttr(HTMLMode, HTMLMode.prototype._provideCompletionItems); + private _provideCompletionItems(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { + return this._worker((w) => w.provideCompletionItems(resource, position)); } static $findColorDeclarations = OneWorkerAttr(HTMLMode, HTMLMode.prototype.findColorDeclarations); diff --git a/src/vs/languages/html/common/htmlWorker.ts b/src/vs/languages/html/common/htmlWorker.ts index be3728962a4..774401e203e 100644 --- a/src/vs/languages/html/common/htmlWorker.ts +++ b/src/vs/languages/html/common/htmlWorker.ts @@ -21,10 +21,9 @@ import {isTag, DELIM_END, DELIM_START, DELIM_ASSIGN, ATTRIB_NAME, ATTRIB_VALUE} import {isEmptyElement} from 'vs/languages/html/common/htmlEmptyTagsShared'; import {filterSuggestions} from 'vs/editor/common/modes/supports/suggestSupport'; import paths = require('vs/base/common/paths'); -import {asWinJsPromise} from 'vs/base/common/async'; import {provideHover} from 'vs/editor/contrib/hover/common/hover'; import {findReferences} from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; -import {suggest} from 'vs/editor/contrib/suggest/common/suggest'; +import {provideCompletionItems} from 'vs/editor/contrib/suggest/common/suggest'; enum LinkDetectionState { LOOKING_FOR_HREF_OR_SRC = 1, @@ -151,10 +150,8 @@ export class HTMLWorker { public provideHover(resource:URI, position:EditorCommon.IPosition): winjs.TPromise { return this._delegateToModeAtPosition(resource, position, (isEmbeddedMode, model) => { if (isEmbeddedMode) { - return asWinJsPromise((token) => { - return provideHover(model, Position.lift(position), token).then((r) => { - return (r.length > 0 ? r[0] : null); - }); + return provideHover(model, Position.lift(position)).then((r) => { + return (r.length > 0 ? r[0] : null); }); } }); @@ -339,10 +336,10 @@ export class HTMLWorker { }); } - public suggest(resource:URI, position:EditorCommon.IPosition, triggerCharacter?:string):winjs.TPromise { + public provideCompletionItems(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { return this._delegateToModeAtPosition(resource, position, (isEmbeddedMode, model) => { if (isEmbeddedMode) { - return suggest(model, Position.lift(position), triggerCharacter); + return provideCompletionItems(model, Position.lift(position)); } return this.suggestHTML(resource, position); diff --git a/src/vs/languages/html/test/common/html-worker.test.ts b/src/vs/languages/html/test/common/html-worker.test.ts index 2c232f560c8..242b757fd00 100644 --- a/src/vs/languages/html/test/common/html-worker.test.ts +++ b/src/vs/languages/html/test/common/html-worker.test.ts @@ -71,7 +71,7 @@ suite('HTML - worker', () => { var env = mockHtmlWorkerEnv(url, content); var position = env.model.getPositionFromOffset(idx); - return env.worker.suggest(url, position).then(result => result[0]); + return env.worker.provideCompletionItems(url, position).then(result => result[0]); }; var assertSuggestion = function(completion: Modes.ISuggestResult, label: string, type?: string, codeSnippet?: string) { diff --git a/src/vs/languages/json/common/json.ts b/src/vs/languages/json/common/json.ts index ce439f473d8..ffab3d7b227 100644 --- a/src/vs/languages/json/common/json.ts +++ b/src/vs/languages/json/common/json.ts @@ -77,7 +77,7 @@ export class JSONMode extends AbstractMode implements Modes.HoverProvider, Modes Modes.SuggestRegistry.register(this.getId(), { triggerCharacters: [], shouldAutotriggerSuggest: true, - suggest: (resource, position) => this.suggest(resource, position) + provideCompletionItems: (model, position, cancellationToken) => this.provideCompletionItems(model, position, cancellationToken) }); } @@ -132,9 +132,13 @@ export class JSONMode extends AbstractMode implements Modes.HoverProvider, Modes return this._worker((w) => w.navigateValueSet(resource, position, up)); } - static $suggest = OneWorkerAttr(JSONMode, JSONMode.prototype.suggest); - public suggest(resource:URI, position:EditorCommon.IPosition):WinJS.TPromise { - return this._worker((w) => w.suggest(resource, position)); + public provideCompletionItems(model:EditorCommon.IReadOnlyModel, position:EditorCommon.IEditorPosition, cancellationToken:CancellationToken): Thenable { + return wireCancellationToken(cancellationToken, this._provideCompletionItems(model.getAssociatedResource(), position)); + } + + static $_provideCompletionItems = OneWorkerAttr(JSONMode, JSONMode.prototype._provideCompletionItems); + private _provideCompletionItems(resource:URI, position:EditorCommon.IPosition):WinJS.TPromise { + return this._worker((w) => w.provideCompletionItems(resource, position)); } public provideHover(model:EditorCommon.IReadOnlyModel, position:EditorCommon.IEditorPosition, cancellationToken:CancellationToken): Thenable { @@ -142,7 +146,7 @@ export class JSONMode extends AbstractMode implements Modes.HoverProvider, Modes } static $_provideHover = OneWorkerAttr(JSONMode, JSONMode.prototype._provideHover); - public _provideHover(resource:URI, position:EditorCommon.IPosition): WinJS.TPromise { + private _provideHover(resource:URI, position:EditorCommon.IPosition): WinJS.TPromise { return this._worker((w) => w.provideHover(resource, position)); } diff --git a/src/vs/languages/json/common/jsonWorker.ts b/src/vs/languages/json/common/jsonWorker.ts index 2a6415ef103..5a52057f78a 100644 --- a/src/vs/languages/json/common/jsonWorker.ts +++ b/src/vs/languages/json/common/jsonWorker.ts @@ -265,7 +265,7 @@ export class JSONWorker { } - public suggest(resource:URI, position:EditorCommon.IPosition):WinJS.TPromise { + public provideCompletionItems(resource:URI, position:EditorCommon.IPosition):WinJS.TPromise { return this.doSuggest(resource, position).then(value => filterSuggestions(value)); } diff --git a/src/vs/languages/json/test/common/jsonworker.test.ts b/src/vs/languages/json/test/common/jsonworker.test.ts index 3fbc5519946..537973e674f 100644 --- a/src/vs/languages/json/test/common/jsonworker.test.ts +++ b/src/vs/languages/json/test/common/jsonworker.test.ts @@ -59,7 +59,7 @@ suite('JSON - Worker', () => { var idx = stringAfter ? value.indexOf(stringAfter) : 0; var position = env.model.getPositionFromOffset(idx); - return env.worker.suggest(url, position).then(result => result[0]); + return env.worker.provideCompletionItems(url, position).then(result => result[0]); }; function testComputeInfo(content:string, schema:jsonSchema.IJSONSchema, position:EditorCommon.IPosition):WinJS.TPromise { diff --git a/src/vs/languages/less/common/less.ts b/src/vs/languages/less/common/less.ts index 09b36614de3..bab360a0151 100644 --- a/src/vs/languages/less/common/less.ts +++ b/src/vs/languages/less/common/less.ts @@ -216,7 +216,7 @@ export class LESSMode extends AbstractMode implements Modes.HoverProvider, Modes Modes.SuggestRegistry.register(this.getId(), { triggerCharacters: [], shouldAutotriggerSuggest: true, - suggest: (resource, position) => this.suggest(resource, position) + provideCompletionItems: (model, position, cancellationToken) => this.provideCompletionItems(model, position, cancellationToken) }); this.tokenizationSupport = createTokenizationSupport(modeService, this, lexer); @@ -263,9 +263,13 @@ export class LESSMode extends AbstractMode implements Modes.HoverProvider, Modes return this._worker((w) => w.findReferences(resource, position)); } - static $suggest = OneWorkerAttr(LESSMode, LESSMode.prototype.suggest); - public suggest(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { - return this._worker((w) => w.suggest(resource, position)); + public provideCompletionItems(model:EditorCommon.IReadOnlyModel, position:EditorCommon.IEditorPosition, cancellationToken:CancellationToken): Thenable { + return wireCancellationToken(cancellationToken, this._provideCompletionItems(model.getAssociatedResource(), position)); + } + + static $_provideCompletionItems = OneWorkerAttr(LESSMode, LESSMode.prototype._provideCompletionItems); + private _provideCompletionItems(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { + return this._worker((w) => w.provideCompletionItems(resource, position)); } public provideHover(model:EditorCommon.IReadOnlyModel, position:EditorCommon.IEditorPosition, cancellationToken:CancellationToken): Thenable { @@ -273,7 +277,7 @@ export class LESSMode extends AbstractMode implements Modes.HoverProvider, Modes } static $_provideHover = OneWorkerAttr(LESSMode, LESSMode.prototype._provideHover); - public _provideHover(resource:URI, position:EditorCommon.IPosition): winjs.TPromise { + private _provideHover(resource:URI, position:EditorCommon.IPosition): winjs.TPromise { return this._worker((w) => w.provideHover(resource, position)); } diff --git a/src/vs/languages/less/test/common/intellisense.test.ts b/src/vs/languages/less/test/common/intellisense.test.ts index e3d6bacf7fd..4ed16b2ebb1 100644 --- a/src/vs/languages/less/test/common/intellisense.test.ts +++ b/src/vs/languages/less/test/common/intellisense.test.ts @@ -40,7 +40,7 @@ suite('LESS - Intellisense', () => { lineNumber: 1 }; } - return worker.suggest(url, position).then(result => result[0]); + return worker.provideCompletionItems(url, position).then(result => result[0]); }; var assertSuggestion= function(completion:Modes.ISuggestResult, label:string) { diff --git a/src/vs/languages/markdown/common/markdown.ts b/src/vs/languages/markdown/common/markdown.ts index 92b3fcdbfb8..674b31697c2 100644 --- a/src/vs/languages/markdown/common/markdown.ts +++ b/src/vs/languages/markdown/common/markdown.ts @@ -23,6 +23,7 @@ import {AbstractMode, ModeWorkerManager} from 'vs/editor/common/modes/abstractMo import {createRichEditSupport} from 'vs/editor/common/modes/monarch/monarchDefinition'; import {createTokenizationSupport} from 'vs/editor/common/modes/monarch/monarchLexer'; import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport'; +import {wireCancellationToken} from 'vs/base/common/async'; export const language = { @@ -239,8 +240,8 @@ export class MarkdownMode extends AbstractMode implements Modes.IEmitOutputSuppo Modes.SuggestRegistry.register(this.getId(), { triggerCharacters: [], shouldAutotriggerSuggest: false, - suggest: (resource, position) => { - return editorWorkerService.textualSuggest(resource, position); + provideCompletionItems: (model, position, cancellationToken) => { + return wireCancellationToken(cancellationToken, editorWorkerService.textualSuggest(model.getAssociatedResource(), position)); } }); } diff --git a/src/vs/languages/razor/common/razor.ts b/src/vs/languages/razor/common/razor.ts index 9125af6b73b..e8c6978433b 100644 --- a/src/vs/languages/razor/common/razor.ts +++ b/src/vs/languages/razor/common/razor.ts @@ -70,7 +70,7 @@ export class RAZORMode extends htmlMode.HTMLMode { Modes.SuggestRegistry.register(this.getId(), { triggerCharacters: ['.', ':', '<', '"', '=', '/'], shouldAutotriggerSuggest: true, - suggest: (resource, position) => this.suggest(resource, position) + provideCompletionItems: (model, position, cancellationToken) => this.provideCompletionItems(model, position, cancellationToken) }); Modes.OccurrencesRegistry.register(this.getId(), this); } diff --git a/src/vs/languages/sass/common/sass.ts b/src/vs/languages/sass/common/sass.ts index ff4239ea5f6..e0e935d9349 100644 --- a/src/vs/languages/sass/common/sass.ts +++ b/src/vs/languages/sass/common/sass.ts @@ -317,7 +317,7 @@ export class SASSMode extends AbstractMode implements Modes.HoverProvider, Modes Modes.SuggestRegistry.register(this.getId(), { triggerCharacters: [], shouldAutotriggerSuggest: true, - suggest: (resource, position) => this.suggest(resource, position) + provideCompletionItems: (model, position, cancellationToken) => this.provideCompletionItems(model, position, cancellationToken) }); this.tokenizationSupport = createTokenizationSupport(modeService, this, lexer); @@ -364,9 +364,13 @@ export class SASSMode extends AbstractMode implements Modes.HoverProvider, Modes return this._worker((w) => w.findReferences(resource, position)); } - static $suggest = OneWorkerAttr(SASSMode, SASSMode.prototype.suggest); - public suggest(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { - return this._worker((w) => w.suggest(resource, position)); + public provideCompletionItems(model:EditorCommon.IReadOnlyModel, position:EditorCommon.IEditorPosition, cancellationToken:CancellationToken): Thenable { + return wireCancellationToken(cancellationToken, this._provideCompletionItems(model.getAssociatedResource(), position)); + } + + static $_provideCompletionItems = OneWorkerAttr(SASSMode, SASSMode.prototype._provideCompletionItems); + private _provideCompletionItems(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { + return this._worker((w) => w.provideCompletionItems(resource, position)); } public provideHover(model:EditorCommon.IReadOnlyModel, position:EditorCommon.IEditorPosition, cancellationToken:CancellationToken): Thenable { @@ -374,7 +378,7 @@ export class SASSMode extends AbstractMode implements Modes.HoverProvider, Modes } static $_provideHover = OneWorkerAttr(SASSMode, SASSMode.prototype._provideHover); - public _provideHover(resource:URI, position:EditorCommon.IPosition): winjs.TPromise { + private _provideHover(resource:URI, position:EditorCommon.IPosition): winjs.TPromise { return this._worker((w) => w.provideHover(resource, position)); } diff --git a/src/vs/languages/sass/test/common/sass-worker.test.ts b/src/vs/languages/sass/test/common/sass-worker.test.ts index 9793267f2e4..a0382ce66ac 100644 --- a/src/vs/languages/sass/test/common/sass-worker.test.ts +++ b/src/vs/languages/sass/test/common/sass-worker.test.ts @@ -36,7 +36,7 @@ suite('SASS - Worker', () => { var idx = stringBefore ? value.indexOf(stringBefore) + stringBefore.length : 0; var position = env.model.getPositionFromOffset(idx); - return env.worker.suggest(url, position).then(result => result[0]); + return env.worker.provideCompletionItems(url, position).then(result => result[0]); }; var testValueSetFor = function(value:string, selection:string, selectionLength: number, up: boolean):WinJS.TPromise { diff --git a/src/vs/languages/typescript/common/languageFeatures.ts b/src/vs/languages/typescript/common/languageFeatures.ts index a28c582949f..61b87bb8bd2 100644 --- a/src/vs/languages/typescript/common/languageFeatures.ts +++ b/src/vs/languages/typescript/common/languageFeatures.ts @@ -16,6 +16,7 @@ import {IModelService} from 'vs/editor/common/services/modelService'; import {TypeScriptWorkerProtocol, LanguageServiceDefaults} from 'vs/languages/typescript/common/typescript'; import * as ts from 'vs/languages/typescript/common/lib/typescriptServices'; import {CancellationToken} from 'vs/base/common/cancellation'; +import {wireCancellationToken} from 'vs/base/common/async'; export function register(modelService: IModelService, markerService: IMarkerService, selector: string, defaults:LanguageServiceDefaults, worker: (first: URI, ...more: URI[]) => TPromise): lifecycle.IDisposable { @@ -173,13 +174,12 @@ class SuggestAdapter extends Adapter implements modes.ISuggestSupport { return true; } - suggest(resource: URI, position: editor.IPosition, triggerCharacter?: string) { - - const model = this._modelService.getModel(resource); + provideCompletionItems(model:editor.IReadOnlyModel, position:editor.IEditorPosition, cancellationToken:CancellationToken): Thenable { const wordInfo = model.getWordUntilPosition(position); + const resource = model.getAssociatedResource(); const offset = this._positionToOffset(resource, position); - return this._worker(resource).then(worker => { + return wireCancellationToken(cancellationToken, this._worker(resource).then(worker => { return worker.getCompletionsAtPosition(resource.toString(), offset); }).then(info => { if (!info) { @@ -197,7 +197,7 @@ class SuggestAdapter extends Adapter implements modes.ISuggestSupport { currentWord: wordInfo && wordInfo.word, suggestions }]; - }); + })); } getSuggestionDetails(resource: URI, position: editor.IPosition, suggestion: modes.ISuggestion) { @@ -246,9 +246,9 @@ class SignatureHelpAdapter extends Adapter implements modes.SignatureHelpProvide public signatureHelpTriggerCharacters = ['(', ',']; - provideSignatureHelp(model: editor.IReadOnlyModel, position: editor.IEditorPosition, token: CancellationToken): TPromise { + provideSignatureHelp(model: editor.IReadOnlyModel, position: editor.IEditorPosition, cancellationToken: CancellationToken): Thenable { let resource = model.getAssociatedResource(); - return this._worker(resource).then(worker => worker.getSignatureHelpItems(resource.toString(), this._positionToOffset(resource, position))).then(info => { + return wireCancellationToken(cancellationToken, this._worker(resource).then(worker => worker.getSignatureHelpItems(resource.toString(), this._positionToOffset(resource, position))).then(info => { if (!info) { return; @@ -287,7 +287,7 @@ class SignatureHelpAdapter extends Adapter implements modes.SignatureHelpProvide return ret; - }); + })); } } @@ -295,10 +295,10 @@ class SignatureHelpAdapter extends Adapter implements modes.SignatureHelpProvide class QuickInfoAdapter extends Adapter implements modes.HoverProvider { - provideHover(model:editor.IReadOnlyModel, position:editor.IEditorPosition, cancellationToken:CancellationToken): TPromise { + provideHover(model:editor.IReadOnlyModel, position:editor.IEditorPosition, cancellationToken:CancellationToken): Thenable { let resource = model.getAssociatedResource(); - return this._worker(resource).then(worker => { + return wireCancellationToken(cancellationToken, this._worker(resource).then(worker => { return worker.getQuickInfoAtPosition(resource.toString(), this._positionToOffset(resource, position)); }).then(info => { if (!info) { @@ -308,7 +308,7 @@ class QuickInfoAdapter extends Adapter implements modes.HoverProvider { range: this._textSpanToRange(resource, info.textSpan), htmlContent: [{ text: ts.displayPartsToString(info.displayParts) }] }; - }); + })); } } diff --git a/src/vs/workbench/api/node/extHostLanguageFeatures.ts b/src/vs/workbench/api/node/extHostLanguageFeatures.ts index 3fdc64c0c54..37f7b2d55f1 100644 --- a/src/vs/workbench/api/node/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/node/extHostLanguageFeatures.ts @@ -469,15 +469,7 @@ interface ISuggestion2 extends modes.ISuggestion { id: string; } -class SuggestAdapter implements modes.ISuggestSupport { - - public get triggerCharacters(): string[] { - throw new Error('illegal state'); - } - - public get shouldAutotriggerSuggest(): boolean { - throw new Error('illegal state'); - } +class SuggestAdapter { private _documents: ExtHostModelService; private _provider: vscode.CompletionItemProvider; @@ -997,8 +989,8 @@ export class MainThreadLanguageFeatures { this._registrations[handle] = modes.SuggestRegistry.register(selector, { triggerCharacters: triggerCharacters, shouldAutotriggerSuggest: true, - suggest: (resource: URI, position: IPosition, triggerCharacter?: string): TPromise => { - return this._proxy.$suggest(handle, resource, position); + provideCompletionItems: (model:IReadOnlyModel, position:IEditorPosition, cancellationToken:CancellationToken): Thenable => { + return wireCancellationToken(cancellationToken, this._proxy.$suggest(handle, model.getAssociatedResource(), position)); }, getSuggestionDetails: (resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise => { return this._proxy.$getSuggestionDetails(handle, resource, position, suggestion); diff --git a/src/vs/workbench/test/node/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/node/api/extHostLanguageFeatures.test.ts index 71638343edf..ae3f7518d21 100644 --- a/src/vs/workbench/test/node/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/node/api/extHostLanguageFeatures.test.ts @@ -32,7 +32,7 @@ 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 {provideSignatureHelp} from 'vs/editor/contrib/parameterHints/common/parameterHints'; -import {suggest} from 'vs/editor/contrib/suggest/common/suggest'; +import {provideCompletionItems} from 'vs/editor/contrib/suggest/common/suggest'; import {formatDocument, formatRange, formatAfterKeystroke} from 'vs/editor/contrib/format/common/format'; const defaultSelector = { scheme: 'far' }; @@ -744,7 +744,7 @@ suite('ExtHostLanguageFeatures', function() { }, [])); return threadService.sync().then(() => { - return suggest(model, { lineNumber: 1, column: 1 }, ',').then(value => { + return provideCompletionItems(model, new EditorPosition(1, 1)).then(value => { assert.ok(value.length >= 1); // check for min because snippets and others contribute let [first] = value; assert.equal(first.suggestions.length, 1); @@ -768,7 +768,7 @@ suite('ExtHostLanguageFeatures', function() { }, [])); return threadService.sync().then(() => { - return suggest(model, { lineNumber: 1, column: 1 }, ',').then(value => { + return provideCompletionItems(model, new EditorPosition(1, 1)).then(value => { assert.ok(value.length >= 1); let [first] = value; assert.equal(first.suggestions.length, 1); @@ -792,7 +792,7 @@ suite('ExtHostLanguageFeatures', function() { }, [])); return threadService.sync().then(() => { - return suggest(model, { lineNumber: 1, column: 1 }, ',').then(value => { + return provideCompletionItems(model, new EditorPosition(1, 1)).then(value => { assert.ok(value.length >= 2); let [first, second] = value; assert.equal(first.suggestions.length, 1); @@ -819,7 +819,7 @@ suite('ExtHostLanguageFeatures', function() { return threadService.sync().then(() => { - return suggest(model, { lineNumber: 1, column: 1 }, ',').then(value => { + return provideCompletionItems(model, new EditorPosition(1, 1)).then(value => { assert.equal(value[0].incomplete, undefined); }); }); @@ -835,7 +835,7 @@ suite('ExtHostLanguageFeatures', function() { return threadService.sync().then(() => { - suggest(model, { lineNumber: 1, column: 1 }, ',').then(value => { + provideCompletionItems(model, new EditorPosition(1, 1)).then(value => { assert.equal(value[0].incomplete, true); }); });