如何使用 CDT 解析器获取字段类型
How to get a field's type by using CDT parser
我正在尝试提取 C++ 源代码的信息。
一是字段的类型。
当调用 info.call() 时我想提取信息类型的源代码。
Info info;
//skip
info.call(); //<- from here
通过创建访问 IASTName 节点的访问者,我尝试像下面那样提取类型信息。
public class CDTVisitor extends ASTVisitor {
public CDTVisitor(boolean visitNodes) {
super(true);
}
public int visit(IASTName node){
if(node.resolveBinding().getName().toString().equals("info"))
System.out.println(((IField)node.getBinding()).getType());
// this not work properly.
//result is "org.eclipse.cdt.internal.core.dom.parser.ProblemType@86be70a"
return 3;
}
}
假设代码实际上是有效的,解析为 ProblemType
的变量类型表明 运行 正在使用此代码的任何工具或插件中的配置问题,或者 project/workspace 包含它所在的代码 运行.
在这种情况下,变量info
的类型是Info
,推测是class或结构类型,或typedef。要正确解析它,CDT 需要能够看到该类型的声明。
如果此类型未在正在分析的同一文件中声明,而是在该文件包含的头文件中声明,CDT 需要使用项目的 index 找到声明。这意味着:
AST 必须是 index-based。例如,如果使用 ITranslationUnit.getAST
创建 AST,则必须使用带有 IIndex
参数的重载,并且必须为其提供 non-null 参数。
由于 IIndex
与 CDT 项目关联,被分析的代码需要是 CDT 项目的一部分,并且该项目需要被索引。
为了让索引器正确解析 #include
指令,需要正确配置项目的包含路径,这样索引器才能真正找到正确的头文件进行解析。
其中任何一个不是这种情况都可能导致类型解析为 ProblemType
。
自我回应。
我无法获得绑定对象的原因是 AST 的类型。
在尝试解析 C++ 源代码时,我应该使用 ICPPASTTranslationUnit。
没有与此相关的代码,我使用 IASTTranslationUnit 作为 return 类型的 AST。
使用ICPPASTTranslationUnit代替IASTTranslationUnit后,我解决了这个问题。
是的,我想通了!这是完整的代码,它可以索引 cpp 项目的“src”文件夹中的所有文件,并输出所有代码表达式的解析类型绑定,包括低级别 API 的 return 值,例如 memcpy。请注意,以下代码中的 project 变量是通过以编程方式导入现有的手动配置的 cpp 项目来创建的。我经常手动创建一个空的cpp项目,然后通过编程将其导入为一个通用项目(导入后Eclipse会自动检测项目类型并完成CPP项目的相关配置)。这比以编程方式从头开始创建和配置 cpp 项目要方便得多。导入项目时,最好不要将项目或包含结构复制到工作区中,因为这可能会导致在子文件夹中无限复制相同的项目(无限文件夹深度)。该代码适用于 Eclipse-2021-12 版本。我下载 Eclipse-For-cpp 并安装 plugin-development 和 jdt 插件。然后我创建一个 Eclipse 插件项目并扩展“org.eclipse.core.runtime.applications”扩展点。
也就是说,它是一个Eclipse-Application插件项目,几乎可以使用Eclipse的所有特性,但不启动Eclipse的图形界面(UI)。您应该添加所有 cdt 相关的 non-ui 插件作为依赖项,因为新版本的 Eclipse 不会再自动添加缺少的插件。
ICProject cproject = CoreModel.getDefault().getCModel().getCProject(project.getName());
// this code creates index for entire project.
IIndex index = CCorePlugin.getIndexManager().getIndex(cproject);
IFolder folder = project.getFolder("src");
IResource[] rcs = folder.members();
// iterate all source files in src folder and visit all expressions to print the resolved type binding.
for (IResource rc : rcs) {
if (rc instanceof IFile) {
IFile f = (IFile) rc;
ITranslationUnit tu= (ITranslationUnit) CoreModel.getDefault().create(f);
index.acquireReadLock(); // we need a read-lock on the index
ICPPASTTranslationUnit ast = null;
try {
ast = (ICPPASTTranslationUnit) tu.getAST(index, ITranslationUnit.AST_SKIP_INDEXED_HEADERS);
} finally {
index.releaseReadLock();
}
if (ast != null) {
ast.accept(new ASTVisitor() {
@Override
public int visit(IASTExpression expression) {
// get the resolved type binding of expression.
IType etp = expression.getExpressionType();
System.out.println("IASTExpression type:" + etp + "#expr_str:" + expression.toString());
return super.visit(expression);
}
});
}
}
}
我正在尝试提取 C++ 源代码的信息。 一是字段的类型。
当调用 info.call() 时我想提取信息类型的源代码。
Info info;
//skip
info.call(); //<- from here
通过创建访问 IASTName 节点的访问者,我尝试像下面那样提取类型信息。
public class CDTVisitor extends ASTVisitor {
public CDTVisitor(boolean visitNodes) {
super(true);
}
public int visit(IASTName node){
if(node.resolveBinding().getName().toString().equals("info"))
System.out.println(((IField)node.getBinding()).getType());
// this not work properly.
//result is "org.eclipse.cdt.internal.core.dom.parser.ProblemType@86be70a"
return 3;
}
}
假设代码实际上是有效的,解析为 ProblemType
的变量类型表明 运行 正在使用此代码的任何工具或插件中的配置问题,或者 project/workspace 包含它所在的代码 运行.
在这种情况下,变量info
的类型是Info
,推测是class或结构类型,或typedef。要正确解析它,CDT 需要能够看到该类型的声明。
如果此类型未在正在分析的同一文件中声明,而是在该文件包含的头文件中声明,CDT 需要使用项目的 index 找到声明。这意味着:
AST 必须是 index-based。例如,如果使用
ITranslationUnit.getAST
创建 AST,则必须使用带有IIndex
参数的重载,并且必须为其提供 non-null 参数。由于
IIndex
与 CDT 项目关联,被分析的代码需要是 CDT 项目的一部分,并且该项目需要被索引。为了让索引器正确解析
#include
指令,需要正确配置项目的包含路径,这样索引器才能真正找到正确的头文件进行解析。
其中任何一个不是这种情况都可能导致类型解析为 ProblemType
。
自我回应。 我无法获得绑定对象的原因是 AST 的类型。
在尝试解析 C++ 源代码时,我应该使用 ICPPASTTranslationUnit。 没有与此相关的代码,我使用 IASTTranslationUnit 作为 return 类型的 AST。
使用ICPPASTTranslationUnit代替IASTTranslationUnit后,我解决了这个问题。
是的,我想通了!这是完整的代码,它可以索引 cpp 项目的“src”文件夹中的所有文件,并输出所有代码表达式的解析类型绑定,包括低级别 API 的 return 值,例如 memcpy。请注意,以下代码中的 project 变量是通过以编程方式导入现有的手动配置的 cpp 项目来创建的。我经常手动创建一个空的cpp项目,然后通过编程将其导入为一个通用项目(导入后Eclipse会自动检测项目类型并完成CPP项目的相关配置)。这比以编程方式从头开始创建和配置 cpp 项目要方便得多。导入项目时,最好不要将项目或包含结构复制到工作区中,因为这可能会导致在子文件夹中无限复制相同的项目(无限文件夹深度)。该代码适用于 Eclipse-2021-12 版本。我下载 Eclipse-For-cpp 并安装 plugin-development 和 jdt 插件。然后我创建一个 Eclipse 插件项目并扩展“org.eclipse.core.runtime.applications”扩展点。 也就是说,它是一个Eclipse-Application插件项目,几乎可以使用Eclipse的所有特性,但不启动Eclipse的图形界面(UI)。您应该添加所有 cdt 相关的 non-ui 插件作为依赖项,因为新版本的 Eclipse 不会再自动添加缺少的插件。
ICProject cproject = CoreModel.getDefault().getCModel().getCProject(project.getName());
// this code creates index for entire project.
IIndex index = CCorePlugin.getIndexManager().getIndex(cproject);
IFolder folder = project.getFolder("src");
IResource[] rcs = folder.members();
// iterate all source files in src folder and visit all expressions to print the resolved type binding.
for (IResource rc : rcs) {
if (rc instanceof IFile) {
IFile f = (IFile) rc;
ITranslationUnit tu= (ITranslationUnit) CoreModel.getDefault().create(f);
index.acquireReadLock(); // we need a read-lock on the index
ICPPASTTranslationUnit ast = null;
try {
ast = (ICPPASTTranslationUnit) tu.getAST(index, ITranslationUnit.AST_SKIP_INDEXED_HEADERS);
} finally {
index.releaseReadLock();
}
if (ast != null) {
ast.accept(new ASTVisitor() {
@Override
public int visit(IASTExpression expression) {
// get the resolved type binding of expression.
IType etp = expression.getExpressionType();
System.out.println("IASTExpression type:" + etp + "#expr_str:" + expression.toString());
return super.visit(expression);
}
});
}
}
}