blob: 97a7f5558392534ca1edc1c57f747e6c8fdd8697 [file] [log] [blame]
//===--- DeclXML.cpp - XML implementation for Decl ASTs -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the XML document class, which provides the means to
// dump out the AST in a XML form that exposes type details and other fields.
//
//===----------------------------------------------------------------------===//
#include "clang/Frontend/DocumentXML.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/Expr.h"
namespace clang {
//---------------------------------------------------------
class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter> {
DocumentXML& Doc;
void addSubNodes(FunctionDecl* FD) {
for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
Visit(FD->getParamDecl(i));
Doc.toParent();
}
}
void addFunctionBody(FunctionDecl* FD) {
if (FD->isThisDeclarationADefinition()) {
Doc.addSubNode("Body");
Doc.PrintStmt(FD->getBody());
Doc.toParent();
}
}
void addSubNodes(RecordDecl* RD) {
for (RecordDecl::field_iterator i = RD->field_begin(),
e = RD->field_end(); i != e; ++i) {
Visit(*i);
Doc.toParent();
}
}
void addSubNodes(CXXRecordDecl* RD) {
addSubNodes(cast<RecordDecl>(RD));
if (RD->isDefinition()) {
// FIXME: This breaks XML generation
//Doc.addAttribute("num_bases", RD->getNumBases());
for (CXXRecordDecl::base_class_iterator
base = RD->bases_begin(),
bend = RD->bases_end();
base != bend;
++base) {
Doc.addSubNode("Base");
Doc.addAttribute("id", base->getType());
AccessSpecifier as = base->getAccessSpecifierAsWritten();
const char* as_name = "";
switch(as) {
case AS_none: as_name = ""; break;
case AS_public: as_name = "public"; break;
case AS_protected: as_name = "protected"; break;
case AS_private: as_name = "private"; break;
}
Doc.addAttributeOptional("access", as_name);
Doc.addAttribute("is_virtual", base->isVirtual());
Doc.toParent();
}
for (CXXRecordDecl::method_iterator i = RD->method_begin(),
e = RD->method_end(); i != e; ++i) {
Visit(*i);
Doc.toParent();
}
}
}
void addSubNodes(EnumDecl* ED) {
for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(),
e = ED->enumerator_end(); i != e; ++i) {
Visit(*i);
Doc.toParent();
}
}
void addSubNodes(EnumConstantDecl* ECD) {
if (ECD->getInitExpr())
Doc.PrintStmt(ECD->getInitExpr());
}
void addSubNodes(FieldDecl* FdD) {
if (FdD->isBitField())
Doc.PrintStmt(FdD->getBitWidth());
}
void addSubNodes(VarDecl* V) {
if (V->getInit())
Doc.PrintStmt(V->getInit());
}
void addSubNodes(ParmVarDecl* argDecl) {
if (argDecl->getDefaultArg())
Doc.PrintStmt(argDecl->getDefaultArg());
}
void addSubNodes(NamespaceDecl* ns) {
for (DeclContext::decl_iterator
d = ns->decls_begin(),
dend = ns->decls_end();
d != dend;
++d) {
Visit(*d);
Doc.toParent();
}
}
void addSpecialAttribute(const char* pName, EnumDecl* ED) {
const QualType& enumType = ED->getIntegerType();
if (!enumType.isNull())
Doc.addAttribute(pName, enumType);
}
void addIdAttribute(LinkageSpecDecl* ED) {
Doc.addAttribute("id", ED);
}
void addIdAttribute(NamedDecl* ND) {
Doc.addAttribute("id", ND);
}
public:
DeclPrinter(DocumentXML& doc) : Doc(doc) {}
#define NODE_XML( CLASS, NAME ) \
void Visit##CLASS(CLASS* T) \
{ \
Doc.addSubNode(NAME);
#define ID_ATTRIBUTE_XML addIdAttribute(T);
#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN);
#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN);
#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocation(T->getLocation());
#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, T);
#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
{ \
const char* pAttributeName = NAME; \
const bool optional = false; \
switch (T->FN) { \
default: assert(0 && "unknown enum value");
#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
{ \
const char* pAttributeName = NAME; \
const bool optional = true; \
switch (T->FN) { \
default: assert(0 && "unknown enum value");
#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
#define END_ENUM_XML } }
#define END_NODE_XML }
#define SUB_NODE_XML( CLASS ) addSubNodes(T);
#define SUB_NODE_SEQUENCE_XML( CLASS ) addSubNodes(T);
#define SUB_NODE_OPT_XML( CLASS ) addSubNodes(T);
#define SUB_NODE_FN_BODY_XML addFunctionBody(T);
#include "clang/Frontend/DeclXML.def"
};
//---------------------------------------------------------
void DocumentXML::writeDeclToXML(Decl *D) {
DeclPrinter(*this).Visit(D);
toParent();
}
//---------------------------------------------------------
} // NS clang