Example 3: Listing classes and members
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 codeFirst, 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 classNext, 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 membersWe'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 functionThe 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 |