2012-07-03 11 views
9

Tôi đang viết phần mở rộng cho Visual Studio intellisense và muốn nhận loại mục ngay trước con trỏ trong trình soạn thảo C#.Tìm loại mục ở vị trí hiện tại trong cửa sổ soạn thảo C#

Tôi hiện có một số ITextBuffer mà tôi có thể sử dụng để lấy tệp nguồn hiện tại.

Tôi cũng có thể có được vị trí hiện tại trong trình soạn thảo như sau:

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

Tuy nhiên tôi không quá chắc chắn làm thế nào để phát hiện các loại mặt hàng đó hiện đằng sau con trỏ trong trình soạn thảo. Tôi đã thử sử dụng Roslyn nhưng có vẻ như đây là một điều đơn giản hơn nhiều để làm hơn thế này. Roslyn có phải là công cụ tốt nhất để thực hiện điều này hay không (thông qua biên dịch tài liệu và điều hướng đến vị trí chính xác trong tài liệu) hoặc có cách nào tốt hơn.

Dưới đây là nỗ lực của tôi trong việc tìm các loại mặt hàng sử dụng Roslyn: (. Không logic mờ)

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 Thật thú vị khi nghe những gì Eric nói về điều này. – MoonKnight

+2

Tại sao bạn không sử dụng 'ITextView.Caret.Position'? – leppie

+0

@leppie im khá mới với VS sdk nhưng âm thanh đó giống như một cách dễ dàng hơn nhiều để có được vị trí con trỏ hiện tại, tôi sẽ thay đổi nó –

Trả lời

3

Trình biên dịch của API rất thận trọng và yêu cầu bạn phải đặt câu hỏi đúng Đơn giản chỉ cần tìm loại điều tại vị trí con trỏ đòi hỏi một số bối cảnh, và câu trả lời có vẻ hiển nhiên với bạn lúc đầu có thể không phải là câu trả lời đúng cho các mục đích sử dụng khác.

Đối với biểu thức chung bạn có thể làm một cái gì đó như thế này: (Lưu ý nó không phải là rất mạnh mẽ)

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

Một giải pháp toàn diện hơn sẽ kiểm tra các nút cha của token và đi từ đó:

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

...

Có rất nhiều trường hợp thú vị và những gì bạn muốn hiển thị dưới dạng loại tương ứng với bất kỳ số nhận dạng hoặc mã thông báo cụ thể nào trong nguồn f ile có thể khác nhau tùy thuộc vào những gì bạn đang cố gắng hoàn thành.

+0

Tuyệt vời trông giống như những gì im sau, bệnh thử nó ra tối nay. –

+0

Tôi đã cho rằng một đi nhưng tôi gặp rắc rối với các GetTypeInfo (IdentifierNameSyntax) cuộc gọi, khi tôi chạy nó tôi nhận được một ExtendedErrorTypeSymbol trở lại, bất kỳ ý tưởng làm thế nào để có được xung quanh này? –