9

Visual Studio intellisense の拡張機能を作成していて、C# エディターでカーソルの直前にある項目の型を取得したいと考えています。

現在ITextBuffer、現在のソース ファイルを取得するために使用できる があります。

以下のように、エディターで現在の位置を取得することもできます。

var dte = Microsoft.VisualStudio.Shell.ServiceProvider.GlobalProvider.GetService(typeof(EnvDTE._DTE)) as EnvDTE.DTE;            
TextSelection sel = (TextSelection)dte.ActiveDocument.Selection;

ただし、エディターで現在カーソルの後ろにあるアイテムのタイプを検出する方法がよくわかりません。私はRoslynを使ってみましたが、これはこれよりもはるかに簡単なことのようです. Roslyn はこれを行うための最良のツールですか (ドキュメントをコンパイルし、ドキュメント内の正しい位置に移動することにより)、またはより良い方法があります。

以下は、Roslyn を使用してアイテムのタイプを見つけようとする私の試みです。

ITextSnapshot snapshot = m_textBuffer.CurrentSnapshot;
SnapshotPoint? triggerPoint = session.GetTriggerPoint(snapshot);

var tree = SyntaxTree.ParseCompilationUnit(m_textBuffer.CurrentSnapshot.GetText());

var nodes = tree.GetRoot().DescendantNodes();

var element = nodes.Where(n => n.Span.End <= triggerPoint.Value.Position).Last();

var comp = Compilation.Create("test", syntaxTrees: new[] { tree });
var semModel = comp.GetSemanticModel(tree);

//I cant work out what to do here to get the type as the element doesnt seem to be of the required type
var s = semModel.GetTypeInfo((AttributeSyntax)element);
4

1 に答える 1

3

コンパイラ API は非常に慎重であり、適切な質問をする必要があります (ファジー ロジックではありません)。カーソル位置にあるものの型を単純に見つけるには、ある程度のコンテキストが必要です。最初は明白に思える答えが、他の使い方の正解。

一般的な式の場合、次のようなことができます: (あまり堅牢ではないことに注意してください)

var root = tree.GetRoot();
var token = root.FindToken(pos);
var nearestExpr = token.Parent.AncestorsAndSelf().OfType<ExpressionSyntax>().First();
var type = semModel.GetTypeInfo(nearestExpr).Type;

より包括的なソリューションは、トークンの親ノードをチェックし、そこから移動します。

var node = token.Parent;
if (node is ExpressionSyntax)
{
    type = semModel.GetTypeInfo((ExpressionSyntax)node).Type;
}
else if (node is VariableDeclaratorSyntax && ((VariableDeclaratorSyntax)node).Identifier == token)
{
    type = (TypeSymbol)semModel.GetDeclaredSymbol((VariableDeclaratorSyntax)node);   
}

...

多くの興味深いケースがあり、ソース ファイル内の特定の識別子またはトークンに対応する型として表示したいものは、何を達成しようとしているかによって異なります。

于 2012-07-03T18:54:52.917 に答える