2012-07-03 18 views
9

Piszę rozszerzenie do Visual Studio intellisense i chciałbym uzyskać typ elementu tuż przed kursorem w edytorze C#.Znajdź typ elementu w bieżącej pozycji w oknie edytora C#

Obecnie mam ITextBuffer, którego mogę użyć do pobrania bieżącego pliku źródłowego.

mogę również uzyskać aktualną pozycję w redakcji, jak poniżej:

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

Jednak nie jestem zbyt pewny jak wykryć typ elementu obecnie za kursorem w edytorze. Próbowałem używać Roslyn, ale wygląda na to, że powinno to być znacznie prostsze niż to. Czy Roslyn jest najlepszym narzędziem do tego (poprzez kompilację dokumentu i nawigację do właściwej pozycji w dokumencie), czy jest lepszy sposób?

Poniżej moja próba znalezienia typ elementu za pomocą Roslyn: (. Nie logiki rozmytej)

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); 
+0

+1 Ciekawie będzie posłuchać, co Eric ma do powiedzenia na ten temat. – MoonKnight

+2

Dlaczego nie używasz 'ITextView.Caret.Position'? – leppie

+0

@leppie im całkiem nowy do SDK VS, ale to brzmi jak o wiele łatwiejszy sposób, aby uzyskać obecny kursor pos, ja go zmienię –

Odpowiedz

3

kompilatora API są bardzo celowe i wymaga, aby zadać właściwe pytanie prostu znalezienie typ rzecz na pozycji kursora wymaga pewnego kontekstu, a odpowiedź, która na pierwszy rzut oka może wydawać ci się oczywista, może nie być poprawną odpowiedzią na inne zastosowania.

Dla ogólnych wyrażeń można zrobić coś takiego: (Uwaga to nie jest bardzo solidna)

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

Bardziej kompleksowe rozwiązanie byłoby sprawdzić węzeł nadrzędny tokena i go stamtąd:

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); 
} 

...

Istnieje wiele interesujących przypadków, które mają być wyświetlane jako typ odpowiadający konkretnemu identyfikatorowi lub tokenowi w źródle f ile może się różnić w zależności od tego, co próbujesz osiągnąć.

+0

Niesamowite, że wygląda jak po, źle wypróbuj dziś wieczorem. –

+0

Dałem to, ale mam problem z wywołaniem GetTypeInfo (IdentifierNameSyntax), po uruchomieniu go otrzymuję ExtendedErrorTypeSymbol z powrotem, jakikolwiek pomysł jak to obejść? –

Powiązane problemy