web-dev-qa-db-ja.com

Roslynを使用したメソッドへのすべての参照の検索

.csファイルのグループをスキャンして、どのファイルがNullable<T>Valueプロパティを呼び出しているかを確認しようとしています(すべての参照を検索しています)。たとえば、これは一致します。

class Program
{
    static void Main()
    {
        int? nullable = 123;
        int value = nullable.Value;
    }
}

Roslynについて知り、いくつかのサンプルを見ましたが、それらの多くは古く、APIが巨大です。これを行うにはどうすればよいですか?

構文ツリーを解析した後、行き詰まっています。これは私がこれまでに持っているものです:

public static void Analyze(string sourceCode)
{
    var tree = CSharpSyntaxTree.ParseText(sourceCode);

    tree./* ??? What goes here? */
}
19
James Ko

あなたはおそらく SymbolFinder クラス、特に FindAllReferences メソッドを探しています。

Roslynに慣れていないようです。私は、人々がRoslynを紹介するのに役立つ一連のブログ投稿 今すぐRoslynを学ぶ を用意しています。

@SLaksが言及しているように、私がカバーするセマンティックモデルにアクセスする必要があります パート7:セマンティックモデルの概要

以下は、APIの使用方法を示すサンプルです。可能であれば、このようにMSBuildWorkspaceに作成する代わりに、AdHocWorkspaceを使用してプロジェクトをディスクからロードします。

var mscorlib = PortableExecutableReference.CreateFromAssembly(typeof(object).Assembly);
var ws = new AdhocWorkspace();
//Create new solution
var solId = SolutionId.CreateNewId();
var solutionInfo = SolutionInfo.Create(solId, VersionStamp.Create());
//Create new project
var project = ws.AddProject("Sample", "C#");
project = project.AddMetadataReference(mscorlib);
//Add project to workspace
ws.TryApplyChanges(project.Solution);
string text = @"
class C
{
    void M()
    {
        M();
        M();
    }
}";
var sourceText = SourceText.From(text);
//Create new document
var doc = ws.AddDocument(project.Id, "NewDoc", sourceText);
//Get the semantic model
var model = doc.GetSemanticModelAsync().Result;
//Get the syntax node for the first invocation to M()
var methodInvocation = doc.GetSyntaxRootAsync().Result.DescendantNodes().OfType<InvocationExpressionSyntax>().First();
var methodSymbol = model.GetSymbolInfo(methodInvocation).Symbol;
//Finds all references to M()
var referencesToM = SymbolFinder.FindReferencesAsync(methodSymbol,  doc.Project.Solution).Result;
43
JoshVarty

問題のジャーナルと最終的な修正として、RoslynにVS2017を使用させました:

空のVS2017プロジェクトの理由は、MSBuildWorkspace WorkspaceFailedイベントがフックされると表示されます。

失敗の最初のラウンドは:

MSB0001:内部MSBuildエラー:Microsoft.Build.Utilities.ToolLocationHelperのタイプ情報がMicrosoft.Build.Utilities.ToolLocationHelper、Microsoft.Build.Utilities.Core、Version = 15.1.0.0、Culture = neutral、PublicKeyTokenとしてホワイトリストキャッシュに存在しました= b03f5f7f11d50a3aがタイプをロードできませんでした。予期せずnull])

これは、NuGetパッケージMicrosoft.Build.Locator 1.1.2およびMicrosoft.Build.Utilities.Core 15.9.20をインストールすることで修正されました

2回目の失敗は次のとおりです。

ファイル「C:\ Users ... vbproj」の処理中にMsbuildが次のメッセージで失敗しました:C:\ Program Files(x86)\ Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets: (1491、5):「Microsoft.Build.Tasks.AssignProjectConfiguration」タスクをアセンブリMicrosoft.Build.Tasks.Core、Version = 15.1.0.0、Culture = neutral、PublicKeyToken = b03f5f7f11d50a3aからロードできませんでした。ファイルまたはアセンブリ 'Microsoft.Build.Tasks.Core、Version = 15.1.0.0、Culture = neutral、PublicKeyToken = b03f5f7f11d50a3a'またはその依存関係の1つを読み込めませんでした。システムは、指定されたファイルを見つけることができません。宣言が正しいこと、アセンブリとそのすべての依存関係が利用可能であること、およびタスクにMicrosoft.Build.Framework.ITaskを実装するパブリッククラスが含まれていることを確認してください。])

これは、NuGet Microsoft.Build.Tasks.Core 15.9.20を追加することで修正されました

失敗の3番目のラウンドは、次のとおりです。===ファイル「C:\ Users ... vbproj」をメッセージで処理するとMsbuildが失敗しました:C:\ Program Files(x86)\ Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets:(1657、5):アセンブリ "C:\ Program Files(x86)\ Microsoft Visual Studio\2017\Enterprise\Common7\IDE \から" GetReferenceNearestTargetFrameworkTask "タスクをインスタンス化できませんでしたCommonExtensions\Microsoft\NuGet\NuGet.Build.Tasks.dll "。コンピューターにインストールされているものと同じバージョンのMicrosoft.Build.Frameworkアセンブリを使用してタスクアセンブリがビルドされていること、およびホストアプリケーションにMicrosoft.Build.Frameworkのバインディングリダイレクトがないことを確認してください。タイプ 'NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask'をタイプ 'Microsoft.Build.Framework.ITask'にキャストできません。])

プロジェクトのMicrosoft.Build.Framework.dll = 15.1.0.0ですが、メッセージには「MSBuild\15.0\Bin」と記載されています。

App.configに追加-修正しました! cf ここにリンクの説明を入力 VS2017ソリューションからプロジェクトをロードできるようになりました

  <!-- vvv Roslyn manual fixup https://github.com/Microsoft/msbuild/issues/2369 -->
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.Build.Framework" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
  </dependentAssembly>
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.Build" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
  </dependentAssembly>
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.Build.Utilities.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
  </dependentAssembly>
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.Build.Tasks.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
  </dependentAssembly>
  <!-- ^^^ Roslyn manual fixup https://github.com/Microsoft/msbuild/issues/2369 -->
1
brewmanz