Я нашел ответ сам.
Решение основано на шаблоне проекта «Автономный инструмент анализа кода» из 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);
Решение частично основано на этом , но я изменил его в соответствии со своими потребностями.
Так что для каждой ссылки,Я буду перемещаться по исходному дереву, пока не найду вызов.Когда я найду один, я получу искомый параметр (на основе его индекса здесь), и если он '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 различных способов перевода строк, и мне нужен был способ найти их все в коде автоматически, в инструменте, который можно автоматизировать.
Это можетне будет лучшим решением, но я сделаю по крайней мере сейчас.