2017-01-31 1 views
0

Я изо всех сил пытаюсь найти подходящий способ привязать поле в структуре C++ к его комментариям, используя libclang 3.9.1 и python 3.5.2.python + libclang; итерация назад и вперед: привязка полей комментариев к полю

До сих пор я получил эту установку и работает: Предполагая, что у меня есть файл Foo.h:

typedef int arbType; 

struct Foo { 
    //First bar comment 
    //Second bar comment 
    int Bar; //Third bar comment - after bar 

    /* First line baz comment - before baz 
     Second line baz comment - before baz 
    */ 
    arbType Baz; //Third line baz comment - after baz 
}; 

Мой питон код экстракт только в онлайн Комментарии:

#bind_comments.py 
import clang.cindex 

def get_cur_comments(cursor): 
    comment = '' 
    print ('\nGetting comment for:', cursor.spelling.decode()) 
    parent_cur = cursor.lexical_parent 
    token_iter = parent_cur.get_tokens() 
    for token in token_iter: 
     if token.cursor == cursor:    
      while token.kind.name != 'PUNCTUATION': 
       token = next(token_iter) 
      token = next(token_iter) 
      if token.kind.name == 'COMMENT': 
       comment = token.spelling.decode().strip('/') 
    return comment 

def main(): 
    index = clang.cindex.Index.create() 
    tu = index.parse(b'Foo.h', [b'-x', b'c++']) 
    tu_iter = tu.cursor.get_children() 
    next(tu_iter) 
    root_cursor = next(tu_iter) 

    for cur in root_cursor.type.get_fields(): 
     print(get_cur_comments(cur)) 

if __name__ == '__main__': 
    main() 

И выход:

C:\>bind_comments.py 

Getting comment for: Bar 
'Third bar comment - after bar' 

Getting comment for: Baz 
'Third line baz comment - after baz' 

Теперь, для моих проблем, заказанных impo rtance, уровень нисходящего:

  1. Как я могу связать для комментариев перед поля? Я смотрел на многие «peeking» решения в python, чтобы узнать, когда я повторяю токены, если следующий - это курсор (поле), который мне интересен, но не нашел ничего, что я мог бы правильно реализовать в моем случае , Просто, чтобы показать вам, насколько серьезно я, вот некоторые из решений я посмотрел на:

  2. Концептуальный недостаток: Я еще не знаю, как сказать разницу между:

    struct Foo { 
        int Bar; // This comment belong to bar 
          // As well as this one 
    
        // While this comment belong to baz already 
        int Baz; 
    }; 
    
  3. Проблемы с производительностью: обратите внимание, что для каждого поля я повторяю список всех его токенов. Если он большой, и у меня много жетонов - я думаю, это будет стоить мне. Я бы хотел найти несколько ярлыков .. Я думал о сохранении токенов в глобальном списке, но что тогда, если поле является объявлением другого struct/class? Добавить токены родителя в список? Это начинает запутаться ...

всего помощники для тех, кто не знает libclang еще:

>>> print(root_cursor.spelling.decode()) 
Foo 
>>> root_cursor.type.get_fields() 
<list_iterator object at 0x0177B770> 
>>> list(root_cursor.type.get_fields()) 
[<clang.cindex.Cursor object at 0x0173B940>, <clang.cindex.Cursor object at 0x017443A0>] 
>>> for cur in root_cursor.type.get_fields(): 
... print (cur.spelling.decode()) 
... 
Bar 
Baz 
>>> root_cursor.get_tokens() 
<generator object TokenGroup.get_tokens at 0x01771180> 

ответ

1

libclang обеспечивает прямую поддержку для извлечения комментариев Javadoc стиле с использованием Cursor свойств brief_comment и raw_comment

с небольшой настройки вашего ввода кода:

s = ''' 
typedef int arbType; 

struct Foo { 
    /// Brief comment about bar 
    /// 
    /// Extra Text about bar 
    int Bar; 

    /** Brief comment about baz 
    * 
    * Extra Text about baz 
    */ 
    arbType Baz; 

    /// Brief only comment 
    int blah; 
}; 
''' 

import clang.cindex 
from clang.cindex import CursorKind 

idx = clang.cindex.Index.create() 
tu = idx.parse('tmp.cpp', args=['-std=c++11'], unsaved_files=[('tmp.cpp', s)], options=0) 
for c in tu.cursor.walk_preorder(): 
    if c.kind == CursorKind.FIELD_DECL: 
     print c.brief_comment 
     print c.raw_comment 
     print 

Производит:

Brief comment about bar 
/// Brief comment about bar 
    /// 
    /// Extra Text about bar 

Brief comment about baz 
/** Brief comment about baz 
    * 
    * Extra Text about baz 
    */ 

Brief only comment 
/// Brief only comment 
+0

Блин, забыл упомянуть об этом:) ... Я уже знал о '' Cursor.brief_comment' и Cursor.raw_comment', но это требует изменения .h файла. Предположим, что я не могу изменить его, и он находится в формате, который появляется в моем вопросе. Как я могу справиться с этим сейчас? (И, BTW, clang предполагают, что перед ним появляются все соответствующие комментарии к курсору. Что относительно встроенных в liner-файлов, например, в моем файле .h'?) В любом случае, спасибо за ваше время ... –