【问题标题】:Roslyn get IdentifierName in ObjectCreationExpressionSyntaxRoslyn 在 ObjectCreationExpressionSyntax 中获取 IdentifierName
【发布时间】:2017-10-03 22:11:49
【问题描述】:

目前我正在使用 roslyn 为 c# 进行简单的代码分析。我需要在一个解决方案中解析所有项目的所有文档,并在该文档中获取声明的使用类。

例如来自:

class Program
{
    static void Main(string[] args)
    {
        var foo = new Foo();
    }
}

我想得到Program 使用Foo

我已经解析了所有文档并获得了里面声明的类。

// all projects in solution
foreach (var project in _solution.Projects)
{
    // all documents inside project
    foreach (var document in project.Documents)
    {
        var syntaxRoot = await document.GetSyntaxRootAsync();
        var model = await document.GetSemanticModelAsync();
        var classes = syntaxRoot.DescendantNodes().OfType<ClassDeclarationSyntax>();
        // all classes inside document
        foreach (var classDeclarationSyntax in classes)
        {
            var symbol = model.GetDeclaredSymbol(classDeclarationSyntax);
            var objectCreationExpressionSyntaxs = classDeclarationSyntax.DescendantNodes().OfType<ObjectCreationExpressionSyntax>();
            // all object creations inside document
            foreach (var objectCreationExpressionSyntax in objectCreationExpressionSyntaxs)
            {
                // TODO: Get the identifier value
            }
        }
    }
}

问题是要获取 IdentifierName Foo。使用debugger,我看到objectCreationExpressionSyntax.Type得到了Identifier.Text得到了我需要的值,但objectCreationExpressionSyntax.Type.Identifier似乎是私有的。

我可以使用SymbolFinder 在解决方案中查找类的所有引用。因为我已经需要解析所有文档,所以它应该可以不用。

也许我走错了路?如何获取标识符值?

【问题讨论】:

    标签: c# roslyn roslyn-code-analysis


    【解决方案1】:

    您需要处理不同类型的TypeSyntaxes。见这里:http://sourceroslyn.io/#Microsoft.CodeAnalysis.CSharp/Syntax/TypeSyntax.cs,29171ac4ad60a546,references

    您在调试器中看到的是一个SimpleNameSyntax,它确实有一个公共Identifier 属性。

    更新

    var ns = objectCreationExpressionSyntax.Type as NameSyntax;
    if (ns != null)
    {
      return ns.Identifier.ToString();
    }
    
    var pts = objectCreationExpressionSyntax.Type as PredefinedTypeSyntax;
    if (pts != null)
    {
      return pts.Keyword.ToString();
    }
    
    ... 
    

    所有其他子类型都需要提交。请注意,ArrayType.ElementType 也是 TypeSyntax,因此您很可能需要将此方法设为递归。

    【讨论】:

    • 好的,怎么做?您的链接并没有真正帮助我理解这一点。你能解释更多或使用一些代码吗?
    • 是的,谢谢。正如@Crowcoder 发布的那样,也许是一个更好的解决方案。会找出女巫一个会满足我的需要。谢谢!
    【解决方案2】:

    字符串可能会产生误导。

    假设您有表达式new SomeClass(),并从中得到字符串“SomeClass”。你怎么知道那是指 Namespace1.SomeClass 还是 Namespace2.SomeClass ?如果使用了using SomeClass = Namespace3.SomeOtherType; 声明怎么办?

    幸运的是,您不必自己进行此分析。编译器可以将 ObjectCreationExpressionSyntax 绑定到符号。你有你的语义模型,使用它。

    foreach (var oce in objectCreationExpressionSyntaxs)
    {
        ITypeSymbol typeSymbol = model.GetTypeInfo(oce).Type;
        // ...
    }
    

    您可以将此符号与从model.GetDeclaredSymbol(classDeclarationSyntax) 获得的符号进行比较,只需确保使用Equals 方法,而不是== 运算符。

    【讨论】:

      【解决方案3】:

      您可以从语法的 Type 属性中获取标识符:

      foreach (var objectCreationExpressionSyntax in objectCreationExpressionSyntaxs)
      {
          IdentifierNameSyntax ins = (IdentifierNameSyntax)objectCreationExpressionSyntax.Type;
          var id = ins.Identifier;
          Console.WriteLine(id.ValueText);
      }
      

      【讨论】:

      • 谢谢,这正是我所需要的。我之前确实得到过这个,但不知道我需要投到IdentifierNameSyntax
      猜你喜欢
      • 2014-08-02
      • 2018-04-11
      • 1970-01-01
      • 2019-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多