目前我正在使用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的所有引用。因为我已经需要解析所有文档,所以它应该没有。
也许我走错了路?如何获取标识符值?
答案 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
方法,而不是==
运算符。