Skip to content
13 changes: 5 additions & 8 deletions ApiExtractor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@ if(BUILD_TESTS)
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/tests)
endif ()

set(QT_USE_QTCORE 1)
set(QT_USE_QTXML 1)
include(${QT_USE_FILE})
add_definitions(${QT_DEFINITIONS})
find_package(Qt5Core REQUIRED)
find_package(Qt5Xml REQUIRED)
find_package(Qt5XmlPatterns REQUIRED)
add_definitions(-DQT_PLUGIN)
add_definitions(-DQT_SHARED)
add_definitions(-DRXX_ALLOCATOR_INIT_0)
Expand Down Expand Up @@ -79,19 +78,17 @@ endif()

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)

qt4_add_resources(apiextractor_RCCS_SRC generator.qrc)
qt4_automoc(apiextractor_SRC)
qt5_add_resources(apiextractor_RCCS_SRC generator.qrc)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/parser
${CMAKE_CURRENT_SOURCE_DIR}/parser/rpp
${QT_INCLUDE_DIR}
${APIEXTRACTOR_EXTRA_INCLUDES}
)

add_library(apiextractor STATIC ${apiextractor_SRC} ${apiextractor_RCCS_SRC})
target_link_libraries(apiextractor ${APIEXTRACTOR_EXTRA_LIBRARIES} ${QT_QTCORE_LIBRARY} ${QT_QTXMLPATTERNS_LIBRARY} ${QT_QTXML_LIBRARY})
target_link_libraries(apiextractor ${APIEXTRACTOR_EXTRA_LIBRARIES} Qt5::Core Qt5::XmlPatterns Qt5::Xml)

if (BUILD_TESTS)
enable_testing()
Expand Down
110 changes: 64 additions & 46 deletions ApiExtractor/abstractmetabuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,20 @@
#include "parser/parser.h"
#include "parser/tokens.h"

#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QTextCodec>
#include <QTextStream>
#include <QVariant>
#include <QTime>
#include <QQueue>
#include <QDir>
#include <QtCore/QDebug>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pedantic: using tll(Qt5::Core), I don't believe this is necessary... if supporting both Qt4/Qt5 is a goal, it might be better to omit these changes.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...that said, the only modules Shiboken should care about are ones that have not been refactored (i.e. Shiboken is not using headers that exist in different modules between Qt4 and Qt5), and this style of include in theory works with Qt4 also. (More to the point, I noticed there is at least one such include prior to these changes...)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dual Qt4/Qt5 support isn't a necessity. It can be done if it isn't too much work, but seeing as upstream doesn't care much about this, I expect we may be left with a fork here anyways :( .

#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QTextCodec>
#include <QtCore/QTextStream>
#include <QtCore/QVariant>
#include <QtCore/QTime>
#include <QtCore/QQueue>
#include <QtCore/QDir>

#include <cstdio>
#include <algorithm>
#include "graph.h"
#include <QTemporaryFile>
#include <QtCore/QTemporaryFile>

static QString stripTemplateArgs(const QString &name)
{
Expand Down Expand Up @@ -451,9 +451,8 @@ bool AbstractMetaBuilder::build(QIODevice* input)
ReportHandler::flush();

// We need to know all global enums
QHash<QString, EnumModelItem> enumMap = m_dom->enumMap();
ReportHandler::setProgressReference(enumMap);
foreach (EnumModelItem item, enumMap) {
ReportHandler::setProgressReference(m_dom->enumMap());
foreach (EnumModelItem item, m_dom->enums()) {
ReportHandler::progress("Generating enum model...");
AbstractMetaEnum *metaEnum = traverseEnum(item, 0, QSet<QString>());
if (metaEnum) {
Expand Down Expand Up @@ -1501,26 +1500,33 @@ void AbstractMetaBuilder::traverseInstantiation(ComplexTypeEntry *entry, Abstrac

addRedirections(entry, metaClass, argClass, accessor);

// Make pointer wrappers dependent on the wrapped object, in order
// to ensure that the pointer comes after the underlying class in
// topological sorting
if (wrapsPointer
&& entry->templateType()->wrapsPointerArg() == ordinal
&& !argClass->baseClassName().isEmpty()) {
QStringList argList = parseTemplateType(metaClass->qualifiedCppName());
QString templateClass = argList.takeFirst();
argList[ordinal] = argClass->baseClass()->qualifiedCppName();
QString baseTemplateClass = QString("%1< %2 >").arg(templateClass).arg(argList.join(", "));

AbstractMetaClass* baseMetaClass = m_metaClasses.findClass(baseTemplateClass);

if (baseMetaClass) {
metaClass->setHasInjectedDependencies();
baseMetaClass->setHasInjectedDependencies();
if (!metaClass->baseClass())
metaClass->setBaseClass(baseMetaClass);
metaClass->addBaseClassName(baseTemplateClass);
} else {
QString warn = QString("want to inherit %1 from same class with arg %2 replaced with %3, but it is an unknown type.")
.arg(metaClass->name()).arg(ordinal).arg(argClass->baseClass()->qualifiedCppName());
ReportHandler::warning(warn);
&& entry->templateType()->wrapsPointerArg() == ordinal) {
metaClass->addExtraDependency(argClass->qualifiedCppName());

// In case of a single template argument, make the pointer to
// base class a dependent of this pointer; needed for
// downcasting to work
if (argTypes.count() == 1 && !argClass->baseClassName().isEmpty()) {
QStringList argList = parseTemplateType(metaClass->qualifiedCppName());
QString templateClass = argList.takeFirst();
argList[ordinal] = argClass->baseClass()->qualifiedCppName();
QString baseTemplateClass = QString("%1< %2 >").arg(templateClass).arg(argList.join(", "));

AbstractMetaClass* baseMetaClass = m_metaClasses.findClass(baseTemplateClass);

if (baseMetaClass) {
if (!metaClass->baseClass())
metaClass->setBaseClass(baseMetaClass);
metaClass->addBaseClassName(baseTemplateClass);
} else {
QString warn = QString("want to inherit %1 from same class with arg %2 replaced with %3, but it is an unknown type.")
.arg(metaClass->name()).arg(ordinal).arg(argClass->baseClass()->qualifiedCppName());
ReportHandler::warning(warn);
}
}
}
}
Expand Down Expand Up @@ -2791,20 +2797,30 @@ AbstractMetaClass* AbstractMetaBuilder::findTemplateClass(const QString& name, c
return 0;
}

AbstractMetaClassList AbstractMetaBuilder::getBaseClasses(const AbstractMetaClass* metaClass, bool useTemplate) const
AbstractMetaClassList AbstractMetaBuilder::resolveClassDependencies(const AbstractMetaClass* metaClass,
const QStringList &names) const
{
AbstractMetaClassList baseClasses;
foreach (const QString& parent, metaClass->baseClassNames()) {
AbstractMetaClass* cls = 0;
if (useTemplate && parent.contains('<'))
AbstractMetaClassList dependencies;
foreach (const QString& parent, names) {
AbstractMetaClass* cls = m_metaClasses.findClass(parent);

if (!cls && parent.contains('<'))
cls = findTemplateClass(parent, metaClass);
else
cls = m_metaClasses.findClass(parent);

if (cls)
baseClasses << cls;
dependencies << cls;
}
return baseClasses;
return dependencies;
}

AbstractMetaClassList AbstractMetaBuilder::getBaseClasses(const AbstractMetaClass* metaClass) const
{
return resolveClassDependencies(metaClass, metaClass->baseClassNames());
}

AbstractMetaClassList AbstractMetaBuilder::getExtraDependencyClasses(const AbstractMetaClass* metaClass) const
{
return resolveClassDependencies(metaClass, metaClass->extraDependencies());
}

bool AbstractMetaBuilder::ancestorHasPrivateCopyConstructor(const AbstractMetaClass* metaClass) const
Expand Down Expand Up @@ -3213,14 +3229,10 @@ AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted(const Abstra
QRegExp regex1("\\(.*\\)");
QRegExp regex2("::.*");
foreach (AbstractMetaClass* clazz, classList) {
if (!clazz->hasInjectedDependencies() &&
(clazz->isInterface() || !clazz->typeEntry()->generateCode()))
continue;

if (clazz->enclosingClass() && map.contains(clazz->enclosingClass()->qualifiedCppName()))
graph.addEdge(map[clazz->enclosingClass()->qualifiedCppName()], map[clazz->qualifiedCppName()]);

AbstractMetaClassList bases = getBaseClasses(clazz, false);
AbstractMetaClassList bases = getBaseClasses(clazz);
foreach(AbstractMetaClass* baseClass, bases) {
// Fix polymorphic expression
if (clazz->baseClass() == baseClass)
Expand All @@ -3230,6 +3242,12 @@ AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted(const Abstra
graph.addEdge(map[baseClass->qualifiedCppName()], map[clazz->qualifiedCppName()]);
}

AbstractMetaClassList extraDeps = getExtraDependencyClasses(clazz);
foreach(AbstractMetaClass* dependencyClass, extraDeps) {
if (map.contains(dependencyClass->qualifiedCppName()))
graph.addEdge(map[dependencyClass->qualifiedCppName()], map[clazz->qualifiedCppName()]);
}

foreach (AbstractMetaFunction* func, clazz->functions()) {
foreach (AbstractMetaArgument* arg, func->arguments()) {
// check methods with default args
Expand Down
10 changes: 7 additions & 3 deletions ApiExtractor/abstractmetabuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
#include "typesystem.h"
#include "typeparser.h"

#include <QSet>
#include <QFileInfo>
#include <QtCore/QSet>
#include <QtCore/QFileInfo>

class TypeDatabase;

Expand Down Expand Up @@ -171,7 +171,8 @@ class AbstractMetaBuilder

AbstractMetaClass *findTemplateClass(const QString& name, const AbstractMetaClass *context,
TypeParser::Info *info = 0, ComplexTypeEntry **baseContainerType = 0) const;
AbstractMetaClassList getBaseClasses(const AbstractMetaClass* metaClass, bool useTemplate = true) const;
AbstractMetaClassList getBaseClasses(const AbstractMetaClass* metaClass) const;
AbstractMetaClassList getExtraDependencyClasses(const AbstractMetaClass* metaClass) const;
bool ancestorHasPrivateCopyConstructor(const AbstractMetaClass* metaClass) const;

bool inheritTemplate(AbstractMetaClass *subclass,
Expand Down Expand Up @@ -244,6 +245,9 @@ class AbstractMetaBuilder
void fixArgumentNames(AbstractMetaFunction* func);
void fillAddedFunctions(AbstractMetaClass* metaClass);

AbstractMetaClassList resolveClassDependencies(const AbstractMetaClass* metaClass,
const QStringList &names) const;

AbstractMetaClassList m_metaClasses;
AbstractMetaClassList m_templates;
AbstractMetaFunctionList m_globalFunctions;
Expand Down
33 changes: 19 additions & 14 deletions ApiExtractor/abstractmetalang.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#include <QtCore/QSet>
#include <QtCore/QStringList>
#include <QtCore/QTextStream>
#include <QSharedPointer>
#include <QtCore/QSharedPointer>


class AbstractMeta;
Expand Down Expand Up @@ -1429,7 +1429,7 @@ class AbstractMetaClass : public AbstractMetaAttributes
m_primaryInterfaceImplementor(0),
m_typeEntry(0),
m_stream(false),
m_hasInjectedDependencies(false)
m_hasDependents(false)
{
}

Expand Down Expand Up @@ -1701,20 +1701,24 @@ class AbstractMetaClass : public AbstractMetaAttributes
*/
bool hasProtectedMembers() const;

/**
* Tells if this class has dependencies injected by the metabuilder.
* \return true if the class has injected dependencies.
*/
bool hasInjectedDependencies() const
bool hasDependents() const
{
return m_hasInjectedDependencies;
return m_hasDependents;
}
/**
* Tell the metaclass that it has injected dependencies.
*/
void setHasInjectedDependencies()

void setHasDependents(bool value)
{
m_hasDependents = value;
}

QStringList extraDependencies() const
{
return m_extraDependencies;
}

void addExtraDependency(const QString &name)
{
m_hasInjectedDependencies = true;
m_extraDependencies.append(name);
}

QList<TypeEntry *> templateArguments() const
Expand Down Expand Up @@ -1982,12 +1986,13 @@ class AbstractMetaClass : public AbstractMetaAttributes
AbstractMetaFunctionList m_externalConversionOperators;

QStringList m_baseClassNames;
QStringList m_extraDependencies;
QList<TypeEntry *> m_templateArgs;
ComplexTypeEntry *m_typeEntry;
// FunctionModelItem m_qDebugStreamFunction;

bool m_stream;
bool m_hasInjectedDependencies;
bool m_hasDependents;
static int m_count;
};

Expand Down
8 changes: 4 additions & 4 deletions ApiExtractor/apiextractor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
*/

#include "apiextractor.h"
#include <QDir>
#include <QDebug>
#include <QTemporaryFile>
#include <QtCore/QDir>
#include <QtCore/QDebug>
#include <QtCore/QTemporaryFile>
#include <iostream>

#include "reporthandler.h"
Expand Down Expand Up @@ -276,7 +276,7 @@ static bool preprocess(const QString& sourceFile,

preprocess.push_include_path(".");
foreach (QString include, includes)
preprocess.push_include_path(QDir::convertSeparators(include).toStdString());
preprocess.push_include_path(QDir::toNativeSeparators(include).toStdString());
preprocess.push_include_path("/usr/include");

QString currentDir = QDir::current().absolutePath();
Expand Down
2 changes: 1 addition & 1 deletion ApiExtractor/apiextractor.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#include "reporthandler.h"
#include "abstractmetalang.h"
#include "apiextractormacros.h"
#include <QStringList>
#include <QtCore/QStringList>

class AbstractMetaBuilder;
class QIODevice;
Expand Down
2 changes: 1 addition & 1 deletion ApiExtractor/docparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#include "docparser.h"
#include <QtCore/QDebug>
#include <QtXmlPatterns/QXmlQuery>
#include <QBuffer>
#include <QtCore/QBuffer>

#include <cstdlib>
#include <libxslt/xsltutils.h>
Expand Down
4 changes: 2 additions & 2 deletions ApiExtractor/docparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
#ifndef DOCPARSER_H
#define DOCPARSER_H

#include <QString>
#include <QDir>
#include <QtCore/QString>
#include <QtCore/QDir>

#include "abstractmetalang.h"

Expand Down
1 change: 0 additions & 1 deletion ApiExtractor/fileout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,6 @@ bool FileOut::done()
.arg(fileWrite.fileName()));
return false;
}
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
stream.setDevice(&fileWrite);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Be very careful if you remove this that you make sure every call to QString::toAscii that could be called after this executes is replaced with toUtf8 and _not_ toLatin1, or you will break things massively in the face of non-ASCII strings.

stream << tmp;
}
Expand Down
10 changes: 5 additions & 5 deletions ApiExtractor/graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@
*/

#include "graph.h"
#include <QVector>
#include <QDebug>
#include <QLinkedList>
#include <QSet>
#include <QtCore/QVector>
#include <QtCore/QDebug>
#include <QtCore/QLinkedList>
#include <QtCore/QSet>
#include <iterator>
#include <algorithm>
#include <iostream>
#include <QFile>
#include <QtCore/QFile>

struct Graph::GraphPrivate
{
Expand Down
6 changes: 3 additions & 3 deletions ApiExtractor/graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
#ifndef GRAPH_H
#define GRAPH_H

#include <QLinkedList>
#include <QHash>
#include <QString>
#include <QtCore/QLinkedList>
#include <QtCore/QHash>
#include <QtCore/QString>

/// A graph that can have their nodes topologically sorted.
class Graph
Expand Down
Loading