TLDR;
私のVisual Studioソリューションで、インデックスプロパティMicrosoft.Extensions.Localization.IStringLocalizer.Item[String]
の参照のconst文字列パラメータをすべて検索するにはどうすればよいですか?すべてのソースコードはC#で書かれています。このソリューションは、MVCカミソリのビューもサポートする必要があります。Roslynを使用してVisual Studioソリューション内のすべての参照を検索します。
追加情報
私はRoslynがこの質問に対する答えだと信じています。しかし、私はまだこれを達成するためにAPIを通して自分の道を見つけていません。私は、構文木、コンパイル、またはセマンティックモデルのどちらを使うべきかについても不明です。以下は他のQに基づいた試みです&ここでstackoverflowで。好きなことがあれば、この必要性の理由を読むことができますhere。
namespace AspNetCoreLocalizationKeysExtractor
{
using System;
using System.Linq;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.MSBuild;
class Program
{
static void Main(string[] args)
{
string solutionPath = @"..\source\MySolution.sln";
var msWorkspace = MSBuildWorkspace.Create();
var solution = msWorkspace.OpenSolutionAsync(solutionPath).Result;
foreach (var project in solution.Projects.Where(p => p.AssemblyName.StartsWith("MyCompanyNamespace.")))
{
var compilation = project.GetCompilationAsync().Result;
var interfaceType = compilation.GetTypeByMetadataName("Microsoft.Extensions.Localization.IStringLocalizer");
// TODO: Find the indexer based on the name ("Item"/"this"?) and/or on the parameter and return type
var indexer = interfaceType.GetMembers().First();
var indexReferences = SymbolFinder.FindReferencesAsync(indexer, solution).Result.ToList();
foreach (var symbol in indexReferences)
{
// TODO: How to get output comprised by "a location" like e.g. a namespace qualified name and the parameter of the index call. E.g:
//
// MyCompanyNamespace.MyLib.SomeClass: "Please try again"
// MyCompanyNamespace.MyWebApp.Views.Shared._Layout: "Welcome to our cool website"
Console.WriteLine(symbol.Definition.ToDisplayString());
}
}
}
}
}
更新:回避策
私は簡単な回避策に頼ることにしました@Oxoronから大きな助けにもかかわらず。現在、RoslynはSymbolFinder.FindReferencesAsync
を使って参照を見つけることができません。これは "サイレント" msbuildの失敗によると思われます。これらのエラーは、このように使用できます。
msWorkspace.WorkspaceFailed += (sender, eventArgs) =>
{
Console.Error.WriteLine($"{eventArgs.Diagnostic.Kind}: {eventArgs.Diagnostic.Message}");
Console.Error.WriteLine();
};
と
var compilation = project.GetCompilationAsync().Result;
foreach (var diagnostic in compilation.GetDiagnostics())
Console.Error.WriteLine(diagnostic);
私の回避策は、おおよそ次のようにされています。もちろん
public void ParseSource()
{
var sourceFiles = from f in Directory.GetFiles(SourceDir, "*.cs*", SearchOption.AllDirectories)
where f.EndsWith(".cs") || f.EndsWith(".cshtml")
where !f.Contains(@"\obj\") && !f.Contains(@"\packages\")
select f;
// _["Hello, World!"]
// _[@"Hello, World!"]
// _localizer["Hello, World!"]
var regex = new Regex(@"_(localizer)?\[""(.*?)""\]");
foreach (var sourceFile in sourceFiles)
{
foreach (var line in File.ReadLines(sourceFile))
{
var matches = regex.Matches(line);
foreach (Match match in matches)
{
var resourceKey = GetResourceKeyFromFileName(sourceFile);
var key = match.Groups[2].Value;
Console.WriteLine($"{resourceKey}: {key}");
}
}
}
}
ソリューションは防弾ではなく、命名規則に依存しています複数の逐語的な文字列は扱えません。しかし、それはおそらく私たちのために仕事をします:-)
Roslyn Analysysの最初のルール:自動的に公開したいコードを書いてください。 localizer ["anyParam"]のようなコードを探したいですか? – Oxoron
はい、まさに@Oxoron :-)そして、const文字列を使った呼び出し以外の特別な場合を処理するコード解析は必要ありません。 –