Search code examples
eclipseeclipse-plugineclipse-cdt

How to access the ICElements of local variables(variables inside function) and variables in header file?


Objective is to access the elements of C-file in eclipse to check customized naming rules for C-elements(global variable, local variable, function declarations). Tried to access the C-file elements as mentioned below. In this case, only able to access global variables and function names in the .c file. How local variables(variables inside functions) & variables in included header files can be accessed?

ITranslationUnit tu = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(input); ICElement[] ele= src.getChildren();


Solution

  • Local variables

    ICElement is mostly used for representing code elements in CDT's various views, such as the Outline View or Type Hierarchy. As such, local variables (which do not appear in these views) do not have an ICElement representation.

    For code analysis use cases like this, it's probably better to use the AST API. The AST is a detailed representation of the entire code in a file. It can be accessed via ITranslationUnit.getAST(). You can then use an ASTVisitor to traverse the AST and visit any declarations you like and check their names.

    Variables in included header files

    There are two sub-categories here: header files inside the project directory, and header files outside the project directory.

    Header files inside the project directory have their own ITranslationUnit, and you can use either the ICElement API or the AST API to analyze them with that ITranslationUnit as a starting point. Note that a file does not need to be open in an editor to obtain an ITranslationUnit for it. You can traverse all of the files in the project with something like ICElementVisitor, with the ICProject as a stating point.

    Header files outside the project directory do not have an ITranslationUnit, and there is no straightforward way to obtain an AST for them. However, assuming your project's indexer is enabled, the indexer does create ASTs for them and store information from those ASTs in the project's index, which you could examine. There are index APIs that can be used to traverse the index; some relevant ones are IIndexManager.getIndex(ICProject), IIndex.getAllFiles(), and IIndexFile.findNames().

    Edit: Additional Tips

    1) How to differentiate between function declarations and simple declarations.

    I can think of two ways:

    • Syntactically, based on the structure of the AST. For function definitions, the type of the declaration node will be IASTFunctionDefintion. For variable declarations, it will be IASTSimpleDeclaration, with the decl-specifier being IASTSimpleDeclSpecifier or IASTNamedTypeSpecifier (you additionally want to check that the declarator is not an IASTFunctionDeclarator, to filter out function declarations that are not definitions).

    • Semantically. If you find the IASTName for the declaration, you can call IASTName.resolveBinding(), and check whether the returned binding is an IFunction or an IVariable.

    2) How to get the return type of a function and the variable type?

    For these tasks, you need to get the binding. A variable's type can be queried by IVariable.getType(), and a function's return type via IFunction.getType().getReturnType().

    3) Is there a way to get an ICElement from an IASTSimpleDeclaration?

    There isn't a simple way that I know of. However, you shouldn't need to - if you're traversing the AST, all the information you could want can be found in the AST.