Roslyn 在 ObjectCreationExpressionSyntax 中获取 IdentifierName
Roslyn get IdentifierName in ObjectCreationExpressionSyntax
目前我正在使用 roslyn 对 c# 进行简单的代码分析。我需要在一个解决方案中解析所有项目的所有文档,并在该文档中获取已声明的已用 classes。
例如来自:
class Program
{
static void Main(string[] args)
{
var foo = new Foo();
}
}
我想要 Program
使用 Foo
。
我已经解析了所有文档并在其中获取了声明的 class。
// 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
在解决方案中查找 Class 的所有引用。因为我已经需要解析所有文档,所以没有它应该可以工作。
也许我走错了路?如何获取标识符值?
您需要处理不同类型的 TypeSyntax
es。看这里:http://sourceroslyn.io/#Microsoft.CodeAnalysis.CSharp/Syntax/TypeSyntax.cs,29171ac4ad60a546,references
你在调试器中看到的是一个 SimpleNameSyntax
,它确实有一个 public 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
,因此您很可能需要使此方法递归。
您可以从语法的类型中获取标识符 属性:
foreach (var objectCreationExpressionSyntax in objectCreationExpressionSyntaxs)
{
IdentifierNameSyntax ins = (IdentifierNameSyntax)objectCreationExpressionSyntax.Type;
var id = ins.Identifier;
Console.WriteLine(id.ValueText);
}
字符串可能会产生误导。
假设您有表达式 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
方法,而不是 ==
运算符。
目前我正在使用 roslyn 对 c# 进行简单的代码分析。我需要在一个解决方案中解析所有项目的所有文档,并在该文档中获取已声明的已用 classes。
例如来自:
class Program
{
static void Main(string[] args)
{
var foo = new Foo();
}
}
我想要 Program
使用 Foo
。
我已经解析了所有文档并在其中获取了声明的 class。
// 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
在解决方案中查找 Class 的所有引用。因为我已经需要解析所有文档,所以没有它应该可以工作。
也许我走错了路?如何获取标识符值?
您需要处理不同类型的 TypeSyntax
es。看这里:http://sourceroslyn.io/#Microsoft.CodeAnalysis.CSharp/Syntax/TypeSyntax.cs,29171ac4ad60a546,references
你在调试器中看到的是一个 SimpleNameSyntax
,它确实有一个 public 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
,因此您很可能需要使此方法递归。
您可以从语法的类型中获取标识符 属性:
foreach (var objectCreationExpressionSyntax in objectCreationExpressionSyntaxs)
{
IdentifierNameSyntax ins = (IdentifierNameSyntax)objectCreationExpressionSyntax.Type;
var id = ins.Identifier;
Console.WriteLine(id.ValueText);
}
字符串可能会产生误导。
假设您有表达式 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
方法,而不是 ==
运算符。