diff options
author | Hugo Lima <hugo.lima@openbossa.org> | 2009-08-27 18:37:30 -0300 |
---|---|---|
committer | Marcelo Lira <marcelo.lira@openbossa.org> | 2009-08-27 19:04:33 -0300 |
commit | 21ec8e15575cb3f58db759d123b2e471f9bd2e22 (patch) | |
tree | 309cd9cba850ccc49265597ff3b195853564955e | |
parent | 39dd735c9486a5808e26a4f07e19522cc904ddd9 (diff) |
Shiboken ported to the new generator/apiextractor architeture.
Reviewed by Marcelo Lira <marcelo.lira@openbossa.org>
-rw-r--r-- | CMakeLists.txt | 16 | ||||
-rw-r--r-- | cppgenerator.cpp | 4 | ||||
-rw-r--r-- | docgenerator.cpp | 1370 | ||||
-rw-r--r-- | docgenerator.h | 213 | ||||
-rw-r--r-- | main.cpp | 38 | ||||
-rw-r--r-- | shiboken.cpp | 27 | ||||
-rw-r--r-- | shibokengenerator.cpp | 135 | ||||
-rw-r--r-- | shibokengenerator.h | 38 | ||||
-rw-r--r-- | tests/samplebinding/CMakeLists.txt | 4 |
9 files changed, 78 insertions, 1767 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bf6e740a..6641513fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,9 @@ find_package(ApiExtractor REQUIRED) add_definitions(${QT_DEFINITIONS}) +set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) +set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE) + set(shiboken_VERSION 0.1) set(CMAKE_BUILD_TYPE Debug) @@ -14,9 +17,8 @@ set(shiboken_SRC shibokengenerator.cpp headergenerator.cpp cppgenerator.cpp -docgenerator.cpp polymorphicdata.cpp -main.cpp +shiboken.cpp ) include_directories(${CMAKE_CURRENT_SOURCE_DIR} @@ -25,12 +27,13 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${QT_INCLUDE_DIR} ${QT_QTCORE_INCLUDE_DIR}) -add_executable(shiboken ${shiboken_SRC}) +add_library(shiboken_generator SHARED ${shiboken_SRC}) -target_link_libraries(shiboken +target_link_libraries(shiboken_generator ${APIEXTRACTOR_LIBRARY} ${QT_QTCORE_LIBRARY} - ${QT_QTXML_LIBRARY}) + ${QT_QTXML_LIBRARY} + -lgenrunner) # FIXME libgenrunner needs a cmake FindPkg script! # uninstall target configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake" @@ -56,6 +59,5 @@ add_custom_target(dist | bzip2 > ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar.bz2 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - -install(TARGETS shiboken DESTINATION bin) +install(TARGETS shiboken_generator DESTINATION ${LIB_INSTALL_DIR}) diff --git a/cppgenerator.cpp b/cppgenerator.cpp index 964bd54d4..7d8bb6ac4 100644 --- a/cppgenerator.cpp +++ b/cppgenerator.cpp @@ -368,7 +368,7 @@ void CppGenerator::writeNonVirtualModifiedFunctionNative(QTextStream& s, const A s << getFunctionReturnType(func) << ' '; s << func->ownerClass()->name() << '_' << func->originalName() << "_modified("; - uint options = SkipRemovedArguments | SkipDefaultValues; + Options options = Options(SkipRemovedArguments) | SkipDefaultValues; if (!func->isStatic()) options |= WriteSelf; @@ -503,7 +503,7 @@ void CppGenerator::writeMethodWrapper(QTextStream& s, const AbstractMetaFunction } if (rfunc->type()) - s << INDENT << getFunctionReturnType(rfunc) << ' ' << retvalVariableName() << ';' << endl; + s << INDENT << translateTypeForWrapperMethod(rfunc->type(), rfunc->implementingClass()) << ' ' << retvalVariableName() << ';' << endl; if (minArgs != maxArgs || maxArgs > 1) { s << INDENT << "int numArgs = "; diff --git a/docgenerator.cpp b/docgenerator.cpp deleted file mode 100644 index 41b30cd62..000000000 --- a/docgenerator.cpp +++ /dev/null @@ -1,1370 +0,0 @@ -/* - * This file is part of the Shiboken Python Binding Generator project. - * - * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: PySide team <contact@pyside.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include "docgenerator.h" -#include <reporthandler.h> -#include <qtdocparser.h> -#include <algorithm> -#include <QtCore/QStack> -#include <QtCore/QTextStream> -#include <QtCore/QXmlStreamReader> -#include <QtCore/QFile> -#include <QtCore/QDir> - -static Indentor INDENT; - -namespace -{ - -static bool functionSort(const AbstractMetaFunction *func1, const AbstractMetaFunction *func2) -{ - return func1->name() < func2->name(); -} - -QString createRepeatedChar(int i, char c) -{ - QString out; - for (int j = 0; j < i; ++j) - out += c; - - return out; -} - -QString escape(QString& str) -{ - return str - .replace("*", "\\*") - .replace("_", "\\_"); -} - -QString escape(const QStringRef& strref) -{ - QString str = strref.toString(); - return escape(str); -} - -} - -QtXmlToSphinx::QtXmlToSphinx(DocGenerator* generator, const QString& doc, const QString& context) - : m_context(context), m_generator(generator), m_insideBold(false), m_insideItalic(false) -{ - m_handlerMap.insert("heading", &QtXmlToSphinx::handleHeadingTag); - m_handlerMap.insert("brief", &QtXmlToSphinx::handleParaTag); - m_handlerMap.insert("para", &QtXmlToSphinx::handleParaTag); - m_handlerMap.insert("italic", &QtXmlToSphinx::handleItalicTag); - m_handlerMap.insert("bold", &QtXmlToSphinx::handleBoldTag); - m_handlerMap.insert("see-also", &QtXmlToSphinx::handleSeeAlsoTag); - m_handlerMap.insert("snippet", &QtXmlToSphinx::handleSnippetTag); - m_handlerMap.insert("dots", &QtXmlToSphinx::handleDotsTag); - m_handlerMap.insert("codeline", &QtXmlToSphinx::handleDotsTag); - m_handlerMap.insert("table", &QtXmlToSphinx::handleTableTag); - m_handlerMap.insert("header", &QtXmlToSphinx::handleRowTag); - m_handlerMap.insert("row", &QtXmlToSphinx::handleRowTag); - m_handlerMap.insert("item", &QtXmlToSphinx::handleItemTag); - m_handlerMap.insert("argument", &QtXmlToSphinx::handleArgumentTag); - m_handlerMap.insert("teletype", &QtXmlToSphinx::handleArgumentTag); - m_handlerMap.insert("link", &QtXmlToSphinx::handleLinkTag); - m_handlerMap.insert("inlineimage", &QtXmlToSphinx::handleImageTag); - m_handlerMap.insert("image", &QtXmlToSphinx::handleImageTag); - m_handlerMap.insert("list", &QtXmlToSphinx::handleListTag); - m_handlerMap.insert("term", &QtXmlToSphinx::handleTermTag); - m_handlerMap.insert("raw", &QtXmlToSphinx::handleRawTag); - m_handlerMap.insert("underline", &QtXmlToSphinx::handleItalicTag); - m_handlerMap.insert("superscript", &QtXmlToSphinx::handleSuperScriptTag); - m_handlerMap.insert("code", &QtXmlToSphinx::handleCodeTag); - m_handlerMap.insert("legalese", &QtXmlToSphinx::handleCodeTag); - m_handlerMap.insert("section", &QtXmlToSphinx::handleAnchorTag); - m_handlerMap.insert("quotefile", &QtXmlToSphinx::handleQuoteFileTag); - - // ignored tags - m_handlerMap.insert("generatedlist", &QtXmlToSphinx::handleIgnoredTag); - m_handlerMap.insert("tableofcontents", &QtXmlToSphinx::handleIgnoredTag); - m_handlerMap.insert("quotefromfile", &QtXmlToSphinx::handleIgnoredTag); - m_handlerMap.insert("skipto", &QtXmlToSphinx::handleIgnoredTag); - m_handlerMap.insert("target", &QtXmlToSphinx::handleIgnoredTag); - - // useless tags - m_handlerMap.insert("description", &QtXmlToSphinx::handleUselessTag); - m_handlerMap.insert("definition", &QtXmlToSphinx::handleUselessTag); - m_handlerMap.insert("printuntil", &QtXmlToSphinx::handleUselessTag); - m_handlerMap.insert("relation", &QtXmlToSphinx::handleUselessTag); - - m_result = transform(doc); -} - -void QtXmlToSphinx::pushOutputBuffer() -{ - QString* buffer = new QString(); - m_buffers << buffer; - m_output.setString(buffer); -} - -QString QtXmlToSphinx::popOutputBuffer() -{ - Q_ASSERT(!m_buffers.isEmpty()); - QString* str = m_buffers.pop(); - QString strcpy(*str); - delete str; - m_output.setString(m_buffers.isEmpty() ? 0 : m_buffers.top()); - return strcpy; -} - - -QString QtXmlToSphinx::transform(const QString& doc) -{ - Q_ASSERT(m_buffers.isEmpty()); - Indentation indentation(INDENT); - if (doc.trimmed().isEmpty()) - return doc; - - pushOutputBuffer(); - - QXmlStreamReader reader(doc); - - while (!reader.atEnd()) { - QXmlStreamReader::TokenType token = reader.readNext(); - if (reader.hasError()) { - m_output << INDENT << "XML Error: " + reader.errorString() + "\n" + doc; - ReportHandler::warning("XML Error: " + reader.errorString() + "\n" + doc); - break; - } - - if (token == QXmlStreamReader::StartElement) { - QStringRef tagName = reader.name(); - TagHandler handler = m_handlerMap.value(tagName.toString(), &QtXmlToSphinx::handleUnknownTag); - if (!m_handlers.isEmpty() && ( (m_handlers.top() == &QtXmlToSphinx::handleIgnoredTag) || - (m_handlers.top() == &QtXmlToSphinx::handleRawTag)) ) - handler = &QtXmlToSphinx::handleIgnoredTag; - - m_handlers.push(handler); - } - if (!m_handlers.isEmpty()) - (this->*(m_handlers.top()))(reader); - - if (token == QXmlStreamReader::EndElement) { - m_handlers.pop(); - m_lastTagName = reader.name().toString(); - } - } - m_output.flush(); - QString retval = popOutputBuffer(); - Q_ASSERT(m_buffers.isEmpty()); - return retval; -} - -QString QtXmlToSphinx::readFromLocation(QString& location, QString& identifier) -{ - QFile inputFile; - inputFile.setFileName(location); - if (!inputFile.open(QIODevice::ReadOnly)) { - ReportHandler::warning("Couldn't read code snippet file: "+inputFile.fileName()); - return QString(); - } - - QRegExp searchString("//!\\s*\\[" + identifier + "\\]"); - QRegExp codeSnippetCode("//!\\s*\\[[\\w\\d\\s]+\\]"); - QString code; - QString line; - bool identifierIsEmpty = identifier.isEmpty(); - bool getCode = false; - - while (!inputFile.atEnd()) { - line = inputFile.readLine(); - if (identifierIsEmpty) - code += line; - else if (getCode && !line.contains(searchString)) - code += line.replace(codeSnippetCode, ""); - else if (line.contains(searchString)) - if (getCode) - break; - else - getCode = true; - } - - if (code.isEmpty()) - ReportHandler::warning("Code snippet file found ("+location+"), but snippet "+ identifier +" not found."); - - return code; -} - -void QtXmlToSphinx::handleHeadingTag(QXmlStreamReader& reader) -{ - static QString heading; - static char type; - static char types[] = { '-', '^' }; - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - int typeIdx = reader.attributes().value("level").toString().toInt(); - if (typeIdx >= sizeof(types)) - type = types[sizeof(types)-1]; - else - type = types[typeIdx]; - } else if (token == QXmlStreamReader::EndElement) { - m_output << createRepeatedChar(heading.length(), type) << endl << endl; - } else if (token == QXmlStreamReader::Characters) { - heading = escape(reader.text()).trimmed(); - m_output << endl << endl << heading << endl; - } -} - -void QtXmlToSphinx::handleParaTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - pushOutputBuffer(); - } else if (token == QXmlStreamReader::EndElement) { - QString result = popOutputBuffer().simplified(); - if (result.startsWith("**Warning:**")) - result.replace(0, 12, ".. warning:: "); - else if (result.startsWith("**Note:**")) - result.replace(0, 9, ".. note:: "); - - m_output << INDENT << result << endl << endl; - } else if (token == QXmlStreamReader::Characters) { - QString text = escape(reader.text()); - if (!m_output.string()->isEmpty()) { - QChar start = text[0]; - QChar end = m_output.string()->at(m_output.string()->length() - 1); - if ((end == '*' || end == '`') && start != ' ' && !start.isPunct()) - m_output << '\\'; - } - m_output << INDENT << text; - } -} - -void QtXmlToSphinx::handleItalicTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement || token == QXmlStreamReader::EndElement) { - m_insideItalic = !m_insideItalic; - m_output << '*'; - } else if (token == QXmlStreamReader::Characters) { - m_output << escape(reader.text()).trimmed(); - } -} - -void QtXmlToSphinx::handleBoldTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement || token == QXmlStreamReader::EndElement) { - m_insideBold = !m_insideBold; - m_output << "**"; - } else if (token == QXmlStreamReader::Characters) { - m_output << escape(reader.text()).trimmed(); - } -} - -void QtXmlToSphinx::handleArgumentTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement || token == QXmlStreamReader::EndElement) - m_output << "``"; - else if (token == QXmlStreamReader::Characters) - m_output << reader.text().toString().trimmed(); -} - -void QtXmlToSphinx::handleSeeAlsoTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) - m_output << INDENT << ".. seealso:: "; - else if (token == QXmlStreamReader::EndElement) - m_output << endl; -} - -void QtXmlToSphinx::handleSnippetTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - bool consecutiveSnippet = m_lastTagName == "snippet" || m_lastTagName == "dots" || m_lastTagName == "codeline"; - if (consecutiveSnippet) { - m_output.flush(); - m_output.string()->chop(2); - } - QString location = reader.attributes().value("location").toString(); - QString identifier = reader.attributes().value("identifier").toString(); - location.prepend(m_generator->codeSnippetDir() + '/'); - QString code = readFromLocation(location, identifier); - if (!consecutiveSnippet) - m_output << INDENT << "::\n\n"; - - Indentation indentation(INDENT); - if (code.isEmpty()) { - m_output << INDENT << "<Code snippet \"" << location << ':' << identifier << "\" not found>" << endl; - } else { - foreach (QString line, code.split("\n")) { - if (!QString(line).trimmed().isEmpty()) - m_output << INDENT << line; - - m_output << endl; - } - } - m_output << endl; - } -} -void QtXmlToSphinx::handleDotsTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - bool consecutiveSnippet = m_lastTagName == "snippet" || m_lastTagName == "dots" || m_lastTagName == "codeline"; - if (consecutiveSnippet) { - m_output.flush(); - m_output.string()->chop(2); - } - Indentation indentation(INDENT); - pushOutputBuffer(); - m_output << INDENT; - int indent = reader.attributes().value("indent").toString().toInt(); - for (int i = 0; i < indent; ++i) - m_output << ' '; - } else if (token == QXmlStreamReader::Characters) { - m_output << reader.text().toString(); - } else if (token == QXmlStreamReader::EndElement) { - m_output << popOutputBuffer() << "\n\n\n"; - } -} - -void QtXmlToSphinx::handleTableTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - m_currentTable.clear(); - m_tableHasHeader = false; - } else if (token == QXmlStreamReader::EndElement) { - // write the table on m_output - m_currentTable.enableHeader(m_tableHasHeader); - m_currentTable.normalize(); - m_output << m_currentTable; - m_currentTable.clear(); - } -} - -void QtXmlToSphinx::handleTermTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - pushOutputBuffer(); - } else if (token == QXmlStreamReader::Characters) { - m_output << reader.text().toString().replace("::", "."); - } else if (token == QXmlStreamReader::EndElement) { - TableCell cell; - cell.data = popOutputBuffer().trimmed(); - m_currentTable << (TableRow() << cell); - } -} - - -void QtXmlToSphinx::handleItemTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - if (m_currentTable.isEmpty()) - m_currentTable << TableRow(); - TableRow& row = m_currentTable.last(); - TableCell cell; - cell.colSpan = reader.attributes().value("colspan").toString().toShort(); - cell.rowSpan = reader.attributes().value("rowspan").toString().toShort(); - row << cell; - pushOutputBuffer(); - } else if (token == QXmlStreamReader::EndElement) { - QString data = popOutputBuffer().trimmed(); - if (!m_currentTable.isEmpty()) { - TableRow& row = m_currentTable.last(); - if (!row.isEmpty()) - row.last().data = data; - } - } -} - -void QtXmlToSphinx::handleRowTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - m_tableHasHeader = reader.name() == "header"; - m_currentTable << TableRow(); - } -} - -void QtXmlToSphinx::handleListTag(QXmlStreamReader& reader) -{ - // BUG We do not support a list inside a table cell - static QString listType; - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - listType = reader.attributes().value("type").toString(); - if (listType == "enum") { - m_currentTable << (TableRow() << "Constant" << "Description"); - m_tableHasHeader = true; - } - INDENT.indent--; - } else if (token == QXmlStreamReader::EndElement) { - INDENT.indent++; - if (!m_currentTable.isEmpty()) { - if (listType == "bullet") { - m_output << endl; - foreach (TableCell cell, m_currentTable.first()) { - QStringList itemLines = cell.data.split('\n'); - m_output << INDENT << "* " << itemLines.first() << endl; - for (int i = 1, max = itemLines.count(); i < max; ++i) - m_output << INDENT << " " << itemLines[i] << endl; - } - m_output << endl; - } else if (listType == "enum") { - m_currentTable.enableHeader(m_tableHasHeader); - m_currentTable.normalize(); - m_output << m_currentTable; - } - } - m_currentTable.clear(); - } -} - -void QtXmlToSphinx::handleLinkTag(QXmlStreamReader& reader) -{ - static QString l_linktag; - static QString l_linkref; - static QString l_linktext; - static QString l_linktagending; - static QString l_type; - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - l_linktagending = "` "; - if (m_insideBold) { - l_linktag.prepend("**"); - l_linktagending.append("**"); - } else if (m_insideItalic) { - l_linktag.prepend('*'); - l_linktagending.append('*'); - } - l_type = reader.attributes().value("type").toString(); - - // TODO: create a flag PROPERTY-AS-FUNCTION to ask if the properties - // are recognized as such or not in the binding - if (l_type == "property") - l_type = "function"; - - if (l_type == "typedef") - l_type = "class"; - - QString linkSource; - if (l_type == "function" || l_type == "class") { - linkSource = "raw"; - } else if (l_type == "enum") { - linkSource = "enum"; - } else if (l_type == "page") { - linkSource = "page"; - } else { - linkSource = "href"; - } - - l_linkref = reader.attributes().value(linkSource).toString(); - l_linkref.replace("::", "."); - l_linkref.remove("()"); - - if (l_type == "function" && !m_context.isEmpty()) { - l_linktag = " :meth:`"; - QStringList rawlinklist = l_linkref.split("."); - if (rawlinklist.size() == 1 || rawlinklist[0] == m_context) - l_linkref.prepend("~" + m_context + '.'); - } else if (l_type == "function" && m_context.isEmpty()) { - l_linktag = " :func:`"; - } else if (l_type == "class") { - l_linktag = " :class:`"; - } else if (l_type == "enum") { - l_linktag = " :attr:`"; - } else if (l_type == "page" && l_linkref == m_generator->moduleName()) { - l_linktag = " :mod:`"; - } else { - l_linktag = " :ref:`"; - } - - } else if (token == QXmlStreamReader::Characters) { - QString linktext = reader.text().toString(); - linktext.replace("::", "."); - QString item = l_linkref.split(".").last(); - if (l_linkref == linktext - || (l_linkref + "()") == linktext - || item == linktext - || (item + "()") == linktext) - l_linktext.clear(); - else - l_linktext = linktext + QLatin1String("<"); - } else if (token == QXmlStreamReader::EndElement) { - if (!l_linktext.isEmpty()) - l_linktagending.prepend('>'); - m_output << l_linktag << l_linktext << escape(l_linkref) << l_linktagending; - } -} - -void QtXmlToSphinx::handleImageTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - QString href = reader.attributes().value("href").toString(); - QDir dir(m_generator->outputDirectory() + '/' + m_generator->packageName().replace(".", "/")); - QString imgPath = dir.relativeFilePath(m_generator->libSourceDir() + "/doc/src/") + '/' + href; - - if (reader.name() == "image") - m_output << INDENT << ".. image:: " << imgPath << endl << endl; - else - m_output << ".. image:: " << imgPath << ' '; - } -} - -void QtXmlToSphinx::handleRawTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - QString format = reader.attributes().value("format").toString(); - m_output << INDENT << ".. raw:: " << format.toLower() << endl << endl; - } else if (token == QXmlStreamReader::Characters) { - QStringList lst(reader.text().toString().split("\n")); - foreach(QString row, lst) - m_output << INDENT << INDENT << row << endl; - } else if (token == QXmlStreamReader::EndElement) { - m_output << endl << endl; - } -} - -void QtXmlToSphinx::handleCodeTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - QString format = reader.attributes().value("format").toString(); - m_output << INDENT << "::" << endl << endl; - INDENT.indent++; - } else if (token == QXmlStreamReader::Characters) { - QStringList lst(reader.text().toString().split("\n")); - foreach(QString row, lst) - m_output << INDENT << INDENT << row << endl; - } else if (token == QXmlStreamReader::EndElement) { - m_output << endl << endl; - INDENT.indent--; - } -} - -void QtXmlToSphinx::handleUnknownTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) - ReportHandler::warning("Unknow QtDoc tag: \"" + reader.name().toString() + "\"."); -} - -void QtXmlToSphinx::handleSuperScriptTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - m_output << " :sup:`"; - pushOutputBuffer(); - } else if (token == QXmlStreamReader::Characters) { - m_output << reader.text().toString(); - } else if (token == QXmlStreamReader::EndElement) { - m_output << popOutputBuffer(); - m_output << '`'; - } -} - -void QtXmlToSphinx::handleIgnoredTag(QXmlStreamReader&) -{ -} - -void QtXmlToSphinx::handleUselessTag(QXmlStreamReader&) -{ - // Tag "description" just marks the init of "Detailed description" title. - // Tag "definition" just marks enums. We have a different way to process them. -} - -void QtXmlToSphinx::handleAnchorTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - QString anchor; - if (reader.attributes().hasAttribute("id")) - anchor = reader.attributes().value("id").toString(); - else if (reader.attributes().hasAttribute("name")) - anchor = reader.attributes().value("name").toString(); - if (!anchor.isEmpty() && m_opened_anchor != anchor) { - m_opened_anchor = anchor; - m_output << INDENT << ".. _" << m_context << "_" << anchor.toLower() << ":" << endl << endl; - } - } else if (token == QXmlStreamReader::EndElement) { - m_opened_anchor = ""; - } -} - -void QtXmlToSphinx::handleQuoteFileTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::Characters) { - QString location = reader.text().toString(); - QString identifier = ""; - location.prepend(m_generator->libSourceDir() + '/'); - QString code = readFromLocation(location, identifier); - - m_output << INDENT << "::\n\n"; - Indentation indentation(INDENT); - if (code.isEmpty()) { - m_output << INDENT << "<Code snippet \"" << location << "\" not found>" << endl; - } else { - foreach (QString line, code.split("\n")) { - if (!QString(line).trimmed().isEmpty()) - m_output << INDENT << line; - - m_output << endl; - } - } - m_output << endl; - } -} - -void QtXmlToSphinx::Table::normalize() -{ - if (m_normalized || isEmpty()) - return; - - int row; - int col; - QtXmlToSphinx::Table& self = *this; - - // add col spans - for (row = 0; row < count(); ++row) { - for (col = 0; col < at(row).count(); ++col) { - QtXmlToSphinx::TableCell& cell = self[row][col]; - if (cell.colSpan > 0) { - QtXmlToSphinx::TableCell newCell; - newCell.colSpan = -1; - for (int i = 0, max = cell.colSpan-1; i < max; ++i) { - self[row].insert(col+1, newCell); - } - cell.colSpan = 0; - col++; - } - } - } - - // row spans - const int numCols = first().count(); - for (col = 0; col < numCols; ++col) { - for (row = 0; row < count(); ++row) { - if (col < self[row].count()) { - QtXmlToSphinx::TableCell& cell = self[row][col]; - if (cell.rowSpan > 0) { - QtXmlToSphinx::TableCell newCell; - newCell.rowSpan = -1; - int max = std::min(cell.rowSpan - 1, count()); - cell.rowSpan = 0; - for (int i = 0; i < max; ++i) { - self[row+i+1].insert(col, newCell); - } - row++; - } - } - } - } - m_normalized = true; -} - -QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table) -{ - if (table.isEmpty()) - return s; - - if (!table.isNormalized()) { - ReportHandler::warning("Attempt to print an unnormalized table!"); - return s; - } - - // calc width and height of each column and row - QVector<int> colWidths(table.first().count()); - QVector<int> rowHeights(table.count()); - for (int i = 0, maxI = table.count(); i < maxI; ++i) { - const QtXmlToSphinx::TableRow& row = table[i]; - for (int j = 0, maxJ = row.count(); j < maxJ; ++j) { - QStringList rowLines = row[j].data.split('\n'); // cache this would be a good idea - foreach (QString str, rowLines) - colWidths[j] = std::max(colWidths[j], str.count()); - rowHeights[i] = std::max(rowHeights[i], row[j].data.count('\n') + 1); - } - } - - if (!*std::max_element(colWidths.begin(), colWidths.end())) - return s; // empty table (table with empty cells) - - // create a horizontal line to be used later. - QString horizontalLine("+"); - for (int i = 0, max = colWidths.count(); i < max; ++i) { - horizontalLine += createRepeatedChar(colWidths[i], '-'); - horizontalLine += '+'; - } - - // write table rows - for (int i = 0, maxI = table.count(); i < maxI; ++i) { // for each row - const QtXmlToSphinx::TableRow& row = table[i]; - - // print line - s << INDENT << '+'; - char c = (!i && table.hasHeader()) ? '=' : '-'; - for (int col = 0, max = colWidths.count(); col < max; ++col) { - char c; - if (row[col].rowSpan == -1) - c = ' '; - else if (i == 1 && table.hasHeader()) - c = '='; - else - c = '-'; - s << createRepeatedChar(colWidths[col], c) << '+'; - } - s << endl; - - - // Print the table cells - for (int rowLine = 0; rowLine < rowHeights[i]; ++rowLine) { // for each line in a row - for (int j = 0, maxJ = row.count(); j < maxJ; ++j) { // for each column - const QtXmlToSphinx::TableCell& cell = row[j]; - QStringList rowLines = cell.data.split('\n'); // FIXME: Cache this!!! - if (!j) // First column, so we need print the identation - s << INDENT; - - if (!j || !cell.colSpan) - s << '|'; - else - s << ' '; - s << qSetFieldWidth(colWidths[j]) << left; - s << (rowLine < rowLines.count() ? rowLines[rowLine] : ""); - s << qSetFieldWidth(0); - } - s << '|' << endl; - } - } - s << INDENT << horizontalLine << endl; - s << endl; - return s; -} - -static QString getClassName(const AbstractMetaClass *cppClass) { - return cppClass->name().replace("::", "."); -} - -static QString getFuncName(const AbstractMetaFunction *cppFunc) { - static bool hashInitialized = false; - static QHash<QString, QString> operatorsHash; - if (!hashInitialized) { - operatorsHash.insert("operator+", "__add__"); - operatorsHash.insert("operator+=", "__iadd__"); - operatorsHash.insert("operator-", "__sub__"); - operatorsHash.insert("operator-=", "__isub__"); - operatorsHash.insert("operator*", "__mul__"); - operatorsHash.insert("operator*=", "__imul__"); - operatorsHash.insert("operator/", "__div__"); - operatorsHash.insert("operator/=", "__idiv__"); - operatorsHash.insert("operator%", "__mod__"); - operatorsHash.insert("operator%=", "__imod__"); - operatorsHash.insert("operator<<", "__lshift__"); - operatorsHash.insert("operator<<=", "__ilshift__"); - operatorsHash.insert("operator>>", "__rshift__"); - operatorsHash.insert("operator>>=", "__irshift__"); - operatorsHash.insert("operator&", "__and__"); - operatorsHash.insert("operator&=", "__iand__"); - operatorsHash.insert("operator|", "__or__"); - operatorsHash.insert("operator|=", "__ior__"); - operatorsHash.insert("operator^", "__xor__"); - operatorsHash.insert("operator^=", "__ixor__"); - operatorsHash.insert("operator==", "__eq__"); - operatorsHash.insert("operator!=", "__ne__"); - operatorsHash.insert("operator<", "__lt__"); - operatorsHash.insert("operator<=", "__le__"); - operatorsHash.insert("operator>", "__gt__"); - operatorsHash.insert("operator>=", "__ge__"); - hashInitialized = true; - } - - QHash<QString, QString>::const_iterator it = operatorsHash.find(cppFunc->name()); - QString result = it != operatorsHash.end() ? it.value() : cppFunc->name(); - return result.replace("::", "."); -} - -QString DocGenerator::fileNameForClass(const AbstractMetaClass *cppClass) const -{ - return QString("%1.rst").arg(getClassName(cppClass)); -} - -void DocGenerator::writeFormatedText(QTextStream& s, const Documentation& doc, const AbstractMetaClass* metaClass) -{ - QString metaClassName; - - if (metaClass) - metaClassName = getClassName(metaClass); - - if (doc.format() == Documentation::Native) { - QtXmlToSphinx x(this, doc.value(), metaClassName); - s << x; - } else { - s << doc.value(); - } - - s << endl; -} - -void DocGenerator::writeFunctionBrief(QTextStream &s, - const AbstractMetaClass *cppClass, - const AbstractMetaFunction *cppFunction) -{ - s << INDENT << "def :meth:`" - << cppFunction->name() << "<"; - if (cppClass && cppClass->name() != cppFunction->name()) - s << getClassName(cppClass) << '.'; - - s << cppFunction->name() << ">`" - << " (" << parseArgDocStyle(cppClass, cppFunction) << "):"; -} - -void DocGenerator::generateClass(QTextStream &s, const AbstractMetaClass *cppClass) -{ - QString doc; - QTextStream doc_s(&doc); - - ReportHandler::debugSparse("Generating Documentation for " + cppClass->fullName()); - s << ".. module:: " << packageName() << endl; - QString className = getClassName(cppClass); - s << ".. _" << className << ":" << endl << endl; - - s << className << endl; - s << createRepeatedChar(className.count(), '*') << endl << endl; - - s << ".. inheritance-diagram:: " << className << endl - << " :parts: 2" << endl << endl; // TODO: This would be a parameter in the future... - - //Function list - AbstractMetaFunctionList functionList = filterFunctions(cppClass); - qSort(functionList.begin(), functionList.end(), functionSort); - -#if 0 - if (functionList.size() > 0) - { - QtXmlToSphinx::Table functionTable; - QtXmlToSphinx::TableRow row; - - s << "Functions\n" - "---------\n\n"; - - - foreach (AbstractMetaFunction *func, functionList) { - if ((func->isConstructor() || func->isModifiedRemoved()) || - (func->declaringClass() != cppClass)) - continue; - - QString rowString; - QTextStream rowStream(&rowString); - - writeFunctionBrief(rowStream, cppClass, func); - row << rowString; - functionTable << row; - row.clear(); - } - functionTable.normalize(); - s << functionTable; - } - -#endif - - doc_s << "Detailed Description\n" - "--------------------\n\n"; - - writeInjectDocumentation(doc_s, DocModification::Prepend, cppClass, 0); - writeFormatedText(doc_s, cppClass->documentation(), cppClass); - - - if (!cppClass->isNamespace()) { - - writeConstructors(doc_s, cppClass); - writeEnums(doc_s, cppClass); - writeFields(doc_s, cppClass); - - foreach (AbstractMetaFunction *func, functionList) { - if ((func->isConstructor() || func->isModifiedRemoved()) || - (func->declaringClass() != cppClass)) - continue; - - if (func->isStatic()) - doc_s << ".. staticmethod:: "; - else - doc_s << ".. method:: "; - - writeFunction(doc_s, true, cppClass, func); - } - } - - writeInjectDocumentation(doc_s, DocModification::Append, cppClass, 0); - - writeFunctionList(s, doc, cppClass); - - s << doc; -} - -QString DocGenerator::parseFunctionDeclaration(const QString &doc, const AbstractMetaClass *cppClass) -{ - //.. method:: QObject.childEvent(arg__1) - //def :meth:`removeEventFilter<QObject.removeEventFilter>` (arg__1): - - QString data = doc; - QString markup; - - if (data.startsWith(".. method::")) - markup = ".. method::"; - else if (data.startsWith(".. staticmethod::")) - markup = ".. staticmethod::"; - else - return QString(); - - data = data.mid(markup.size()); //remove .. method:: - data = data.mid(data.indexOf(".") + 1); //remove class name - - QString methName = data.mid(0, data.indexOf("(")); - QString methArgs = data.mid(data.indexOf("(")); - - data = QString("def :meth:`%1<%2.%3>` %4") - .arg(methName) - .arg(cppClass->name()) - .arg(methName) - .arg(methArgs); - - return data; -} - - -void DocGenerator::writeFunctionList(QTextStream &s, const QString &content, const AbstractMetaClass *cppClass) -{ - QStringList functionList; - QStringList staticFunctionList; - - QStringList lst = content.split("\n"); - foreach(QString row, lst) { - QString data = row.trimmed(); - if (data.startsWith(".. method::")) { - functionList << parseFunctionDeclaration(data, cppClass); - } - else if (data.startsWith(".. staticmethod::")) { - staticFunctionList << parseFunctionDeclaration(data, cppClass); - } - } - - if ((functionList.size() > 0) || (staticFunctionList.size() > 0)) - { - QtXmlToSphinx::Table functionTable; - QtXmlToSphinx::TableRow row; - - s << "Synopsis" << endl - << "--------" << endl << endl; - - if (functionList.size() > 0) { - s << "Functions" << endl - << "^^^^^^^^^" << endl << endl; - - qSort(functionList); - foreach (QString func, functionList) { - row << func; - functionTable << row; - row.clear(); - } - - functionTable.normalize(); - s << functionTable << endl; - functionTable.clear(); - } - - if (staticFunctionList.size() > 0) { - s << "Static functions" << endl - << "^^^^^^^^^^^^^^^^" << endl; - - qSort(staticFunctionList); - foreach (QString func, staticFunctionList) { - row << func; - functionTable << row; - row.clear(); - } - - functionTable.normalize(); - s << functionTable << endl; - } - } -} - -void DocGenerator::writeEnums(QTextStream& s, const AbstractMetaClass* cppClass) -{ - static const QString section_title(".. attribute:: "); - - foreach (AbstractMetaEnum *en, cppClass->enums()) { - s << section_title << getClassName(cppClass) << "." << en->name() << endl << endl; - writeFormatedText(s, en->documentation(), cppClass); - } -} - -void DocGenerator::writeFields(QTextStream &s, const AbstractMetaClass *cppClass) -{ - static const QString section_title(".. attribute:: "); - - foreach (AbstractMetaField *field, cppClass->fields()) { - s << section_title << getClassName(cppClass) << "." << field->name() << endl << endl; - //TODO: request for member ‘documentation’ is ambiguous - writeFormatedText(s, field->AbstractMetaAttributes::documentation(), cppClass); - } -} - -void DocGenerator::writeConstructors(QTextStream &s, const AbstractMetaClass *cppClass) -{ - static const QString sectionTitle = ".. class:: "; - static const QString sectionTitleSpace = QString(sectionTitle.size(), ' '); - - AbstractMetaFunctionList lst = cppClass->queryFunctions(AbstractMetaClass::Constructors | AbstractMetaClass::Visible); - - bool first = true; - QHash<QString, AbstractMetaArgument *> arg_map; - - foreach(AbstractMetaFunction *func, lst) { - if (func->isModifiedRemoved()) - continue; - - if (first) { - first = false; - s << sectionTitle; - } else { - s << sectionTitleSpace; - } - writeFunction(s, false, cppClass, func); - foreach(AbstractMetaArgument *arg, func->arguments()) - { - if (!arg_map.contains(arg->argumentName())) { - arg_map.insert(arg->argumentName(), arg); - } - } - } - - s << endl; - - foreach (AbstractMetaArgument *arg, arg_map.values()) { - Indentation indentation(INDENT); - writeParamerteType(s, cppClass, arg); - } - - s << endl; - - foreach (AbstractMetaFunction *func, lst) { - writeFormatedText(s, func->documentation(), cppClass); - } -} - -QString DocGenerator::parseArgDocStyle(const AbstractMetaClass *cppClass, const AbstractMetaFunction *func) -{ - QString ret; - bool optional = false; - - foreach (AbstractMetaArgument *arg, func->arguments()) { - - if (func->argumentRemoved(arg->argumentIndex() + 1)) - continue; - - if (arg->argumentIndex() > 0) - ret += ","; - - if (!arg->defaultValueExpression().isEmpty() && (!optional)) { - ret += "["; - optional = true; - } - - ret += arg->argumentName(); - - if (optional) - ret += "=" + arg->defaultValueExpression(); - } - - if (optional) - ret += "]"; - - return ret; -} - -void DocGenerator::writeDocSnips(QTextStream &s, - const CodeSnipList &codeSnips, - CodeSnip::Position position, - TypeSystem::Language language) -{ - Indentation indentation(INDENT); - QStringList invalidStrings; - const static QString startMarkup("[sphinx-begin]"); - const static QString endMarkup("[sphinx-end]"); - - invalidStrings << "*" << "//" << "/*" << "*/"; - - foreach (CodeSnip snip, codeSnips) { - if ((snip.position != position) || - !(snip.language & language)) - continue; - - QString code = snip.code(); - while (code.contains(startMarkup) && code.contains(endMarkup)) { - int startBlock = code.indexOf(startMarkup) + startMarkup.size(); - int endBlock = code.indexOf(endMarkup); - - if ((startBlock == -1) || (endBlock == -1)) - break; - - QString codeBlock = code.mid(startBlock, endBlock - startBlock); - QStringList rows = codeBlock.split("\n"); - int currenRow = 0; - int offset = 0; - - foreach(QString row, rows) { - foreach(QString invalidString, invalidStrings) { - row = row.remove(invalidString); - } - - if (row.trimmed().size() == 0) { - if (currenRow == 0) - continue; - else - s << endl; - } - - if (currenRow == 0) { - //find offset - for (int i=0, i_max = row.size(); i < i_max; i++) { - if (row[i] == ' ') - offset++; - else if (row[i] == '\n') - offset = 0; - else - break; - } - } - row = row.mid(offset); - s << row << endl; - currenRow++; - } - - code = code.mid(endBlock+endMarkup.size()); - } - } -} - -void DocGenerator::writeInjectDocumentation(QTextStream &s, - DocModification::Mode mode, - const AbstractMetaClass *cppClass, - const AbstractMetaFunction *func) -{ - Indentation indentation(INDENT); - - foreach (DocModification mod, cppClass->typeEntry()->docModifications()) { - if (mod.mode() == mode) { - bool modOk = func ? mod.signature() == func->minimalSignature() : mod.signature().isEmpty(); - - if (modOk) { - Documentation doc; - Documentation::Format fmt; - - if (mod.format == TypeSystem::NativeCode) - fmt = Documentation::Native; - else if (mod.format == TypeSystem::TargetLangCode) - fmt = Documentation::Target; - else - continue; - - doc.setValue(mod.code() , fmt); - s << INDENT; - writeFormatedText(s, doc, cppClass); - } - } - } - - s << endl; - - if (func) { - writeDocSnips(s, getCodeSnips(func), - (mode == DocModification::Prepend ? CodeSnip::Beginning : CodeSnip::End), - TypeSystem::TargetLangCode); - } else { - writeDocSnips(s, cppClass->typeEntry()->codeSnips(), - (mode == DocModification::Prepend ? CodeSnip::Beginning : CodeSnip::End), - TypeSystem::TargetLangCode); - } -} - -void DocGenerator::writeFunctionSignature(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func) -{ - if (!func->isConstructor()) - s << getClassName(cppClass) << '.'; - s << getFuncName(func) << "(" << parseArgDocStyle(cppClass, func) << ")"; -} - -QString DocGenerator::translateToPythonType(const AbstractMetaType *type, const AbstractMetaClass *cppClass) -{ - QString originalType = translateType(type, cppClass, Generator::ExcludeConst | Generator::ExcludeReference); - QString strType = originalType; - - //remove "*" - strType.remove("*"); - TypeEntry *te = TypeDatabase::instance()->findType(originalType.trimmed()); - if (te) { - return te->targetLangName(); - } else { - //remove <, > - strType.remove(">"); - strType.remove("<"); - - //replace :: - strType.replace("::", "."); - - //Translate ContainerType - if (strType.contains("QList") || strType.contains("QVector")) { - strType.replace("QList", "List of "); - strType.replace("QVector", "List of "); - } else if (strType.contains("QHash") || strType.contains("QMap")) { - strType.remove("QHash"); - strType.remove("QMap"); - QStringList types = strType.split(","); - strType = QString("Dictionary with keys of type %1 and values of type %2.") - .arg(types[0]).arg(types[1]); - } - return strType; - } -} - -void DocGenerator::writeParamerteType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaArgument *arg) -{ - s << INDENT << ":param " << arg->argumentName() << ": " - << translateToPythonType(arg->type(), cppClass) << endl; -} - -void DocGenerator::writeFunctionParametersType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction* func) -{ - Indentation indentation(INDENT); - - s << endl; - foreach (AbstractMetaArgument *arg, func->arguments()) { - - if (func->argumentRemoved(arg->argumentIndex() + 1)) - continue; - - writeParamerteType(s, cppClass, arg); - } - - if (!func->isConstructor() && func->type()) { - s << INDENT << ":rtype: " << translateToPythonType(func->type(), cppClass) << endl; - } - s << endl; -} - -void DocGenerator::writeFunction(QTextStream &s, bool writeDoc, const AbstractMetaClass *cppClass, const AbstractMetaFunction* func) -{ - writeFunctionSignature(s, cppClass, func); - s << endl; - - if (writeDoc) { - s << endl; - writeFunctionParametersType(s, cppClass, func); - s << endl; - writeInjectDocumentation(s, DocModification::Prepend, cppClass, func); - writeFormatedText(s, func->documentation(), cppClass); - writeInjectDocumentation(s, DocModification::Append, cppClass, func); - } -} - -void DocGenerator::finishGeneration() -{ - if (classes().isEmpty()) - return; - - QFile input(outputDirectory() + '/' + subDirectoryForPackage(packageName()) + "/index.rst"); - input.open(QIODevice::WriteOnly); - QTextStream s(&input); - - s << ".. module:: " << packageName() << endl << endl; - - QString title = packageName() + " contents"; - s << title << endl; - s << createRepeatedChar(title.length(), '*') << endl << endl; - s << ".. toctree::" << endl; - - /* Avoid showing "Detailed Description for *every* class in toc tree */ - Indentation indentation(INDENT); - s << INDENT << ":maxdepth: 1" << endl << endl; - - QStringList classList; - foreach (AbstractMetaClass *cls, classes()) { - if (!shouldGenerate(cls)) - continue; - classList << getClassName(cls); - } - classList.sort(); - - foreach (QString clazz, classList) - s << INDENT << clazz << endl; - - s << endl << endl; - - s << "Detailed Description" << endl; - s << "--------------------" << endl << endl; - - if (m_moduleDoc.format() == Documentation::Native) { - QtXmlToSphinx x(this, m_moduleDoc.value(), moduleName()); - s << x; - } else { - s << m_moduleDoc.value(); - } -} - -bool DocGenerator::prepareGeneration(const QMap<QString, QString>& args) -{ - ShibokenGenerator::prepareGeneration(args); - m_libSourceDir = args.value("library-source-dir"); - setOutputDirectory(args.value("documentation-out-dir")); - m_docDataDir = args.value("documentation-data-dir"); - m_codeSnippetDir = args.value("documentation-code-snippets-dir", m_libSourceDir); - - if (m_libSourceDir.isEmpty() || m_docDataDir.isEmpty()) { - ReportHandler::warning("Documentation data dir and/or Qt source dir not informed, " - "documentation will not be extracted from Qt sources."); - return false; - } else { - QtDocParser docParser; - docParser.setPackageName(packageName()); - docParser.setDocumentationDataDirectory(m_docDataDir); - docParser.setLibrarySourceDirectory(m_libSourceDir); - foreach(AbstractMetaClass* cppClass, classes()) { - docParser.fillDocumentation(cppClass); - } - m_moduleDoc = docParser.retrieveModuleDocumentation(); - return true; - } -} - - -QMap<QString, QString> DocGenerator::options() const -{ - QMap<QString, QString> options; - options.insert("library-source-dir", "Directory where library source code is located"); - options.insert("documentation-out-dir", "The directory where the generated documentation files will be written"); - options.insert("documentation-data-dir", "Directory with XML files generated by documentation tool (qdoc3 or Doxygen)"); - options.insert("documentation-code-snippets-dir", "Directory used to search code snippets used by the documentation"); - return options; -} - diff --git a/docgenerator.h b/docgenerator.h deleted file mode 100644 index 6298f41cb..000000000 --- a/docgenerator.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * This file is part of the Shiboken Python Binding Generator project. - * - * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: PySide team <contact@pyside.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ -#ifndef DOCGENERATOR_H -#define DOCGENERATOR_H - -#include "shibokengenerator.h" -#include <QtCore/QStack> - -class QXmlStreamReader; -class DocGenerator; - -class QtXmlToSphinx -{ -public: - struct TableCell - { - short rowSpan; - short colSpan; - QString data; - - TableCell(const QString& text = QString()) : rowSpan(0), colSpan(0), data(text) {} - TableCell(const char* text) : rowSpan(0), colSpan(0), data(text) {} - }; - - typedef QList<TableCell> TableRow; - class Table : public QList<TableRow> - { - public: - Table() : m_hasHeader(false), m_normalized(false) - { - } - - void enableHeader(bool enable) - { - m_hasHeader = enable; - } - - bool hasHeader() const - { - return m_hasHeader; - } - - void normalize(); - - bool isNormalized() const - { - return m_normalized; - } - - void clear() - { - m_normalized = false; - QList<TableRow>::clear(); - } - - private: - bool m_hasHeader; - bool m_normalized; - }; - - QtXmlToSphinx(DocGenerator* generator, const QString& doc, const QString& context = QString()); - - QString result() const - { - return m_result; - } - -private: - QString transform(const QString& doc); - - void handleHeadingTag(QXmlStreamReader& reader); - void handleParaTag(QXmlStreamReader& reader); - void handleItalicTag(QXmlStreamReader& reader); - void handleBoldTag(QXmlStreamReader& reader); - void handleArgumentTag(QXmlStreamReader& reader); - void handleSeeAlsoTag(QXmlStreamReader& reader); - void handleSnippetTag(QXmlStreamReader& reader); - void handleDotsTag(QXmlStreamReader& reader); - void handleLinkTag(QXmlStreamReader& reader); - void handleImageTag(QXmlStreamReader& reader); - void handleListTag(QXmlStreamReader& reader); - void handleTermTag(QXmlStreamReader& reader); - void handleSuperScriptTag(QXmlStreamReader& reader); - void handleQuoteFileTag(QXmlStreamReader& reader); - - // table tagsvoid QtXmlToSphinx::handleValueTag(QXmlStreamReader& reader) - - void handleTableTag(QXmlStreamReader& reader); - void handleRowTag(QXmlStreamReader& reader); - void handleItemTag(QXmlStreamReader& reader); - void handleRawTag(QXmlStreamReader& reader); - void handleCodeTag(QXmlStreamReader& reader); - - void handleIgnoredTag(QXmlStreamReader& reader); - void handleUnknownTag(QXmlStreamReader& reader); - void handleUselessTag(QXmlStreamReader& reader); - void handleAnchorTag(QXmlStreamReader& reader); - - typedef void (QtXmlToSphinx::*TagHandler)(QXmlStreamReader&); - QHash<QString, TagHandler> m_handlerMap; - QStack<TagHandler> m_handlers; - QTextStream m_output; - QString m_result; - - QStack<QString*> m_buffers; - - - Table m_currentTable; - bool m_tableHasHeader; - QString m_context; - DocGenerator* m_generator; - bool m_insideBold; - bool m_insideItalic; - QString m_lastTagName; - QString m_opened_anchor; - - QString readFromLocation(QString& location, QString& identifier); - void pushOutputBuffer(); - QString popOutputBuffer(); - void writeTable(Table& table); -}; - -inline QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx& xmlToSphinx) -{ - return s << xmlToSphinx.result(); -} - -QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table); - -/** -* The DocGenerator generates documentation from library being binded. -*/ -class DocGenerator : public ShibokenGenerator -{ -public: - virtual GeneratorType type() const - { - return DocumentationType; - } - - QString libSourceDir() const - { - return m_libSourceDir; - } - - virtual bool prepareGeneration(const QMap<QString, QString>& args); - - const char* name() const - { - return "DocGenerator"; - } - - QMap<QString, QString> options() const; - - QString codeSnippetDir() const - { - return m_codeSnippetDir; - } - -protected: - QString fileNameForClass(const AbstractMetaClass* cppClass) const; - void generateClass(QTextStream& s, const AbstractMetaClass* cppClass); - void finishGeneration(); -private: - void writeEnums(QTextStream& s, const AbstractMetaClass* cppClass); - - void writeFields(QTextStream &s, const AbstractMetaClass *cppClass); - void writeArguments(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction *func); - void writeFunctionBrief(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction *cppFunction); - void writeFunctionSignature(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func); - void writeFunction(QTextStream& s, bool writeDoc, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func); - void writeFunctionParametersType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction* func); - void writeFunctionList(QTextStream &se, const QString &content, const AbstractMetaClass *cppClass); - void writeParamerteType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaArgument *arg); - - void writeConstructors(QTextStream &s, const AbstractMetaClass *cppClass); - void writeFormatedText(QTextStream& s, const Documentation& doc, const AbstractMetaClass* metaclass = 0); - void writeInjectDocumentation(QTextStream &s, DocModification::Mode mode, const AbstractMetaClass *cppClass, const AbstractMetaFunction *func); - void writeDocSnips(QTextStream &s, const CodeSnipList &codeSnips, CodeSnip::Position position, TypeSystem::Language language); - - - QString parseArgDocStyle(const AbstractMetaClass *cppClass, const AbstractMetaFunction *func); - QString parseFunctionDeclaration(const QString &data, const AbstractMetaClass *cppClass); - QString translateToPythonType(const AbstractMetaType *type, const AbstractMetaClass *cppClass); - - QString m_docDataDir; - QString m_libSourceDir; - QString m_codeSnippetDir; - QStringList m_functionList; - Documentation m_moduleDoc; -}; - -#endif // DOCGENERATOR_H diff --git a/main.cpp b/main.cpp deleted file mode 100644 index 8700551f5..000000000 --- a/main.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of the Shiboken Python Binding Generator project. - * - * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: PySide team <contact@pyside.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include <QtCore/QCoreApplication> -#include <apiextractor/apiextractor.h> -#include "headergenerator.h" -#include "cppgenerator.h" - -int main(int argc, char *argv[]) -{ - QCoreApplication app(argc, argv); // needed by qxmlpatterns - - ApiExtractor extractor(argc, argv); - extractor.addGenerator(new HeaderGenerator); - extractor.addGenerator(new CppGenerator); - return extractor.exec(); -} - diff --git a/shiboken.cpp b/shiboken.cpp new file mode 100644 index 000000000..6930a96de --- /dev/null +++ b/shiboken.cpp @@ -0,0 +1,27 @@ +/* +* This file is part of the Shiboken Python Binding Generator project. +* +* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +* +* Contact: PySide team <contact@pyside.org> +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +* 02110-1301 USA +* +*/ + +#include "cppgenerator.h" +#include "headergenerator.h" + +EXPORT_GENERATOR_PLUGIN(new CppGenerator << new HeaderGenerator) diff --git a/shibokengenerator.cpp b/shibokengenerator.cpp index 9f5316eed..288040c42 100644 --- a/shibokengenerator.cpp +++ b/shibokengenerator.cpp @@ -142,46 +142,6 @@ FunctionModificationList ShibokenGenerator::functionModifications(const Abstract return mods; } -/* -QString ShibokenGenerator::translateType(const AbstractMetaType* cType, - const AbstractMetaClass* context, - int option) const -{ - QString s; - - if (context != 0 - && cType != 0 - && context->typeEntry()->isGenericClass() - && cType->originalTemplateType()) - { - cType = cType->originalTemplateType(); - } - - if (!cType) { - s = "void"; - } else if (cType->isArray()) { - s = translateType(cType->arrayElementType(), context) + "[]"; - } else if (cType->isEnum() || cType->isFlags()) { - if (option & Generator::EnumAsInts) - s = "int"; - else - s = cType->cppSignature(); - } else if (cType->isValue() || cType->isObject() || cType->isReference()) { - s = cType->typeEntry()->qualifiedCppName(); - if (cType->isObject()) - s.append('*'); - } else { - s = cType->cppSignature(); - if (cType->isConstant() && (option & Generator::ExcludeConst)) - s.replace("const", ""); - if (cType->isReference() && (option & Generator::ExcludeReference)) - s.replace("&", ""); - } - - return s; -} -*/ - QString ShibokenGenerator::translateTypeForWrapperMethod(const AbstractMetaType* cType, const AbstractMetaClass* context) const { @@ -200,58 +160,6 @@ QString ShibokenGenerator::translateTypeForWrapperMethod(const AbstractMetaType* return result; } -QString ShibokenGenerator::translateType(const AbstractMetaType *cType, - const AbstractMetaClass *context, - int option) const -{ - QString s; - - if (context && cType && - context->typeEntry()->isGenericClass() && - cType->originalTemplateType()) { - qDebug() << "set original templateType" << cType->name(); - cType = cType->originalTemplateType(); - } - - if (!cType) { - s = "void"; - } else if (cType->isArray()) { - s = translateType(cType->arrayElementType(), context) + "[]"; - } else if (cType->isEnum() || cType->isFlags()) { - if (option & Generator::EnumAsInts) - s = "int"; - else - s = cType->cppSignature(); -#if 0 - } else if (c_type->isContainer()) { - qDebug() << "is container" << c_type->cppSignature(); - s = c_type->name(); - if (!(option & SkipTemplateParameters)) { - s += " < "; - QList<AbstractMetaType *> args = c_type->instantiations(); - for (int i = 0; i < args.size(); ++i) { - if (i) - s += ", "; - qDebug() << "container type: " << args.at(i)->cppSignature() << " / " << args.at(i)->instantiations().count(); - s += translateType(args.at(i), context, option); - } - s += " > "; - } -#endif - } else { - s = cType->cppSignature(); - if (cType->isConstant() && (option & Generator::ExcludeConst)) - s.replace("const", ""); - if (cType->isReference() && (option & Generator::ExcludeReference)) - s.replace("&", ""); - } - - s.replace(" *", "*"); - s.replace("char*", "char *"); - - return s; -} - QString ShibokenGenerator::wrapperName(const AbstractMetaClass* metaClass) { QString result = metaClass->name(); @@ -293,7 +201,7 @@ QString ShibokenGenerator::cpythonEnumName(const EnumTypeEntry* enumEntry) return result; } -QString ShibokenGenerator::getFunctionReturnType(const AbstractMetaFunction* func) const +QString ShibokenGenerator::getFunctionReturnType(const AbstractMetaFunction* func, Options options) const { if (func->ownerClass() && (func->isConstructor() || func->isCopyConstructor())) return func->ownerClass()->qualifiedCppName() + '*'; @@ -520,13 +428,13 @@ QString ShibokenGenerator::cpythonCheckFunction(const TypeEntry* type, bool gene QString ShibokenGenerator::argumentString(const AbstractMetaFunction *func, const AbstractMetaArgument *argument, - uint options) const + Options options) const { QString modified_type = func->typeReplaced(argument->argumentIndex() + 1); QString arg; if (modified_type.isEmpty()) - arg = translateType(argument->type(), func->implementingClass(), (Generator::Option) options); + arg = translateType(argument->type(), func->implementingClass(), options); else arg = modified_type.replace('$', '.'); @@ -557,14 +465,14 @@ QString ShibokenGenerator::argumentString(const AbstractMetaFunction *func, void ShibokenGenerator::writeArgument(QTextStream &s, const AbstractMetaFunction *func, const AbstractMetaArgument *argument, - uint options) const + Options options) const { s << argumentString(func, argument, options); } void ShibokenGenerator::writeFunctionArguments(QTextStream &s, const AbstractMetaFunction *func, - uint options) const + Options options) const { AbstractMetaArgumentList arguments = func->arguments(); @@ -586,19 +494,19 @@ void ShibokenGenerator::writeFunctionArguments(QTextStream &s, } } -QString ShibokenGenerator::functionReturnType(const AbstractMetaFunction* func, int option) const +QString ShibokenGenerator::functionReturnType(const AbstractMetaFunction* func, Options options) const { QString modifiedReturnType = QString(func->typeReplaced(0)); - if (!modifiedReturnType.isNull() && !(option & OriginalTypeDescription)) + if (!modifiedReturnType.isNull() && !(options & OriginalTypeDescription)) return modifiedReturnType; else - return translateType(func->type(), func->implementingClass(), option); + return translateType(func->type(), func->implementingClass(), options); } QString ShibokenGenerator::functionSignature(const AbstractMetaFunction *func, QString prepend, QString append, - int option, + Options options, int argCount) const { AbstractMetaArgumentList arguments = func->arguments(); @@ -610,9 +518,9 @@ QString ShibokenGenerator::functionSignature(const AbstractMetaFunction *func, if (!(func->isEmptyFunction() || func->isNormal() || func->isSignal())) { - option = Option(option | Generator::SkipReturnType); + options |= Generator::SkipReturnType; } else { - s << functionReturnType(func, option) << ' '; + s << functionReturnType(func, options) << ' '; } // name @@ -621,10 +529,10 @@ QString ShibokenGenerator::functionSignature(const AbstractMetaFunction *func, name = wrapperName(func->ownerClass()); s << prepend << name << append << '('; - writeFunctionArguments(s, func, option); + writeFunctionArguments(s, func, options); s << ')'; - if (func->isConstant() && !(option & Generator::ExcludeMethodConst)) + if (func->isConstant() && !(options & Generator::ExcludeMethodConst)) s << " const"; return result; @@ -633,10 +541,10 @@ QString ShibokenGenerator::functionSignature(const AbstractMetaFunction *func, QString ShibokenGenerator::signatureForDefaultVirtualMethod(const AbstractMetaFunction *func, QString prepend, QString append, - int option, + Options options, int argCount) const { - QString defaultMethodSignature = functionSignature(func, prepend, append, option, argCount); + QString defaultMethodSignature = functionSignature(func, prepend, append, options, argCount); QString staticSelf("("); if (func->isConstant()) staticSelf += "const "; @@ -659,7 +567,7 @@ bool ShibokenGenerator::hasInjectedCodeOrSignatureModification(const AbstractMet void ShibokenGenerator::writeArgumentNames(QTextStream &s, const AbstractMetaFunction *func, - uint options) const + Options options) const { AbstractMetaArgumentList arguments = func->arguments(); int argCount = 0; @@ -762,7 +670,7 @@ AbstractMetaFunctionList ShibokenGenerator::queryFunctions(const AbstractMetaCla void ShibokenGenerator::writeFunctionCall(QTextStream& s, const AbstractMetaFunction* func, - uint options) const + Options options) const { if (!(options & Generator::SkipName)) s << (func->isConstructor() ? func->ownerClass()->qualifiedCppName() : func->originalName()); @@ -828,7 +736,7 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, QTextStream tmpStream(&code); Indentation indent1(INDENT); Indentation indent2(INDENT); - snip.formattedCode(tmpStream, INDENT); + formatCode(tmpStream, snip.code(), INDENT); if (func) { // replace template variable for return variable name @@ -904,3 +812,10 @@ static void dumpFunction(AbstractMetaFunctionList lst) << "is operator:" << func->isOperatorOverload() << "is global:" << func->isInGlobalScope(); } + + +bool ShibokenGenerator::doSetup(const QMap<QString, QString>& args) +{ + return true; +} + diff --git a/shibokengenerator.h b/shibokengenerator.h index 51c0d393a..407fb5f9a 100644 --- a/shibokengenerator.h +++ b/shibokengenerator.h @@ -24,7 +24,7 @@ #ifndef SHIBOKENGENERATOR_H #define SHIBOKENGENERATOR_H -#include <apiextractor/generator.h> +#include <generatorrunner/generator.h> #include <QtCore/QTextStream> class DocParser; @@ -37,21 +37,9 @@ class ShibokenGenerator : public Generator public: ShibokenGenerator(); - /** - * Translate metatypes to C++ format. - * \param metaType a pointer to metatype - * \param context the current meta class - * \param option some extra options - * \return the metatype translated to C++ format - */ - virtual QString translateType(const AbstractMetaType* metaType, - const AbstractMetaClass* context, - int option = NoOption) const; - QString translateTypeForWrapperMethod(const AbstractMetaType* cType, const AbstractMetaClass* context) const; - /** * Write a function argument in the C++ in the text stream \p s. * This function just call \code s << argumentString(); \endcode @@ -63,7 +51,7 @@ public: void writeArgument(QTextStream &s, const AbstractMetaFunction* func, const AbstractMetaArgument* argument, - uint options = 0) const; + Options options = NoOption) const; /** * Create a QString in the C++ format to an function argument. * \param func the current metafunction. @@ -72,11 +60,11 @@ public: */ QString argumentString(const AbstractMetaFunction* func, const AbstractMetaArgument* argument, - uint options = 0) const; + Options options = NoOption) const; void writeArgumentNames(QTextStream &s, const AbstractMetaFunction* func, - uint options = 0) const; + Options options = NoOption) const; /** * Function used to write the fucntion arguments on the class buffer. @@ -87,8 +75,8 @@ public: */ void writeFunctionArguments(QTextStream &s, const AbstractMetaFunction* func, - uint options = 0) const; - QString functionReturnType(const AbstractMetaFunction* func, int option = NoOption) const; + Options options = NoOption) const; + QString functionReturnType(const AbstractMetaFunction* func, Options options = NoOption) const; /** * Write a code snip into the buffer \p s. * CodeSnip are codes inside inject-code tags. @@ -115,13 +103,13 @@ public: QString functionSignature(const AbstractMetaFunction* func, QString prepend = "", QString append = "", - int option = NoOption, + Options options = NoOption, int arg_count = -1) const; QString signatureForDefaultVirtualMethod(const AbstractMetaFunction* func, QString prepend = "", QString append = "_default", - int option = NoOption, + Options option = NoOption, int arg_count = -1) const; virtual QString subDirectoryForClass(const AbstractMetaClass* metaClass) const @@ -179,13 +167,11 @@ public: return cpythonEnumName(metaEnum->typeEntry()); } - QString getFunctionReturnType(const AbstractMetaFunction* func) const; + QString getFunctionReturnType(const AbstractMetaFunction* func, Options options = NoOption) const; QString getFormatUnitString(const AbstractMetaArgumentList arguments) const; - virtual bool prepareGeneration(const QMap<QString, QString>& args) - { - return true; - } + + bool doSetup(const QMap<QString, QString>& args); protected: bool m_native_jump_table; @@ -206,7 +192,7 @@ protected: AbstractMetaFunctionList queryFunctions(const AbstractMetaClass* metaClass, bool allFunction = false); void writeFunctionCall(QTextStream& s, const AbstractMetaFunction* metaFunc, - uint options = 0) const; + Options options = NoOption) const; AbstractMetaFunctionList filterFunctions(const AbstractMetaClass* metaClass); AbstractMetaFunctionList queryGlobalOperators(const AbstractMetaClass* metaClass); diff --git a/tests/samplebinding/CMakeLists.txt b/tests/samplebinding/CMakeLists.txt index f0c04188e..08c8ee7ff 100644 --- a/tests/samplebinding/CMakeLists.txt +++ b/tests/samplebinding/CMakeLists.txt @@ -21,8 +21,10 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/size_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/virtualmethods_wrapper.cpp ) +find_program(GENERATOR generatorrunner REQUIRED) + add_custom_command(OUTPUT ${sample_SRC} -COMMAND ${CMAKE_BINARY_DIR}/shiboken +COMMAND ${GENERATOR} --generatorSet=${shiboken_BINARY_DIR}/shiboken ${CMAKE_CURRENT_SOURCE_DIR}/global.h --include-paths=${libsample_SOURCE_DIR} --typesystem-paths=${CMAKE_CURRENT_SOURCE_DIR} |