0

特定のコンテンツ タイプに intelliSense を提供する Visual Studio 拡張機能を作成しています。私が今直面している問題は、ユーザーが文字を入力したときに Visual Studio が空の行に提供する「自動インデント」の効果です。

ここでは、空の行で (仮想空間上で) 完了セッションが開始されています。

前

他の行にはタブ記号があり、キャレットのある行にはタブがないことに注意してください。

use が入力を開始すると、VS は必要なタブ文字を行に自動的かつ正しく追加します。

後

ここでの問題は、追加されたタブが明らかにユーザー入力の一部になり、その結果CurrentSession.SelectedCompletionSet.SelectBestMatch()またはFilter()メソッドがここで「C」で始まる現在のアイテムを見つけることができないことです (ユーザーが代わりに \t\tC を入力したと考えてください)。

自動インデントを必要としない他の場所でセッションを開始すると、すべて正常に機能します。

何か案が?

編集(詳細):次のようなコードフローを使用しました:

Lua と Clojure では、仮想空間で intelliSense を提供しない (つまり、常に特定の文字セットの後に開始される) ため、この問題に直面することはありません。

もう一方の Ook にも同じ問題がありました。

4

1 に答える 1

2

修正された回答:

ああ、なるほど。明示的なコマンドからではなく、入力による完了トリガーについて言及していると考えて、あなたの質問を解釈しました。C# エディターで "show whitespace" を有効にすると、ここで何を行うかを確認できます。"show completion" コマンドをトリガーすると、明示的に空白が認識されるため、仮想空間で浮遊することはありません。おそらくこれも行う必要があります。(または、シナリオを検出し、ApplicableTo スパンを調整することで最初の入力時に修正することもできますが、おそらく問題に値するものではありません。)

挿入する空白は IEditorOperations から取得できます。したがって、MEF は IEditorOperationsFactoryService をインポートしてから、次のようにします。

var editorOperations = editorOperationsFactoryService.GetEditorOperations(textView);
var whitespace = editorOperations.GetWhitespaceForVirtualSpace(textView.Caret.Position.VirtualBufferPosition);
if (whitespace.Length != 0)
{
    textView.TextBuffer.Insert(textView.Caret.Position.BufferPosition, whitespace);
}

(冗談はさておき、私がこれに答えたとき、Roslyn C# および VB エディターでこれをどのように処理したか知りたいと思っていました。答えは「そうではありません」でしたが、コードの後半で純粋に運が良かったので、フィルタリングは引き続き機能しました。)

元の回答:

問題の説明から、次のように補完を実装していると思われます。文字が入力されようとしていることがわかっており (キーボード フィルターまたは を介し​​てIOleCommandTarget)、追跡スパンが空のスパンである ICompletionSession をトリガーします。現在のキャレット位置。

これを修正する最善の方法は、キーが押されてエディターに入る前ではなく、キーが押された後にセッションをトリガーすることです。これは、C# と VB の補完のために Roslyn 実装で行っていることです。次に、AugmentCompletionSession 呼び出しで CompletionSet を作成するときに、キャレットの周囲の空白以外の文字で構成される「適用対象」スパンを計算します。これを計算する最も簡単な方法GetWordExtentは、テキスト構造ナビゲーターから呼び出すことです。

これにより、他のシナリオが正しく機能します。ユーザーが C と入力し、Esc キーを押して、引き続き識別子を入力するシナリオを考えてみましょう。完了を再度トリガーしたい場合は、とにかく「C」がスパンの一部としてカウントされるように計算を行う必要があります。

于 2013-02-01T17:43:05.600 に答える