Example 3: Listing classes and members
| In this topic: |
In this example, we'll use the semantics tree to find all the members of the class to which the node of interest belongs. Once we've found them, for now, we're just going to log them and return a place-holder.
Creating new test case code
First, let's modify our testcase.cc code, so that it reads like this:
class CFoo
{
public:
CFoo() { init(); }
CFoo(int x) { init(x); }
void init(int x = 0, const char* y = 0);
private:
int m_x;
const char* m_y;
};
void CFoo::init(int x, const char* y)
{
m_x = x;
m_y = y;
}
Adding a check for class
Next, we'll modify the checker pattern so that the checker gets invoked only for function definitions for the 'init' function. We'll switch back to a simple custom predicate function type, as we're just going to log the function name, and we'll call it listClassInfo():
<error id="EX.FIRST" enabled="true" severity="3"
title="Function Definition" message="Called.">
<pattern>
// FuncDef [ getName() = ‘init’] [
listClassInfo() ]
</pattern>
</error>
Now let's create our custom predicate so that it navigates up the semantics tree to our outer scope, validates that this outer scope is a class, and logs the name of the class in the build log:
#include <stdio.h>
#include <XPath_plugins.h>
#include <ktcAPI.h>
int listClassInfo(ktc_tree_t node)
{
ktc_semanticInfo_t si = ktc_getSemanticInfo(node);
if( ktc_sema_isFunction(si) )
{
ktc_semanticInfo_t ci = ktc_sema_getScope(si);
if( ci && ktc_sema_isClass(ci) )
fprintf(stderr, "Class name: %s\n", ktc_sema_getIdentifier(ci));
}
return 1;
}
HOOKS_SET_START
XPath_register_int_hook("listClassInfo", listClassInfo);
HOOKS_SET_END
When you execute this checker on the new test case, your build log should now contain a line reading:
Class name: CFoo
Adding a list of class members
We've made our way from a member function definition to its surrounding class scope, so now let's list all the class members and log them. The ktc API provides a simple means of iterating through all members of a class, or of any scope, which we can use by modifying the previous code:
#include <stdio.h>
#include <XPath_plugins.h>
#include <ktcAPI.h>
void logger(ktc_semanticInfo_t mi)
{
fprintf(stderr, "\tMember: %s\n", ktc_sema_getQualifiedName(mi));
}
int listClassInfo(ktc_tree_t node)
{
ktc_semanticInfo_t si = ktc_getSemanticInfo(node);
if( ktc_sema_isFunction(si) )
{
ktc_semanticInfo_t ci = ktc_sema_getScope(si);
if( ci && ktc_sema_isClass(ci) )
{
fprintf(stderr, "Class name: %s\n", ktc_sema_getIdentifier(ci));
ktc_sema_forAllClassDeclarations(ci, logger);
}
}
return 1;
}
HOOKS_SET_START
XPath_register_int_hook("listClassInfo", listClassInfo);
HOOKS_SET_END
When you execute the checker, you should see the following entries in the build log:
Class name: CFoo
Member: CFoo::#destructor
Member: CFoo::m_x
Member: CFoo::m_y
Member: CFoo::#constructor
Member: CFoo::#constructor
Member: CFoo::init
Member: CFoo::init
Filtering the logger function
The checker logs each declaration or definition of a class member, whether it's a method or a variable. To narrow it down to just the member variables, we can add a filter in the logger() function:
void logger(ktc_semanticInfo_t mi)
{
if( ktc_sema_isVariable(mi) )
fprintf(stderr, "\tMember: %s\n", ktc_sema_getQualifiedName(mi));
}
Now the build log will contain:
Class name: CFoo
Member: CFoo::m_x
Member: CFoo::m_y