diff --git a/src/vs/editor/contrib/parameterHints/browser/parameterHints.ts b/src/vs/editor/contrib/parameterHints/browser/parameterHints.ts index c844be393dbaefabb9a873004452d3dd124aed62..372ee8bd93efe0eef96e42f959197f47f67eb492 100644 --- a/src/vs/editor/contrib/parameterHints/browser/parameterHints.ts +++ b/src/vs/editor/contrib/parameterHints/browser/parameterHints.ts @@ -7,17 +7,16 @@ import * as nls from 'vs/nls'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { TPromise } from 'vs/base/common/winjs.base'; -import { IKeybindingContextKey, IKeybindingService } from 'vs/platform/keybinding/common/keybindingService'; +import { dispose } from 'vs/base/common/lifecycle'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { EditorAction } from 'vs/editor/common/editorAction'; import { ICommonCodeEditor, IEditorActionDescriptorData, IEditorContribution } from 'vs/editor/common/editorCommon'; import { CommonEditorRegistry, ContextKey, EditorActionDescriptor } from 'vs/editor/common/editorCommonExtensions'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { EditorBrowserRegistry } from 'vs/editor/browser/editorBrowserExtensions'; import { SignatureHelpProviderRegistry } from 'vs/editor/common/modes'; -import { ParameterHintsModel } from './parameterHintsModel'; import { ParameterHintsWidget } from './parameterHintsWidget'; - -const CONTEXT_PARAMETER_HINTS_VISIBLE = 'parameterHintsVisible'; +import { Context } from '../common/parameterHints'; class ParameterHintsController implements IEditorContribution { @@ -28,27 +27,11 @@ class ParameterHintsController implements IEditorContribution { } private editor:ICodeEditor; - private model: ParameterHintsModel; private widget: ParameterHintsWidget; - private parameterHintsVisible: IKeybindingContextKey; - constructor(editor:ICodeEditor, @IKeybindingService keybindingService: IKeybindingService) { + constructor(editor:ICodeEditor, @IInstantiationService instantiationService: IInstantiationService) { this.editor = editor; - this.model = new ParameterHintsModel(this.editor); - this.parameterHintsVisible = keybindingService.createKey(CONTEXT_PARAMETER_HINTS_VISIBLE, false); - this.widget = new ParameterHintsWidget(this.model, this.editor, () => { - this.parameterHintsVisible.set(true); - }, () => { - this.parameterHintsVisible.reset(); - }); - } - - dispose(): void { - this.model.dispose(); - this.model = null; - - this.widget.destroy(); - this.widget = null; + this.widget = instantiationService.createInstance(ParameterHintsWidget, this.editor); } getId(): string { @@ -68,7 +51,11 @@ class ParameterHintsController implements IEditorContribution { } trigger(): void { - this.model.trigger(0); + this.widget.trigger(); + } + + dispose(): void { + this.widget = dispose(this.widget); } } @@ -111,7 +98,7 @@ CommonEditorRegistry.registerEditorCommand( weight, { primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape] }, true, - CONTEXT_PARAMETER_HINTS_VISIBLE, + Context.Visible, handler(c => c.closeWidget()) ); @@ -120,7 +107,7 @@ CommonEditorRegistry.registerEditorCommand( weight, { primary: KeyCode.UpArrow, secondary: [KeyMod.Alt | KeyCode.UpArrow] }, true, - CONTEXT_PARAMETER_HINTS_VISIBLE, + Context.Visible, handler(c =>c.showPrevHint()) ); @@ -129,6 +116,6 @@ CommonEditorRegistry.registerEditorCommand( weight, { primary: KeyCode.DownArrow, secondary: [KeyMod.Alt | KeyCode.DownArrow] }, true, - CONTEXT_PARAMETER_HINTS_VISIBLE, + Context.Visible, handler(c => c.showNextHint()) ); diff --git a/src/vs/editor/contrib/parameterHints/browser/parameterHintsModel.ts b/src/vs/editor/contrib/parameterHints/browser/parameterHintsModel.ts deleted file mode 100644 index f328b23bd25e4c168df49dedd1101ca8886f2bee..0000000000000000000000000000000000000000 --- a/src/vs/editor/contrib/parameterHints/browser/parameterHintsModel.ts +++ /dev/null @@ -1,129 +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 { RunOnceScheduler } from 'vs/base/common/async'; -import { onUnexpectedError } from 'vs/base/common/errors'; -import Event, {Emitter} from 'vs/base/common/event'; -import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; -import { ICommonCodeEditor, ICursorSelectionChangedEvent } from 'vs/editor/common/editorCommon'; -import { SignatureHelpProviderRegistry, SignatureHelp } from 'vs/editor/common/modes'; -import { provideSignatureHelp } from '../common/parameterHints'; - -export interface IHintEvent { - hints: SignatureHelp; -} - -export class ParameterHintsModel extends Disposable { - - static DELAY = 120; // ms - - private _onHint = this._register(new Emitter()); - onHint: Event = this._onHint.event; - - private _onCancel = this._register(new Emitter()); - onCancel: Event = this._onCancel.event; - - private editor: ICommonCodeEditor; - private triggerCharactersListeners: IDisposable[]; - private active: boolean; - private throttledDelayer: RunOnceScheduler; - - constructor(editor:ICommonCodeEditor) { - super(); - - this.editor = editor; - this.triggerCharactersListeners = []; - - this.throttledDelayer = new RunOnceScheduler(() => this.doTrigger(), ParameterHintsModel.DELAY); - - this.active = false; - - this._register(this.editor.onDidChangeModel(e => this.onModelChanged())); - this._register(this.editor.onDidChangeModelMode(_ => this.onModelChanged())); - this._register(this.editor.onDidChangeCursorSelection(e => this.onCursorChange(e))); - this._register(SignatureHelpProviderRegistry.onDidChange(this.onModelChanged, this)); - this.onModelChanged(); - } - - cancel(silent: boolean = false): void { - this.active = false; - - this.throttledDelayer.cancel(); - - if (!silent) { - this._onCancel.fire(void 0); - } - } - - trigger(delay = ParameterHintsModel.DELAY): void { - if (!SignatureHelpProviderRegistry.has(this.editor.getModel())) { - return; - } - - this.cancel(true); - return this.throttledDelayer.schedule(delay); - } - - private doTrigger(): void { - provideSignatureHelp(this.editor.getModel(), this.editor.getPosition()) - .then(null, onUnexpectedError) - .then(result => { - if (!result || result.signatures.length === 0) { - this.cancel(); - this._onCancel.fire(void 0); - return false; - } - - this.active = true; - - const event:IHintEvent = { hints: result }; - this._onHint.fire(event); - return true; - }); - } - - isTriggered():boolean { - return this.active || this.throttledDelayer.isScheduled(); - } - - private onModelChanged(): void { - if (this.active) { - this.cancel(); - } - this.triggerCharactersListeners = dispose(this.triggerCharactersListeners); - - const model = this.editor.getModel(); - if (!model) { - return; - } - - const support = SignatureHelpProviderRegistry.ordered(model)[0]; - if (!support) { - return; - } - - this.triggerCharactersListeners = support.signatureHelpTriggerCharacters.map((ch) => { - return this.editor.addTypingListener(ch, () => { - this.trigger(); - }); - }); - } - - private onCursorChange(e: ICursorSelectionChangedEvent): void { - if (e.source === 'mouse') { - this.cancel(); - } else if (this.isTriggered()) { - this.trigger(); - } - } - - dispose(): void { - this.cancel(true); - this.triggerCharactersListeners = dispose(this.triggerCharactersListeners); - - super.dispose(); - } -} diff --git a/src/vs/editor/contrib/parameterHints/browser/parameterHintsWidget.ts b/src/vs/editor/contrib/parameterHints/browser/parameterHintsWidget.ts index e60a42283ff056d6601b32d0ca4534d096e33f9d..7b45ee3d991668c1c13bc7a2dbeaca577fff0999 100644 --- a/src/vs/editor/contrib/parameterHints/browser/parameterHintsWidget.ts +++ b/src/vs/editor/contrib/parameterHints/browser/parameterHintsWidget.ts @@ -7,27 +7,148 @@ import 'vs/css!./parameterHints'; import nls = require('vs/nls'); -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; import { TPromise } from 'vs/base/common/winjs.base'; import * as dom from 'vs/base/browser/dom'; import aria = require('vs/base/browser/ui/aria/aria'); -import { SignatureHelp, SignatureInformation } from 'vs/editor/common/modes'; +import { SignatureHelp, SignatureInformation, SignatureHelpProviderRegistry } from 'vs/editor/common/modes'; import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser'; -import { IHintEvent, ParameterHintsModel } from './parameterHintsModel'; +import { RunOnceScheduler } from 'vs/base/common/async'; +import { onUnexpectedError } from 'vs/base/common/errors'; +import Event, {Emitter} from 'vs/base/common/event'; +import { ICommonCodeEditor, ICursorSelectionChangedEvent } from 'vs/editor/common/editorCommon'; +import { IKeybindingContextKey, IKeybindingService } from 'vs/platform/keybinding/common/keybindingService'; +import { Context, provideSignatureHelp } from '../common/parameterHints'; const $ = dom.emmet; +export interface IHintEvent { + hints: SignatureHelp; +} + +export class ParameterHintsModel extends Disposable { + + static DELAY = 120; // ms + + private _onHint = this._register(new Emitter()); + onHint: Event = this._onHint.event; + + private _onCancel = this._register(new Emitter()); + onCancel: Event = this._onCancel.event; + + private editor: ICommonCodeEditor; + private triggerCharactersListeners: IDisposable[]; + private active: boolean; + private throttledDelayer: RunOnceScheduler; + + constructor(editor:ICommonCodeEditor) { + super(); + + this.editor = editor; + this.triggerCharactersListeners = []; + + this.throttledDelayer = new RunOnceScheduler(() => this.doTrigger(), ParameterHintsModel.DELAY); + + this.active = false; + + this._register(this.editor.onDidChangeModel(e => this.onModelChanged())); + this._register(this.editor.onDidChangeModelMode(_ => this.onModelChanged())); + this._register(this.editor.onDidChangeCursorSelection(e => this.onCursorChange(e))); + this._register(SignatureHelpProviderRegistry.onDidChange(this.onModelChanged, this)); + this.onModelChanged(); + } + + cancel(silent: boolean = false): void { + this.active = false; + + this.throttledDelayer.cancel(); + + if (!silent) { + this._onCancel.fire(void 0); + } + } + + trigger(delay = ParameterHintsModel.DELAY): void { + if (!SignatureHelpProviderRegistry.has(this.editor.getModel())) { + return; + } + + this.cancel(true); + return this.throttledDelayer.schedule(delay); + } + + private doTrigger(): void { + provideSignatureHelp(this.editor.getModel(), this.editor.getPosition()) + .then(null, onUnexpectedError) + .then(result => { + if (!result || result.signatures.length === 0) { + this.cancel(); + this._onCancel.fire(void 0); + return false; + } + + this.active = true; + + const event:IHintEvent = { hints: result }; + this._onHint.fire(event); + return true; + }); + } + + isTriggered():boolean { + return this.active || this.throttledDelayer.isScheduled(); + } + + private onModelChanged(): void { + if (this.active) { + this.cancel(); + } + this.triggerCharactersListeners = dispose(this.triggerCharactersListeners); + + const model = this.editor.getModel(); + if (!model) { + return; + } + + const support = SignatureHelpProviderRegistry.ordered(model)[0]; + if (!support) { + return; + } + + this.triggerCharactersListeners = support.signatureHelpTriggerCharacters.map((ch) => { + return this.editor.addTypingListener(ch, () => { + this.trigger(); + }); + }); + } + + private onCursorChange(e: ICursorSelectionChangedEvent): void { + if (e.source === 'mouse') { + this.cancel(); + } else if (this.isTriggered()) { + this.trigger(); + } + } + + dispose(): void { + this.cancel(true); + this.triggerCharactersListeners = dispose(this.triggerCharactersListeners); + + super.dispose(); + } +} + interface ISignatureView { top: number; height: number; } -export class ParameterHintsWidget implements IContentWidget { +export class ParameterHintsWidget implements IContentWidget, IDisposable { static ID = 'editor.widget.parameterHintsWidget'; - private editor: ICodeEditor; private model: ParameterHintsModel; + private parameterHintsVisible: IKeybindingContextKey; private element: HTMLElement; private signatures: HTMLElement; private overloads: HTMLElement; @@ -38,20 +159,13 @@ export class ParameterHintsWidget implements IContentWidget { private announcedLabel: string; private disposables: IDisposable[]; - private _onShown: () => void; - private _onHidden: () => void; - // Editor.IContentWidget.allowEditorOverflow allowEditorOverflow = true; - constructor(model: ParameterHintsModel, editor: ICodeEditor, onShown: () => void, onHidden: () => void) { - this._onShown = onShown; - this._onHidden = onHidden; - this.editor = editor; - this.model = null; + constructor(private editor: ICodeEditor, @IKeybindingService keybindingService: IKeybindingService) { + this.model = new ParameterHintsModel(editor); + this.parameterHintsVisible = keybindingService.createKey(Context.Visible, false); this.visible = false; - this.model = model; - this.disposables = []; this.disposables.push(this.model.onHint((e:IHintEvent) => { @@ -62,7 +176,9 @@ export class ParameterHintsWidget implements IContentWidget { this.select(this.currentSignature); })); - this.disposables.push(this.model.onCancel(() => this.hide())); + this.disposables.push(this.model.onCancel(() => { + this.hide(); + })); this.element = $('.editor-widget.parameter-hints-widget'); @@ -109,7 +225,7 @@ export class ParameterHintsWidget implements IContentWidget { return; } - this._onShown(); + this.parameterHintsVisible.set(true); this.visible = true; TPromise.timeout(100).done(() => dom.addClass(this.element, 'visible')); this.editor.layoutContentWidget(this); @@ -120,7 +236,7 @@ export class ParameterHintsWidget implements IContentWidget { return; } - this._onHidden(); + this.parameterHintsVisible.reset(); this.visible = false; this.parameterHints = null; this.announcedLabel = null; @@ -318,7 +434,11 @@ export class ParameterHintsWidget implements IContentWidget { return ParameterHintsWidget.ID; } - destroy(): void { + trigger(): void { + this.model.trigger(0); + } + + dispose(): void { this.disposables = dispose(this.disposables); this.model = null; } diff --git a/src/vs/editor/contrib/parameterHints/common/parameterHints.ts b/src/vs/editor/contrib/parameterHints/common/parameterHints.ts index bcfe63893d9681cba3716251d8b435382d86ef75..77870db1739a95f570897192bb4506bf5205484d 100644 --- a/src/vs/editor/contrib/parameterHints/common/parameterHints.ts +++ b/src/vs/editor/contrib/parameterHints/common/parameterHints.ts @@ -12,6 +12,10 @@ import { SignatureHelp, SignatureHelpProviderRegistry } from 'vs/editor/common/m import { asWinJsPromise } from 'vs/base/common/async'; import { Position } from 'vs/editor/common/core/position'; +export const Context = { + Visible: 'parameterHintsVisible' +}; + export function provideSignatureHelp(model:IReadOnlyModel, position:Position): TPromise { const support = SignatureHelpProviderRegistry.ordered(model)[0];