【问题标题】:Find parameters value of specific method with Roslyn使用 Roslyn 查找特定方法的参数值
【发布时间】:2019-02-08 15:03:34
【问题描述】:

我需要找出所有出现的方法调用。

示例: 我有这样的课:

public class Foo
{
   public string Bar(string firstParam, string secondParam){}
}

我需要做的是打开一个解决方案并找到类 Foo 中方法 Bar 的所有用法。现在,对于每种用法,我想检索第一个参数作为字符串传递时的值。

所以如果我的代码中有这行:

foo.Bar("some value", "something else")

那么我应该检索“一些价值”。

现在如果我有:

foo.Bar(someProperty, "something else")

那我应该忽略它。

我在研究过程中确实找到了很多资源,但我似乎找不到真正有效的方法。

【问题讨论】:

  • 我不确定您是否需要与 Roslyn 一起执行此操作。我知道在 VS 中你可以右键单击一个方法并选择 Find all references 或使用热键你可以按住 Ctrl 并按 K 然后按 R 来做同样的事情。它没有得到您正在搜索的详细信息,但我想您可以很容易地将该逻辑调整到您自己的 VS 扩展中。如果您使用 Roslyn,那么您正在寻找关于它的编译时间信息或在 ide 中预编译信息,但我不确定在没有看到全貌的情况下这有什么帮助。
  • 实际上我自己解决了我的问题。当我回到办公室时,我会发布答案。我需要在独立程序中执行此操作,而不是在 VS 中。我会在回答中提供更多细节。

标签: c# roslyn


【解决方案1】:

我自己找到了答案。

该解决方案基于 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 种不同的方式来翻译字符串,我需要一种在代码中自动找到它们的方法,在一个可以自动化的工具中。

这可能不是最好的解决方案,但至少现在我会这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多