4

Visual Studio拡張パッケージのVSSDKとRoslyn SDKの間でブリッジしようとしていますが、これに苦労しています。 Visual Studioから与えられたActivePoint.AbsoluteCharOffsetは、FindToken(オフセット)を使用しているときにRoslynから取得した要素と一致しません。私は、これが私の現在の作業ハックに基づいて各側がEOL文字をどのように数えるかとは関係があると確信していますが、私のハックが長期的に成立するのは100%ではありません。Visual Studioのテキスト選択(キャレット位置)からRoslyn SyntaxTokenを取得

私のハックは、この行です:charOffset += point.Line;

私はオフセットのcharへの行数を追加し、これは私が私がactivepointによって無視されているすべての改行文字に追加してい推測して動作するようですカウント。

ヘルパー

private VisualStudioWorkspace workspace = null; 
public RoslynUtilities(VisualStudioWorkspace workspace) 
{ 
    this.workspace = workspace; 
} 
public Solution Solution { get { return workspace.CurrentSolution; } } 
public Document GetDocumentFromPath(string fullPath) 
{ 
    foreach (Project proj in this.Solution.Projects) 
    {    
     foreach (Document doc in proj.Documents) 
     { 
      if (doc.FilePath == fullPath) 
       return doc;     
     } 
    } 
    return null; 
} 
public SyntaxTree GetSyntaxTreeFromDocumentPath(string fullPath) 
{ 
    Document doc = GetDocumentFromPath(fullPath); 
    if (doc != null) 
     return doc.GetSyntaxTreeAsync().Result; 
    else 
     return null; 
} 
public SyntaxNode GetNodeByFilePosition(string fullPath, int absoluteChar) 
{ 
    SyntaxTree tree = GetSyntaxTreeFromDocumentPath(fullPath); 
    if(tree != null) 
    { 
     var compUnit = tree.GetCompilationUnitRoot(); 
     if(compUnit != null) 
     { 
      return compUnit.FindToken(absoluteChar, true).Parent; 
     } 
    } 
    return null;       
} 
private VisualStudioWorkspace GetRoslynWorkspace() 
    { 
     var componentModel = (IComponentModel)GetGlobalService(typeof(SComponentModel)); 
     return componentModel.GetService<VisualStudioWorkspace>(); 
    } 

メインパート

EnvDTE80.DTE2 applicationObject = (EnvDTE80.DTE2)GetService(typeof(SDTE)); 
EnvDTE.TextSelection ts = applicationObject.ActiveWindow.Selection as EnvDTE.TextSelection; 
if (ts == null) 
    return; 

EnvDTE.VirtualPoint point = ts.ActivePoint; 
int charOffset = point.AbsoluteCharOffset; 
charOffset += point.Line;//HACK ALERT 

Parse.Roslyn.RoslynUtilities roslyn = new Parse.Roslyn.RoslynUtilities(GetRoslynWorkspace()); 
SyntaxNode node = roslyn.GetNodeByFilePosition(applicationObject.ActiveDocument.FullName, charOffset); 

答えて

10

私は非常ロスリンと対話する代わりにEnvDTEインタフェースのMicrosoft.VisualStudio.Text.Editor.IWpfTextViewバッファからMicrosoft.VisualStudio.Text.SnapshotPointを使用してお勧めします。

メインのコードは次のようになります。

Microsoft.VisualStudio.Text.Editor.IWpfTextView textView = 
    GetTextView(); 

Microsoft.VisualStudio.Text.SnapshotPoint caretPosition = 
    textView.Caret.Position.BufferPosition; 

Microsoft.CodeAnalysis.Document document = 
    caretPosition.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); 

Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax invocationExpressionNode = 
    document.GetSyntaxRootAsync().Result. 
     FindToken(caretPosition).Parent.AncestorsAndSelf(). 
     OfType<Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax>(). 
     FirstOrDefault(); 

は完全例えばCreate a typed variable from the current method invocationを参照してください。

+0

ありがとうございます!私はそれを切り替え、.AncestorsAndSelfで始まるすべてを単に削除することで最後の行を編集し、私が望むことをしました。何らかの理由で私の古い方法は常に+2文字で、これは何を返しますが、これは正しいです。 –

+0

誰かがこの仲間を怒らせている。 –

+2

Microsoft.Codeanalysis 2.0で 'GetOpenDocumentInCurrentContextWithChanges'拡張メソッドを使用すると、(これまでのところ、私が文書化されていないのが分かるように)Microsoft.VisualStudio 15.0への依存性が導入され、プラグインが作成されるようになりました。 Visual Studio 2015では動作しません。したがって、この方法を使いたい場合は、Visual Studio 2017を使用することに制限したくない場合は、Microsoft.CodeAnalysis 1.3.2をビルドする必要があります。 –

関連する問題