diff options
author | Michi Henning <michi@zeroc.com> | 2006-11-22 08:35:01 +0000 |
---|---|---|
committer | Michi Henning <michi@zeroc.com> | 2006-11-22 08:35:01 +0000 |
commit | 9073302574725750291e339e0bb4a60b1475c114 (patch) | |
tree | e2cf193e77df8aa481b5f2683802e56b25113787 /cpp/src/slice2html/Gen.cpp | |
parent | change .dll extension to .pyd to support Python 2.5 on Windows (diff) | |
download | ice-9073302574725750291e339e0bb4a60b1475c114.tar.bz2 ice-9073302574725750291e339e0bb4a60b1475c114.tar.xz ice-9073302574725750291e339e0bb4a60b1475c114.zip |
Intermediate check-in for slice2html.
Diffstat (limited to 'cpp/src/slice2html/Gen.cpp')
-rw-r--r-- | cpp/src/slice2html/Gen.cpp | 1955 |
1 files changed, 1955 insertions, 0 deletions
diff --git a/cpp/src/slice2html/Gen.cpp b/cpp/src/slice2html/Gen.cpp new file mode 100644 index 00000000000..6ae96c6b1a7 --- /dev/null +++ b/cpp/src/slice2html/Gen.cpp @@ -0,0 +1,1955 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2006 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <IceUtil/DisableWarnings.h> +#include <IceUtil/Functional.h> +#include <Gen.h> + +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef _WIN32 +#include <direct.h> +#else +#include <unistd.h> +#endif + +#ifdef __BCPLUSPLUS__ +# include <iterator> +#endif + +using namespace std; +using namespace Slice; +using namespace IceUtil; + +namespace Slice +{ + +void +generate(const UnitPtr& unit, const ::std::string& dir, + const ::std::string& header, const ::std::string& footer, unsigned indexCount) +{ + unit->mergeModules(); + + // + // I don't want the top-level module to be sorted, therefore no + // p->sort() before or after the p->sortContents(). + // + unit->sortContents(false); + + GeneratorBase::setOutputDir(dir); + GeneratorBase::setHeader(header); + GeneratorBase::setFooter(footer); + GeneratorBase::setIndexCount(indexCount); + + IndexVisitor iv; + unit->visit(&iv, false); + + Visitor v; + unit->visit(&v, false); +} + +} + +string Slice::GeneratorBase::_dir = "."; +string Slice::GeneratorBase::_header1; +string Slice::GeneratorBase::_header2; +string Slice::GeneratorBase::_footer; +unsigned Slice::GeneratorBase::_indexCount = 0; + +void +Slice::GeneratorBase::setOutputDir(const string& dir) +{ + if(!dir.empty()) + { + _dir = dir; + makeDir(_dir); + } +} + +void +Slice::GeneratorBase::setHeader(const string& header) +{ + if(header.empty()) + { + ostringstream hdr1; + XMLOutput O1(hdr1); + O1 << "<!-- Generated by Ice version " << ICE_STRING_VERSION << " -->"; + O1 << sp; + O1 << nl << "<!DOCTYPE html PUBLIC \"-//W3C//dtD html 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">"; + O1 << se("html"); + O1 << se("head"); + O1 << se("title") << nl; + _header1 = hdr1.str(); + + // _header1 and _header2 store the bit preceding and following the title. + // _header1, the title text, and _header2 are written by openDoc(). + + ostringstream hdr2; + XMLOutput O2(hdr2); + O2.inc(); + O2.inc(); + O2 << nl << "<title/>"; + O2.dec(); + O2 << nl << "</head>"; + O2 << nl << "<body>"; + _header2 = hdr2.str(); + } + else + { + readFile(header, _header1, _header2); + } +} + +void +Slice::GeneratorBase::setFooter(const string& footer) +{ + ostringstream ftr; + XMLOutput O(ftr); + if(footer.empty()) + { + O << " </body>"; + } + else + { + O << readFile(footer); + } + O << nl << "</html>"; + _footer = ftr.str(); +} + +void +Slice::GeneratorBase::setIndexCount(int ic) +{ + _indexCount = ic; +} + +Slice::GeneratorBase::GeneratorBase(XMLOutput& o) + : _out(o) +{ +} + +Slice::GeneratorBase::~GeneratorBase() +{ +} + +void +Slice::GeneratorBase::openDoc(const string& file, const string& title) +{ + openStream(_dir + "/" + file); + + _out << _header1; + _out << title; + _out << _header2; + _out.inc(); + _out.inc(); +} + +void +Slice::GeneratorBase::openDoc(const ContainedPtr& c) +{ + string path = _dir; + StringList components = toStringList(c); + StringList::const_iterator i = components.begin(); + for(StringList::size_type num = 0; num < components.size() - 1; ++num, ++i) + { + path += "/" + *i; + makeDir(path); + } + path += "/" + *i + ".html"; + + openStream(path); + + _out << _header1; + _out << c->scoped().substr(2); // Text for title element. + _out << _header2; + _out.inc(); + _out.inc(); +} + +void +Slice::GeneratorBase::closeDoc() +{ + _out.dec(); + _out.dec(); + _out << nl << _footer; + _out << nl; +} + +void +Slice::GeneratorBase::start(const std::string& element, const std::string& classes) +{ + string s = element; + if(!classes.empty()) + { + s += " class=\"" + classes + "\""; + } + _out << se(s); +} + +void +Slice::GeneratorBase::end() +{ + _out << ee; +} + +string +Slice::GeneratorBase::getComment(const ContainedPtr& contained, const ContainerPtr& container, bool summary) +{ + string s = contained->comment(); + string comment; + for(unsigned int i = 0; i < s.size(); ++i) + { + if(s[i] == '\\' && i + 1 < s.size() && s[i + 1] == '[') + { + comment += '['; + ++i; + } + else if(s[i] == '[') + { + string literal; + for(++i; i < s.size(); ++i) + { + if(s[i] == ']') + { + break; + } + + literal += s[i]; + } + comment += toString(literal, container); + } + else if(summary && s[i] == '.' && (i + 1 >= s.size() || isspace(s[i + 1]))) + { + comment += '.'; + break; + } + else + { + comment += s[i]; + } + + } + return comment; +} + +void +Slice::GeneratorBase::printComment(const ContainedPtr& p, const string& deprecateReason) +{ +#ifndef NDEBUG + int indent = _out.currIndent(); +#endif + + ContainerPtr container = ContainerPtr::dynamicCast(p); + if(!container) + { + container = p->container(); + } + + string comment = getComment(p, container, false); + StringList par = getTagged("param", comment); + StringList ret = getTagged("return", comment); + StringList throws = getTagged("throws", comment); + StringList see = getTagged("see", comment); + + string::size_type pos = comment.find_last_not_of(" \t\r\n"); + if(pos != string::npos) + { + comment.erase(pos + 1); + _out.zeroIndent(); + _out << nl << comment; + _out.restoreIndent(); + } + + if(!deprecateReason.empty()) + { + end(); + start("dd"); + _out << nl << deprecateReason; + } + + assert(_out.currIndent() == indent); + + bool startedList = false; + + if(!par.empty()) + { + start("dl"); + startedList = true; + start("dt", "Heading"); + _out << "Parameters"; + end(); + start("dd"); + start("dl"); + for(StringList::const_iterator q = par.begin(); q != par.end(); ++q) + { + string term; + pos = q->find_first_of(" \t\r\n"); + if(pos != string::npos) + { + term = q->substr(0, pos); + } + string item; + pos = q->find_first_not_of(" \t\r\n", pos); + if(pos != string::npos) + { + item = q->substr(pos); + } + + start("dt", "Symbol"); + _out << term; + end(); + start("dd"); + _out << nl << item; + end(); + } + end(); + end(); + } + + if(!ret.empty()) + { + if(!startedList) + { + start("dl"); + startedList = true; + } + start("dt"); + _out << "Return Value"; + end(); + start("dd", "Symbol"); + _out << ret.front(); + end(); + } + + + if(!throws.empty()) + { + if(!startedList) + { + start("dl"); + startedList = true; + } + start("dt", "Heading"); + _out << "Exceptions"; + end(); + start("dd"); + start("dl"); + for(StringList::const_iterator q = throws.begin(); q != throws.end(); ++q) + { + string term; + pos = q->find_first_of(" \t\r\n"); + if(pos != string::npos) + { + term = q->substr(0, pos); + } + string item; + pos = q->find_first_not_of(" \t\r\n", pos); + if(pos != string::npos) + { + item = q->substr(pos); + } + + start("dt", "Symbol"); + _out << toString(term, container); + end(); + start("dd"); + _out << nl << item; + end(); + } + end(); + end(); + } + + + ClassList derivedClasses; + ClassDefPtr def = ClassDefPtr::dynamicCast(p); + if(def) + { + derivedClasses = p->unit()->findDerivedClasses(def); + } + if(!derivedClasses.empty()) + { + if(!startedList) + { + start("dl"); + startedList = true; + } + start("dt", "Heading"); + _out << "Derived Classes and Interfaces"; + end(); + start("dd"); + start("dl"); + for(ClassList::const_iterator q = derivedClasses.begin(); q != derivedClasses.end(); ++q) + { + start("dt", "Symbol"); + _out << toString(*q, container); + end(); + } + end(); + end(); + } + + ExceptionList derivedExceptions; + ExceptionPtr ex = ExceptionPtr::dynamicCast(p); + if(ex) + { + derivedExceptions = p->unit()->findDerivedExceptions(ex); + if(!derivedExceptions.empty()) + { + if(!startedList) + { + start("dl"); + startedList = true; + } + start("dt", "Heading"); + _out << "Derived Exceptions"; + end(); + start("dd"); + start("dl"); + for(ExceptionList::const_iterator q = derivedExceptions.begin(); q != derivedExceptions.end(); ++q) + { + start("dt", "Symbol"); + _out << toString(*q, container); + end(); + } + end(); + end(); + } + + ContainedList usedBy; + usedBy = p->unit()->findUsedBy(ex); + if(!usedBy.empty()) + { + if(!startedList) + { + start("dl"); + startedList = true; + } + start("dt", "Heading"); + _out << "Used By"; + end(); + start("dd"); + start("dl", "UsedBy"); + // + // We first extract the symbol names from the used-by list and sort + // them, otherwise the symbols appear in random order. + // + StringList sl; + for(ContainedList::const_iterator q = usedBy.begin(); q != usedBy.end(); ++q) + { + sl.push_back(toString(*q, container)); + } + sl.sort(); + for(StringList::const_iterator r = sl.begin(); r != sl.end(); ++r) + { + start("dt", "Symbol"); + _out << *r; + end(); + } + end(); + end(); + } + } + + ContainedList usedBy; + ConstructedPtr constructed; + if(def) + { + constructed = def->declaration(); + } + else + { + constructed = ConstructedPtr::dynamicCast(p); + } + if(constructed) + { + usedBy = p->unit()->findUsedBy(constructed); + } + if(!usedBy.empty()) + { + // + // We first accumulate the strings in a list instead of printing + // each stringified entry in the usedBy list. This is necessary because + // the usedBy list can contain operations and parameters. But toString() + // on a parameter returns the string for the parameter's operation, so + // we can end up printing the same operation name more than once. + // + StringList strings; + for(ContainedList::const_iterator q = usedBy.begin(); q != usedBy.end(); ++q) + { + strings.push_back(toString(*q, container)); + } + strings.sort(); + strings.unique(); + + if(!startedList) + { + start("dl"); + startedList = true; + } + start("dt", "Heading"); + _out << "Used By"; + end(); + start("dd"); + start("dl", "UsedBy"); + for(list<string>::const_iterator p = strings.begin(); p != strings.end(); ++p) + { + start("dt", "Symbol"); + _out << *p; + end(); + } + end(); + end(); + } + + if(!see.empty()) + { + if(!startedList) + { + start("dl"); + startedList = true; + } + start("dt", "Heading"); + _out << "See Also"; + end(); + start("dd"); + start("dl", "UsedBy"); + for(StringList::const_iterator q = see.begin(); q != see.end(); ++q) + { + start("dt", "Symbol"); + _out << toString(*q, container); + end(); + } + end(); + end(); + } + + if(startedList) + { + end(); + } + + assert(_out.currIndent() == indent); +} + +void +Slice::GeneratorBase::printMetaData(const ContainedPtr& p) +{ + list<string> metaData = p->getMetaData(); + + if(!metaData.empty()) + { + _out << "["; + list<string>::const_iterator q = metaData.begin(); + while(q != metaData.end()) + { + _out << " \"" << *q << "\""; + if(++q != metaData.end()) + { + _out << ","; + } + } + _out << " ]" << nl; + } +} + +void +Slice::GeneratorBase::printSummary(const ContainedPtr& p, bool deprecated) +{ + ContainerPtr container = ContainerPtr::dynamicCast(p); + if(!container) + { + container = p->container(); + } + + string summary = getComment(p, container, true); + start("dd", "Summary"); + _out << nl << summary; + end(); + + if(deprecated) + { + start("dd", "Deprecated"); + _out << nl << "Deprecated."; + end(); + } +} + +string +Slice::GeneratorBase::toString(const SyntaxTreeBasePtr& p, const ContainerPtr& container, bool asTarget) +{ + string linkend; + string s; + + static const char* builtinTable[] = + { + "byte", + "bool", + "short", + "int", + "long", + "float", + "double", + "string", + "Object", + "Object*", + "LocalObject" + }; + + BuiltinPtr builtin = BuiltinPtr::dynamicCast(p); + if(builtin) + { + s = builtinTable[builtin->kind()]; + } + + ProxyPtr proxy = ProxyPtr::dynamicCast(p); + if(proxy) + { + if(proxy->_class()->includeLevel() == 0) + { + linkend = containedToId(proxy->_class(), asTarget); + } + s = getScopedMinimized(proxy->_class(), container); + s += "*"; + } + + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(p); + if(cl) + { + // + // We must generate the id from the definition, not from the + // declaration, provided that a definition is available. + // + ContainedPtr definition = cl->definition(); + if(definition && definition->includeLevel() == 0) + { + linkend = containedToId(definition, asTarget); + } + s = getScopedMinimized(cl, container); + } + + ExceptionPtr ex = ExceptionPtr::dynamicCast(p); + if(ex) + { + if(ex->includeLevel() == 0) + { + linkend = containedToId(ex, asTarget); + } + s = getScopedMinimized(ex, container); + } + + StructPtr st = StructPtr::dynamicCast(p); + if(st) + { + if(st->includeLevel() == 0) + { + linkend = containedToId(st, asTarget); + } + s = getScopedMinimized(st, container); + } + + EnumeratorPtr en = EnumeratorPtr::dynamicCast(p); + if(en) + { + if(en->includeLevel() == 0) + { + linkend = containedToId(en, asTarget); + } + s = getScopedMinimized(en, container); + } + + OperationPtr op = OperationPtr::dynamicCast(p); + if(op) + { + if(op->includeLevel() == 0) + { + linkend = containedToId(op, asTarget); + } + s = getScopedMinimized(op, container); + } + + ParamDeclPtr pd = ParamDeclPtr::dynamicCast(p); + if(pd) + { + op = OperationPtr::dynamicCast(pd->container()); + assert(op); + if(pd->includeLevel() == 0) + { + linkend = containedToId(op, asTarget); + } + s = getScopedMinimized(op, container); + } + + if(s.empty()) + { + ContainedPtr contained = ContainedPtr::dynamicCast(p); + assert(contained); + if(contained->includeLevel() == 0) + { + linkend = containedToId(contained, asTarget); + } + s = getScopedMinimized(contained, container); + } + + if(linkend.empty()) + { + return s; + } + else + { + string ret = "<a "; + ret += asTarget ? "name" : "href"; + ret += "=" + linkend + + ">" + s + "</a>"; + return ret; + } +} + +string +Slice::GeneratorBase::toString(const string& str, const ContainerPtr& container, bool asTarget) +{ + string s = str; + + TypeList types = container->lookupType(s, false); + if(!types.empty()) + { + return toString(types.front(), container, asTarget); + } + + ContainedList contList = container->lookupContained(s, false); + if(!contList.empty()) + { + return toString(contList.front(), container, asTarget); + } + + // + // If we can't find the string, printing it in typewriter + // font is the best we can do. + // + return "<span class=Symbol>" + s + "</span>"; +} + +StringList +Slice::GeneratorBase::getTagged(const string& tag, string& comment) +{ + StringList result; + string::size_type begin = 0; + while(begin < comment.size()) + { + begin = comment.find("@" + tag, begin); + if(begin == string::npos) + { + return result; + } + + string::size_type pos1 = comment.find_first_not_of(" \t\r\n", begin + tag.size() + 1); + if(pos1 == string::npos) + { + comment.erase(begin); + return result; + } + + string::size_type pos2 = comment.find('@', pos1); + string line = comment.substr(pos1, pos2 - pos1); + comment.erase(begin, pos2 - 1 - begin); + + string::size_type pos3 = line.find_last_not_of(" \t\r\n"); + if(pos3 != string::npos) + { + line.erase(pos3 + 1); + } + result.push_back(line); + } + + return result; +} + +#if 0 +string +Slice::GeneratorBase::getScopedMinimized(const ContainedPtr& contained, const ContainerPtr& container) +{ + cerr << "contained is " << contained->scoped() << endl; + cerr << "container is " << ContainedPtr::dynamicCast(container)->scoped() << endl; + StringList anchors; + ContainedPtr c = contained; + while(!ExceptionPtr::dynamicCast(c) && + !ClassDeclPtr::dynamicCast(c) && + !ClassDefPtr::dynamicCast(c) && + !StructPtr::dynamicCast(c) && + !ModulePtr::dynamicCast(c)) + { + cerr << "Pushing " << c->name() << endl; + anchors.push_front(c->name()); + c = ContainedPtr::dynamicCast(c->container()); + } + + cerr << "c is " << ContainedPtr::dynamicCast(c)->scoped() << endl; +#if 0 + StringList from = toStringList(contained); + StringList to = toStringList(ContainedPtr::dynamicCast(container)); + + StringList::const_iterator f = from.begin(); + StringList::const_iterator t = to.begin(); + while(f != from.end() && t != to.end()) + { + } +#endif + cerr << "returning" << endl; + return ""; +} +#endif + +string +Slice::GeneratorBase::getScopedMinimized(const ContainedPtr& contained, const ContainerPtr& container) +{ + cerr << "get" << endl; + cerr << "contained: " << contained->scoped() << endl; + if(container) + { + cerr << "container: " << ContainedPtr::dynamicCast(container)->scoped() << endl; + } + string s = contained->scoped(); + ContainerPtr p = container; + ContainedPtr q = ContainedPtr::dynamicCast(p); + + if(!q) // Container is the global module + { + return s.substr(2); + } + + do + { + string s2 = q->scoped(); + s2 += "::"; + + if(s.find(s2) == 0) + { + return s.substr(s2.size()); + } + + p = q->container(); + q = ContainedPtr::dynamicCast(p); + } + while(q); + + return s; +} + +string +Slice::GeneratorBase::containedToId(const ContainedPtr& contained, bool asTarget) +{ + assert(contained); + + string scoped = contained->scoped(); + if(scoped[0] == ':') + { + scoped.erase(0, 2); + } + + string id; + id.reserve(scoped.size()); + + for(unsigned int i = 0; i < scoped.size(); ++i) + { + if(scoped[i] == ':') + { + id += '.'; + ++i; + } + else + { + id += scoped[i]; + } + } + + // + // A link name cannot start with a period. + // + if(id[0] == '.') + { + id.erase(0, 1); + } + + return '"' + id + '"'; +} + +void +Slice::GeneratorBase::openStream(const string& path) +{ + _out.open(path.c_str()); + if(!_out.isOpen()) + { + string err = "cannot open `" + path + "' for writing"; + throw err; + } +} + +StringList +Slice::GeneratorBase::toStringList(const ContainedPtr& c) +{ + string scoped = c->scoped(); + assert(scoped.size() > 2); + assert(scoped[0] == ':'); + assert(scoped[1] == ':'); + + StringList ids; + string::size_type next = 2; + string::size_type endpos; + while((endpos = scoped.find("::", next)) != string::npos) + { + ids.push_back(scoped.substr(next, endpos - next)); + next = endpos; + if(next != string::npos) + { + ++next; + ++next; + } + } + ids.push_back(scoped.substr(next)); + + return ids; +} + +void +Slice::GeneratorBase::makeDir(const string& dir) +{ + struct stat st; + int rc = stat(dir.c_str(), &st); + if(rc == 0) + { + return; + } +#ifdef _WIN32 + rc = mkdir(dir.c_str()) +#else + rc = mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); +#endif + if(rc != 0) + { + string err = "cannot create directory `" + dir + "'"; + throw err; + } +} + +string +Slice::GeneratorBase::readFile(const string& file) +{ + ifstream in(file.c_str()); + if(!in) + { + string err = "cannot open `" + file + "' for reading"; + throw err; + } + + ostringstream result; + string line; + getline(in, line); + while(!line.empty()) + { + result << line << '\n'; + getline(in, line); + } + + return result.str(); +} + +void +Slice::GeneratorBase::readFile(const string& file, string& part1, string& part2) +{ + ifstream in(file.c_str()); + if(!in) + { + string err = "cannot open `" + file + "' for reading"; + throw err; + } + + string line; + + ostringstream p1; + getline(in, line); + while(!line.empty() && line != "TITLE") + { + p1 << line << '\n'; + getline(in, line); + } + part1 = p1.str(); + + if(line.empty()) + { + string err = "no TITLE marker in `" + file + "'"; + throw err; + } + + ostringstream p2; + p2 << endl; + getline(in, line); + while(!line.empty()) + { + p2 << line << '\n'; + getline(in, line); + } + part2 = p2.str(); +} + +Slice::IndexGenerator::IndexGenerator() + : GeneratorBase(_out) +{ + openDoc("index.html", "Slice Documentation Index"); +} + +Slice::IndexGenerator::~IndexGenerator() +{ + ::std::sort(_modules.begin(), _modules.end()); + + start("dl"); + start("dt"); + _out << "Modules"; + end(); + start("dd"); + start("dl"); + for(ModuleDescriptions::const_iterator i = _modules.begin(); i != _modules.end(); ++i) + { + start("dt"); + _out << i->first; + end(); + start("dd"); + _out << i->second; + end(); + } + end(); + end(); + end(); + + closeDoc(); +} + +void +Slice::IndexGenerator::generate(const ModulePtr& m) +{ + string name = toString(m, 0, false); + string comment = getComment(m, 0, true); + _modules.push_back(make_pair(name, comment)); +} + +Slice::IndexVisitor::IndexVisitor() +{ +} + +bool +Slice::IndexVisitor::visitUnitStart(const UnitPtr& unit) +{ + return true; +} + +bool +Slice::IndexVisitor::visitModuleStart(const ModulePtr& m) +{ + _ig.generate(m); + return false; +} + +Slice::ModuleGenerator::ModuleGenerator(XMLOutput& o) + : GeneratorBase(o) +{ +} + +void +Slice::ModuleGenerator::generate(const ModulePtr& m) +{ +#ifndef NDEBUG + int indent = _out.currIndent(); +#endif + + openDoc(m); + + start("dl"); + start("dt", "Symbol"); + _out << m->name(); + end(); + + start("dd"); + start("dl"); + string metadata, deprecateReason; + if(m->findMetaData("deprecate", metadata)) + { + deprecateReason = "This module is deprecated."; + if(metadata.find("deprecate:") == 0 && metadata.size() > 10) + { + deprecateReason = metadata.substr(10); + } + } + start("dt", "Heading"); + _out << "Overview"; + end(); + start("dd"); + start("dl"); + start("dt"); + start("span", "Synopsis"); + printMetaData(m); + _out << "module " << m->name(); + end(); + end(); + start("dd"); + printComment(m, deprecateReason); + end(); + end(); + + visitContainer(m); + + end(); + end(); + end(); + end(); + + closeDoc(); + + assert(_out.currIndent() == indent); +} + +void +Slice::ModuleGenerator::visitContainer(const ContainerPtr& p) +{ +#ifndef NDEBUG + int indent = _out.currIndent(); +#endif + + ModuleList modules = p->modules(); + modules.erase(remove_if(modules.begin(), modules.end(), ::IceUtil::constMemFun(&Contained::includeLevel)), + modules.end()); + + if(_indexCount > 0 && modules.size() >= _indexCount) + { + start("dt", "Heading"); + _out << "Module Index"; + end(); + start("dd"); + start("dl"); + for(ModuleList::const_iterator q = modules.begin(); q != modules.end(); ++q) + { + start("dt", "Symbol"); + _out << toString(*q, p); + end(); + start("dd"); + string metadata; + printSummary(*q, (*q)->findMetaData("deprecate", metadata)); + end(); + } + end(); + end(); + } + + assert(_out.currIndent() == indent); + + ClassList classesAndInterfaces = p->classes(); + classesAndInterfaces.erase(remove_if(classesAndInterfaces.begin(), classesAndInterfaces.end(), + ::IceUtil::constMemFun(&Contained::includeLevel)), + classesAndInterfaces.end()); + ClassList classes; + ClassList interfaces; + remove_copy_if(classesAndInterfaces.begin(), classesAndInterfaces.end(), back_inserter(classes), + ::IceUtil::constMemFun(&ClassDef::isInterface)); + remove_copy_if(classesAndInterfaces.begin(), classesAndInterfaces.end(), back_inserter(interfaces), + not1(::IceUtil::constMemFun(&ClassDef::isInterface))); + + if(_indexCount > 0 && classes.size() >= _indexCount) + { + start("dt", "Heading"); + _out << "Class Index"; + end(); + start("dd"); + start("dl"); + for(ClassList::const_iterator q = classes.begin(); q != classes.end(); ++q) + { + start("dt", "Symbol"); + _out << toString(*q, p); + end(); + start("dd"); + string metadata; + printSummary(*q, (*q)->findMetaData("deprecate", metadata)); + end(); + } + end(); + end(); + } + + assert(_out.currIndent() == indent); + + if(_indexCount > 0 && interfaces.size() >= _indexCount) + { + start("dt", "Heading"); + _out << "Interface Index"; + end(); + start("dd"); + start("dl"); + for(ClassList::const_iterator q = interfaces.begin(); q != interfaces.end(); ++q) + { + start("dt", "Symbol"); + _out << toString(*q, p); + end(); + start("dd"); + string metadata; + printSummary(*q, (*q)->findMetaData("deprecate", metadata)); + end(); + } + end(); + end(); + } + + assert(_out.currIndent() == indent); + + ExceptionList exceptions = p->exceptions(); + exceptions.erase(remove_if(exceptions.begin(), exceptions.end(), ::IceUtil::constMemFun(&Contained::includeLevel)), + exceptions.end()); + + if(_indexCount > 0 && exceptions.size() >= _indexCount) + { + start("dt", "Heading"); + _out << "Exception Index"; + end(); + start("dd"); + start("dl"); + for(ExceptionList::const_iterator q = exceptions.begin(); q != exceptions.end(); ++q) + { + start("dt", "Symbol"); + _out << toString(*q, p); + end(); + start("dd"); + string metadata; + printSummary(*q, (*q)->findMetaData("deprecate", metadata)); + end(); + } + end(); + end(); + } + + assert(_out.currIndent() == indent); + + StructList structs = p->structs(); + structs.erase(remove_if(structs.begin(), structs.end(), ::IceUtil::constMemFun(&Contained::includeLevel)), + structs.end()); + + if(_indexCount > 0 && structs.size() >= _indexCount) + { + start("dt", "Heading"); + _out << "Structure Index"; + end(); + start("dd"); + start("dl"); + for(StructList::const_iterator q = structs.begin(); q != structs.end(); ++q) + { + start("dt", "Symbol"); + _out << toString(*q, p); + end(); + start("dd"); + string metadata; + printSummary(*q, (*q)->findMetaData("deprecate", metadata)); + end(); + } + end(); + end(); + } + + assert(_out.currIndent() == indent); + + SequenceList sequences = p->sequences(); + sequences.erase(remove_if(sequences.begin(), sequences.end(), ::IceUtil::constMemFun(&Contained::includeLevel)), + sequences.end()); + + if(_indexCount > 0 && sequences.size() >= _indexCount) + { + start("dt", "Heading"); + _out << "Sequence Index"; + end(); + start("dd"); + start("dl"); + for(SequenceList::const_iterator q = sequences.begin(); q != sequences.end(); ++q) + { + start("dt", "Symbol"); + _out << toString(*q, p); + end(); + start("dd"); + string metadata; + printSummary(*q, (*q)->findMetaData("deprecate", metadata)); + end(); + } + end(); + end(); + } + + assert(_out.currIndent() == indent); + + DictionaryList dictionaries = p->dictionaries(); + dictionaries.erase(remove_if(dictionaries.begin(), dictionaries.end(), + ::IceUtil::constMemFun(&Contained::includeLevel)), + dictionaries.end()); + + if(_indexCount > 0 && dictionaries.size() >= _indexCount) + { + start("dt", "Heading"); + _out << "Dictionary Index"; + end(); + start("dd"); + start("dl"); + for(DictionaryList::const_iterator q = dictionaries.begin(); q != dictionaries.end(); ++q) + { + start("dt", "Symbol"); + _out << toString(*q, p); + end(); + start("dd"); + string metadata; + printSummary(*q, (*q)->findMetaData("deprecate", metadata)); + end(); + } + end(); + end(); + } + + assert(_out.currIndent() == indent); + + EnumList enums = p->enums(); + enums.erase(remove_if(enums.begin(), enums.end(), ::IceUtil::constMemFun(&Contained::includeLevel)), + enums.end()); + + if(_indexCount > 0 && enums.size() >= _indexCount) + { + start("dt", "Heading"); + _out << "Enumeration Index"; + end(); + start("dd"); + start("dl"); + for(EnumList::const_iterator q = enums.begin(); q != enums.end(); ++q) + { + start("dt", "Symbol"); + _out << toString(*q, p); + end(); + start("dd"); + string metadata; + printSummary(*q, (*q)->findMetaData("deprecate", metadata)); + end(); + } + end(); + end(); + } + + assert(_out.currIndent() == indent); + + if(!sequences.empty()) + { + start("dt", "Heading"); + _out << "Sequences"; + end(); + start("dd"); + for(SequenceList::const_iterator q = sequences.begin(); q != sequences.end(); ++q) + { + start("dl"); + start("dt"); + start("span", "Synopsis"); + printMetaData(*q); + if((*q)->isLocal()) + { + _out << "local "; + } + TypePtr type = (*q)->type(); + _out << "sequence<" << toString(type, p) << "> " << (*q)->name(); + end(); + end(); + + start("dd"); + string metadata, deprecateReason; + if((*q)->findMetaData("deprecate", metadata)) + { + deprecateReason = "This type is deprecated."; + if(metadata.find("deprecate:") == 0 && metadata.size() > 10) + { + deprecateReason = metadata.substr(10); + } + } + + printComment(*q, deprecateReason); + end(); + end(); + } + end(); + } + + if(!dictionaries.empty()) + { + start("dt", "Heading"); + _out << "Dictionaries"; + end(); + start("dd"); + for(DictionaryList::const_iterator q = dictionaries.begin(); q != dictionaries.end(); ++q) + { + start("dl"); + start("dt"); + start("span", "Synopsis"); + printMetaData(*q); + if((*q)->isLocal()) + { + _out << "local "; + } + TypePtr keyType = (*q)->keyType(); + TypePtr valueType = (*q)->valueType(); + _out << "dictionary<" << toString(keyType, p) << ", " << toString(valueType, p) << "> " + << (*q)->name(); + end(); + end(); + + start("dd"); + string metadata, deprecateReason; + if((*q)->findMetaData("deprecate", metadata)) + { + deprecateReason = "This type is deprecated."; + if(metadata.find("deprecate:") == 0 && metadata.size() > 10) + { + deprecateReason = metadata.substr(10); + } + } + + printComment(*q, deprecateReason); + end(); + end(); + } + end(); + } +} + +Slice::ExceptionGenerator::ExceptionGenerator(XMLOutput& o) + : GeneratorBase(o) +{ +} + +void +Slice::ExceptionGenerator::generate(const ExceptionPtr& e) +{ +#ifndef NDEBUG + int indent = _out.currIndent(); +#endif + + openDoc(e); + + start("dl"); + start("dt", "Symbol, Heading"); + _out << e->name(); + end(); + + string metadata, deprecateReason; + bool deprecatedException = e->findMetaData("deprecate", metadata); + if(deprecatedException) + { + deprecateReason = "This module is deprecated."; + if(metadata.find("deprecate:") == 0 && metadata.size() > 10) + { + deprecateReason = metadata.substr(10); + } + } + + start("dd"); + start("dl"); + start("dt", "Heading"); + _out << "Overview"; + end(); + + start("dd"); + start("dl"); + start("dt"); + start("span", "Synopsis"); + printMetaData(e); + if(e->isLocal()) + { + _out << "local "; + } + _out << "exception " << e->name(); + ExceptionPtr base = e->base(); + if(base) + { + _out.inc(); + _out << nl << "extends "; + _out.inc(); + _out << nl << toString(base, e); + _out.dec(); + _out.dec(); + } + end(); + end(); + start("dd"); + printComment(e, deprecateReason); + end(); + end(); + + DataMemberList dataMembers = e->dataMembers(); + if(!dataMembers.empty()) + { + start("dt", "Heading"); + _out << "Data Members"; + end(); + start("dd"); + start("dl"); + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + start("dt", "Symbol"); + printMetaData(*q); + TypePtr type = (*q)->type(); + _out << toString(type, e) << " " << (*q)->name() << ";"; + end(); + + start("dd"); + string reason; + metadata.clear(); + if(deprecatedException || (*q)->findMetaData("deprecate", metadata)) + { + reason = "This member is deprecated."; + if(metadata.find("deprecate:") == 0 && metadata.size() > 10) + { + reason = metadata.substr(10); + } + } + + printComment(*q, reason); + end(); + } + end(); + end(); + } + end(); + end(); + end(); + end(); + + closeDoc(); + + assert(_out.currIndent() == indent); +} + +Slice::ClassGenerator::ClassGenerator(XMLOutput& o) + : GeneratorBase(o) +{ +} + +void +Slice::ClassGenerator::generate(const ClassDefPtr& c) +{ +#ifndef NDEBUG + int indent = _out.currIndent(); +#endif + + openDoc(c); + + start("dl"); + start("dt", "Symbol"); + _out << c->name(); + end(); + + string metadata, deprecateReason; + bool deprecatedClass = c->findMetaData("deprecate", metadata); + if(deprecatedClass) + { + deprecateReason = "This "; + deprecateReason += c->isInterface() ? "interface" : "class"; + deprecateReason += " is deprecated."; + if(metadata.find("deprecate:") == 0 && metadata.size() > 10) + { + deprecateReason = metadata.substr(10); + } + } + + start("dd"); + start("dl"); + start("dt", "Heading"); + _out << "Overview"; + end(); + start("dd"); + start("dl"); + start("dt"); + start("span", "Synopsis"); + printMetaData(c); + if(c->isLocal()) + { + _out << "local "; + } + _out << (c->isInterface() ? "interface" : "class" )<< " " << c->name(); + + ClassList bases = c->bases(); + if(!bases.empty() && !bases.front()->isInterface()) + { + _out << " extends " << toString(bases.front(), c); + bases.pop_front(); + } + + if(!bases.empty()) + { + _out << (c->isInterface() ? " extends " : " implements "); + ClassList::const_iterator q = bases.begin(); + while(q != bases.end()) + { + _out << toString(*q, c); + if(++q != bases.end()) + { + _out << ", "; + } + } + } + end(); + end(); + + start("dd"); + printComment(c, deprecateReason); + end(); + end(); + end(); + + OperationList operations = c->operations(); + if(!operations.empty()) + { + start("dt", "Heading"); + _out << "Operations"; + end(); + start("dd"); + start("dl"); + for(OperationList::const_iterator q = operations.begin(); q != operations.end(); ++q) + { + start("dt"); + start("span", "Synopsis"); + TypePtr returnType = (*q)->returnType(); + _out << (returnType ? toString(returnType, c) : string("void")) << " "<< (*q)->name() << "("; + ParamDeclList params = (*q)->parameters(); + ParamDeclList::const_iterator r = params.begin(); + while(r != params.end()) + { + if((*r)->isOutParam()) + { + _out << "out "; + } + _out << toString((*r)->type(), *q) << " " << (*r)->name(); + if(++r != params.end()) + { + _out << ", "; + } + } + _out << ")"; + ExceptionList throws = (*q)->throws(); + if(!throws.empty()) + { + _out << " throws "; + ExceptionList::const_iterator t = throws.begin(); + while(t != throws.end()) + { + _out << toString(*t, c); + if(++t != throws.end()) + { + _out << ", "; + } + } + } + end(); + end(); + + start("dd"); + string reason; + metadata.clear(); + if(deprecatedClass || (*q)->findMetaData("deprecate", metadata)) + { + reason = "This operation is deprecated."; + if(metadata.find("deprecate:") == 0 && metadata.size() > 10) + { + reason = metadata.substr(10); + } + } + printComment(*q, reason); + end(); + } + end(); + end(); + } + + DataMemberList dataMembers = c->dataMembers(); + if(!dataMembers.empty()) + { + start("dl"); + start("dt", "Heading"); + _out << "Data Members"; + end(); + start("dl"); + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + start("dt"); + start("span", "Synopsis"); + printMetaData(*q); + TypePtr type = (*q)->type(); + _out << toString(type, c) << " " << (*q)->name() << ";"; + end(); + end(); + + start("dd"); + string reason; + metadata.clear(); + if(deprecatedClass || (*q)->findMetaData("deprecate", metadata)) + { + reason = "This member is deprecated."; + if(metadata.find("deprecate:") == 0 && metadata.size() > 10) + { + reason = metadata.substr(10); + } + } + + printComment(*q, reason); + end(); + } + end(); + end(); + } + + end(); + end(); + end(); + + closeDoc(); + + assert(_out.currIndent() == indent); +} + +Slice::StructGenerator::StructGenerator(XMLOutput& o) + : GeneratorBase(o) +{ +} + +void +Slice::StructGenerator::generate(const StructPtr& s) +{ +#ifndef NDEBUG + int indent = _out.currIndent(); +#endif + + openDoc(s); + + start("dl"); + start("dt", "Symbol, Heading"); + _out << s->name(); + end(); + + string metadata, deprecateReason; + bool deprecatedException = s->findMetaData("deprecate", metadata); + if(deprecatedException) + { + deprecateReason = "This module is deprecated."; + if(metadata.find("deprecate:") == 0 && metadata.size() > 10) + { + deprecateReason = metadata.substr(10); + } + } + + start("dd"); + start("dl"); + start("dt", "Heading"); + _out << "Overview"; + end(); + + start("dd"); + start("dl"); + start("dt"); + start("span", "Synopsis"); + printMetaData(s); + if(s->isLocal()) + { + _out << "local "; + } + _out << "struct " << s->name(); + end(); + end(); + start("dd"); + printComment(s, deprecateReason); + end(); + end(); + + DataMemberList dataMembers = s->dataMembers(); + if(!dataMembers.empty()) + { + start("dt", "Heading"); + _out << "Data Members"; + end(); + start("dd"); + start("dl"); + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + start("dt", "Symbol"); + printMetaData(*q); + TypePtr type = (*q)->type(); + _out << toString(type, s) << " " << (*q)->name() << ";"; + end(); + + start("dd"); + string reason; + metadata.clear(); + if(deprecatedException || (*q)->findMetaData("deprecate", metadata)) + { + reason = "This member is deprecated."; + if(metadata.find("deprecate:") == 0 && metadata.size() > 10) + { + reason = metadata.substr(10); + } + } + + printComment(*q, reason); + end(); + } + end(); + end(); + } + end(); + end(); + end(); + end(); + + closeDoc(); + + assert(_out.currIndent() == indent); +} + +Slice::EnumGenerator::EnumGenerator(XMLOutput& o) + : GeneratorBase(o) +{ +} + +void +Slice::EnumGenerator::generate(const EnumPtr& e) +{ +#ifndef NDEBUG + int indent = _out.currIndent(); +#endif + + openDoc(e); + + start("dl"); + start("dt", "Symbol, Heading"); + _out << e->name(); + end(); + + string metadata, deprecateReason; + bool deprecatedException = e->findMetaData("deprecate", metadata); + if(deprecatedException) + { + deprecateReason = "This enumeration is deprecated."; + if(metadata.find("deprecate:") == 0 && metadata.size() > 10) + { + deprecateReason = metadata.substr(10); + } + } + + start("dd"); + start("dl"); + start("dt", "Heading"); + _out << "Overview"; + end(); + + start("dd"); + start("dl"); + start("dt"); + start("span", "Synopsis"); + printMetaData(e); + if(e->isLocal()) + { + _out << "local "; + } + _out << "enum " << e->name(); + end(); + end(); + + start("dd"); + printComment(e, deprecateReason); + end(); + end(); + + EnumeratorList enumerators = e->getEnumerators(); + if(!enumerators.empty()) + { + start("dt", "Heading"); + _out << "Enumerators"; + end(); + start("dd"); + start("dl"); + for(EnumeratorList::const_iterator q = enumerators.begin(); q != enumerators.end(); ++q) + { + start("dt", "Symbol"); + _out << (*q)->name(); + end(); + + start("dd"); + string reason; + // + // Enumerators do not support metadata. + // + printComment(*q, reason); + end(); + } + end(); + end(); + } + end(); + end(); + end(); + end(); + + closeDoc(); + + assert(_out.currIndent() == indent); +} + +Slice::Visitor::Visitor() +{ +} + +bool +Slice::Visitor::visitUnitStart(const UnitPtr& unit) +{ + return true; +} + +bool +Slice::Visitor::visitModuleStart(const ModulePtr& m) +{ + XMLOutput O; + ModuleGenerator mg(O); + mg.generate(m); + return true; +} + +bool +Slice::Visitor::visitExceptionStart(const ExceptionPtr& e) +{ + XMLOutput O; + ExceptionGenerator eg(O); + eg.generate(e); + return true; +} + +bool +Slice::Visitor::visitClassDefStart(const ClassDefPtr& c) +{ + XMLOutput O; + ClassGenerator cg(O); + cg.generate(c); + return true; +} + +bool +Slice::Visitor::visitStructStart(const StructPtr& s) +{ + XMLOutput O; + StructGenerator sg(O); + sg.generate(s); + return true; +} + +void +Slice::Visitor::visitEnum(const EnumPtr& e) +{ + XMLOutput O; + EnumGenerator eg(O); + eg.generate(e); +} |