我自己找到了答案。
该解决方案基于 Visual Studio 中的“独立代码分析工具”项目模板。
由于此模板附带解决方案打开和工作区创建,我将跳过这部分。
private static async Task<List<INamedTypeSymbol>> GetDeclarationOfType(string typeName, Solution solution)
{
var symbols = await SymbolFinder.FindSourceDeclarationsAsync(solution, x => x.Equals(typeName));
return symbols.Where(x => x.Kind == SymbolKind.NamedType).Cast<INamedTypeSymbol>().ToList();
}
这里我只是使用SymbolFinder 来查找我要查找的类型的声明。
对于每个返回的符号,然后我获取名称是我的类名的成员(然后是方法):
var members = symbol.GetMembers().Where(x => x.Name.Equals("MyMethod"));
对于每个匹配的成员,然后我获取所有引用:
var references = await SymbolFinder.FindReferencesAsync(member, solution);
该解决方案部分基于this one,但我根据需要对其进行了修改。
因此,对于每个引用,我都会浏览源代码树,直到找到调用。
当我找到一个时,我会得到我正在寻找的参数(基于它的索引)如果它是'kind'是SyntaxKind.StringLiteralExpression那么我有我需要的一切:
foreach (var referencedSymbol in references)
{
foreach (var location in referencedSymbol.Locations)
{
var theToken = location.Location.SourceTree.GetRoot().FindToken(location.Location.SourceSpan.Start);
var theNode = theToken.Parent;
while (!theNode.IsKind(SyntaxKind.InvocationExpression))
{
theNode = theNode.Parent;
if (theNode == null) break; // There isn't an InvocationExpression in this branch of the tree
}
if (theNode != null)
{
var argument = ((InvocationExpressionSyntax) theNode).ArgumentList.Arguments[searchPattern.ArgumentIndex];
if (argument.Expression.IsKind(SyntaxKind.StringLiteralExpression))
{
textToTranslate.Add(argument.ToString());
}
}
}
}
对参数本身调用ToString()会返回参数的实际值,即传递给方法的参数的字符串值。
作为参考,我的用例是从我的解决方案中提取所有可翻译的字符串。
这是一个非常大的解决方案(超过 170 个项目),它使用 5 种不同的方式来翻译字符串,我需要一种在代码中自动找到它们的方法,在一个可以自动化的工具中。
这可能不是最好的解决方案,但至少现在我会这样做。