aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/ApiExtractor/apiextractor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken6/ApiExtractor/apiextractor.cpp')
-rw-r--r--sources/shiboken6/ApiExtractor/apiextractor.cpp284
1 files changed, 284 insertions, 0 deletions
diff --git a/sources/shiboken6/ApiExtractor/apiextractor.cpp b/sources/shiboken6/ApiExtractor/apiextractor.cpp
new file mode 100644
index 000000000..aa552cdd3
--- /dev/null
+++ b/sources/shiboken6/ApiExtractor/apiextractor.cpp
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $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$
+**
+****************************************************************************/
+
+#include "apiextractor.h"
+#include "abstractmetalang.h"
+
+#include <QDir>
+#include <QDebug>
+#include <QTemporaryFile>
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+
+#include "reporthandler.h"
+#include "typesystem.h"
+#include "fileout.h"
+#include "abstractmetabuilder.h"
+#include "typedatabase.h"
+#include "typesystem.h"
+
+ApiExtractor::ApiExtractor()
+{
+ // Environment TYPESYSTEMPATH
+ QString envTypesystemPaths = QFile::decodeName(qgetenv("TYPESYSTEMPATH"));
+ if (!envTypesystemPaths.isEmpty())
+ TypeDatabase::instance()->addTypesystemPath(envTypesystemPaths);
+}
+
+ApiExtractor::~ApiExtractor()
+{
+ delete m_builder;
+}
+
+void ApiExtractor::addTypesystemSearchPath (const QString& path)
+{
+ TypeDatabase::instance()->addTypesystemPath(path);
+}
+
+void ApiExtractor::addTypesystemSearchPath(const QStringList& paths)
+{
+ for (const QString &path : paths)
+ addTypesystemSearchPath(path);
+}
+
+void ApiExtractor::addIncludePath(const HeaderPath& path)
+{
+ m_includePaths << path;
+}
+
+void ApiExtractor::addIncludePath(const HeaderPaths& paths)
+{
+ m_includePaths << paths;
+}
+
+void ApiExtractor::setLogDirectory(const QString& logDir)
+{
+ m_logDirectory = logDir;
+}
+
+void ApiExtractor::setCppFileNames(const QFileInfoList &cppFileName)
+{
+ m_cppFileNames = cppFileName;
+}
+
+void ApiExtractor::setTypeSystem(const QString& typeSystemFileName)
+{
+ m_typeSystemFileName = typeSystemFileName;
+}
+
+void ApiExtractor::setSkipDeprecated(bool value)
+{
+ m_skipDeprecated = value;
+ if (m_builder)
+ m_builder->setSkipDeprecated(m_skipDeprecated);
+}
+
+void ApiExtractor::setSuppressWarnings ( bool value )
+{
+ TypeDatabase::instance()->setSuppressWarnings(value);
+}
+
+void ApiExtractor::setSilent ( bool value )
+{
+ ReportHandler::setSilent(value);
+}
+
+bool ApiExtractor::setApiVersion(const QString& package, const QString &version)
+{
+ return TypeDatabase::setApiVersion(package, version);
+}
+
+void ApiExtractor::setDropTypeEntries(QString dropEntries)
+{
+ dropEntries.remove(QLatin1Char(' '));
+ QStringList entries = dropEntries.split(QLatin1Char(';'));
+ TypeDatabase::instance()->setDropTypeEntries(entries);
+}
+
+const AbstractMetaEnumList &ApiExtractor::globalEnums() const
+{
+ Q_ASSERT(m_builder);
+ return m_builder->globalEnums();
+}
+
+const AbstractMetaFunctionList &ApiExtractor::globalFunctions() const
+{
+ Q_ASSERT(m_builder);
+ return m_builder->globalFunctions();
+}
+
+const AbstractMetaClassList &ApiExtractor::classes() const
+{
+ Q_ASSERT(m_builder);
+ return m_builder->classes();
+}
+
+const AbstractMetaClassList &ApiExtractor::smartPointers() const
+{
+ Q_ASSERT(m_builder);
+ return m_builder->smartPointers();
+}
+
+AbstractMetaClassList ApiExtractor::classesTopologicalSorted(const Dependencies &additionalDependencies) const
+{
+ Q_ASSERT(m_builder);
+ return m_builder->classesTopologicalSorted(m_builder->classes(), additionalDependencies);
+}
+
+PrimitiveTypeEntryList ApiExtractor::primitiveTypes() const
+{
+ return TypeDatabase::instance()->primitiveTypes();
+}
+
+ContainerTypeEntryList ApiExtractor::containerTypes() const
+{
+ return TypeDatabase::instance()->containerTypes();
+}
+
+const AbstractMetaEnum* ApiExtractor::findAbstractMetaEnum(const TypeEntry* typeEntry) const
+{
+ return m_builder->findEnum(typeEntry);
+}
+
+int ApiExtractor::classCount() const
+{
+ Q_ASSERT(m_builder);
+ return m_builder->classes().count();
+}
+
+// Add defines required for parsing Qt code headers
+static void addPySideExtensions(QByteArrayList *a)
+{
+ // Make "signals:", "slots:" visible as access specifiers
+ a->append(QByteArrayLiteral("-DQT_ANNOTATE_ACCESS_SPECIFIER(a)=__attribute__((annotate(#a)))"));
+
+ // Q_PROPERTY is defined as class annotation which does not work since a
+ // sequence of properties will to expand to a sequence of annotations
+ // annotating nothing, causing clang to complain. Instead, define it away in a
+ // static assert with the stringified argument in a ','-operator (cf qdoc).
+ a->append(QByteArrayLiteral("-DQT_ANNOTATE_CLASS(type,...)=static_assert(sizeof(#__VA_ARGS__),#type);"));
+}
+
+bool ApiExtractor::run(bool usePySideExtensions)
+{
+ if (m_builder)
+ return false;
+
+ if (!TypeDatabase::instance()->parseFile(m_typeSystemFileName)) {
+ std::cerr << "Cannot parse file: " << qPrintable(m_typeSystemFileName);
+ return false;
+ }
+
+ const QString pattern = QDir::tempPath() + QLatin1Char('/')
+ + m_cppFileNames.constFirst().baseName()
+ + QStringLiteral("_XXXXXX.hpp");
+ QTemporaryFile ppFile(pattern);
+ bool autoRemove = !qEnvironmentVariableIsSet("KEEP_TEMP_FILES");
+ // make sure that a tempfile can be written
+ if (!ppFile.open()) {
+ std::cerr << "could not create tempfile " << qPrintable(pattern)
+ << ": " << qPrintable(ppFile.errorString()) << '\n';
+ return false;
+ }
+ for (const auto &cppFileName : qAsConst(m_cppFileNames)) {
+ ppFile.write("#include \"");
+ ppFile.write(cppFileName.absoluteFilePath().toLocal8Bit());
+ ppFile.write("\"\n");
+ }
+ const QString preprocessedCppFileName = ppFile.fileName();
+ ppFile.close();
+ m_builder = new AbstractMetaBuilder;
+ m_builder->setLogDirectory(m_logDirectory);
+ m_builder->setGlobalHeaders(m_cppFileNames);
+ m_builder->setSkipDeprecated(m_skipDeprecated);
+ m_builder->setHeaderPaths(m_includePaths);
+ QByteArrayList arguments;
+ arguments.reserve(m_includePaths.size() + 1);
+ for (const HeaderPath &headerPath : qAsConst(m_includePaths))
+ arguments.append(HeaderPath::includeOption(headerPath));
+ arguments.append(QFile::encodeName(preprocessedCppFileName));
+ if (ReportHandler::isDebug(ReportHandler::SparseDebug)) {
+ qCInfo(lcShiboken).noquote().nospace()
+ << "clang language level: " << int(m_languageLevel)
+ << "\nclang arguments: " << arguments;
+ }
+
+ if (usePySideExtensions)
+ addPySideExtensions(&arguments);
+
+ const bool result = m_builder->build(arguments, m_languageLevel);
+ if (!result)
+ autoRemove = false;
+ if (!autoRemove) {
+ ppFile.setAutoRemove(false);
+ std::cerr << "Keeping temporary file: " << qPrintable(QDir::toNativeSeparators(preprocessedCppFileName)) << '\n';
+ }
+ return result;
+}
+
+LanguageLevel ApiExtractor::languageLevel() const
+{
+ return m_languageLevel;
+}
+
+void ApiExtractor::setLanguageLevel(LanguageLevel languageLevel)
+{
+ m_languageLevel = languageLevel;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+template <class Container>
+static void debugFormatSequence(QDebug &d, const char *key, const Container& c)
+{
+ if (c.isEmpty())
+ return;
+ const auto begin = c.begin();
+ d << "\n " << key << '[' << c.size() << "]=(";
+ for (auto it = begin, end = c.end(); it != end; ++it) {
+ if (it != begin)
+ d << ", ";
+ d << *it;
+ }
+ d << ')';
+}
+
+QDebug operator<<(QDebug d, const ApiExtractor &ae)
+{
+ QDebugStateSaver saver(d);
+ d.noquote();
+ d.nospace();
+ if (ReportHandler::debugLevel() >= ReportHandler::FullDebug)
+ d.setVerbosity(3); // Trigger verbose output of AbstractMetaClass
+ d << "ApiExtractor(typeSystem=\"" << ae.typeSystem() << "\", cppFileNames=\""
+ << ae.cppFileNames() << ", ";
+ ae.m_builder->formatDebug(d);
+ d << ')';
+ return d;
+}
+#endif // QT_NO_DEBUG_STREAM