Roslyn在ObjectCreationExpressionSyntax中获取IdentifierName

时间:2017-05-05 12:18:26

标签: c# roslyn roslyn-code-analysis

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

例如来自:

# Alter module and reload
with open(os.path.join(dir.name, 'test_package', 'some_module.py'), "w") as f:
    f.write("def a():\n    print(\"new\")\n    return 1\n")

importlib.reload(some_module)

# Check wether modifications have been reloaded
assert some_module.a() == 1

sys.path.pop(0)

我希望class Program { static void Main(string[] args) { var foo = new Foo(); } } 使用Program

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

Foo

问题是获取IdentifierName // 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 } } } } 。使用debugger,我看到Foo得到objectCreationExpressionSyntax.Type得到了我需要的值,但Identifier.Text似乎是私有的。

我可以使用objectCreationExpressionSyntax.Type.Identifier查找解决方案中Class的所有引用。因为我已经需要解析所有文档,所以它应该没有。

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

3 个答案:

答案 0 :(得分:1)

您需要处理不同类型的TypeSyntax es。见这里:http://source.roslyn.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,因此您很可能需要递归此方法。

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

字符串可能会产生误导。

假设您有表达式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方法,而不是==运算符。