Как извлекать комментарии и сопоставлять объявления с помощью RecursiveASTVisitor в libclang С++?

Я пишу утилиту, которая должна анализировать файлы заголовков С++ (и C), извлекать структуры, перечисления, поля и т.д. и генерировать код на других языках на основе извлеченной информации. Я решил использовать libclang для этого.

Я использую RecursiveASTVisitor, и мне кажется, что я могу извлечь всю необходимую информацию, кроме комментариев.

Я хочу иметь комментарий, который появляется прямо над каждым объявлением (полем, строкой, классом, перечислением), и добавлять его текст при генерации кода на других языках.

Проблема в том, что все образцы, которые я видел, которые используют комментарии, используют CxCursor и интерфейс C для clang, и я понятия не имею, как получить CxCursor в моем контексте.

Итак - как я могу извлекать комментарии при использовании RecursiveASTVisitor?

Ответ 1

С еще одним выкапыванием я нашел это:

Для любого релевантного посещения Decl (VisitXXXDecl) я могу сделать это:

virtual bool VisitDecl(Decl* d)
{
    ASTContext& ctx = d->getASTContext();
    SourceManager& sm = ctx.getSourceManager();

    const RawComment* rc = d->getASTContext().getRawCommentForDeclNoCache(d);
    if (rc)
    {
        //Found comment!
        SourceRange range = rc->getSourceRange();

        PresumedLoc startPos = sm.getPresumedLoc(range.getBegin());
        PresumedLoc endPos = sm.getPresumedLoc(range.getEnd());

        std::string raw = rc->getRawText(sm);
        std::string brief = rc->getBriefText(ctx);

        // ... Do something with positions or comments
    }

    // ...
}

Обратите внимание, что это указывает (насколько я мог видеть...) комментарии, которые находятся в строке (-ах) выше (и рядом!), в текущую декларацию в коде и которые находятся в одном из следующих форматов

  • /// Comment
  • /** Comment */
  • //! Comment

Например, в следующем случае:

/// A field with a long long comment
/// A two-liner
long long LongLongData;

raw будет:

/// A field with a long long comment
    /// A two-liner

И brief будет:

A field with a long long comment A two-liner

В любом случае, это достаточно хорошо для моих нужд.

Ответ 2

Вышеприведенный ответ идеален. Но чтобы API getRawCommentForDeclNoCache возвращал нормальные комментарии, такие как // or /*, вам нужно предоставить опцию "- fparse-all-comments" при вызове clang. Поскольку по умолчанию clang анализирует только комментарии стиля Doxygen.