Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
jrieken authored and hwhung0111 committed Aug 28, 2019
1 parent 52abea9 commit 2e58035
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 6 deletions.
50 changes: 46 additions & 4 deletions src/vs/editor/contrib/suggest/suggestController.ts
Expand Up @@ -7,7 +7,7 @@ import { alert } from 'vs/base/browser/ui/aria/aria';
import { isNonEmptyArray } from 'vs/base/common/arrays';
import { onUnexpectedError } from 'vs/base/common/errors';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { dispose, IDisposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { dispose, IDisposable, DisposableStore, toDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorAction, EditorCommand, registerEditorAction, registerEditorCommand, registerEditorContribution, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { EditOperation } from 'vs/editor/common/core/editOperation';
Expand All @@ -33,9 +33,49 @@ import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerServ
import { IdleValue } from 'vs/base/common/async';
import { isObject } from 'vs/base/common/types';
import { CommitCharacterController } from './suggestCommitCharacters';
import { IPosition } from 'vs/editor/common/core/position';
import { TrackedRangeStickiness, ITextModel } from 'vs/editor/common/model';

const _sticky = false; // for development purposes only

class LineSuffix {

private readonly _marker: string[] | undefined;

constructor(private readonly _model: ITextModel, private readonly _position: IPosition) {
// spy on what's happening right of the cursor. two cases:
// 1. end of line -> check that it's still end of line
// 2. mid of line -> add a marker and compute the delta
const maxColumn = _model.getLineMaxColumn(_position.lineNumber);
if (maxColumn !== _position.column) {
const offset = _model.getOffsetAt(_position);
const end = _model.getPositionAt(offset + 1);
this._marker = _model.deltaDecorations([], [{
range: Range.fromPositions(_position, end),
options: { stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges }
}]);
}
}

dispose(): void {
if (this._marker) {
this._model.deltaDecorations(this._marker, []);
}
}

delta(position: IPosition): number {
if (this._position.lineNumber !== position.lineNumber) {
return 0;
} else if (this._marker) {
const range = this._model.getDecorationRange(this._marker[0]);
const end = this._model.getOffsetAt(range!.getStartPosition());
return end - this._model.getOffsetAt(position);
} else {
return this._model.getLineMaxColumn(position.lineNumber) - position.column;
}
}
}

export class SuggestController implements IEditorContribution {

private static readonly ID: string = 'editor.contrib.suggestController';
Expand All @@ -47,9 +87,9 @@ export class SuggestController implements IEditorContribution {
private readonly _model: SuggestModel;
private readonly _widget: IdleValue<SuggestWidget>;
private readonly _alternatives: IdleValue<SuggestAlternatives>;
private readonly _lineSuffix = new MutableDisposable<LineSuffix>();
private readonly _toDispose = new DisposableStore();


constructor(
private _editor: ICodeEditor,
@IEditorWorkerService editorWorker: IEditorWorkerService,
Expand Down Expand Up @@ -115,6 +155,7 @@ export class SuggestController implements IEditorContribution {

this._toDispose.add(this._model.onDidTrigger(e => {
this._widget.getValue().showTriggered(e.auto, e.shy ? 250 : 50);
this._lineSuffix.value = new LineSuffix(this._editor.getModel()!, e.position);
}));
this._toDispose.add(this._model.onDidSuggest(e => {
if (!e.shy) {
Expand All @@ -123,7 +164,7 @@ export class SuggestController implements IEditorContribution {
}
}));
this._toDispose.add(this._model.onDidCancel(e => {
if (this._widget && !e.retrigger) {
if (!e.retrigger) {
this._widget.getValue().hideWidget();
}
}));
Expand Down Expand Up @@ -154,6 +195,7 @@ export class SuggestController implements IEditorContribution {
this._toDispose.dispose();
this._widget.dispose();
this._model.dispose();
this._lineSuffix.dispose();
}

protected _insertSuggestion(event: ISelectedSuggestion | undefined, keepAlternativeSuggestions: boolean, undoStops: boolean): void {
Expand Down Expand Up @@ -192,7 +234,7 @@ export class SuggestController implements IEditorContribution {
}

const overwriteBefore = position.column - suggestion.range.startColumn;
const overwriteAfter = suggestion.range.endColumn - position.column;
const overwriteAfter = (suggestion.range.endColumn - position.column) + this._lineSuffix.value!.delta(this._editor.getPosition());

SnippetController2.get(this._editor).insert(insertText, {
overwriteBefore: overwriteBefore + columnDelta,
Expand Down
5 changes: 3 additions & 2 deletions src/vs/editor/contrib/suggest/suggestModel.ts
Expand Up @@ -10,7 +10,7 @@ import { Emitter, Event } from 'vs/base/common/event';
import { IDisposable, dispose, DisposableStore, isDisposable } from 'vs/base/common/lifecycle';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { CursorChangeReason, ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
import { Position } from 'vs/editor/common/core/position';
import { Position, IPosition } from 'vs/editor/common/core/position';
import { Selection } from 'vs/editor/common/core/selection';
import { ITextModel, IWordAtPosition } from 'vs/editor/common/model';
import { CompletionItemProvider, StandardTokenType, CompletionContext, CompletionProviderRegistry, CompletionTriggerKind, CompletionItemKind, completionKindFromString } from 'vs/editor/common/modes';
Expand All @@ -28,6 +28,7 @@ export interface ICancelEvent {
export interface ITriggerEvent {
readonly auto: boolean;
readonly shy: boolean;
readonly position: IPosition;
}

export interface ISuggestEvent {
Expand Down Expand Up @@ -365,7 +366,7 @@ export class SuggestModel implements IDisposable {
// Cancel previous requests, change state & update UI
this.cancel(retrigger);
this._state = auto ? State.Auto : State.Manual;
this._onDidTrigger.fire({ auto, shy: context.shy });
this._onDidTrigger.fire({ auto, shy: context.shy, position: this._editor.getPosition() });

// Capture context when request was sent
this._context = ctx;
Expand Down

0 comments on commit 2e58035

Please sign in to comment.