2016-10-27 3 views
1

Мне нужно проанализировать файл кода на C++ и найти в нем все вызовы функций с полными именами. Я использую привязки Python от libclang, потому что это кажется проще, чем писать собственный C++-парсер, даже если документация разрежена.Как получить полностью квалифицированные имена функций с помощью libclang?

Пример C++ код:

namespace a { 
    namespace b { 
    class Thing { 
    public: 
     Thing(); 
     void DoSomething(); 
     int DoAnotherThing(); 
    private: 
     int thisThing; 
    }; 
    } 
} 

int main() 
{ 
    a::b::Thing *thing = new a::b::Thing(); 
    thing->DoSomething(); 
    return 0; 
} 

Python скрипт:

import clang.cindex 
import sys 

def find_function_calls(node): 
    if node.kind == clang.cindex.CursorKind.CALL_EXPR: 
    # What do I do here? 
    pass 
    for child in node.get_children(): 
    find_function_calls(child) 

index = clang.cindex.Index.create() 
tu = index.parse(sys.argv[1]) 
find_function_calls(tu.cursor) 

Выход Я ищу список полностью уточненных имен функций, которые были названы:

a::b::Thing::Thing 
a::b::Thing::DoSomething 

Я могу получить «короткое» имя функции, используя node.spelling, но я не знаю, как найти класс/пространство имен, к которому он принадлежит.

ответ

2

Вы можете использовать свойство курсора referenced, чтобы получить дескриптор этого определения, а затем вы можете вернуть АСТ через свойство semantic_parent (остановка в корне или когда тип курсора является единицей перевода) для создания полностью квалифицированного имя.

import clang.cindex 
from clang.cindex import CursorKind 

def fully_qualified(c): 
    if c is None: 
     return '' 
    elif c.kind == CursorKind.TRANSLATION_UNIT: 
     return '' 
    else: 
     res = fully_qualified(c.semantic_parent) 
     if res != '': 
      return res + '::' + c.spelling 
    return c.spelling 

idx = clang.cindex.Index.create() 
tu = idx.parse('tmp.cpp', args='-xc++ --std=c++11'.split()) 
for c in tu.cursor.walk_preorder(): 
    if c.kind == CursorKind.CALL_EXPR: 
     print fully_qualified(c.referenced) 

Который производит:

a::b::Thing::Thing 
a::b::Thing::DoSomething