move more logic into suggest model

This commit is contained in:
Johannes Rieken 2016-08-17 12:36:31 +02:00
parent 7db3469c87
commit d7771265a8
2 changed files with 95 additions and 88 deletions

View file

@ -7,13 +7,10 @@
import * as nls from 'vs/nls';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { forEach } from 'vs/base/common/collections';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ICommonCodeEditor, IEditorContribution, EditorContextKeys, ModeContextKeys } from 'vs/editor/common/editorCommon';
import { editorAction, ServicesAccessor, EditorAction, EditorCommand, CommonEditorRegistry } from 'vs/editor/common/editorCommonExtensions';
import { ISuggestSupport, SuggestRegistry } from 'vs/editor/common/modes';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorBrowserRegistry } from 'vs/editor/browser/editorBrowserExtensions';
import { getSnippetController, CodeSnippet } from 'vs/editor/contrib/snippet/common/snippet';
@ -31,7 +28,7 @@ export class SuggestController implements IEditorContribution {
private model: SuggestModel;
private widget: SuggestWidget;
private triggerCharacterListeners: IDisposable[];
private toDispose: IDisposable[] = [];
constructor(
@ -39,22 +36,12 @@ export class SuggestController implements IEditorContribution {
@IInstantiationService instantiationService: IInstantiationService
) {
this.model = new SuggestModel(this.editor);
this.widget = instantiationService.createInstance(SuggestWidget, this.editor);
this.toDispose.push(this.model.onDidTrigger(e => this.widget.showTriggered(e)));
this.toDispose.push(this.model.onDidSuggest(e => this.widget.showSuggestions(e)));
this.toDispose.push(this.model.onDidCancel(e => this.widget.showDidCancel(e)));
this.widget = instantiationService.createInstance(SuggestWidget, this.editor);
this.toDispose.push(this.widget.onDidSelect(this.onDidSelectItem, this));
this.triggerCharacterListeners = [];
this.toDispose.push(editor.onDidChangeConfiguration(() => this.update()));
this.toDispose.push(editor.onDidChangeModel(() => this.update()));
this.toDispose.push(editor.onDidChangeModelMode(() => this.update()));
this.toDispose.push(SuggestRegistry.onDidChange(this.update, this));
this.update();
}
getId(): string {
@ -63,8 +50,6 @@ export class SuggestController implements IEditorContribution {
dispose(): void {
this.toDispose = dispose(this.toDispose);
this.triggerCharacterListeners = dispose(this.triggerCharacterListeners);
if (this.widget) {
this.widget.dispose();
this.widget = null;
@ -88,39 +73,6 @@ export class SuggestController implements IEditorContribution {
this.model.cancel();
}
private update(): void {
this.triggerCharacterListeners = dispose(this.triggerCharacterListeners);
if (this.editor.getConfiguration().readOnly
|| !this.editor.getModel()
|| !this.editor.getConfiguration().contribInfo.suggestOnTriggerCharacters) {
return;
}
const supportsByTriggerCharacter: { [ch: string]: ISuggestSupport[] } = Object.create(null);
for (const support of SuggestRegistry.all(this.editor.getModel())) {
if (isFalsyOrEmpty(support.triggerCharacters)) {
continue;
}
for (const ch of support.triggerCharacters) {
const array = supportsByTriggerCharacter[ch];
if (!array) {
supportsByTriggerCharacter[ch] = [support];
} else {
array.push(support);
}
}
}
forEach(supportsByTriggerCharacter, entry => {
this.triggerCharacterListeners.push(this.editor.addTypingListener(entry.key, () => {
this.model.trigger(true, false, entry.value);
}));
});
}
triggerSuggest(): void {
this.model.trigger(false, false);
this.editor.focus();

View file

@ -5,6 +5,8 @@
'use strict';
import {onUnexpectedError} from 'vs/base/common/errors';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { forEach } from 'vs/base/common/collections';
import Event, { Emitter } from 'vs/base/common/event';
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
import {startsWith} from 'vs/base/common/strings';
@ -140,8 +142,9 @@ enum State {
export class SuggestModel implements IDisposable {
private toDispose: IDisposable[];
private autoSuggestDelay: number;
private toDispose: IDisposable[] = [];
private quickSuggestDelay: number;
private triggerCharacterListeners: IDisposable[] = [];
private triggerAutoSuggestPromise: TPromise<void>;
private state: State;
@ -171,15 +174,83 @@ export class SuggestModel implements IDisposable {
this.incomplete = false;
this.context = null;
this.toDispose = [];
this.toDispose.push(this._onDidCancel, this._onDidSuggest, this._onDidTrigger);
this.toDispose.push(this.editor.onDidChangeConfiguration(() => this.onEditorConfigurationChange()));
this.toDispose.push(this.editor.onDidChangeCursorSelection(e => this.onCursorChange(e)));
this.toDispose.push(this.editor.onDidChangeModel(() => this.cancel()));
this.toDispose.push(SuggestRegistry.onDidChange(this.onSuggestRegistryChange, this));
this.onEditorConfigurationChange();
// wire up various listeners
this.toDispose.push(this.editor.onDidChangeModel(() => {
this.updateTriggerCharacters();
this.cancel();
}));
this.toDispose.push(editor.onDidChangeModelMode(() => {
this.updateTriggerCharacters();
this.cancel();
}));
this.toDispose.push(this.editor.onDidChangeConfiguration(() => {
this.updateTriggerCharacters();
this.updateQuickSuggest();
}));
this.toDispose.push(SuggestRegistry.onDidChange(() => {
this.updateTriggerCharacters();
this.updateActiveSuggestSession();
}));
this.toDispose.push(this.editor.onDidChangeCursorSelection(e => {
this.onCursorChange(e);
}));
this.updateTriggerCharacters();
this.updateQuickSuggest();
}
dispose(): void {
dispose([this._onDidCancel, this._onDidSuggest, this._onDidTrigger]);
this.toDispose = dispose(this.toDispose);
this.triggerCharacterListeners = dispose(this.triggerCharacterListeners);
this.cancel();
}
// --- handle configuration & precondition changes
private updateQuickSuggest(): void {
this.quickSuggestDelay = this.editor.getConfiguration().contribInfo.quickSuggestionsDelay;
if (isNaN(this.quickSuggestDelay) || (!this.quickSuggestDelay && this.quickSuggestDelay !== 0) || this.quickSuggestDelay < 0) {
this.quickSuggestDelay = 10;
}
}
private updateTriggerCharacters(): void {
this.triggerCharacterListeners = dispose(this.triggerCharacterListeners);
if (this.editor.getConfiguration().readOnly
|| !this.editor.getModel()
|| !this.editor.getConfiguration().contribInfo.suggestOnTriggerCharacters) {
return;
}
const supportsByTriggerCharacter: { [ch: string]: ISuggestSupport[] } = Object.create(null);
for (const support of SuggestRegistry.all(this.editor.getModel())) {
if (isFalsyOrEmpty(support.triggerCharacters)) {
continue;
}
for (const ch of support.triggerCharacters) {
const array = supportsByTriggerCharacter[ch];
if (!array) {
supportsByTriggerCharacter[ch] = [support];
} else {
array.push(support);
}
}
}
forEach(supportsByTriggerCharacter, entry => {
this.triggerCharacterListeners.push(this.editor.addTypingListener(entry.key, () => {
this.trigger(true, false, entry.value);
}));
});
}
// --- trigger/retrigger/cancel suggest
cancel(retrigger: boolean = false): boolean {
const actuallyCanceled = this.state !== State.Idle;
@ -203,8 +274,14 @@ export class SuggestModel implements IDisposable {
return actuallyCanceled;
}
private isAutoSuggest(): boolean {
return this.state === State.Auto;
private updateActiveSuggestSession(): void {
if (this.state !== State.Idle) {
if (!SuggestRegistry.has(this.editor.getModel())) {
this.cancel();
} else {
this.trigger(this.state === State.Auto, true);
}
}
}
private onCursorChange(e: ICursorSelectionChangedEvent): void {
@ -241,7 +318,7 @@ export class SuggestModel implements IDisposable {
this.cancel();
if (ctx.shouldAutoTrigger()) {
this.triggerAutoSuggestPromise = TPromise.timeout(this.autoSuggestDelay);
this.triggerAutoSuggestPromise = TPromise.timeout(this.quickSuggestDelay);
this.triggerAutoSuggestPromise.then(() => {
this.triggerAutoSuggestPromise = null;
this.trigger(true);
@ -255,19 +332,6 @@ export class SuggestModel implements IDisposable {
}
}
private onSuggestRegistryChange(): void {
if (this.state === State.Idle) {
return;
}
if (!SuggestRegistry.has(this.editor.getModel())) {
this.cancel();
return;
}
this.trigger(this.state === State.Auto, true);
}
public trigger(auto: boolean, retrigger: boolean = false, onlyFrom?: ISuggestSupport[]): void {
const model = this.editor.getModel();
@ -311,6 +375,10 @@ export class SuggestModel implements IDisposable {
}).then(null, onUnexpectedError);
}
private isAutoSuggest(): boolean {
return this.state === State.Auto;
}
public getTriggerPosition(): IPosition {
const {lineNumber, column} = this.context;
return { lineNumber, column };
@ -355,17 +423,4 @@ export class SuggestModel implements IDisposable {
});
}
}
private onEditorConfigurationChange(): void {
this.autoSuggestDelay = this.editor.getConfiguration().contribInfo.quickSuggestionsDelay;
if (isNaN(this.autoSuggestDelay) || (!this.autoSuggestDelay && this.autoSuggestDelay !== 0) || this.autoSuggestDelay < 0) {
this.autoSuggestDelay = 10;
}
}
dispose(): void {
this.toDispose = dispose(this.toDispose);
this.cancel();
}
}