2017-05-05 70 views
0

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

例如来自:

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在解决方案中查找所有类的引用。由于我已经需要解析所有文件,它应该没有工作。

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

回答

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(); 
} 

... 

所有其他亚型将需要递交。请注意0​​也是TypeSyntax,所以你很可能需要使这个方法递归。

+0

好的,该怎么做?你的链接并没有真正帮助我理解这一点。你能解释更多还是使用一些代码? –

+0

希望更新的答案有帮助。 – Tamas

+0

是的,谢谢。也许是一个@Crowcoder发布的更好的解决方案。会弄清楚巫婆会符合我的需要。谢谢! –

0

你可以从语法的类型属性的标识符:

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

谢谢,那正是我需要的。我确实得到了这个,但并不知道我需要投射到'IdentifierNameSyntax' –

0

字符串可能会产生误导。

假设您的表达式为new SomeClass(),并且您将字符串“SomeClass”取出。你怎么知道这是否指Namespace1.SomeClassNamespace2.SomeClass?如果使用了using SomeClass = Namespace3.SomeOtherType;声明怎么办?

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

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

你可以比较你从model.GetDeclaredSymbol(classDeclarationSyntax)得到符号这个符号,只是确保你使用Equals方法,而不是==操作。

相关问题