llvm-project/clang/tools/libclang/CXComment.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

409 lines
12 KiB
C++
Raw Normal View History

//===- CXComment.cpp - libclang APIs for manipulating CXComments ----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines all libclang APIs related to walking comment AST.
//
//===----------------------------------------------------------------------===//
#include "CXComment.h"
#include "CXCursor.h"
#include "CXString.h"
#include "clang-c/Documentation.h"
#include "clang-c/Index.h"
#include "clang/AST/Decl.h"
#include "clang/Index/CommentToXML.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"
#include <climits>
using namespace clang;
using namespace clang::comments;
using namespace clang::cxcomment;
CXComment clang_Cursor_getParsedComment(CXCursor C) {
using namespace clang::cxcursor;
if (!clang_isDeclaration(C.kind))
return createCXComment(nullptr, nullptr);
const Decl *D = getCursorDecl(C);
const ASTContext &Context = getCursorContext(C);
const FullComment *FC = Context.getCommentForDecl(D, /*PP=*/nullptr);
return createCXComment(FC, getCursorTU(C));
}
enum CXCommentKind clang_Comment_getKind(CXComment CXC) {
const Comment *C = getASTNode(CXC);
if (!C)
return CXComment_Null;
switch (C->getCommentKind()) {
case Comment::NoCommentKind:
return CXComment_Null;
case Comment::TextCommentKind:
return CXComment_Text;
case Comment::InlineCommandCommentKind:
return CXComment_InlineCommand;
case Comment::HTMLStartTagCommentKind:
return CXComment_HTMLStartTag;
case Comment::HTMLEndTagCommentKind:
return CXComment_HTMLEndTag;
case Comment::ParagraphCommentKind:
return CXComment_Paragraph;
case Comment::BlockCommandCommentKind:
return CXComment_BlockCommand;
case Comment::ParamCommandCommentKind:
return CXComment_ParamCommand;
case Comment::TParamCommandCommentKind:
return CXComment_TParamCommand;
case Comment::VerbatimBlockCommentKind:
return CXComment_VerbatimBlockCommand;
case Comment::VerbatimBlockLineCommentKind:
return CXComment_VerbatimBlockLine;
case Comment::VerbatimLineCommentKind:
return CXComment_VerbatimLine;
case Comment::FullCommentKind:
return CXComment_FullComment;
}
llvm_unreachable("unknown CommentKind");
}
unsigned clang_Comment_getNumChildren(CXComment CXC) {
const Comment *C = getASTNode(CXC);
if (!C)
return 0;
return C->child_count();
}
CXComment clang_Comment_getChild(CXComment CXC, unsigned ChildIdx) {
const Comment *C = getASTNode(CXC);
if (!C || ChildIdx >= C->child_count())
return createCXComment(nullptr, nullptr);
Comment AST: TableGen'ize all command lists in CommentCommandTraits.cpp. Now we have a list of all commands. This is a good thing in itself, but it also enables us to easily implement typo correction for command names. With this change we have objects that contain information about each command, so it makes sense to resolve command name just once during lexing (currently we store command names as strings and do a linear search every time some property value is needed). Thus comment token and AST nodes were changed to contain a command ID -- index into a tables of builtin and registered commands. Unknown commands are registered during parsing and thus are also uniformly assigned an ID. Using an ID instead of a StringRef is also a nice memory optimization since ID is a small integer that fits into a common bitfield in Comment class. This change implies that to get any information about a command (even a command name) we need a CommandTraits object to resolve the command ID to CommandInfo*. Currently a fresh temporary CommandTraits object is created whenever it is needed since it does not have any state. But with this change it has state -- new commands can be registered, so a CommandTraits object was added to ASTContext. Also, in libclang CXComment has to be expanded to include a CXTranslationUnit so that all functions working on comment AST nodes can get a CommandTraits object. This breaks binary compatibility of CXComment APIs. Now clang_FullComment_getAsXML(CXTranslationUnit TU, CXComment CXC) doesn't need TU parameter anymore, so it was removed. This is a source-incompatible change for this C API. llvm-svn: 163540
2012-09-11 04:32:42 +08:00
return createCXComment(*(C->child_begin() + ChildIdx), CXC.TranslationUnit);
}
unsigned clang_Comment_isWhitespace(CXComment CXC) {
const Comment *C = getASTNode(CXC);
if (!C)
return false;
if (const TextComment *TC = dyn_cast<TextComment>(C))
return TC->isWhitespace();
if (const ParagraphComment *PC = dyn_cast<ParagraphComment>(C))
return PC->isWhitespace();
return false;
}
unsigned clang_InlineContentComment_hasTrailingNewline(CXComment CXC) {
const InlineContentComment *ICC = getASTNodeAs<InlineContentComment>(CXC);
if (!ICC)
return false;
return ICC->hasTrailingNewline();
}
CXString clang_TextComment_getText(CXComment CXC) {
const TextComment *TC = getASTNodeAs<TextComment>(CXC);
if (!TC)
return cxstring::createNull();
return cxstring::createRef(TC->getText());
}
CXString clang_InlineCommandComment_getCommandName(CXComment CXC) {
const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
if (!ICC)
return cxstring::createNull();
Comment AST: TableGen'ize all command lists in CommentCommandTraits.cpp. Now we have a list of all commands. This is a good thing in itself, but it also enables us to easily implement typo correction for command names. With this change we have objects that contain information about each command, so it makes sense to resolve command name just once during lexing (currently we store command names as strings and do a linear search every time some property value is needed). Thus comment token and AST nodes were changed to contain a command ID -- index into a tables of builtin and registered commands. Unknown commands are registered during parsing and thus are also uniformly assigned an ID. Using an ID instead of a StringRef is also a nice memory optimization since ID is a small integer that fits into a common bitfield in Comment class. This change implies that to get any information about a command (even a command name) we need a CommandTraits object to resolve the command ID to CommandInfo*. Currently a fresh temporary CommandTraits object is created whenever it is needed since it does not have any state. But with this change it has state -- new commands can be registered, so a CommandTraits object was added to ASTContext. Also, in libclang CXComment has to be expanded to include a CXTranslationUnit so that all functions working on comment AST nodes can get a CommandTraits object. This breaks binary compatibility of CXComment APIs. Now clang_FullComment_getAsXML(CXTranslationUnit TU, CXComment CXC) doesn't need TU parameter anymore, so it was removed. This is a source-incompatible change for this C API. llvm-svn: 163540
2012-09-11 04:32:42 +08:00
const CommandTraits &Traits = getCommandTraits(CXC);
return cxstring::createRef(ICC->getCommandName(Traits));
}
enum CXCommentInlineCommandRenderKind
clang_InlineCommandComment_getRenderKind(CXComment CXC) {
const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
if (!ICC)
return CXCommentInlineCommandRenderKind_Normal;
switch (ICC->getRenderKind()) {
case InlineCommandComment::RenderNormal:
return CXCommentInlineCommandRenderKind_Normal;
case InlineCommandComment::RenderBold:
return CXCommentInlineCommandRenderKind_Bold;
case InlineCommandComment::RenderMonospaced:
return CXCommentInlineCommandRenderKind_Monospaced;
case InlineCommandComment::RenderEmphasized:
return CXCommentInlineCommandRenderKind_Emphasized;
case InlineCommandComment::RenderAnchor:
return CXCommentInlineCommandRenderKind_Anchor;
}
llvm_unreachable("unknown InlineCommandComment::RenderKind");
}
unsigned clang_InlineCommandComment_getNumArgs(CXComment CXC) {
const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
if (!ICC)
return 0;
return ICC->getNumArgs();
}
CXString clang_InlineCommandComment_getArgText(CXComment CXC,
unsigned ArgIdx) {
const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
if (!ICC || ArgIdx >= ICC->getNumArgs())
return cxstring::createNull();
return cxstring::createRef(ICC->getArgText(ArgIdx));
}
CXString clang_HTMLTagComment_getTagName(CXComment CXC) {
const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC);
if (!HTC)
return cxstring::createNull();
return cxstring::createRef(HTC->getTagName());
}
unsigned clang_HTMLStartTagComment_isSelfClosing(CXComment CXC) {
const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
if (!HST)
return false;
return HST->isSelfClosing();
}
unsigned clang_HTMLStartTag_getNumAttrs(CXComment CXC) {
const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
if (!HST)
return 0;
return HST->getNumAttrs();
}
CXString clang_HTMLStartTag_getAttrName(CXComment CXC, unsigned AttrIdx) {
const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
if (!HST || AttrIdx >= HST->getNumAttrs())
return cxstring::createNull();
return cxstring::createRef(HST->getAttr(AttrIdx).Name);
}
CXString clang_HTMLStartTag_getAttrValue(CXComment CXC, unsigned AttrIdx) {
const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
if (!HST || AttrIdx >= HST->getNumAttrs())
return cxstring::createNull();
return cxstring::createRef(HST->getAttr(AttrIdx).Value);
}
CXString clang_BlockCommandComment_getCommandName(CXComment CXC) {
const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
if (!BCC)
return cxstring::createNull();
Comment AST: TableGen'ize all command lists in CommentCommandTraits.cpp. Now we have a list of all commands. This is a good thing in itself, but it also enables us to easily implement typo correction for command names. With this change we have objects that contain information about each command, so it makes sense to resolve command name just once during lexing (currently we store command names as strings and do a linear search every time some property value is needed). Thus comment token and AST nodes were changed to contain a command ID -- index into a tables of builtin and registered commands. Unknown commands are registered during parsing and thus are also uniformly assigned an ID. Using an ID instead of a StringRef is also a nice memory optimization since ID is a small integer that fits into a common bitfield in Comment class. This change implies that to get any information about a command (even a command name) we need a CommandTraits object to resolve the command ID to CommandInfo*. Currently a fresh temporary CommandTraits object is created whenever it is needed since it does not have any state. But with this change it has state -- new commands can be registered, so a CommandTraits object was added to ASTContext. Also, in libclang CXComment has to be expanded to include a CXTranslationUnit so that all functions working on comment AST nodes can get a CommandTraits object. This breaks binary compatibility of CXComment APIs. Now clang_FullComment_getAsXML(CXTranslationUnit TU, CXComment CXC) doesn't need TU parameter anymore, so it was removed. This is a source-incompatible change for this C API. llvm-svn: 163540
2012-09-11 04:32:42 +08:00
const CommandTraits &Traits = getCommandTraits(CXC);
return cxstring::createRef(BCC->getCommandName(Traits));
}
unsigned clang_BlockCommandComment_getNumArgs(CXComment CXC) {
const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
if (!BCC)
return 0;
return BCC->getNumArgs();
}
CXString clang_BlockCommandComment_getArgText(CXComment CXC,
unsigned ArgIdx) {
const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
if (!BCC || ArgIdx >= BCC->getNumArgs())
return cxstring::createNull();
return cxstring::createRef(BCC->getArgText(ArgIdx));
}
CXComment clang_BlockCommandComment_getParagraph(CXComment CXC) {
const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
if (!BCC)
return createCXComment(nullptr, nullptr);
Comment AST: TableGen'ize all command lists in CommentCommandTraits.cpp. Now we have a list of all commands. This is a good thing in itself, but it also enables us to easily implement typo correction for command names. With this change we have objects that contain information about each command, so it makes sense to resolve command name just once during lexing (currently we store command names as strings and do a linear search every time some property value is needed). Thus comment token and AST nodes were changed to contain a command ID -- index into a tables of builtin and registered commands. Unknown commands are registered during parsing and thus are also uniformly assigned an ID. Using an ID instead of a StringRef is also a nice memory optimization since ID is a small integer that fits into a common bitfield in Comment class. This change implies that to get any information about a command (even a command name) we need a CommandTraits object to resolve the command ID to CommandInfo*. Currently a fresh temporary CommandTraits object is created whenever it is needed since it does not have any state. But with this change it has state -- new commands can be registered, so a CommandTraits object was added to ASTContext. Also, in libclang CXComment has to be expanded to include a CXTranslationUnit so that all functions working on comment AST nodes can get a CommandTraits object. This breaks binary compatibility of CXComment APIs. Now clang_FullComment_getAsXML(CXTranslationUnit TU, CXComment CXC) doesn't need TU parameter anymore, so it was removed. This is a source-incompatible change for this C API. llvm-svn: 163540
2012-09-11 04:32:42 +08:00
return createCXComment(BCC->getParagraph(), CXC.TranslationUnit);
}
CXString clang_ParamCommandComment_getParamName(CXComment CXC) {
const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
if (!PCC || !PCC->hasParamName())
return cxstring::createNull();
return cxstring::createRef(PCC->getParamNameAsWritten());
}
unsigned clang_ParamCommandComment_isParamIndexValid(CXComment CXC) {
const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
if (!PCC)
return false;
return PCC->isParamIndexValid();
}
unsigned clang_ParamCommandComment_getParamIndex(CXComment CXC) {
const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
if (!PCC || !PCC->isParamIndexValid() || PCC->isVarArgParam())
return ParamCommandComment::InvalidParamIndex;
return PCC->getParamIndex();
}
unsigned clang_ParamCommandComment_isDirectionExplicit(CXComment CXC) {
const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
if (!PCC)
return false;
return PCC->isDirectionExplicit();
}
enum CXCommentParamPassDirection clang_ParamCommandComment_getDirection(
CXComment CXC) {
const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
if (!PCC)
return CXCommentParamPassDirection_In;
switch (PCC->getDirection()) {
case ParamCommandComment::In:
return CXCommentParamPassDirection_In;
case ParamCommandComment::Out:
return CXCommentParamPassDirection_Out;
case ParamCommandComment::InOut:
return CXCommentParamPassDirection_InOut;
}
llvm_unreachable("unknown ParamCommandComment::PassDirection");
}
CXString clang_TParamCommandComment_getParamName(CXComment CXC) {
const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
if (!TPCC || !TPCC->hasParamName())
return cxstring::createNull();
return cxstring::createRef(TPCC->getParamNameAsWritten());
}
unsigned clang_TParamCommandComment_isParamPositionValid(CXComment CXC) {
const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
if (!TPCC)
return false;
return TPCC->isPositionValid();
}
unsigned clang_TParamCommandComment_getDepth(CXComment CXC) {
const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
if (!TPCC || !TPCC->isPositionValid())
return 0;
return TPCC->getDepth();
}
unsigned clang_TParamCommandComment_getIndex(CXComment CXC, unsigned Depth) {
const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
if (!TPCC || !TPCC->isPositionValid() || Depth >= TPCC->getDepth())
return 0;
return TPCC->getIndex(Depth);
}
CXString clang_VerbatimBlockLineComment_getText(CXComment CXC) {
const VerbatimBlockLineComment *VBL =
getASTNodeAs<VerbatimBlockLineComment>(CXC);
if (!VBL)
return cxstring::createNull();
return cxstring::createRef(VBL->getText());
}
CXString clang_VerbatimLineComment_getText(CXComment CXC) {
const VerbatimLineComment *VLC = getASTNodeAs<VerbatimLineComment>(CXC);
if (!VLC)
return cxstring::createNull();
return cxstring::createRef(VLC->getText());
}
//===----------------------------------------------------------------------===//
// Converting comments to XML.
//===----------------------------------------------------------------------===//
CXString clang_HTMLTagComment_getAsString(CXComment CXC) {
const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC);
if (!HTC)
return cxstring::createNull();
CXTranslationUnit TU = CXC.TranslationUnit;
if (!TU->CommentToXML)
TU->CommentToXML = new clang::index::CommentToXMLConverter();
SmallString<128> Text;
TU->CommentToXML->convertHTMLTagNodeToText(
HTC, Text, cxtu::getASTUnit(TU)->getASTContext());
return cxstring::createDup(Text.str());
}
CXString clang_FullComment_getAsHTML(CXComment CXC) {
const FullComment *FC = getASTNodeAs<FullComment>(CXC);
if (!FC)
return cxstring::createNull();
CXTranslationUnit TU = CXC.TranslationUnit;
if (!TU->CommentToXML)
TU->CommentToXML = new clang::index::CommentToXMLConverter();
SmallString<1024> HTML;
TU->CommentToXML
->convertCommentToHTML(FC, HTML, cxtu::getASTUnit(TU)->getASTContext());
return cxstring::createDup(HTML.str());
}
Comment AST: TableGen'ize all command lists in CommentCommandTraits.cpp. Now we have a list of all commands. This is a good thing in itself, but it also enables us to easily implement typo correction for command names. With this change we have objects that contain information about each command, so it makes sense to resolve command name just once during lexing (currently we store command names as strings and do a linear search every time some property value is needed). Thus comment token and AST nodes were changed to contain a command ID -- index into a tables of builtin and registered commands. Unknown commands are registered during parsing and thus are also uniformly assigned an ID. Using an ID instead of a StringRef is also a nice memory optimization since ID is a small integer that fits into a common bitfield in Comment class. This change implies that to get any information about a command (even a command name) we need a CommandTraits object to resolve the command ID to CommandInfo*. Currently a fresh temporary CommandTraits object is created whenever it is needed since it does not have any state. But with this change it has state -- new commands can be registered, so a CommandTraits object was added to ASTContext. Also, in libclang CXComment has to be expanded to include a CXTranslationUnit so that all functions working on comment AST nodes can get a CommandTraits object. This breaks binary compatibility of CXComment APIs. Now clang_FullComment_getAsXML(CXTranslationUnit TU, CXComment CXC) doesn't need TU parameter anymore, so it was removed. This is a source-incompatible change for this C API. llvm-svn: 163540
2012-09-11 04:32:42 +08:00
CXString clang_FullComment_getAsXML(CXComment CXC) {
const FullComment *FC = getASTNodeAs<FullComment>(CXC);
if (!FC)
return cxstring::createNull();
Comment AST: TableGen'ize all command lists in CommentCommandTraits.cpp. Now we have a list of all commands. This is a good thing in itself, but it also enables us to easily implement typo correction for command names. With this change we have objects that contain information about each command, so it makes sense to resolve command name just once during lexing (currently we store command names as strings and do a linear search every time some property value is needed). Thus comment token and AST nodes were changed to contain a command ID -- index into a tables of builtin and registered commands. Unknown commands are registered during parsing and thus are also uniformly assigned an ID. Using an ID instead of a StringRef is also a nice memory optimization since ID is a small integer that fits into a common bitfield in Comment class. This change implies that to get any information about a command (even a command name) we need a CommandTraits object to resolve the command ID to CommandInfo*. Currently a fresh temporary CommandTraits object is created whenever it is needed since it does not have any state. But with this change it has state -- new commands can be registered, so a CommandTraits object was added to ASTContext. Also, in libclang CXComment has to be expanded to include a CXTranslationUnit so that all functions working on comment AST nodes can get a CommandTraits object. This breaks binary compatibility of CXComment APIs. Now clang_FullComment_getAsXML(CXTranslationUnit TU, CXComment CXC) doesn't need TU parameter anymore, so it was removed. This is a source-incompatible change for this C API. llvm-svn: 163540
2012-09-11 04:32:42 +08:00
CXTranslationUnit TU = CXC.TranslationUnit;
if (!TU->CommentToXML)
TU->CommentToXML = new clang::index::CommentToXMLConverter();
SmallString<1024> XML;
TU->CommentToXML
->convertCommentToXML(FC, XML, cxtu::getASTUnit(TU)->getASTContext());
return cxstring::createDup(XML.str());
}