From 5b205769a6f898093fd9f04d33856e5686414303 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint <Friedemann.Kleint@qt.io> Date: Fri, 26 Jan 2018 11:12:47 +0100 Subject: [PATCH] qdoc: Add a logging category Remove the debug functionality from the Generator class and add a logging category instead. Add some debug statements outputting the command line arguments and clang arguments. This makes it possible to obtain logging output by setting for example QT_LOGGING_RULES=qt.qdoc.debug=true . Task-number: PYSIDE-363 Change-Id: I3ecfe548e14aa3e2d03f19d07fc61a2647b75111 Reviewed-by: Martin Smith <martin.smith@qt.io> --- src/qdoc/clangcodeparser.cpp | 29 +++++++++++++++++++++++++- src/qdoc/generator.cpp | 25 +++++++++++----------- src/qdoc/generator.h | 4 +--- src/qdoc/loggingcategory.h | 40 ++++++++++++++++++++++++++++++++++++ src/qdoc/main.cpp | 35 +++++++++++++++++-------------- src/qdoc/qdoc.pro | 1 + 6 files changed, 103 insertions(+), 31 deletions(-) create mode 100644 src/qdoc/loggingcategory.h diff --git a/src/qdoc/clangcodeparser.cpp b/src/qdoc/clangcodeparser.cpp index 3c5d615c2..ea4ffb18e 100644 --- a/src/qdoc/clangcodeparser.cpp +++ b/src/qdoc/clangcodeparser.cpp @@ -47,6 +47,7 @@ #include "codechunk.h" #include "config.h" #include "clangcodeparser.h" +#include "loggingcategory.h" #include "qdocdatabase.h" #include <qdebug.h> #include <qscopedvaluerollback.h> @@ -61,6 +62,25 @@ QT_BEGIN_NAMESPACE static CXTranslationUnit_Flags flags_ = (CXTranslationUnit_Flags)0; static CXIndex index_ = 0; +#ifndef QT_NO_DEBUG_STREAM +template <class T> +static QDebug operator<<(QDebug debug, const std::vector<T> &v) +{ + QDebugStateSaver saver(debug); + debug.noquote(); + debug.nospace(); + const size_t size = v.size(); + debug << "std::vector<>[" << size << "]("; + for (size_t i = 0; i < size; ++i) { + if (i) + debug << ", "; + debug << v[i]; + } + debug << ')'; + return debug; +} +#endif // !QT_NO_DEBUG_STREAM + /*! Call clang_visitChildren on the given cursor with the lambda as a callback T can be any functor that is callable with a CXCursor parameter and returns a CXChildVisitResult @@ -975,6 +995,8 @@ void ClangCodeParser::initializeParser(const Config &config) } } } + qCDebug(lcQdoc).nospace() << __FUNCTION__ << " Clang v" << CINDEX_VERSION_MAJOR + << '.' << CINDEX_VERSION_MINOR; } /*! @@ -1170,6 +1192,8 @@ void ClangCodeParser::buildPCH() tmpHeader.toLatin1().data(), args_.data(), static_cast<int>(args_.size()), nullptr, 0, flags_ | CXTranslationUnit_ForSerialization, &tu); + qCDebug(lcQdoc) << __FUNCTION__ << "clang_parseTranslationUnit2(" + << tmpHeader << args_ << ") returns" << err; if (!err && tu) { pchName_ = pchFileDir_->path().toUtf8() + "/" + module + ".pch"; auto error = clang_saveTranslationUnit(tu, pchName_.constData(), clang_defaultSaveOptions(tu)); @@ -1238,6 +1262,8 @@ void ClangCodeParser::parseSourceFile(const Location& /*location*/, const QStrin CXTranslationUnit tu; CXErrorCode err = clang_parseTranslationUnit2(index_, filePath.toLocal8Bit(), args_.data(), static_cast<int>(args_.size()), nullptr, 0, flags_, &tu); + qCDebug(lcQdoc) << __FUNCTION__ << "clang_parseTranslationUnit2(" + << filePath << args_ << ") returns" << err; if (err || !tu) { qWarning() << "(qdoc) Could not parse source file" << filePath << " error code:" << err; clang_disposeIndex(index_); @@ -1397,7 +1423,8 @@ Node* ClangCodeParser::parseFnArg(const Location& location, const QString& fnArg 1, flags, &tu); - + qCDebug(lcQdoc) << __FUNCTION__ << "clang_parseTranslationUnit2(" + << dummyFileName << args_ << ") returns" << err; if (err || !tu) { location.error(ClangCodeParser::tr("clang could not parse \\fn %1").arg(fnArg)); clang_disposeTranslationUnit(tu); diff --git a/src/qdoc/generator.cpp b/src/qdoc/generator.cpp index 8d088b13f..760488bea 100644 --- a/src/qdoc/generator.cpp +++ b/src/qdoc/generator.cpp @@ -36,6 +36,7 @@ #include "doc.h" #include "editdistance.h" #include "generator.h" +#include "loggingcategory.h" #include "openedlist.h" #include "quoter.h" #include "separator.h" @@ -83,7 +84,6 @@ QString Generator::sinceTitles[] = }; QStringList Generator::styleDirs; QStringList Generator::styleFiles; -bool Generator::debugging_ = false; bool Generator::noLinkErrors_ = false; bool Generator::autolinkErrors_ = false; bool Generator::redirectDocumentationToDevNull_ = false; @@ -99,25 +99,26 @@ static QLatin1String gt(">"); static QLatin1String lt("<"); static QLatin1String quot("""); +static inline void setDebugEnabled(bool v) +{ + const_cast<QLoggingCategory &>(lcQdoc()).setEnabled(QtDebugMsg, v); +} + void Generator::startDebugging(const QString& message) { - debugging_ = true; - qDebug() << "START DEBUGGING:" << message; + setDebugEnabled(true); + qCDebug(lcQdoc, "START DEBUGGING: %s", qPrintable(message)); } void Generator::stopDebugging(const QString& message) { - debugging_ = false; - qDebug() << "STOP DEBUGGING:" << message; + qCDebug(lcQdoc, "STOP DEBUGGING: %s", qPrintable(message)); + setDebugEnabled(false); } -/*! - Prints \a message as an aid to debugging the release version. - */ -void Generator::debug(const QString& message) +bool Generator::debugging() { - if (debugging()) - qDebug() << " DEBUG:" << message; + return lcQdoc().isEnabled(QtDebugMsg); } /*! @@ -306,7 +307,7 @@ void Generator::beginSubPage(const Node* node, const QString& fileName) node->location().error(tr("Output file already exists; overwriting %1").arg(outFile->fileName())); if (!outFile->open(QFile::WriteOnly)) node->location().fatal(tr("Cannot open output file '%1'").arg(outFile->fileName())); - Generator::debug("Writing: " + path); + qCDebug(lcQdoc, "Writing: %s", qPrintable(path)); outFileNames_ << fileName; QTextStream* out = new QTextStream(outFile); diff --git a/src/qdoc/generator.h b/src/qdoc/generator.h index ac8fbbbcf..0bcabc90f 100644 --- a/src/qdoc/generator.h +++ b/src/qdoc/generator.h @@ -81,10 +81,9 @@ public: static const QStringList& outputFileNames() { return outFileNames_; } static void writeOutFileNames(); static void augmentImageDirs(QSet<QString>& moreImageDirs); - static void debug(const QString& message); static void startDebugging(const QString& message); static void stopDebugging(const QString& message); - static bool debugging() { return debugging_; } + static bool debugging(); static bool noLinkErrors() { return noLinkErrors_; } static bool autolinkErrors() { return autolinkErrors_; } static void setQDocPass(QDocPass t) { qdocPass_ = t; } @@ -221,7 +220,6 @@ private: static QStringList scriptFiles; static QStringList styleDirs; static QStringList styleFiles; - static bool debugging_; static bool noLinkErrors_; static bool autolinkErrors_; static bool redirectDocumentationToDevNull_; diff --git a/src/qdoc/loggingcategory.h b/src/qdoc/loggingcategory.h new file mode 100644 index 000000000..812ef7af8 --- /dev/null +++ b/src/qdoc/loggingcategory.h @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LOGGINGCATEGORY_H +#define LOGGINGCATEGORY_H + +#include <QtCore/qloggingcategory.h> + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(lcQdoc) + +QT_END_NAMESPACE + +#endif diff --git a/src/qdoc/main.cpp b/src/qdoc/main.cpp index 4dd307541..172261281 100644 --- a/src/qdoc/main.cpp +++ b/src/qdoc/main.cpp @@ -46,6 +46,7 @@ #include "cppcodeparser.h" #include "doc.h" #include "htmlgenerator.h" +#include "loggingcategory.h" #include "webxmlgenerator.h" #include "location.h" #include "plaincodemarker.h" @@ -70,6 +71,8 @@ QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcQdoc, "qt.qdoc") + bool creationTimeBefore(const QFileInfo &fi1, const QFileInfo &fi2) { return fi1.lastModified() < fi2.lastModified(); @@ -363,9 +366,9 @@ static void processQdocconfFile(const QString &fileName) qdb->clearSearchOrder(); if (!Generator::singleExec()) { if (!Generator::preparing()) { - Generator::debug(" loading index files"); + qCDebug(lcQdoc, " loading index files"); loadIndexFiles(config, outputFormats); - Generator::debug(" done loading index files"); + qCDebug(lcQdoc, " done loading index files"); } qdb->newPrimaryTree(project); } @@ -392,7 +395,7 @@ static void processQdocconfFile(const QString &fileName) QSet<QString> excludedDirs = QSet<QString>::fromList(config.getCanonicalPathList(CONFIG_EXCLUDEDIRS)); QSet<QString> excludedFiles = QSet<QString>::fromList(config.getCanonicalPathList(CONFIG_EXCLUDEFILES)); - Generator::debug("Adding doc/image dirs found in exampledirs to imagedirs"); + qCDebug(lcQdoc, "Adding doc/image dirs found in exampledirs to imagedirs"); QSet<QString> exampleImageDirs; QStringList exampleImageList = config.getExampleImageFiles(excludedDirs, excludedFiles); for (int i = 0; i < exampleImageList.size(); ++i) { @@ -409,7 +412,7 @@ static void processQdocconfFile(const QString &fileName) QStringList headerList; QStringList sourceList; - Generator::debug("Reading headerdirs"); + qCDebug(lcQdoc, "Reading headerdirs"); headerList = config.getAllFiles(CONFIG_HEADERS,CONFIG_HEADERDIRS,excludedDirs,excludedFiles); QMap<QString,QString> headers; QMultiMap<QString,QString> headerFileNames; @@ -423,7 +426,7 @@ static void processQdocconfFile(const QString &fileName) headerFileNames.insert(t,t); } - Generator::debug("Reading sourcedirs"); + qCDebug(lcQdoc, "Reading sourcedirs"); sourceList = config.getAllFiles(CONFIG_SOURCES,CONFIG_SOURCEDIRS,excludedDirs,excludedFiles); QMap<QString,QString> sources; QMultiMap<QString,QString> sourceFileNames; @@ -440,7 +443,7 @@ static void processQdocconfFile(const QString &fileName) Find all the qdoc files in the example dirs, and add them to the source files to be parsed. */ - Generator::debug("Reading exampledirs"); + qCDebug(lcQdoc, "Reading exampledirs"); QStringList exampleQdocList = config.getExampleQdocFiles(excludedDirs, excludedFiles); for (int i=0; i<exampleQdocList.size(); ++i) { if (!sources.contains(exampleQdocList[i])) { @@ -454,14 +457,14 @@ static void processQdocconfFile(const QString &fileName) to the big tree. */ - Generator::debug("Parsing header files"); + qCDebug(lcQdoc, "Parsing header files"); int parsed = 0; QMap<QString,QString>::ConstIterator h = headers.constBegin(); while (h != headers.constEnd()) { CodeParser *codeParser = CodeParser::parserForHeaderFile(h.key()); if (codeParser) { ++parsed; - Generator::debug(QString("Parsing " + h.key())); + qCDebug(lcQdoc, "Parsing %s", qPrintable(h.key())); codeParser->parseHeaderFile(config.location(), h.key()); } ++h; @@ -476,25 +479,25 @@ static void processQdocconfFile(const QString &fileName) add it to the big tree. */ parsed = 0; - Generator::debug("Parsing source files"); + qCDebug(lcQdoc, "Parsing source files"); QMap<QString,QString>::ConstIterator s = sources.constBegin(); while (s != sources.constEnd()) { CodeParser *codeParser = CodeParser::parserForSourceFile(s.key()); if (codeParser) { ++parsed; - Generator::debug(QString("Parsing " + s.key())); + qCDebug(lcQdoc, "Parsing %s", qPrintable(s.key())); codeParser->parseSourceFile(config.location(), s.key()); } ++s; } - Generator::debug(QString("Parsing done.")); + qCDebug(lcQdoc, "Parsing done."); /* Now the primary tree has been built from all the header and source files. Resolve all the class names, function names, targets, URLs, links, and other stuff that needs resolving. */ - Generator::debug("Resolving stuff prior to generating docs"); + qCDebug(lcQdoc, "Resolving stuff prior to generating docs"); qdb->resolveIssues(); } else { @@ -508,7 +511,7 @@ static void processQdocconfFile(const QString &fileName) format can be requested. The tree is traversed for each one. */ - Generator::debug("Generating docs"); + qCDebug(lcQdoc, "Generating docs"); QSet<QString>::ConstIterator of = outputFormats.constBegin(); while (of != outputFormats.constEnd()) { Generator* generator = Generator::generatorForFormat(*of); @@ -525,7 +528,7 @@ static void processQdocconfFile(const QString &fileName) #endif qdb->clearLinkCounts(); - Generator::debug("Terminating qdoc classes"); + qCDebug(lcQdoc, "Terminating qdoc classes"); if (Generator::debugging()) Generator::stopDebugging(project); @@ -538,7 +541,7 @@ static void processQdocconfFile(const QString &fileName) Location::terminate(); QDir::setCurrent(prevCurrentDir); - Generator::debug("qdoc classes terminated"); + qCDebug(lcQdoc, "qdoc classes terminated"); } class QDocCommandLineParser : public QCommandLineParser @@ -708,6 +711,8 @@ void QDocCommandLineParser::process(const QCoreApplication &app) autolinkErrors = isSet(autoLinkErrorsOption); if (isSet(debugOption)) Generator::startDebugging(QString("command line")); + qCDebug(lcQdoc).noquote() << "Arguments :" << QCoreApplication::arguments(); + if (isSet(prepareOption)) Generator::setQDocPass(Generator::Prepare); if (isSet(generateOption)) diff --git a/src/qdoc/qdoc.pro b/src/qdoc/qdoc.pro index 5364ed0ef..30de9df08 100644 --- a/src/qdoc/qdoc.pro +++ b/src/qdoc/qdoc.pro @@ -44,6 +44,7 @@ HEADERS += atom.h \ helpprojectwriter.h \ htmlgenerator.h \ location.h \ + loggingcategory.h \ node.h \ openedlist.h \ plaincodemarker.h \ -- GitLab