Некоторое время я пытался найти достойный способ привязать поле в структуре C ++ к его комментариям, используя libclang 3.9.1, и python 3.5.2.
До сих пор я получил эту настройку и работает:
Предполагая, что у меня есть файл 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
};
Мой код на Python извлекает только встроенные комментарии:
#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'
Теперь для моих задач, упорядоченных по важности, на нисходящем уровне:
Как я могу связать комментарии до поля? Я посмотрел на многие «заглядывающие» решения в python, чтобы во время итерации токенов выяснить, является ли следующий курсором (полем), который меня интересует, но не нашел ничего, что я мог бы правильно реализовать в моем случае , Просто чтобы показать вам, насколько я серьезен, вот несколько решений, на которые я посмотрел:
Концептуальный недостаток: я пока не знаю, как определить разницу между:
struct Foo {
int Bar; // This comment belong to bar
// As well as this one
// While this comment belong to baz already
int Baz;
};
Просто помощники для тех, кто еще не знает 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>
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
Других решений пока нет …