aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/ApiExtractor
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken2/ApiExtractor')
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp300
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.h12
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h31
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.cpp105
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.h38
-rw-r--r--sources/shiboken2/ApiExtractor/apiextractor.cpp4
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp188
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp2
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp49
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangutils.h13
-rw-r--r--sources/shiboken2/ApiExtractor/doc/conf.py.in4
-rw-r--r--sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst20
-rw-r--r--sources/shiboken2/ApiExtractor/docparser.cpp17
-rw-r--r--sources/shiboken2/ApiExtractor/doxygenparser.cpp28
-rw-r--r--sources/shiboken2/ApiExtractor/fileout.cpp151
-rw-r--r--sources/shiboken2/ApiExtractor/fileout.h8
-rw-r--r--sources/shiboken2/ApiExtractor/include.cpp5
-rw-r--r--sources/shiboken2/ApiExtractor/include.h3
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.cpp173
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.h43
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel_enums.h6
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp31
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testabstractmetatype.h2
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testtyperevision.cpp15
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testutil.h3
-rw-r--r--sources/shiboken2/ApiExtractor/typedatabase.cpp167
-rw-r--r--sources/shiboken2/ApiExtractor/typedatabase.h3
-rw-r--r--sources/shiboken2/ApiExtractor/typeparser.cpp57
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.cpp3357
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.h104
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem_enums.h6
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem_p.h95
32 files changed, 2944 insertions, 2096 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
index 84c116708..4aa5d72dd 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
@@ -241,7 +241,7 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications()
}
}
-AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(ArgumentModelItem argument)
+AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(const ArgumentModelItem &argument)
{
AbstractMetaClass* returned = 0;
AbstractMetaType *type = translateType(argument->type());
@@ -256,7 +256,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(ArgumentModelItem
/**
* Checks the argument of a hash function and flags the type if it is a complex type
*/
-void AbstractMetaBuilderPrivate::registerHashFunction(FunctionModelItem function_item)
+void AbstractMetaBuilderPrivate::registerHashFunction(const FunctionModelItem &function_item)
{
ArgumentList arguments = function_item->arguments();
if (arguments.size() == 1) {
@@ -269,12 +269,12 @@ void AbstractMetaBuilderPrivate::registerHashFunction(FunctionModelItem function
* Check if a class has a debug stream operator that can be used as toString
*/
-void AbstractMetaBuilderPrivate::registerToStringCapability(FunctionModelItem function_item)
+void AbstractMetaBuilderPrivate::registerToStringCapability(const FunctionModelItem &function_item)
{
ArgumentList arguments = function_item->arguments();
if (arguments.size() == 2) {
if (arguments.at(0)->type().toString() == QLatin1String("QDebug")) {
- ArgumentModelItem arg = arguments.at(1);
+ const ArgumentModelItem &arg = arguments.at(1);
if (AbstractMetaClass *cls = argumentToClass(arg)) {
if (arg->type().indirections() < 2)
cls->setToStringCapability(true);
@@ -283,7 +283,7 @@ void AbstractMetaBuilderPrivate::registerToStringCapability(FunctionModelItem fu
}
}
-void AbstractMetaBuilderPrivate::traverseOperatorFunction(FunctionModelItem item)
+void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelItem &item)
{
if (item->accessPolicy() != CodeModel::Public)
return;
@@ -348,7 +348,7 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(FunctionModelItem item
setupFunctionDefaults(metaFunction, baseoperandClass);
baseoperandClass->addFunction(metaFunction);
Q_ASSERT(!metaFunction->wasPrivate());
- } else if (metaFunction) {
+ } else {
delete metaFunction;
}
@@ -356,7 +356,7 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(FunctionModelItem item
}
}
-void AbstractMetaBuilderPrivate::traverseStreamOperator(FunctionModelItem item)
+void AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem &item)
{
ArgumentList arguments = item->arguments();
if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
@@ -404,7 +404,7 @@ void AbstractMetaBuilderPrivate::traverseStreamOperator(FunctionModelItem item)
funcClass->typeEntry()->addExtraInclude(streamClass->typeEntry()->include());
m_currentClass = oldCurrentClass;
- } else if (streamFunction) {
+ } else {
delete streamFunction;
}
@@ -422,7 +422,7 @@ void AbstractMetaBuilderPrivate::fixQObjectForScope(const FileModelItem &dom,
TypeEntry* entry = types->findType(qualifiedName);
if (entry) {
if (isQObject(dom, qualifiedName) && entry->isComplex())
- ((ComplexTypeEntry*) entry)->setQObject(true);
+ static_cast<ComplexTypeEntry *>(entry)->setQObject(true);
}
}
@@ -616,7 +616,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
}
}
} else if (entry->isEnum() && (entry->generateCode() & TypeEntry::GenerateTargetLang)) {
- const QString name = ((EnumTypeEntry*) entry)->targetLangQualifier();
+ const QString name = static_cast<const EnumTypeEntry *>(entry)->targetLangQualifier();
AbstractMetaClass *cls = AbstractMetaClass::findClass(m_metaClasses, name);
bool enumFound = false;
@@ -848,7 +848,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel
return metaClass;
}
-AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumItem,
+AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem &enumItem,
AbstractMetaClass *enclosing,
const QSet<QString> &enumsDeclarations)
{
@@ -857,7 +857,7 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumIte
TypeEntry* typeEntry = 0;
if (enumItem->accessPolicy() == CodeModel::Private) {
QStringList names = enumItem->qualifiedName();
- QString enumName = names.constLast();
+ const QString &enumName = names.constLast();
QString nspace;
if (names.size() > 1)
nspace = QStringList(names.mid(0, names.size() - 1)).join(colonColon());
@@ -1014,7 +1014,7 @@ AbstractMetaClass* AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelIt
AbstractMetaClass *metaClass = new AbstractMetaClass;
metaClass->setTypeDef(true);
metaClass->setTypeEntry(type);
- metaClass->setBaseClassNames(QStringList() << typeDef->type().qualifiedName().join(colonColon()));
+ metaClass->setBaseClassNames(QStringList(typeDef->type().toString()));
*metaClass += AbstractMetaAttributes::Public;
// Set the default include file name
@@ -1204,18 +1204,18 @@ void AbstractMetaBuilderPrivate::traverseNamespaceMembers(NamespaceModelItem ite
m_currentClass = oldCurrentClass;
}
-static inline QString fieldSignatureWithType(VariableModelItem field)
+static inline QString fieldSignatureWithType(const VariableModelItem &field)
{
return field->name() + QStringLiteral(" -> ") + field->type().toString();
}
static inline QString qualifiedFieldSignatureWithType(const QString &className,
- VariableModelItem field)
+ const VariableModelItem &field)
{
return className + colonColon() + fieldSignatureWithType(field);
}
-AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(VariableModelItem field,
+AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(const VariableModelItem &field,
const AbstractMetaClass *cls)
{
QString fieldName = field->name();
@@ -1272,7 +1272,7 @@ AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(VariableModelItem f
return metaField;
}
-void AbstractMetaBuilderPrivate::traverseFields(ScopeModelItem scope_item,
+void AbstractMetaBuilderPrivate::traverseFields(const ScopeModelItem &scope_item,
AbstractMetaClass *metaClass)
{
const VariableList &variables = scope_item->variables();
@@ -1327,14 +1327,8 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaF
static bool _compareAbstractMetaTypes(const AbstractMetaType* type, const AbstractMetaType* other)
{
- if (!type && !other)
- return true;
- if (!type || !other)
- return false;
- return type->typeEntry() == other->typeEntry()
- && type->isConstant() == other->isConstant()
- && type->referenceType() == other->referenceType()
- && type->indirections() == other->indirections();
+ return (type != nullptr) == (other != nullptr)
+ && (type == nullptr || *type == *other);
}
static bool _compareAbstractMetaFunctions(const AbstractMetaFunction* func, const AbstractMetaFunction* other)
@@ -1426,7 +1420,7 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
}
} else if (QPropertySpec* reset = metaClass->propertySpecForReset(metaFunction->name())) {
// Property resetter must be in the form "void name()"
- if ((!metaFunction->type()) && (metaFunction->arguments().size() == 0)) {
+ if ((!metaFunction->type()) && metaFunction->arguments().isEmpty()) {
*metaFunction += AbstractMetaAttributes::PropertyResetter;
metaFunction->setPropertySpec(reset);
}
@@ -1635,7 +1629,7 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass)
return true;
}
-void AbstractMetaBuilderPrivate::traverseEnums(ScopeModelItem scopeItem,
+void AbstractMetaBuilderPrivate::traverseEnums(const ScopeModelItem &scopeItem,
AbstractMetaClass *metaClass,
const QStringList &enumsDeclarations)
{
@@ -1724,10 +1718,9 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu
replacedExpression = metaFunction->replacedDefaultExpression(m_currentClass, i + 1);
if (!replacedExpression.isEmpty()) {
- QString expr = replacedExpression;
if (!metaFunction->removedDefaultExpression(m_currentClass, i + 1)) {
- metaArg->setDefaultValueExpression(expr);
- metaArg->setOriginalDefaultValueExpression(expr);
+ metaArg->setDefaultValueExpression(replacedExpression);
+ metaArg->setOriginalDefaultValueExpression(replacedExpression);
if (metaArg->type()->isEnum() || metaArg->type()->isFlags())
m_enumDefaultArguments << QPair<AbstractMetaArgument*, AbstractMetaFunction*>(metaArg, metaFunction);
@@ -1784,7 +1777,7 @@ void AbstractMetaBuilderPrivate::fixArgumentNames(AbstractMetaFunction *func, co
}
}
-static QString functionSignature(FunctionModelItem functionItem)
+static QString functionSignature(const FunctionModelItem &functionItem)
{
QStringList args;
const ArgumentList &arguments = functionItem->arguments();
@@ -1803,7 +1796,8 @@ static inline QString qualifiedFunctionSignatureWithType(const FunctionModelItem
return result;
}
-static inline QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n)
+static inline QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n,
+ const QString &why)
{
QString result;
QTextStream str(&result);
@@ -1811,23 +1805,16 @@ static inline QString msgUnmatchedParameterType(const ArgumentModelItem &arg, in
<< (n + 1);
if (!arg->name().isEmpty())
str << " \"" << arg->name() << '"';
+ str << ": " << why;
return result;
}
-static inline QString msgUnmatchedReturnType(const FunctionModelItem &functionItem)
+static inline QString msgUnmatchedReturnType(const FunctionModelItem &functionItem,
+ const QString &why)
{
return QLatin1String("unmatched return type '")
- + functionItem->type().toString() + QLatin1Char('\'');
-}
-
-static inline QString msgVoidParameterType(const ArgumentModelItem &arg, int n)
-{
- QString result;
- QTextStream str(&result);
- str << "'void' encountered at parameter #" << (n + 1);
- if (!arg->name().isEmpty())
- str << " \"" << arg->name() << '"';
- return result;
+ + functionItem->type().toString()
+ + QLatin1String("': ") + why;
}
static QString msgSkippingFunction(const FunctionModelItem &functionItem,
@@ -1911,7 +1898,7 @@ bool AbstractMetaBuilderPrivate::setArrayArgumentType(AbstractMetaFunction *func
return true;
}
-AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModelItem functionItem)
+AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const FunctionModelItem &functionItem)
{
if (functionItem->isDeleted() || !functionItem->templateParameters().isEmpty())
return nullptr;
@@ -1936,13 +1923,16 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
QString rejectReason;
if (TypeDatabase::instance()->isFunctionRejected(className, functionName, &rejectReason)) {
m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
- return 0;
- }
- else if (TypeDatabase::instance()->isFunctionRejected(className,
- functionSignature(functionItem), &rejectReason)) {
- m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
- return 0;
+ return nullptr;
}
+ const QString &signature = functionSignature(functionItem);
+ const bool rejected =
+ TypeDatabase::instance()->isFunctionRejected(className, signature, &rejectReason);
+ qCDebug(lcShiboken).nospace().noquote() << __FUNCTION__
+ << ": Checking rejection for signature \"" << signature << "\" for " << className
+ << ": " << rejected;
+ if (rejected)
+ return nullptr;
if (functionItem->isFriend())
return 0;
@@ -1987,6 +1977,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
else
*metaFunction += AbstractMetaAttributes::Protected;
+ QString errorMessage;
switch (metaFunction->functionType()) {
case AbstractMetaFunction::DestructorFunction:
break;
@@ -2005,9 +1996,9 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
AbstractMetaType *type = nullptr;
if (!returnType.isVoid()) {
- type = translateType(returnType);
+ type = translateType(returnType, true, &errorMessage);
if (!type) {
- const QString reason = msgUnmatchedReturnType(functionItem);
+ const QString reason = msgUnmatchedReturnType(functionItem, errorMessage);
qCWarning(lcShiboken, "%s",
qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason)));
m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn, AbstractMetaBuilder::UnmatchedReturnType);
@@ -2033,7 +2024,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
AbstractMetaArgumentList metaArguments;
for (int i = 0; i < arguments.size(); ++i) {
- ArgumentModelItem arg = arguments.at(i);
+ const ArgumentModelItem &arg = arguments.at(i);
if (TypeDatabase::instance()->isArgumentTypeRejected(className, arg->type().toString(), &rejectReason)) {
m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
@@ -2041,7 +2032,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
return nullptr;
}
- AbstractMetaType *metaType = translateType(arg->type());
+ AbstractMetaType *metaType = translateType(arg->type(), true, &errorMessage);
if (!metaType) {
// If an invalid argument has a default value, simply remove it
if (arg->defaultValue()) {
@@ -2058,18 +2049,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
break;
}
Q_ASSERT(metaType == 0);
- const QString reason = msgUnmatchedParameterType(arg, i);
- qCWarning(lcShiboken, "%s",
- qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason)));
- const QString rejectedFunctionSignature = originalQualifiedSignatureWithReturn
- + QLatin1String(": ") + reason;
- m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::UnmatchedArgumentType);
- delete metaFunction;
- return nullptr;
- }
-
- if (metaType == Q_NULLPTR) {
- const QString reason = msgVoidParameterType(arg, i);
+ const QString reason = msgUnmatchedParameterType(arg, i, errorMessage);
qCWarning(lcShiboken, "%s",
qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason)));
const QString rejectedFunctionSignature = originalQualifiedSignatureWithReturn
@@ -2091,7 +2071,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
// Find the correct default values
for (int i = 0, size = metaArguments.size(); i < size; ++i) {
- ArgumentModelItem arg = arguments.at(i);
+ const ArgumentModelItem &arg = arguments.at(i);
AbstractMetaArgument* metaArg = metaArguments.at(i);
//use relace-default-expression for set default value
@@ -2211,15 +2191,17 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const AddedFunction:
QString msg = QStringLiteral("Type '%1' wasn't found in the type database.\n").arg(typeName);
- if (candidates.isEmpty())
- qFatal(qPrintable(QString(msg + QLatin1String("Declare it in the type system using the proper <*-type> tag."))), NULL);
+ if (candidates.isEmpty()) {
+ qFatal("%sDeclare it in the type system using the proper <*-type> tag.",
+ qPrintable(msg));
+ }
msg += QLatin1String("Remember to inform the full qualified name for the type you want to use.\nCandidates are:\n");
candidates.sort();
for (const QString& candidate : qAsConst(candidates)) {
msg += QLatin1String(" ") + candidate + QLatin1Char('\n');
}
- qFatal(qPrintable(msg), NULL);
+ qFatal("%s", qPrintable(msg));
}
AbstractMetaType *metaType = new AbstractMetaType;
@@ -2243,51 +2225,83 @@ static const TypeEntry* findTypeEntryUsingContext(const AbstractMetaClass* metaC
{
const TypeEntry* type = 0;
QStringList context = metaClass->qualifiedCppName().split(colonColon());
- while(!type && (context.size() > 0) ) {
+ while (!type && !context.isEmpty()) {
type = TypeDatabase::instance()->findType(context.join(colonColon()) + colonColon() + qualifiedName);
context.removeLast();
}
return type;
}
+static QString msgUnableToTranslateType(const QString &t, const QString &why)
+{
+ return QLatin1String("Unable to translate type \"")
+ + t + QLatin1String("\": ") + why;
+}
+
+static inline QString msgUnableToTranslateType(const TypeInfo &typeInfo,
+ const QString &why)
+{
+ return msgUnableToTranslateType(typeInfo.toString(), why);
+}
+
+static inline QString msgCannotFindTypeEntry(const QString &t)
+{
+ return QLatin1String("Cannot find type entry for \"") + t + QLatin1String("\".");
+}
+
+static inline QString msgCannotTranslateTemplateArgument(int i,
+ const TypeInfo &typeInfo,
+ const QString &why)
+{
+ QString result;
+ QTextStream(&result) << "Unable to translate template argument "
+ << (i + 1) << typeInfo.toString() << ": " << why;
+ return result;
+}
+
AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei,
- bool resolveType)
+ bool resolveType,
+ QString *errorMessage)
+{
+ return translateTypeStatic(_typei, m_currentClass, this, resolveType, errorMessage);
+}
+
+AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo &_typei,
+ AbstractMetaClass *currentClass,
+ AbstractMetaBuilderPrivate *d,
+ bool resolveType,
+ QString *errorMessageIn)
{
// 1. Test the type info without resolving typedefs in case this is present in the
// type system
- TypeInfo typei;
if (resolveType) {
- if (AbstractMetaType *resolved = translateType(_typei, false))
+ if (AbstractMetaType *resolved = translateTypeStatic(_typei, currentClass, d, false, errorMessageIn))
return resolved;
}
- if (!resolveType) {
- typei = _typei;
- } else {
+ TypeInfo typeInfo = _typei;
+ if (resolveType) {
// Go through all parts of the current scope (including global namespace)
// to resolve typedefs. The parser does not properly resolve typedefs in
// the global scope when they are referenced from inside a namespace.
// This is a work around to fix this bug since fixing it in resolveType
// seemed non-trivial
- int i = m_scopes.size() - 1;
+ int i = d ? d->m_scopes.size() - 1 : -1;
while (i >= 0) {
- typei = TypeInfo::resolveType(_typei, m_scopes.at(i--));
- if (typei.qualifiedName().join(colonColon()) != _typei.qualifiedName().join(colonColon()))
+ typeInfo = TypeInfo::resolveType(_typei, d->m_scopes.at(i--));
+ if (typeInfo.qualifiedName().join(colonColon()) != _typei.qualifiedName().join(colonColon()))
break;
}
}
- if (typei.isFunctionPointer())
+ if (typeInfo.isFunctionPointer()) {
+ if (errorMessageIn)
+ *errorMessageIn = msgUnableToTranslateType(_typei, QLatin1String("Unsupported function pointer."));
return nullptr;
+ }
QString errorMessage;
- TypeInfo typeInfo = TypeParser::parse(typei.toString(), &errorMessage);
- if (typeInfo.qualifiedName().isEmpty()) {
- qWarning().noquote().nospace() << "Unable to translate type \"" << _typei.toString()
- << "\": " << errorMessage;
- return 0;
- }
// 2. Handle arrays.
// 2.1 Handle char arrays with unspecified size (aka "const char[]") as "const char*" with
@@ -2312,16 +2326,22 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ
if (!typeInfo.arrayElements().isEmpty() && !isConstCharStarCase) {
TypeInfo newInfo;
//newInfo.setArguments(typeInfo.arguments());
- newInfo.setIndirections(typeInfo.indirections());
+ newInfo.setIndirectionsV(typeInfo.indirectionsV());
newInfo.setConstant(typeInfo.isConstant());
+ newInfo.setVolatile(typeInfo.isVolatile());
newInfo.setFunctionPointer(typeInfo.isFunctionPointer());
newInfo.setQualifiedName(typeInfo.qualifiedName());
newInfo.setReferenceType(typeInfo.referenceType());
newInfo.setVolatile(typeInfo.isVolatile());
- AbstractMetaType *elementType = translateType(newInfo);
- if (!elementType)
+ AbstractMetaType *elementType = translateTypeStatic(newInfo, currentClass, d, true, &errorMessage);
+ if (!elementType) {
+ if (errorMessageIn) {
+ errorMessage.prepend(QLatin1String("Unable to translate array element: "));
+ *errorMessageIn = msgUnableToTranslateType(_typei, errorMessage);
+ }
return nullptr;
+ }
for (int i = typeInfo.arrayElements().size() - 1; i >= 0; --i) {
AbstractMetaType *arrayType = new AbstractMetaType;
@@ -2329,7 +2349,9 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ
const QString &arrayElement = typeInfo.arrayElements().at(i);
if (!arrayElement.isEmpty()) {
bool _ok;
- const qint64 elems = findOutValueFromString(arrayElement, _ok);
+ const qint64 elems = d
+ ? d->findOutValueFromString(arrayElement, _ok)
+ : arrayElement.toLongLong(&_ok, 0);
if (_ok)
arrayType->setArrayElementCount(int(elems));
}
@@ -2344,8 +2366,11 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ
QStringList qualifierList = typeInfo.qualifiedName();
if (qualifierList.isEmpty()) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("horribly broken type '%1'").arg(_typei.toString());
+ errorMessage = msgUnableToTranslateType(_typei, QLatin1String("horribly broken type"));
+ if (errorMessageIn)
+ *errorMessageIn = errorMessage;
+ else
+ qCWarning(lcShiboken,"%s", qPrintable(errorMessage));
return nullptr;
}
@@ -2353,19 +2378,21 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ
QString name = qualifierList.takeLast();
// 4. Special case QFlags (include instantiation in name)
- if (qualifiedName == QLatin1String("QFlags"))
+ if (qualifiedName == QLatin1String("QFlags")) {
qualifiedName = typeInfo.toString();
+ typeInfo.clearInstantiations();
+ }
const TypeEntry *type = 0;
// 5. Try to find the type
// 5.1 - Try first using the current scope
- if (m_currentClass) {
- type = findTypeEntryUsingContext(m_currentClass, qualifiedName);
+ if (currentClass) {
+ type = findTypeEntryUsingContext(currentClass, qualifiedName);
// 5.1.1 - Try using the class parents' scopes
- if (!type && !m_currentClass->baseClassNames().isEmpty()) {
- const AbstractMetaClassList &baseClasses = getBaseClasses(m_currentClass);
+ if (!type && d && !currentClass->baseClassNames().isEmpty()) {
+ const AbstractMetaClassList &baseClasses = d->getBaseClasses(currentClass);
for (const AbstractMetaClass *cls : baseClasses) {
type = findTypeEntryUsingContext(cls, qualifiedName);
if (type)
@@ -2388,36 +2415,44 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ
// 8. No? Check if the current class is a template and this type is one
// of the parameters.
- if (!type && m_currentClass) {
- const QVector<TypeEntry *> &template_args = m_currentClass->templateArguments();
+ if (!type && currentClass) {
+ const QVector<TypeEntry *> &template_args = currentClass->templateArguments();
for (TypeEntry *te : template_args) {
if (te->name() == qualifiedName)
type = te;
}
}
- if (!type)
+ if (!type) {
+ if (errorMessageIn) {
+ *errorMessageIn =
+ msgUnableToTranslateType(_typei, msgCannotFindTypeEntry(qualifiedName));
+ }
return nullptr;
+ }
// Used to for diagnostics later...
- m_usedTypes << type;
+ if (d)
+ d->m_usedTypes << type;
// These are only implicit and should not appear in code...
Q_ASSERT(!type->isInterface());
AbstractMetaType *metaType = new AbstractMetaType;
metaType->setTypeEntry(type);
- metaType->setIndirections(typeInfo.indirections());
+ metaType->setIndirectionsV(typeInfo.indirectionsV());
metaType->setReferenceType(typeInfo.referenceType());
metaType->setConstant(typeInfo.isConstant());
+ metaType->setVolatile(typeInfo.isVolatile());
metaType->setOriginalTypeDescription(_typei.toString());
- const auto &templateArguments = typeInfo.arguments();
+ const auto &templateArguments = typeInfo.instantiations();
for (int t = 0, size = templateArguments.size(); t < size; ++t) {
- TypeInfo ti = templateArguments.at(t);
- ti.setQualifiedName(ti.instantiationName());
- AbstractMetaType *targType = translateType(ti);
+ const TypeInfo &ti = templateArguments.at(t);
+ AbstractMetaType *targType = translateTypeStatic(ti, currentClass, d, true, &errorMessage);
if (!targType) {
+ if (errorMessageIn)
+ *errorMessageIn = msgCannotTranslateTemplateArgument(t, ti, errorMessage);
delete metaType;
return nullptr;
}
@@ -2434,6 +2469,33 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ
return metaType;
}
+AbstractMetaType *AbstractMetaBuilder::translateType(const TypeInfo &_typei,
+ AbstractMetaClass *currentClass,
+ bool resolveType,
+ QString *errorMessage)
+{
+ return AbstractMetaBuilderPrivate::translateTypeStatic(_typei, currentClass,
+ nullptr, resolveType,
+ errorMessage);
+}
+
+AbstractMetaType *AbstractMetaBuilder::translateType(const QString &t,
+ AbstractMetaClass *currentClass,
+ bool resolveType,
+ QString *errorMessageIn)
+{
+ QString errorMessage;
+ TypeInfo typeInfo = TypeParser::parse(t, &errorMessage);
+ if (typeInfo.qualifiedName().isEmpty()) {
+ errorMessage = msgUnableToTranslateType(t, errorMessage);
+ if (errorMessageIn)
+ *errorMessageIn = errorMessage;
+ else
+ qCWarning(lcShiboken, "%s", qPrintable(errorMessage));
+ return nullptr;
+ }
+ return translateType(typeInfo, currentClass, resolveType, errorMessageIn);
+}
qint64 AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringValue, bool &ok)
{
@@ -2472,7 +2534,7 @@ qint64 AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringV
return 0;
}
-QString AbstractMetaBuilderPrivate::fixDefaultValue(ArgumentModelItem item,
+QString AbstractMetaBuilderPrivate::fixDefaultValue(const ArgumentModelItem &item,
AbstractMetaType *type,
AbstractMetaFunction *fnc,
AbstractMetaClass *implementingClass,
@@ -2728,7 +2790,7 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
const AbstractMetaClass *templateClass,
const TypeInfo &info)
{
- QVector<TypeInfo> targs = info.arguments();
+ QVector<TypeInfo> targs = info.instantiations();
QVector<AbstractMetaType *> templateTypes;
if (subclass->isTypeDef()) {
@@ -2764,13 +2826,13 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
temporaryType->setTypeEntry(t);
temporaryType->setConstant(i.isConstant());
temporaryType->setReferenceType(i.referenceType());
- temporaryType->setIndirections(i.indirections());
+ temporaryType->setIndirectionsV(i.indirectionsV());
temporaryType->decideUsagePattern();
templateTypes << temporaryType;
} else {
qCWarning(lcShiboken).noquote().nospace()
<< "Ignoring template parameter " << templateParamName << " from "
- << info.instantiationName() << ", because I don't know what it is.";
+ << info.toString() << ", because I don't know what it is.";
}
}
@@ -2827,13 +2889,9 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
// if the instantiation has a function named the same as an existing
// function we have shadowing so we need to skip it.
- bool found = false;
- for (int i = 0; i < funcs.size(); ++i) {
- if (funcs.at(i)->name() == f->name()) {
- found = true;
- continue;
- }
- }
+ const bool found =
+ std::any_of(funcs.cbegin(), funcs.cend(),
+ [f] (const AbstractMetaFunction *needle) { return needle->name() == f->name(); });
if (found) {
delete f;
continue;
@@ -2878,9 +2936,9 @@ void AbstractMetaBuilderPrivate::parseQ_Property(AbstractMetaClass *metaClass,
const QStringList &declarations)
{
for (int i = 0; i < declarations.size(); ++i) {
- QString p = declarations.at(i);
+ const QString &p = declarations.at(i);
- QStringList l = p.split(QLatin1String(" "));
+ QStringList l = p.split(QLatin1Char(' '));
QStringList qualifiedScopeName = currentScope()->qualifiedName();
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h
index a0ca71b94..bea2ac4c0 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.h
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h
@@ -38,7 +38,9 @@ QT_FORWARD_DECLARE_CLASS(QIODevice)
class AbstractMetaBuilderPrivate;
class AbstractMetaClass;
+class AbstractMetaType;
class AbstractMetaEnumValue;
+class TypeInfo;
class AbstractMetaBuilder
{
@@ -83,6 +85,16 @@ public:
*/
void setGlobalHeader(const QString& globalHeader);
+ static AbstractMetaType *translateType(const TypeInfo &_typei,
+ AbstractMetaClass *currentClass = nullptr,
+ bool resolveType = true,
+ QString *errorMessage = nullptr);
+ static AbstractMetaType *translateType(const QString &t,
+ AbstractMetaClass *currentClass = nullptr,
+ bool resolveType = true,
+ QString *errorMessage = nullptr);
+
+
#ifndef QT_NO_DEBUG_STREAM
void formatDebug(QDebug &d) const;
#endif
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h
index 59e3cfc94..7f4d222a3 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h
@@ -60,7 +60,7 @@ public:
ScopeModelItem currentScope() const { return m_scopes.constLast(); }
- AbstractMetaClass *argumentToClass(ArgumentModelItem);
+ AbstractMetaClass *argumentToClass(const ArgumentModelItem &);
void addAbstractMetaClass(AbstractMetaClass *cls);
AbstractMetaClass *traverseTypeDef(const FileModelItem &dom,
@@ -74,9 +74,9 @@ public:
bool setupInheritance(AbstractMetaClass *metaClass);
AbstractMetaClass *traverseNamespace(const FileModelItem &dom,
const NamespaceModelItem &item);
- AbstractMetaEnum *traverseEnum(EnumModelItem item, AbstractMetaClass *enclosing,
+ AbstractMetaEnum *traverseEnum(const EnumModelItem &item, AbstractMetaClass *enclosing,
const QSet<QString> &enumsDeclarations);
- void traverseEnums(ScopeModelItem item, AbstractMetaClass *parent,
+ void traverseEnums(const ScopeModelItem &item, AbstractMetaClass *parent,
const QStringList &enumsDeclarations);
AbstractMetaFunctionList classFunctionList(const ScopeModelItem &scopeItem,
bool *constructorRejected);
@@ -85,18 +85,18 @@ public:
bool *constructorRejected);
void traverseFunctions(ScopeModelItem item, AbstractMetaClass *parent);
void applyFunctionModifications(AbstractMetaFunction* func);
- void traverseFields(ScopeModelItem item, AbstractMetaClass *parent);
- void traverseStreamOperator(FunctionModelItem functionItem);
- void traverseOperatorFunction(FunctionModelItem item);
+ void traverseFields(const ScopeModelItem &item, AbstractMetaClass *parent);
+ void traverseStreamOperator(const FunctionModelItem &functionItem);
+ void traverseOperatorFunction(const FunctionModelItem &item);
AbstractMetaFunction* traverseFunction(const AddedFunction &addedFunc);
AbstractMetaFunction* traverseFunction(const AddedFunction &addedFunc,
AbstractMetaClass *metaClass);
- AbstractMetaFunction *traverseFunction(FunctionModelItem function);
- AbstractMetaField *traverseField(VariableModelItem field,
+ AbstractMetaFunction *traverseFunction(const FunctionModelItem &function);
+ AbstractMetaField *traverseField(const VariableModelItem &field,
const AbstractMetaClass *cls);
void checkFunctionModifications();
- void registerHashFunction(FunctionModelItem functionItem);
- void registerToStringCapability(FunctionModelItem functionItem);
+ void registerHashFunction(const FunctionModelItem &functionItem);
+ void registerToStringCapability(const FunctionModelItem &functionItem);
/**
* A conversion operator function should not have its owner class as
@@ -118,12 +118,19 @@ public:
void setupFunctionDefaults(AbstractMetaFunction *metaFunction,
AbstractMetaClass *metaClass);
- QString fixDefaultValue(ArgumentModelItem item, AbstractMetaType *type,
+ QString fixDefaultValue(const ArgumentModelItem &item, AbstractMetaType *type,
AbstractMetaFunction *fnc, AbstractMetaClass *,
int argumentIndex);
AbstractMetaType *translateType(const AddedFunction::TypeInfo &typeInfo);
AbstractMetaType *translateType(const TypeInfo &type,
- bool resolveType = true);
+ bool resolveType = true,
+ QString *errorMessage = nullptr);
+ static AbstractMetaType *translateTypeStatic(const TypeInfo &type,
+ AbstractMetaClass *current,
+ AbstractMetaBuilderPrivate *d = nullptr,
+ bool resolveType = true,
+ QString *errorMessageIn = nullptr);
+
qint64 findOutValueFromString(const QString &stringValue, bool &ok);
AbstractMetaClass *findTemplateClass(const QString& name, const AbstractMetaClass *context,
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
index 5be7050bf..de7182c71 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
@@ -31,6 +31,8 @@
#include "typedatabase.h"
#include "typesystem.h"
+#include <parser/codemodel.h>
+
#ifndef QT_NO_DEBUG_STREAM
# include <QtCore/QMetaEnum>
# include <QtCore/QMetaObject>
@@ -112,8 +114,8 @@ void AbstractMetaAttributes::assignMetaAttributes(const AbstractMetaAttributes &
AbstractMetaType::AbstractMetaType() :
m_constant(false),
+ m_volatile(false),
m_cppInstantiation(true),
- m_indirections(0),
m_reserved(0)
{
}
@@ -155,8 +157,9 @@ AbstractMetaType *AbstractMetaType::copy() const
cpy->setTypeUsagePattern(typeUsagePattern());
cpy->setConstant(isConstant());
+ cpy->setVolatile(isVolatile());
cpy->setReferenceType(referenceType());
- cpy->setIndirections(indirections());
+ cpy->setIndirectionsV(indirectionsV());
cpy->setInstantiations(instantiations());
cpy->setArrayElementCount(arrayElementCount());
cpy->setOriginalTypeDescription(originalTypeDescription());
@@ -278,6 +281,26 @@ bool AbstractMetaType::hasTemplateChildren() const
return false;
}
+bool AbstractMetaType::equals(const AbstractMetaType &rhs) const
+{
+ if (m_typeEntry != rhs.m_typeEntry || m_constant != rhs.m_constant
+ || m_referenceType != rhs.m_referenceType
+ || m_indirections != rhs.m_indirections
+ || m_instantiations.size() != rhs.m_instantiations.size()
+ || m_arrayElementCount != rhs.m_arrayElementCount) {
+ return false;
+ }
+ if ((m_arrayElementType != nullptr) != (rhs.m_arrayElementType != nullptr)
+ || (m_arrayElementType != nullptr && !m_arrayElementType->equals(*rhs.m_arrayElementType))) {
+ return false;
+ }
+ for (int i = 0, size = m_instantiations.size(); i < size; ++i) {
+ if (!m_instantiations.at(i)->equals(*rhs.m_instantiations.at(i)))
+ return false;
+ }
+ return true;
+}
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const AbstractMetaType *at)
{
@@ -291,16 +314,32 @@ QDebug operator<<(QDebug d, const AbstractMetaType *at)
d << ", typeEntry=" << at->typeEntry() << ", signature=\""
<< at->cppSignature() << "\", pattern="
<< at->typeUsagePattern();
- if (at->indirections())
- d << ", indirections=" << at->indirections();
+ const auto indirections = at->indirectionsV();
+ if (!indirections.isEmpty()) {
+ d << ", indirections=";
+ for (auto i : indirections)
+ d << ' ' << TypeInfo::indirectionKeyword(i);
+ }
if (at->referenceType())
d << ", reftype=" << at->referenceType();
if (at->isConstant())
d << ", [const]";
+ if (at->isVolatile())
+ d << ", [volatile]";
if (at->isArray()) {
d << ", array of \"" << at->arrayElementType()->cppSignature()
<< "\", arrayElementCount=" << at->arrayElementCount();
}
+ const auto &instantiations = at->instantiations();
+ if (const int instantiationsSize = instantiations.size()) {
+ d << ", instantiations[" << instantiationsSize << "]=<";
+ for (int i = 0; i < instantiationsSize; ++i) {
+ if (i)
+ d << ", ";
+ d << instantiations.at(i);
+ }
+ }
+ d << '>';
}
} else {
d << '0';
@@ -504,18 +543,17 @@ QStringList AbstractMetaFunction::introspectionCompatibleSignatures(const QStrin
if (arguments.size() == resolvedArguments.size()) {
QString signature = name() + QLatin1Char('(') + resolvedArguments.join(QLatin1Char(',')) + QLatin1Char(')');
return QStringList(TypeDatabase::normalizedSignature(signature));
- } else {
- QStringList returned;
-
- AbstractMetaArgument *argument = arguments.at(resolvedArguments.size());
- QStringList minimalTypeSignature = argument->type()->minimalSignature().split(QLatin1String("::"));
- for (int i = 0; i < minimalTypeSignature.size(); ++i) {
- returned += introspectionCompatibleSignatures(QStringList(resolvedArguments)
- << QStringList(minimalTypeSignature.mid(minimalTypeSignature.size() - i - 1)).join(QLatin1String("::")));
- }
+ }
+ QStringList returned;
- return returned;
+ AbstractMetaArgument *argument = arguments.at(resolvedArguments.size());
+ QStringList minimalTypeSignature = argument->type()->minimalSignature().split(QLatin1String("::"));
+ for (int i = 0; i < minimalTypeSignature.size(); ++i) {
+ returned += introspectionCompatibleSignatures(QStringList(resolvedArguments)
+ << QStringList(minimalTypeSignature.mid(minimalTypeSignature.size() - i - 1)).join(QLatin1String("::")));
}
+
+ return returned;
}
QString AbstractMetaFunction::signature() const
@@ -809,8 +847,9 @@ FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaC
while (implementor) {
mods += implementor->typeEntry()->functionModifications(minimalSignature());
if ((implementor == implementor->baseClass()) ||
- (implementor == implementingClass() && (mods.size() > 0)))
+ (implementor == implementingClass() && !mods.isEmpty())) {
break;
+ }
const AbstractMetaClassList &interfaces = implementor->interfaces();
for (const AbstractMetaClass *interface : interfaces)
mods += this->modifications(interface);
@@ -873,14 +912,14 @@ bool AbstractMetaFunction::hasSignatureModifications() const
return false;
}
-bool AbstractMetaFunction::isConversionOperator(QString funcName)
+bool AbstractMetaFunction::isConversionOperator(const QString& funcName)
{
static const QRegularExpression opRegEx(QStringLiteral("^operator(?:\\s+(?:const|volatile))?\\s+(\\w+\\s*)&?$"));
Q_ASSERT(opRegEx.isValid());
return opRegEx.match(funcName).hasMatch();
}
-bool AbstractMetaFunction::isOperatorOverload(QString funcName)
+bool AbstractMetaFunction::isOperatorOverload(const QString& funcName)
{
if (isConversionOperator(funcName))
return true;
@@ -1723,7 +1762,7 @@ QDebug operator<<(QDebug d, const AbstractMetaEnum *ae)
bool AbstractMetaClass::hasConstructors() const
{
- return queryFunctions(Constructors).size();
+ return !queryFunctions(Constructors).isEmpty();
}
bool AbstractMetaClass::hasCopyConstructor() const
@@ -2002,8 +2041,8 @@ void AbstractMetaClass::fixFunctions()
{
if (m_functionsFixed)
return;
- else
- m_functionsFixed = true;
+
+ m_functionsFixed = true;
AbstractMetaClass *superClass = baseClass();
AbstractMetaFunctionList funcs = functions();
@@ -2046,8 +2085,7 @@ void AbstractMetaClass::fixFunctions()
// we generally don't care about private functions, but we have to get the ones that are
// virtual in case they override abstract functions.
bool add = (sf->isNormal() || sf->isSignal() || sf->isEmptyFunction());
- for (int fi = 0; fi < funcs.size(); ++fi) {
- AbstractMetaFunction *f = funcs.at(fi);
+ for (AbstractMetaFunction *f : funcs) {
if (f->isRemovedFromAllLanguages(f->implementingClass()))
continue;
@@ -2114,7 +2152,8 @@ void AbstractMetaClass::fixFunctions()
if (mod.isNonFinal()) {
hasNonFinalModifier = true;
break;
- } else if (mod.isPrivate()) {
+ }
+ if (mod.isPrivate()) {
isBaseImplPrivate = true;
break;
}
@@ -2222,6 +2261,8 @@ QString AbstractMetaType::formatSignature(bool minimal) const
QString result;
if (isConstant())
result += QLatin1String("const ");
+ if (isVolatile())
+ result += QLatin1String("volatile ");
if (isArray()) {
// Build nested array dimensions a[2][3] in correct order
result += m_arrayElementType->minimalSignature();
@@ -2245,10 +2286,10 @@ QString AbstractMetaType::formatSignature(bool minimal) const
result += QLatin1String(" >");
}
- if (!minimal && (m_indirections != 0 || m_referenceType != NoReference))
+ if (!minimal && (!m_indirections.isEmpty() || m_referenceType != NoReference))
result += QLatin1Char(' ');
- if (m_indirections)
- result += QString(m_indirections, QLatin1Char('*'));
+ for (Indirection i : m_indirections)
+ result += TypeInfo::indirectionKeyword(i);
switch (referenceType()) {
case NoReference:
break;
@@ -2406,6 +2447,18 @@ QDebug operator<<(QDebug d, const AbstractMetaClass *ac)
}
d << ')';
}
+ const auto &templateArguments = ac->templateArguments();
+ if (const int count = templateArguments.size()) {
+ d << ", templateArguments=[" << count << "](";
+ for (int i = 0; i < count; ++i) {
+ if (i)
+ d << ", ";
+ d << templateArguments.at(i);
+ }
+ d << ')';
+ }
+
+
} else {
d << '0';
}
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h
index d1a0fbf88..d84a82af3 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetalang.h
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h
@@ -288,6 +288,7 @@ class AbstractMetaType
{
Q_GADGET
public:
+ typedef QVector<Indirection> Indirections;
enum TypeUsagePattern {
InvalidPattern,
@@ -436,6 +437,9 @@ public:
m_constant = constant;
}
+ bool isVolatile() const { return m_volatile; }
+ void setVolatile(bool v) { m_volatile = v; }
+
bool isConstRef() const;
ReferenceType referenceType() const { return m_referenceType; }
@@ -443,16 +447,21 @@ public:
int actualIndirections() const
{
- return m_indirections + (m_referenceType == LValueReference ? 1 : 0);
- }
- int indirections() const
- {
- return m_indirections;
+ return m_indirections.size() + (m_referenceType == LValueReference ? 1 : 0);
}
+
+ Indirections indirectionsV() const { return m_indirections; }
+ void setIndirectionsV(const Indirections &i) { m_indirections = i; }
+ void clearIndirections() { m_indirections.clear(); }
+
+ // "Legacy"?
+ int indirections() const { return m_indirections.size(); }
void setIndirections(int indirections)
{
- m_indirections = indirections;
+ m_indirections = Indirections(indirections, Indirection::Pointer);
}
+ void addIndirection(Indirection i = Indirection::Pointer)
+ { m_indirections.append(i); }
void setArrayElementCount(int n)
{
@@ -527,6 +536,8 @@ public:
bool hasTemplateChildren() const;
+ bool equals(const AbstractMetaType &rhs) const;
+
private:
TypeUsagePattern determineUsagePattern() const;
QString formatSignature(bool minimal) const;
@@ -541,18 +552,25 @@ private:
int m_arrayElementCount = -1;
const AbstractMetaType *m_arrayElementType = nullptr;
const AbstractMetaType *m_originalTemplateType = nullptr;
+ Indirections m_indirections;
TypeUsagePattern m_pattern = InvalidPattern;
uint m_constant : 1;
+ uint m_volatile : 1;
uint m_cppInstantiation : 1;
- int m_indirections : 4;
- uint m_reserved : 26; // unused
+ uint m_reserved : 29; // unused
+
ReferenceType m_referenceType = NoReference;
AbstractMetaTypeList m_children;
Q_DISABLE_COPY(AbstractMetaType)
};
+inline bool operator==(const AbstractMetaType &t1, const AbstractMetaType &t2)
+{ return t1.equals(t2); }
+inline bool operator!=(const AbstractMetaType &t1, const AbstractMetaType &t2)
+{ return !t1.equals(t2); }
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const AbstractMetaType *at);
#endif
@@ -816,13 +834,13 @@ public:
return m_explicit;
}
- static bool isConversionOperator(QString funcName);
+ static bool isConversionOperator(const QString& funcName);
bool isConversionOperator() const
{
return isConversionOperator(originalName());
}
- static bool isOperatorOverload(QString funcName);
+ static bool isOperatorOverload(const QString& funcName);
bool isOperatorOverload() const
{
return isOperatorOverload(originalName());
diff --git a/sources/shiboken2/ApiExtractor/apiextractor.cpp b/sources/shiboken2/ApiExtractor/apiextractor.cpp
index 171011cd4..80ffc3910 100644
--- a/sources/shiboken2/ApiExtractor/apiextractor.cpp
+++ b/sources/shiboken2/ApiExtractor/apiextractor.cpp
@@ -194,9 +194,9 @@ const AbstractMetaEnum* ApiExtractor::findAbstractMetaEnum(const TypeEntry* type
if (!typeEntry)
return 0;
if (typeEntry->isFlags())
- return findAbstractMetaEnum(reinterpret_cast<const FlagsTypeEntry*>(typeEntry));
+ return findAbstractMetaEnum(static_cast<const FlagsTypeEntry*>(typeEntry));
if (typeEntry->isEnum())
- return findAbstractMetaEnum(reinterpret_cast<const EnumTypeEntry*>(typeEntry));
+ return findAbstractMetaEnum(static_cast<const EnumTypeEntry*>(typeEntry));
return 0;
}
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp
index af7f96068..1623e6a6e 100644
--- a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp
@@ -146,6 +146,7 @@ class BuilderPrivate {
public:
typedef QHash<CXCursor, ClassModelItem> CursorClassHash;
typedef QHash<CXCursor, TypeDefModelItem> CursorTypedefHash;
+ typedef QHash<CXType, TypeInfo> TypeInfoHash;
explicit BuilderPrivate(BaseVisitor *bv) : m_baseVisitor(bv), m_model(new CodeModel)
{
@@ -180,9 +181,14 @@ public:
CodeModel::FunctionType t = CodeModel::Normal) const;
FunctionModelItem createMemberFunction(const CXCursor &cursor) const;
void qualifyConstructor(const CXCursor &cursor);
+ TypeInfo createTypeInfoHelper(const CXType &type) const; // uncashed
TypeInfo createTypeInfo(const CXType &type) const;
TypeInfo createTypeInfo(const CXCursor &cursor) const
{ return createTypeInfo(clang_getCursorType(cursor)); }
+ void addTemplateInstantiations(const CXType &type,
+ QString *typeName,
+ TypeInfo *t) const;
+ bool addTemplateInstantiationsRecursion(const CXType &type, TypeInfo *t) const;
TemplateParameterModelItem createTemplateParameter(const CXCursor &cursor) const;
TemplateParameterModelItem createNonTypeTemplateParameter(const CXCursor &cursor) const;
@@ -205,6 +211,8 @@ public:
CursorClassHash m_cursorClassHash;
CursorTypedefHash m_cursorTypedefHash;
+ mutable TypeInfoHash m_typeInfoHash; // Cache type information
+
ClassModelItem m_currentClass;
EnumModelItem m_currentEnum;
FunctionModelItem m_currentFunction;
@@ -256,7 +264,7 @@ FunctionModelItem BuilderPrivate::createFunction(const CXCursor &cursor,
name = fixTypeName(name);
FunctionModelItem result(new _FunctionModelItem(m_model, name));
setFileName(cursor, result.data());
- result->setType(createTypeInfo(clang_getCursorResultType(cursor)));
+ result->setType(createTypeInfoHelper(clang_getCursorResultType(cursor)));
result->setFunctionType(t);
result->setScope(m_scope);
result->setStatic(clang_Cursor_getStorageClass(cursor) == CX_SC_Static);
@@ -335,7 +343,7 @@ TemplateParameterModelItem BuilderPrivate::createTemplateParameter(const CXCurso
TemplateParameterModelItem BuilderPrivate::createNonTypeTemplateParameter(const CXCursor &cursor) const
{
TemplateParameterModelItem result = createTemplateParameter(cursor);
- result->setType(createTypeInfo(cursor));
+ result->setType(createTypeInfoHelper(clang_getCursorType(cursor)));
return result;
}
@@ -359,38 +367,6 @@ struct ArrayDimensionResult
int position;
};
-static ArrayDimensionResult arrayDimensions(const QString &typeName)
-{
- ArrayDimensionResult result;
- result.position = typeName.indexOf(QLatin1Char('['));
- for (int openingPos = result.position; openingPos != -1; ) {
- const int closingPos = typeName.indexOf(QLatin1Char(']'), openingPos + 1);
- if (closingPos == -1)
- break;
- result.dimensions.append(typeName.midRef(openingPos + 1, closingPos - openingPos - 1));
- openingPos = typeName.indexOf(QLatin1Char('['), closingPos + 1);
- }
- return result;
-}
-
-// Array helpers: Parse "a[2][4]" into a list of dimensions or "" for none
-static QStringList parseArrayArgs(const CXType &type, QString *typeName)
-{
- const ArrayDimensionResult dimensions = arrayDimensions(*typeName);
- Q_ASSERT(!dimensions.dimensions.isEmpty());
-
- QStringList result;
- // get first dimension from clang, preferably.
- // "a[]" is seen as pointer by Clang, set special indicator ""
- const long long size = clang_getArraySize(type);
- result.append(size >= 0 ? QString::number(size) : QString());
- // Parse out remaining dimensions
- for (int i = 1, count = dimensions.dimensions.size(); i < count; ++i)
- result.append(dimensions.dimensions.at(i).toString());
- typeName->truncate(dimensions.position);
- return result;
-}
-
// Create qualified name "std::list<std::string>" -> ("std", "list<std::string>")
static QStringList qualifiedName(const QString &t)
{
@@ -412,71 +388,132 @@ static QStringList qualifiedName(const QString &t)
return result;
}
-TypeInfo BuilderPrivate::createTypeInfo(const CXType &type) const
+static bool isArrayType(CXTypeKind k)
+{
+ return k == CXType_ConstantArray || k == CXType_IncompleteArray
+ || k == CXType_VariableArray || k == CXType_DependentSizedArray;
+}
+
+static bool isPointerType(CXTypeKind k)
+{
+ return k == CXType_Pointer || k == CXType_LValueReference || k == CXType_RValueReference;
+}
+
+bool BuilderPrivate::addTemplateInstantiationsRecursion(const CXType &type, TypeInfo *t) const
+{
+ // Template arguments
+ switch (type.kind) {
+ case CXType_Elaborated:
+ case CXType_Record:
+ case CXType_Unexposed:
+ if (const int numTemplateArguments = qMax(0, clang_Type_getNumTemplateArguments(type))) {
+ for (unsigned tpl = 0; tpl < unsigned(numTemplateArguments); ++tpl) {
+ const CXType argType = clang_Type_getTemplateArgumentAsType(type, tpl);
+ // CXType_Invalid is returned when hitting on a specialization
+ // of a non-type template (template <int v>).
+ if (argType.kind == CXType_Invalid)
+ return false;
+ t->addInstantiation(createTypeInfoHelper(argType));
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+static void dummyTemplateArgumentHandler(int, const QStringRef &) {}
+
+void BuilderPrivate::addTemplateInstantiations(const CXType &type,
+ QString *typeName,
+ TypeInfo *t) const
+{
+ // In most cases, for templates like "Vector<A>", Clang will give us the
+ // arguments by recursing down the type. However this will fail for example
+ // within template classes (for functions like the copy constructor):
+ // template <class T>
+ // class Vector {
+ // Vector(const Vector&);
+ // };
+ // In that case, have TypeInfo parse the list from the spelling.
+ // Finally, remove the list "<>" from the type name.
+ const bool parsed = addTemplateInstantiationsRecursion(type, t)
+ && !t->instantiations().isEmpty();
+ const QPair<int, int> pos = parsed
+ ? parseTemplateArgumentList(*typeName, dummyTemplateArgumentHandler)
+ : t->parseTemplateArgumentList(*typeName);
+ if (pos.first != -1 && pos.second != -1 && pos.second > pos.first)
+ typeName->remove(pos.first, pos.second - pos.first);
+}
+
+TypeInfo BuilderPrivate::createTypeInfoHelper(const CXType &type) const
{
if (type.kind == CXType_Pointer) { // Check for function pointers, first.
const CXType pointeeType = clang_getPointeeType(type);
const int argCount = clang_getNumArgTypes(pointeeType);
if (argCount >= 0) {
- TypeInfo result = createTypeInfo(clang_getResultType(pointeeType));
+ TypeInfo result = createTypeInfoHelper(clang_getResultType(pointeeType));
result.setFunctionPointer(true);
for (int a = 0; a < argCount; ++a)
- result.addArgument(createTypeInfo(clang_getArgType(pointeeType, unsigned(a))));
+ result.addArgument(createTypeInfoHelper(clang_getArgType(pointeeType, unsigned(a))));
return result;
}
}
TypeInfo typeInfo;
- QString typeName = fixTypeName(getTypeName(type));
-
- int indirections = 0;
- // "int **"
- for ( ; typeName.endsWith(QLatin1Char('*')) ; ++indirections)
- typeName.chop(1);
- typeInfo.setIndirections(indirections);
- // "int &&"
- if (typeName.endsWith(QLatin1String("&&"))) {
- typeName.chop(2);
- typeInfo.setReferenceType(RValueReference);
- } else if (typeName.endsWith(QLatin1Char('&'))) { // "int &"
- typeName.chop(1);
- typeInfo.setReferenceType(LValueReference);
- }
- // "int [3], int[]"
- if (type.kind == CXType_ConstantArray || type.kind == CXType_IncompleteArray
- || type.kind == CXType_VariableArray || type.kind == CXType_DependentSizedArray) {
- typeInfo.setArrayElements(parseArrayArgs(type, &typeName));
+ CXType nestedType = type;
+ for (; isArrayType(nestedType.kind); nestedType = clang_getArrayElementType(nestedType)) {
+ const long long size = clang_getArraySize(nestedType);
+ typeInfo.addArrayElement(size >= 0 ? QString::number(size) : QString());
}
- bool isConstant = clang_isConstQualifiedType(type) != 0;
- // A "char *const" parameter, is considered to be const-qualified by Clang, but
- // not in the TypeInfo sense (corresponds to "char *" and not "const char *").
- if (type.kind == CXType_Pointer && isConstant && typeName.endsWith(QLatin1String("const"))) {
- typeName.chop(5);
- typeName = typeName.trimmed();
- isConstant = false;
- }
- // Clang has been observed to return false for "const int .."
- if (!isConstant && typeName.startsWith(QLatin1String("const "))) {
- typeName.remove(0, 6);
- isConstant = true;
+ TypeInfo::Indirections indirections;
+ for (; isPointerType(nestedType.kind); nestedType = clang_getPointeeType(nestedType)) {
+ switch (nestedType.kind) {
+ case CXType_Pointer:
+ indirections.prepend(clang_isConstQualifiedType(nestedType) != 0
+ ? Indirection::ConstPointer : Indirection::Pointer);
+ break;
+ case CXType_LValueReference:
+ typeInfo.setReferenceType(LValueReference);
+ break;
+ case CXType_RValueReference:
+ typeInfo.setReferenceType(RValueReference);
+ break;
+ default:
+ break;
+ }
}
- typeInfo.setConstant(isConstant);
+ typeInfo.setIndirectionsV(indirections);
- // clang_isVolatileQualifiedType() returns true for "volatile int", but not for "volatile int *"
- if (typeName.startsWith(QLatin1String("volatile "))) {
- typeName.remove(0, 9);
- typeInfo.setVolatile(true);
+ typeInfo.setConstant(clang_isConstQualifiedType(nestedType) != 0);
+ typeInfo.setVolatile(clang_isVolatileQualifiedType(nestedType) != 0);
+
+ QString typeName = getTypeName(nestedType);
+ while (TypeInfo::stripLeadingConst(&typeName)
+ || TypeInfo::stripLeadingVolatile(&typeName)) {
}
- typeName = typeName.trimmed();
+ // Obtain template instantiations if the name has '<' (thus excluding
+ // typedefs like "std::string".
+ if (typeName.contains(QLatin1Char('<')))
+ addTemplateInstantiations(nestedType, &typeName, &typeInfo);
typeInfo.setQualifiedName(qualifiedName(typeName));
// 3320:CINDEX_LINKAGE int clang_getNumArgTypes(CXType T); function ptr types?
return typeInfo;
}
+TypeInfo BuilderPrivate::createTypeInfo(const CXType &type) const
+{
+ TypeInfoHash::iterator it = m_typeInfoHash.find(type);
+ if (it == m_typeInfoHash.end())
+ it = m_typeInfoHash.insert(type, createTypeInfoHelper(type));
+ return it.value();
+}
+
// extract an expression from the cursor via source
// CXCursor_EnumConstantDecl, ParmDecl (a = Flag1 | Flag2)
QString BuilderPrivate::cursorValueExpression(BaseVisitor *bv, const CXCursor &cursor) const
@@ -795,9 +832,8 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor)
d->m_currentFunction = d->createMemberFunction(cursor);
d->m_scopeStack.back()->addFunction(d->m_currentFunction);
break;
- } else {
- return Skip; // inline member functions outside class
}
+ return Skip; // inline member functions outside class
}
}
Q_FALLTHROUGH(); // fall through to free template function.
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp
index ce0b6554d..e116f8b83 100644
--- a/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp
@@ -166,7 +166,7 @@ static inline const char **byteArrayListToFlatArgV(const QByteArrayList &bl)
return result;
}
-static QByteArray msgCreateTranslationUnit(const QByteArrayList clangArgs, unsigned flags)
+static QByteArray msgCreateTranslationUnit(const QByteArrayList &clangArgs, unsigned flags)
{
QByteArray result = "clang_parseTranslationUnit2(0x";
result += QByteArray::number(flags, 16);
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp
index 2ff18b23b..8bee28cdf 100644
--- a/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp
@@ -46,6 +46,18 @@ uint qHash(const CXCursor &c, uint seed)
^ qHash(c.data[1]) ^ qHash(c.data[2]) ^ seed;
}
+bool operator==(const CXType &t1, const CXType &t2)
+{
+ return t1.kind == t2.kind && t1.data[0] == t2.data[0]
+ && t1.data[1] == t2.data[1];
+}
+
+uint qHash(const CXType &ct, uint seed)
+{
+ return uint(ct.kind) ^ uint(0xFFFFFFFF & quintptr(ct.data[0]))
+ ^ uint(0xFFFFFFFF & quintptr(ct.data[1])) ^ seed;
+}
+
namespace clang {
SourceLocation getExpansionLocation(const CXSourceLocation &location)
@@ -160,6 +172,43 @@ QVector<Diagnostic> getDiagnostics(CXTranslationUnit tu)
return result;
}
+QPair<int, int> parseTemplateArgumentList(const QString &l,
+ const TemplateArgumentHandler &handler,
+ int from)
+{
+ const int ltPos = l.indexOf(QLatin1Char('<'), from);
+ if (ltPos == - 1)
+ return qMakePair(-1, -1);
+ int startPos = ltPos + 1;
+ int level = 1;
+ for (int p = startPos, end = l.size(); p < end; ) {
+ const char c = l.at(p).toLatin1();
+ switch (c) {
+ case ',':
+ case '>':
+ handler(level, l.midRef(startPos, p - startPos).trimmed());
+ ++p;
+ if (c == '>') {
+ if (--level == 0)
+ return qMakePair(ltPos, p);
+ // Skip over next ',': "a<b<c,d>,e>"
+ for (; p < end && (l.at(p).isSpace() || l.at(p) == QLatin1Char(',')); ++p) {}
+ }
+ startPos = p;
+ break;
+ case '<':
+ handler(level, l.midRef(startPos, p - startPos).trimmed());
+ ++level;
+ startPos = ++p;
+ break;
+ default:
+ ++p;
+ break;
+ }
+ }
+ return qMakePair(-1, -1);
+}
+
CXDiagnosticSeverity maxSeverity(const QVector<Diagnostic> &ds)
{
CXDiagnosticSeverity result = CXDiagnostic_Ignored;
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangutils.h b/sources/shiboken2/ApiExtractor/clangparser/clangutils.h
index 98d0c9752..b290aac9a 100644
--- a/sources/shiboken2/ApiExtractor/clangparser/clangutils.h
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangutils.h
@@ -34,11 +34,16 @@
#include <QtCore/QString>
#include <QtCore/QVector>
+#include <functional>
+
QT_FORWARD_DECLARE_CLASS(QDebug)
bool operator==(const CXCursor &c1, const CXCursor &c2);
uint qHash(const CXCursor &c, uint seed = 0);
+bool operator==(const CXType &t1, const CXType &t2);
+uint qHash(const CXType &ct, uint seed);
+
namespace clang {
QString getCursorKindName(CXCursorKind cursorKind);
@@ -92,6 +97,14 @@ struct Diagnostic {
QVector<Diagnostic> getDiagnostics(CXTranslationUnit tu);
CXDiagnosticSeverity maxSeverity(const QVector<Diagnostic> &ds);
+// Parse a template argument list "a<b<c,d>,e>" and invoke a handler
+// with each match (level and string). Return begin and end of the list.
+typedef std::function<void(int /*level*/, const QStringRef &)> TemplateArgumentHandler;
+
+QPair<int, int> parseTemplateArgumentList(const QString &l,
+ const TemplateArgumentHandler &handler,
+ int from = 0);
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug, const SourceLocation &);
QDebug operator<<(QDebug, const Diagnostic &);
diff --git a/sources/shiboken2/ApiExtractor/doc/conf.py.in b/sources/shiboken2/ApiExtractor/doc/conf.py.in
index 7251aaccd..609c4a363 100644
--- a/sources/shiboken2/ApiExtractor/doc/conf.py.in
+++ b/sources/shiboken2/ApiExtractor/doc/conf.py.in
@@ -132,10 +132,6 @@ html_theme_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_themes']
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-html_use_smartypants = True
-
# Custom sidebar templates, maps document names to template names.
#html_sidebars = { '' : ''}
diff --git a/sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst b/sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst
index 322f9bca6..c5f6463fd 100644
--- a/sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst
+++ b/sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst
@@ -348,6 +348,26 @@ custom-type
The **name** attribute is the name of the custom type, e.g., "PyObject".
+.. _smart-pointer-type:
+
+smart-pointer-type
+^^^^^^^^^^^^^^^^^^
+
+ The smart pointer type node indicates that the given class is a smart pointer
+ and requires inserting calls to **getter** to access the pointeee.
+ Currently, only the **type** *shared* is supported and the usage is limited
+ to function return values.
+ **ref-count-method** specifies the name of the method used to do reference counting.
+
+ .. code-block:: xml
+
+ <typesystem>
+ <smart-pointer-type name="..."
+ since="..."
+ type="..."
+ getter="..."
+ ref-count-method="..."/>
+ </typesystem>
.. _function:
diff --git a/sources/shiboken2/ApiExtractor/docparser.cpp b/sources/shiboken2/ApiExtractor/docparser.cpp
index 9305332ba..ce089c1f5 100644
--- a/sources/shiboken2/ApiExtractor/docparser.cpp
+++ b/sources/shiboken2/ApiExtractor/docparser.cpp
@@ -50,9 +50,7 @@ DocParser::DocParser()
#endif
}
-DocParser::~DocParser()
-{
-}
+DocParser::~DocParser() = default;
QString DocParser::getDocumentation(QXmlQuery& xquery, const QString& query,
const DocModificationList& mods) const
@@ -154,13 +152,16 @@ QString DocParser::msgCannotFindDocumentation(const QString &fileName,
namespace
{
-struct XslResources
+class XslResources
{
- xmlDocPtr xmlDoc;
- xsltStylesheetPtr xslt;
- xmlDocPtr xslResult;
+ Q_DISABLE_COPY(XslResources)
+
+public:
+ xmlDocPtr xmlDoc = nullptr;
+ xsltStylesheetPtr xslt = nullptr;
+ xmlDocPtr xslResult = nullptr;
- XslResources() : xmlDoc(0), xslt(0), xslResult(0) {}
+ XslResources() = default;
~XslResources()
{
diff --git a/sources/shiboken2/ApiExtractor/doxygenparser.cpp b/sources/shiboken2/ApiExtractor/doxygenparser.cpp
index dfdb37a47..7a0346cc6 100644
--- a/sources/shiboken2/ApiExtractor/doxygenparser.cpp
+++ b/sources/shiboken2/ApiExtractor/doxygenparser.cpp
@@ -35,23 +35,17 @@
#include <QtCore/QFile>
#include <QtCore/QDir>
-namespace
+static QString getSectionKindAttr(const AbstractMetaFunction *func)
{
-
-QString getSectionKindAttr(const AbstractMetaFunction* func)
-{
- if (func->isSignal()) {
+ if (func->isSignal())
return QLatin1String("signal");
- } else {
- QString kind = func->isPublic() ? QLatin1String("public") : QLatin1String("protected");
- if (func->isStatic())
- kind += QLatin1String("-static");
- else if (func->isSlot())
- kind += QLatin1String("-slot");
- return kind;
- }
-}
-
+ QString kind = func->isPublic()
+ ? QLatin1String("public") : QLatin1String("protected");
+ if (func->isStatic())
+ kind += QLatin1String("-static");
+ else if (func->isSlot())
+ kind += QLatin1String("-slot");
+ return kind;
}
Documentation DoxygenParser::retrieveModuleDocumentation()
@@ -77,9 +71,9 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass)
bool isProperty = false;
QString doxyFilePath;
- for (int i = 0; i < numPrefixes; ++i) {
+ for (const char *prefix : prefixes) {
doxyFilePath = documentationDataDirectory() + QLatin1Char('/')
- + QLatin1String(prefixes[i]) + doxyFileSuffix;
+ + QLatin1String(prefix) + doxyFileSuffix;
if (QFile::exists(doxyFilePath))
break;
doxyFilePath.clear();
diff --git a/sources/shiboken2/ApiExtractor/fileout.cpp b/sources/shiboken2/ApiExtractor/fileout.cpp
index e3c96d57b..522c98fb5 100644
--- a/sources/shiboken2/ApiExtractor/fileout.cpp
+++ b/sources/shiboken2/ApiExtractor/fileout.cpp
@@ -50,24 +50,25 @@ static const char colorInfo[] = "";
static const char colorReset[] = "";
#endif
-FileOut::FileOut(QString n):
- name(n),
- stream(&tmp),
- isDone(false)
-{}
+FileOut::FileOut(QString n) :
+ name(std::move(n)),
+ stream(&tmp),
+ isDone(false)
+{
+}
+
+FileOut::~FileOut()
+{
+ if (!isDone)
+ done();
+}
-static int* lcsLength(QList<QByteArray> a, QList<QByteArray> b)
+static QVector<int> lcsLength(const QByteArrayList &a, const QByteArrayList &b)
{
const int height = a.size() + 1;
const int width = b.size() + 1;
- int *res = new int[width * height];
-
- for (int row = 0; row < height; row++)
- res[width * row] = 0;
-
- for (int col = 0; col < width; col++)
- res[col] = 0;
+ QVector<int> res(width * height, 0);
for (int row = 1; row < height; row++) {
for (int col = 1; col < width; col++) {
@@ -89,88 +90,84 @@ enum Type {
struct Unit
{
- Unit(Type type, int pos) :
- type(type),
- start(pos),
- end(pos) {}
-
Type type;
int start;
int end;
- void print(QList<QByteArray> a, QList<QByteArray> b)
- {
- if (type == Unchanged) {
- if ((end - start) > 9) {
- for (int i = start; i <= start + 2; i++)
- std::printf(" %s\n", a[i].data());
- std::printf("%s=\n= %d more lines\n=%s\n", colorInfo, end - start - 6, colorReset);
- for (int i = end - 2; i <= end; i++)
- std::printf(" %s\n", a[i].data());
- } else {
- for (int i = start; i <= end; i++)
- std::printf(" %s\n", a[i].data());
- }
- } else if (type == Add) {
- std::printf("%s", colorAdd);
- for (int i = start; i <= end; i++)
- std::printf("+ %s\n", b[i].data());
- std::printf("%s", colorReset);
- } else if (type == Delete) {
- std::printf("%s", colorDelete);
- for (int i = start; i <= end; i++)
- std::printf("- %s\n", a[i].data());
- std::printf("%s", colorReset);
- }
- }
+ void print(const QByteArrayList &a, const QByteArrayList &b) const;
};
-static QList<Unit*> *unitAppend(QList<Unit*> *res, Type type, int pos)
+void Unit::print(const QByteArrayList &a, const QByteArrayList &b) const
{
- if (!res) {
- res = new QList<Unit*>;
- res->append(new Unit(type, pos));
- return res;
+ switch (type) {
+ case Unchanged:
+ if ((end - start) > 9) {
+ for (int i = start; i <= start + 2; i++)
+ std::printf(" %s\n", a.at(i).constData());
+ std::printf("%s=\n= %d more lines\n=%s\n",
+ colorInfo, end - start - 6, colorReset);
+ for (int i = end - 2; i <= end; i++)
+ std::printf(" %s\n", a.at(i).constData());
+ } else {
+ for (int i = start; i <= end; i++)
+ std::printf(" %s\n", a.at(i).constData());
+ }
+ break;
+ case Add:
+ std::fputs(colorAdd, stdout);
+ for (int i = start; i <= end; i++)
+ std::printf("+ %s\n", b.at(i).constData());
+ std::fputs(colorReset, stdout);
+ break;
+ case Delete:
+ std::fputs(colorDelete, stdout);
+ for (int i = start; i <= end; i++)
+ std::printf("- %s\n", a.at(i).constData());
+ std::fputs(colorReset, stdout);
+ break;
}
+}
- Unit *last = res->last();
- if (last->type == type)
- last->end = pos;
+static void unitAppend(Type type, int pos, QVector<Unit> *units)
+{
+ if (!units->isEmpty() && units->last().type == type)
+ units->last().end = pos;
else
- res->append(new Unit(type, pos));
-
- return res;
+ units->append(Unit{type, pos, pos});
}
-static QList<Unit*> *diffHelper(int *lcs, QList<QByteArray> a, QList<QByteArray> b, int row, int col)
+static QVector<Unit> diffHelper(const QVector<int> &lcs,
+ const QByteArrayList &a, const QByteArrayList &b,
+ int row, int col)
{
- if (row > 0 && col > 0 && (a[row-1] == b[col-1])) {
- return unitAppend(diffHelper(lcs, a, b, row - 1, col - 1), Unchanged, row - 1);
- } else {
- int width = b.size() + 1;
- if ((col > 0)
- && (row == 0 || lcs[width * row + col-1] >= lcs[width *(row-1) + col])) {
- return unitAppend(diffHelper(lcs, a, b, row, col - 1), Add, col - 1);
- } else if ((row > 0)
- && (col == 0 || lcs[width * row + col-1] < lcs[width *(row-1) + col])) {
- return unitAppend(diffHelper(lcs, a, b, row - 1, col), Delete, row - 1);
- }
+ if (row > 0 && col > 0 && a.at(row - 1) == b.at(col - 1)) {
+ QVector<Unit> result = diffHelper(lcs, a, b, row - 1, col - 1);
+ unitAppend(Unchanged, row - 1, &result);
+ return result;
}
- delete lcs;
- return 0;
-}
-static void diff(QList<QByteArray> a, QList<QByteArray> b)
-{
- QList<Unit*> *res = diffHelper(lcsLength(a, b), a, b, a.size(), b.size());
- for (int i = 0; i < res->size(); i++) {
- Unit *unit = res->at(i);
- unit->print(a, b);
- delete(unit);
+ const int width = b.size() + 1;
+ if (col > 0
+ && (row == 0 || lcs.at(width * row + col -1 ) >= lcs.at(width * (row - 1) + col))) {
+ QVector<Unit> result = diffHelper(lcs, a, b, row, col - 1);
+ unitAppend(Add, col - 1, &result);
+ return result;
+ }
+ if (row > 0
+ && (col == 0 || lcs.at(width * row + col-1) < lcs.at(width * (row - 1) + col))) {
+ QVector<Unit> result = diffHelper(lcs, a, b, row - 1, col);
+ unitAppend(Delete, row - 1, &result);
+ return result;
}
- delete(res);
+ return QVector<Unit>{};
}
+static void diff(const QByteArrayList &a, const QByteArrayList &b)
+{
+ const QVector<Unit> res = diffHelper(lcsLength(a, b), a, b, a.size(), b.size());
+ for (const Unit &unit : res)
+ unit.print(a, b);
+}
FileOut::State FileOut::done()
{
diff --git a/sources/shiboken2/ApiExtractor/fileout.h b/sources/shiboken2/ApiExtractor/fileout.h
index 539ae7a43..ed995425d 100644
--- a/sources/shiboken2/ApiExtractor/fileout.h
+++ b/sources/shiboken2/ApiExtractor/fileout.h
@@ -43,12 +43,8 @@ private:
public:
enum State { Failure, Unchanged, Success };
- FileOut(QString name);
- ~FileOut()
- {
- if (!isDone)
- done();
- }
+ explicit FileOut(QString name);
+ ~FileOut();
State done();
State done(QString *errorMessage);
diff --git a/sources/shiboken2/ApiExtractor/include.cpp b/sources/shiboken2/ApiExtractor/include.cpp
index 963999b9d..d6a451992 100644
--- a/sources/shiboken2/ApiExtractor/include.cpp
+++ b/sources/shiboken2/ApiExtractor/include.cpp
@@ -36,10 +36,9 @@ QString Include::toString() const
{
if (m_type == IncludePath)
return QLatin1String("#include <") + m_name + QLatin1Char('>');
- else if (m_type == LocalPath)
+ if (m_type == LocalPath)
return QLatin1String("#include \"") + m_name + QLatin1Char('"');
- else
- return QLatin1String("import ") + m_name + QLatin1Char(';');
+ return QLatin1String("import ") + m_name + QLatin1Char(';');
}
uint qHash(const Include& inc)
diff --git a/sources/shiboken2/ApiExtractor/include.h b/sources/shiboken2/ApiExtractor/include.h
index 16059876a..4890eea2c 100644
--- a/sources/shiboken2/ApiExtractor/include.h
+++ b/sources/shiboken2/ApiExtractor/include.h
@@ -42,7 +42,8 @@ public:
enum IncludeType {
IncludePath,
LocalPath,
- TargetLangImport
+ TargetLangImport,
+ InvalidInclude
};
Include() : m_type(IncludePath) {}
diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp
index d862692dd..2c8042dc0 100644
--- a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp
+++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp
@@ -29,11 +29,15 @@
#include "codemodel.h"
+
+#include <clangparser/clangutils.h>
+
#include <algorithm>
#include <functional>
#include <iostream>
#include <QDebug>
#include <QDir>
+#include <QtCore/QStack>
// Predicate to find an item by name in a list of QSharedPointer<Item>
template <class T> class ModelItemNamePredicate : public std::unary_function<bool, QSharedPointer<T> >
@@ -140,16 +144,18 @@ TypeInfo TypeInfo::combine(const TypeInfo &__lhs, const TypeInfo &__rhs)
__result.setVolatile(__result.isVolatile() || __rhs.isVolatile());
if (__rhs.referenceType() > __result.referenceType())
__result.setReferenceType(__rhs.referenceType());
- __result.setIndirections(__result.indirections() + __rhs.indirections());
+ __result.m_indirections.append(__rhs.m_indirections);
__result.setArrayElements(__result.arrayElements() + __rhs.arrayElements());
+ __result.m_instantiations.append(__rhs.m_instantiations);
return __result;
}
bool TypeInfo::isVoid() const
{
- return m_indirections == 0 && m_referenceType == NoReference
+ return m_indirections.isEmpty() && m_referenceType == NoReference
&& m_arguments.isEmpty() && m_arrayElements.isEmpty()
+ && m_instantiations.isEmpty()
&& m_qualifiedName.size() == 1
&& m_qualifiedName.constFirst() == QLatin1String("void");
}
@@ -193,19 +199,76 @@ TypeInfo TypeInfo::resolveType(CodeModelItem __item, TypeInfo const &__type, Cod
return otherType;
}
+// Handler for clang::parseTemplateArgumentList() that populates
+// TypeInfo::m_instantiations
+class TypeInfoTemplateArgumentHandler :
+ public std::binary_function<void, int, const QStringRef &>
+{
+public:
+ explicit TypeInfoTemplateArgumentHandler(TypeInfo *t)
+ {
+ m_parseStack.append(t);
+ }
+
+ void operator()(int level, const QStringRef &name)
+ {
+ if (level > m_parseStack.size()) {
+ Q_ASSERT(!top()->m_instantiations.isEmpty());
+ m_parseStack.push(&top()->m_instantiations.back());
+ }
+ while (level < m_parseStack.size())
+ m_parseStack.pop();
+ TypeInfo instantiation;
+ instantiation.setQualifiedName(qualifiedName(name));
+ top()->addInstantiation(instantiation);
+ }
+
+private:
+ TypeInfo *top() const { return m_parseStack.back(); }
+
+ static QStringList qualifiedName(const QStringRef &name)
+ {
+ QStringList result;
+ const QVector<QStringRef> nameParts = name.split(QLatin1String("::"));
+ result.reserve(nameParts.size());
+ for (const QStringRef &p : nameParts)
+ result.append(p.toString());
+ return result;
+ }
+
+ QStack<TypeInfo *> m_parseStack;
+};
+
+QPair<int, int> TypeInfo::parseTemplateArgumentList(const QString &l, int from)
+{
+ return clang::parseTemplateArgumentList(l, clang::TemplateArgumentHandler(TypeInfoTemplateArgumentHandler(this)), from);
+}
+
QString TypeInfo::toString() const
{
QString tmp;
-
- tmp += m_qualifiedName.join(QLatin1String("::"));
if (isConstant())
- tmp += QLatin1String(" const");
+ tmp += QLatin1String("const ");
if (isVolatile())
- tmp += QLatin1String(" volatile");
+ tmp += QLatin1String("volatile ");
- if (indirections())
- tmp += QString(indirections(), QLatin1Char('*'));
+ tmp += m_qualifiedName.join(QLatin1String("::"));
+
+ if (const int instantiationCount = m_instantiations.size()) {
+ tmp += QLatin1Char('<');
+ for (int i = 0; i < instantiationCount; ++i) {
+ if (i)
+ tmp += QLatin1String(", ");
+ tmp += m_instantiations.at(i).toString();
+ }
+ if (tmp.endsWith(QLatin1Char('>')))
+ tmp += QLatin1Char(' ');
+ tmp += QLatin1Char('>');
+ }
+
+ for (Indirection i : m_indirections)
+ tmp.append(indirectionKeyword(i));
switch (referenceType()) {
case NoReference:
@@ -238,20 +301,6 @@ QString TypeInfo::toString() const
return tmp;
}
-QStringList TypeInfo::instantiationName() const
-{
- QStringList result = m_qualifiedName;
- if (const int argumentCount = m_arguments.size()) {
- QString &last = result.last();
- for (int i = 0; i < argumentCount; ++i) {
- last += i ? QLatin1String(", ") : QLatin1String("< ");
- last += m_arguments.at(i).toString();
- }
- last += QLatin1String(" >");
- }
- return result;
-}
-
bool TypeInfo::operator==(const TypeInfo &other) const
{
if (arrayElements().count() != other.arrayElements().count())
@@ -269,7 +318,41 @@ bool TypeInfo::operator==(const TypeInfo &other) const
return flags == other.flags
&& m_qualifiedName == other.m_qualifiedName
- && (!m_functionPointer || m_arguments == other.m_arguments);
+ && (!m_functionPointer || m_arguments == other.m_arguments)
+ && m_instantiations == other.m_instantiations;
+}
+
+QString TypeInfo::indirectionKeyword(Indirection i)
+{
+ return i == Indirection::Pointer
+ ? QStringLiteral("*") : QStringLiteral("*const");
+}
+
+static inline QString constQualifier() { return QStringLiteral("const"); }
+static inline QString volatileQualifier() { return QStringLiteral("volatile"); }
+
+bool TypeInfo::stripLeadingConst(QString *s)
+{
+ return stripLeadingQualifier(constQualifier(), s);
+}
+
+bool TypeInfo::stripLeadingVolatile(QString *s)
+{
+ return stripLeadingQualifier(volatileQualifier(), s);
+}
+
+bool TypeInfo::stripLeadingQualifier(const QString &qualifier, QString *s)
+{
+ // "const int x"
+ const int qualifierSize = qualifier.size();
+ if (s->size() < qualifierSize + 1 || !s->startsWith(qualifier)
+ || !s->at(qualifierSize).isSpace()) {
+ return false;
+ }
+ s->remove(0, qualifierSize + 1);
+ while (!s->isEmpty() && s->at(0).isSpace())
+ s->remove(0, 1);
+ return true;
}
#ifndef QT_NO_DEBUG_STREAM
@@ -292,8 +375,11 @@ void TypeInfo::formatDebug(QDebug &d) const
d << ", [const]";
if (m_volatile)
d << ", [volatile]";
- if (m_indirections)
- d << ", indirections=" << m_indirections;
+ if (!m_indirections.isEmpty()) {
+ d << ", indirections=";
+ for (auto i : m_indirections)
+ d << ' ' << TypeInfo::indirectionKeyword(i);
+ }
switch (m_referenceType) {
case NoReference:
break;
@@ -304,6 +390,11 @@ void TypeInfo::formatDebug(QDebug &d) const
d << ", [rvalref]";
break;
}
+ if (!m_instantiations.isEmpty()) {
+ d << ", template<";
+ formatSequence(d, m_instantiations.begin(), m_instantiations.end());
+ d << '>';
+ }
if (m_functionPointer) {
d << ", function ptr(";
formatSequence(d, m_arguments.begin(), m_arguments.end());
@@ -358,9 +449,7 @@ _CodeModelItem::_CodeModelItem(CodeModel *model, const QString &name, int kind)
{
}
-_CodeModelItem::~_CodeModelItem()
-{
-}
+_CodeModelItem::~_CodeModelItem() = default;
int _CodeModelItem::kind() const
{
@@ -532,9 +621,7 @@ QDebug operator<<(QDebug d, const _CodeModelItem *t)
#endif // !QT_NO_DEBUG_STREAM
// ---------------------------------------------------------------------------
-_ClassModelItem::~_ClassModelItem()
-{
-}
+_ClassModelItem::~_ClassModelItem() = default;
TemplateParameterList _ClassModelItem::templateParameters() const
{
@@ -624,9 +711,7 @@ FunctionModelItem _ScopeModelItem::declaredFunction(FunctionModelItem item)
return FunctionModelItem();
}
-_ScopeModelItem::~_ScopeModelItem()
-{
-}
+_ScopeModelItem::~_ScopeModelItem() = default;
void _ScopeModelItem::addEnumsDeclaration(const QString &enumsDeclaration)
{
@@ -835,11 +920,9 @@ void _ArgumentModelItem::formatDebug(QDebug &d) const
}
#endif // !QT_NO_DEBUG_STREAM
// ---------------------------------------------------------------------------
-_FunctionModelItem::~_FunctionModelItem()
-{
-}
+_FunctionModelItem::~_FunctionModelItem() = default;
-bool _FunctionModelItem::isSimilar(FunctionModelItem other) const
+bool _FunctionModelItem::isSimilar(const FunctionModelItem &other) const
{
if (name() != other->name())
return false;
@@ -871,7 +954,7 @@ ArgumentList _FunctionModelItem::arguments() const
return m_arguments;
}
-void _FunctionModelItem::addArgument(ArgumentModelItem item)
+void _FunctionModelItem::addArgument(const ArgumentModelItem& item)
{
m_arguments.append(item);
}
@@ -1091,9 +1174,7 @@ void _EnumModelItem::formatDebug(QDebug &d) const
#endif // !QT_NO_DEBUG_STREAM
// ---------------------------------------------------------------------------
-_EnumeratorModelItem::~_EnumeratorModelItem()
-{
-}
+_EnumeratorModelItem::~_EnumeratorModelItem() = default;
QString _EnumeratorModelItem::stringValue() const
{
@@ -1114,9 +1195,7 @@ void _EnumeratorModelItem::formatDebug(QDebug &d) const
#endif // !QT_NO_DEBUG_STREAM
// ---------------------------------------------------------------------------
-_TemplateParameterModelItem::~_TemplateParameterModelItem()
-{
-}
+_TemplateParameterModelItem::~_TemplateParameterModelItem() = default;
TypeInfo _TemplateParameterModelItem::type() const
{
@@ -1164,9 +1243,7 @@ CodeModel::AccessPolicy _MemberModelItem::accessPolicy() const
return m_accessPolicy;
}
-_MemberModelItem::~_MemberModelItem()
-{
-}
+_MemberModelItem::~_MemberModelItem() = default;
void _MemberModelItem::setAccessPolicy(CodeModel::AccessPolicy accessPolicy)
{
diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.h b/sources/shiboken2/ApiExtractor/parser/codemodel.h
index ac1fe26c1..a2cbcd6c0 100644
--- a/sources/shiboken2/ApiExtractor/parser/codemodel.h
+++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h
@@ -36,6 +36,7 @@
#include "enumvalue.h"
#include <QtCore/QHash>
+#include <QtCore/QPair>
#include <QtCore/QSet>
#include <QtCore/QString>
#include <QtCore/QStringList>
@@ -100,6 +101,8 @@ class TypeInfo
{
friend class TypeParser;
public:
+ typedef QVector<Indirection> Indirections;
+
TypeInfo() : flags(0), m_referenceType(NoReference) {}
QStringList qualifiedName() const
@@ -137,14 +140,16 @@ public:
ReferenceType referenceType() const { return m_referenceType; }
void setReferenceType(ReferenceType r) { m_referenceType = r; }
- int indirections() const
- {
- return m_indirections;
- }
+ Indirections indirectionsV() const { return m_indirections; }
+ void setIndirectionsV(const Indirections &i) { m_indirections = i; }
+ void addIndirection(Indirection i) { m_indirections.append(i); }
+
+ // "Legacy", rename?
+ int indirections() const { return m_indirections.size(); }
void setIndirections(int indirections)
{
- m_indirections = indirections;
+ m_indirections = Indirections(indirections, Indirection::Pointer);
}
bool isFunctionPointer() const
@@ -165,6 +170,8 @@ public:
m_arrayElements = arrayElements;
}
+ void addArrayElement(const QString &a) { m_arrayElements.append(a); }
+
QVector<TypeInfo> arguments() const { return m_arguments; }
void setArguments(const QVector<TypeInfo> &arguments);
@@ -174,6 +181,13 @@ public:
m_arguments.append(arg);
}
+ QVector<TypeInfo> instantiations() const { return m_instantiations; }
+ void setInstantiations(const QVector<TypeInfo> &i) { m_instantiations = i; }
+ void addInstantiation(const TypeInfo &i) { m_instantiations.append(i); }
+ void clearInstantiations() { m_instantiations.clear(); }
+
+ QPair<int, int> parseTemplateArgumentList(const QString &l, int from = 0);
+
bool operator==(const TypeInfo &other) const;
bool operator!=(const TypeInfo &other) const
@@ -185,8 +199,6 @@ public:
QString toString() const;
- QStringList instantiationName() const;
-
static TypeInfo combine(const TypeInfo &__lhs, const TypeInfo &__rhs);
static TypeInfo resolveType(TypeInfo const &__type, CodeModelItem __scope);
@@ -194,12 +206,22 @@ public:
void formatDebug(QDebug &d) const;
#endif
+ static QString indirectionKeyword(Indirection i);
+
+ static bool stripLeadingConst(QString *s);
+ static bool stripLeadingVolatile(QString *s);
+ static bool stripLeadingQualifier(const QString &qualifier, QString *s);
+
private:
+ friend class TypeInfoTemplateArgumentHandler;
+
static TypeInfo resolveType(CodeModelItem item, TypeInfo const &__type, CodeModelItem __scope);
QStringList m_qualifiedName;
QStringList m_arrayElements;
QVector<TypeInfo> m_arguments;
+ QVector<TypeInfo> m_instantiations;
+ Indirections m_indirections;
union {
uint flags;
@@ -208,8 +230,7 @@ private:
uint m_constant: 1;
uint m_volatile: 1;
uint m_functionPointer: 1;
- uint m_indirections: 6;
- uint m_padding: 23;
+ uint m_padding: 29;
};
};
@@ -547,7 +568,7 @@ public:
ArgumentList arguments() const;
- void addArgument(ArgumentModelItem item);
+ void addArgument(const ArgumentModelItem& item);
CodeModel::FunctionType functionType() const;
void setFunctionType(CodeModel::FunctionType functionType);
@@ -582,7 +603,7 @@ public:
bool isVariadics() const;
void setVariadics(bool isVariadics);
- bool isSimilar(FunctionModelItem other) const;
+ bool isSimilar(const FunctionModelItem &other) const;
#ifndef QT_NO_DEBUG_STREAM
void formatDebug(QDebug &d) const override;
diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h b/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h
index b8a10ba93..9a3cc0e07 100644
--- a/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h
+++ b/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h
@@ -41,4 +41,10 @@ enum EnumKind {
EnumClass // C++ 11 : enum class Foo { value1, value2 }
};
+enum class Indirection
+{
+ Pointer, // int *
+ ConstPointer // int *const
+};
+
#endif // CODEMODEL_ENUMS_H
diff --git a/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp
index 7f1361a7d..86bf64495 100644
--- a/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp
+++ b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp
@@ -31,6 +31,37 @@
#include "testutil.h"
#include <abstractmetalang.h>
#include <typesystem.h>
+#include <parser/codemodel.h>
+#include <typeparser.h>
+
+void TestAbstractMetaType::parsing_data()
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<QString>("output");
+ QTest::newRow("primitive")
+ << QString::fromLatin1("int") << QString::fromLatin1("int");
+ QTest::newRow("ref")
+ << QString::fromLatin1("int &") << QString::fromLatin1("int&");
+ QTest::newRow("pointer")
+ << QString::fromLatin1("int **") << QString::fromLatin1("int**");
+ QTest::newRow("const ref")
+ << QString::fromLatin1("const int &") << QString::fromLatin1("const int&");
+ QTest::newRow("const pointer")
+ << QString::fromLatin1("const int **") << QString::fromLatin1("const int**");
+ QTest::newRow("const pointer const")
+ << QString::fromLatin1("const int *const*") << QString::fromLatin1("const int*const*");
+}
+
+void TestAbstractMetaType::parsing()
+{
+ QFETCH(QString, input);
+ QFETCH(QString, output);
+ QString errorMessage;
+ const TypeInfo ti = TypeParser::parse(input, &errorMessage);
+ QVERIFY2(errorMessage.isEmpty(), qPrintable(errorMessage));
+ const QString actual = ti.toString();
+ QCOMPARE(actual, output);
+}
void TestAbstractMetaType::testConstCharPtrType()
{
diff --git a/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.h b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.h
index b2aa7544f..b39a27a54 100644
--- a/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.h
+++ b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.h
@@ -35,6 +35,8 @@ class TestAbstractMetaType : public QObject
{
Q_OBJECT
private slots:
+ void parsing_data();
+ void parsing();
void testConstCharPtrType();
void testCharType();
void testTypedef();
diff --git a/sources/shiboken2/ApiExtractor/tests/testtyperevision.cpp b/sources/shiboken2/ApiExtractor/tests/testtyperevision.cpp
index 1ec7ce025..a3130e499 100644
--- a/sources/shiboken2/ApiExtractor/tests/testtyperevision.cpp
+++ b/sources/shiboken2/ApiExtractor/tests/testtyperevision.cpp
@@ -49,21 +49,22 @@ void TestTypeRevision::testRevisionAttr()
QVERIFY(!builder.isNull());
AbstractMetaClassList classes = builder->classes();
const AbstractMetaClass *rev0 = AbstractMetaClass::findClass(classes, QLatin1String("Rev_0"));
- QCOMPARE(getTypeRevision(rev0->typeEntry()), 0);
+ QCOMPARE(rev0->typeEntry()->revision(), 0);
const AbstractMetaClass *rev1 = AbstractMetaClass::findClass(classes, QLatin1String("Rev_1"));
- QCOMPARE(getTypeRevision(rev1->typeEntry()), 1);
+ QCOMPARE(rev1->typeEntry()->revision(), 1);
AbstractMetaClass *rev2 = AbstractMetaClass::findClass(classes, QLatin1String("Rev_2"));
- QCOMPARE(getTypeRevision(rev2->typeEntry()), 2);
+ QCOMPARE(rev2->typeEntry()->revision(), 2);
AbstractMetaEnum* rev3 = rev2->findEnum(QLatin1String("Rev_3"));
- QCOMPARE(getTypeRevision(rev3->typeEntry()), 3);
+ QCOMPARE(rev3->typeEntry()->revision(), 3);
FlagsTypeEntry* rev4 = rev3->typeEntry()->flags();
- QCOMPARE(getTypeRevision(rev4), 4);
+ QCOMPARE(rev4->revision(), 4);
AbstractMetaEnum* rev5 = rev2->findEnum(QLatin1String("Rev_5"));
- QCOMPARE(getTypeRevision(rev5->typeEntry()), 5);
- QCOMPARE(getTypeRevision(rev5->typeEntry()->flags()), 5);
+ const EnumTypeEntry *revEnumTypeEntry = rev5->typeEntry();
+ QCOMPARE(revEnumTypeEntry->revision(), 5);
+ QCOMPARE(revEnumTypeEntry->flags()->revision(), 5);
}
QTEST_APPLESS_MAIN(TestTypeRevision)
diff --git a/sources/shiboken2/ApiExtractor/tests/testutil.h b/sources/shiboken2/ApiExtractor/tests/testutil.h
index 6152793f5..dea6d92d8 100644
--- a/sources/shiboken2/ApiExtractor/tests/testutil.h
+++ b/sources/shiboken2/ApiExtractor/tests/testutil.h
@@ -53,7 +53,8 @@ namespace TestUtil
buffer.setData(xmlCode);
if (!buffer.open(QIODevice::ReadOnly))
return Q_NULLPTR;
- td->parseFile(&buffer);
+ if (!td->parseFile(&buffer))
+ return nullptr;
buffer.close();
// parse C++ code
QTemporaryFile tempSource(QDir::tempPath() + QLatin1String("/st_XXXXXX_main.cpp"));
diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp
index 9529de40a..6372a8715 100644
--- a/sources/shiboken2/ApiExtractor/typedatabase.cpp
+++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp
@@ -263,6 +263,8 @@ static inline QString msgRejectReason(const TypeRejection &r, const QString &nee
str << " matches class \"" << r.className.pattern() << "\" and \"" << needle
<< "\" matches \"" << r.pattern.pattern() << '"';
break;
+ case TypeRejection::Invalid:
+ break;
}
return result;
}
@@ -518,7 +520,10 @@ bool TypeDatabase::parseFile(QIODevice* device, bool generate)
{
QXmlStreamReader reader(device);
Handler handler(this, generate);
- return handler.parse(reader);
+ const bool result = handler.parse(reader);
+ if (!result)
+ qCWarning(lcShiboken, "%s", qPrintable(handler.errorString()));
+ return result;
}
PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const
@@ -574,28 +579,15 @@ void TypeDatabase::setDropTypeEntries(QStringList dropTypeEntries)
m_dropTypeEntries.sort();
}
-// Using std::pair to save some memory
-// the pair means (revision, typeIndex)
-// This global variable exists only because we can't break the ABI
-typedef QHash<const TypeEntry*, std::pair<int, int> > TypeRevisionMap;
-Q_GLOBAL_STATIC(TypeRevisionMap, typeEntryFields);
static bool computeTypeIndexes = true;
static int maxTypeIndex;
-int getTypeRevision(const TypeEntry* typeEntry)
-{
- return typeEntryFields()->value(typeEntry).first;
-}
-
-void setTypeRevision(TypeEntry* typeEntry, int revision)
+static bool typeEntryLessThan(const TypeEntry* t1, const TypeEntry* t2)
{
- (*typeEntryFields())[typeEntry].first = revision;
- computeTypeIndexes = true;
-}
-
-static bool compareTypeEntriesByName(const TypeEntry* t1, const TypeEntry* t2)
-{
- return t1->qualifiedCppName() < t2->qualifiedCppName();
+ if (t1->revision() < t2->revision())
+ return true;
+ return t1->revision() == t2->revision()
+ && t1->qualifiedCppName() < t2->qualifiedCppName();
}
static void _computeTypeIndexes()
@@ -604,8 +596,11 @@ static void _computeTypeIndexes()
typedef QMap<int, TypeEntryList> GroupedTypeEntries;
GroupedTypeEntries groupedEntries;
+ TypeEntryList list;
+
// Group type entries by revision numbers
const TypeEntryHash &allEntries = tdb->allEntries();
+ list.reserve(allEntries.size());
for (TypeEntryHash::const_iterator tit = allEntries.cbegin(), end = allEntries.cend(); tit != end; ++tit) {
for (TypeEntry *entry : tit.value()) {
if (entry->isPrimitive()
@@ -618,31 +613,33 @@ static void _computeTypeIndexes()
|| entry->isVoid()
|| entry->isCustom())
continue;
- groupedEntries[getTypeRevision(entry)] << entry;
+ if (!list.contains(entry)) // Remove duplicates
+ list.append(entry);
}
}
+ // Sort the type entries by revision, name
+ std::sort(list.begin(), list.end(), typeEntryLessThan);
+
maxTypeIndex = 0;
- GroupedTypeEntries::iterator it = groupedEntries.begin();
- for (; it != groupedEntries.end(); ++it) {
- // Remove duplicates
- TypeEntryList::iterator newEnd = std::unique(it.value().begin(), it.value().end());
- it.value().erase(newEnd, it.value().end());
- // Sort the type entries by name
- qSort(it.value().begin(), newEnd, compareTypeEntriesByName);
-
- for (TypeEntry *entry : qAsConst(it.value())) {
- (*typeEntryFields())[entry].second = maxTypeIndex++;
- }
- }
+ for (TypeEntry *e : qAsConst(list))
+ e->setSbkIndex(maxTypeIndex++);
computeTypeIndexes = false;
}
-int getTypeIndex(const TypeEntry* typeEntry)
+void TypeEntry::setRevision(int r)
+{
+ if (m_revision != r) {
+ m_revision = r;
+ computeTypeIndexes = true;
+ }
+}
+
+int TypeEntry::sbkIndex() const
{
if (computeTypeIndexes)
_computeTypeIndexes();
- return typeEntryFields()->value(typeEntry).second;
+ return m_sbkIndex;
}
int getMaxTypeIndex()
@@ -684,33 +681,95 @@ bool TypeDatabase::checkApiVersion(const QString &package,
}
#ifndef QT_NO_DEBUG_STREAM
+
+#define FORMAT_BOOL(name, var) \
+ if (var) \
+ d << ", [" << name << ']';
+
+#define FORMAT_NONEMPTY_STRING(name, var) \
+ if (!var.isEmpty()) \
+ d << ", " << name << "=\"" << var << '"';
+
+#define FORMAT_LIST_SIZE(name, var) \
+ if (!var.isEmpty()) \
+ d << ", " << var.size() << ' ' << name;
+
+void TypeEntry::formatDebug(QDebug &d) const
+{
+ const QString cppName = qualifiedCppName();
+ d << '"' << m_name << '"';
+ if (m_name != cppName)
+ d << "\", cppName=\"" << cppName << '"';
+ d << ", type=" << m_type << ", codeGeneration=0x"
+ << hex << m_codeGeneration << dec;
+ FORMAT_NONEMPTY_STRING("package", m_targetLangPackage)
+ FORMAT_BOOL("preferredConversion", m_preferredConversion)
+ FORMAT_BOOL("stream", m_stream)
+ FORMAT_LIST_SIZE("codeSnips", m_codeSnips)
+ FORMAT_NONEMPTY_STRING("conversionRule", m_conversionRule)
+ if (!m_version.isNull() && m_version > QVersionNumber(0, 0))
+ d << ", version=" << m_version;
+ if (m_revision)
+ d << ", revision=" << m_revision;
+ if (m_sbkIndex)
+ d << ", sbkIndex=" << m_sbkIndex;
+ if (m_include.isValid())
+ d << ", include=" << m_include;
+ if (const int count = m_extraIncludes.size()) {
+ d << ", extraIncludes[" << count << "]=";
+ for (int i = 0; i < count; ++i) {
+ if (i)
+ d << ", ";
+ d << m_extraIncludes.at(i);
+ }
+ }
+}
+
+void ComplexTypeEntry::formatDebug(QDebug &d) const
+{
+ TypeEntry::formatDebug(d);
+ FORMAT_NONEMPTY_STRING("targetLangName", m_targetLangName)
+ FORMAT_BOOL("QObject", m_qobject)
+ FORMAT_BOOL("polymorphicBase", m_polymorphicBase)
+ FORMAT_BOOL("genericClass", m_genericClass)
+ if (m_typeFlags != 0)
+ d << ", typeFlags=" << m_typeFlags;
+ d << ", copyableFlag=" << m_copyableFlag;
+ FORMAT_NONEMPTY_STRING("defaultSuperclass", m_defaultSuperclass)
+ FORMAT_NONEMPTY_STRING("polymorphicIdValue", m_polymorphicIdValue)
+ FORMAT_NONEMPTY_STRING("held", m_heldTypeValue)
+ FORMAT_NONEMPTY_STRING("lookupName", m_lookupName)
+ FORMAT_NONEMPTY_STRING("targetType", m_targetType)
+ FORMAT_NONEMPTY_STRING("hash", m_hashFunction)
+ FORMAT_LIST_SIZE("addedFunctions", m_addedFunctions)
+ FORMAT_LIST_SIZE("functionMods", m_functionMods)
+ FORMAT_LIST_SIZE("fieldMods", m_fieldMods)
+}
+
+void EnumTypeEntry::formatDebug(QDebug &d) const
+{
+ TypeEntry::formatDebug(d);
+ FORMAT_NONEMPTY_STRING("package", m_packageName)
+ FORMAT_NONEMPTY_STRING("qualifier", m_qualifier)
+ FORMAT_NONEMPTY_STRING("targetLangName", m_targetLangName)
+ FORMAT_NONEMPTY_STRING("lowerBound", m_lowerBound)
+ FORMAT_NONEMPTY_STRING("lupperBound", m_upperBound)
+ FORMAT_BOOL("extensible", m_extensible)
+ FORMAT_BOOL("forceInteger", m_forceInteger)
+ if (m_flags)
+ d << ", flags=(" << m_flags << ')';
+}
+
QDebug operator<<(QDebug d, const TypeEntry *te)
{
QDebugStateSaver saver(d);
d.noquote();
d.nospace();
d << "TypeEntry(";
- if (te) {
- const QString name = te->name();
- const QString cppName = te->qualifiedCppName();
- d << '"' << name << '"';
- if (name != cppName)
- d << "\", cppName=\"" << cppName << '"';
- d << ", type=" << te->type();
- if (te->include().isValid())
- d << ", include=" << te->include();
- const IncludeList &extraIncludes = te->extraIncludes();
- if (const int count = extraIncludes.size()) {
- d << ", extraIncludes[" << count << "]=";
- for (int i = 0; i < count; ++i) {
- if (i)
- d << ", ";
- d << extraIncludes.at(i);
- }
- }
- } else {
+ if (te)
+ te->formatDebug(d);
+ else
d << '0';
- }
d << ')';
return d;
}
diff --git a/sources/shiboken2/ApiExtractor/typedatabase.h b/sources/shiboken2/ApiExtractor/typedatabase.h
index 2e7b009c2..3664d76b7 100644
--- a/sources/shiboken2/ApiExtractor/typedatabase.h
+++ b/sources/shiboken2/ApiExtractor/typedatabase.h
@@ -54,9 +54,6 @@ struct TypeRejection;
QT_FORWARD_DECLARE_CLASS(QDebug)
-void setTypeRevision(TypeEntry* typeEntry, int revision);
-int getTypeRevision(const TypeEntry* typeEntry);
-int getTypeIndex(const TypeEntry* typeEntry);
int getMaxTypeIndex();
class ContainerTypeEntry;
diff --git a/sources/shiboken2/ApiExtractor/typeparser.cpp b/sources/shiboken2/ApiExtractor/typeparser.cpp
index 02c85421b..c440fb66d 100644
--- a/sources/shiboken2/ApiExtractor/typeparser.cpp
+++ b/sources/shiboken2/ApiExtractor/typeparser.cpp
@@ -49,13 +49,14 @@ public:
GreaterThanToken,
ConstToken,
+ VolatileToken,
Identifier,
NoToken,
InvalidToken
};
Scanner(const QString &s)
- : m_pos(0), m_length(s.length()), m_chars(s.constData())
+ : m_pos(0), m_length(s.length()), m_tokenStart(-1), m_chars(s.constData())
{
}
@@ -137,13 +138,30 @@ Scanner::Token Scanner::nextToken(QString *errorMessage)
}
}
- if (tok == Identifier && m_pos - m_tokenStart == 5) {
- if (m_chars[m_tokenStart] == QLatin1Char('c')
- && m_chars[m_tokenStart + 1] == QLatin1Char('o')
- && m_chars[m_tokenStart + 2] == QLatin1Char('n')
- && m_chars[m_tokenStart + 3] == QLatin1Char('s')
- && m_chars[m_tokenStart + 4] == QLatin1Char('t'))
- tok = ConstToken;
+ if (tok == Identifier) {
+ switch (m_pos - m_tokenStart) {
+ case 5:
+ if (m_chars[m_tokenStart] == QLatin1Char('c')
+ && m_chars[m_tokenStart + 1] == QLatin1Char('o')
+ && m_chars[m_tokenStart + 2] == QLatin1Char('n')
+ && m_chars[m_tokenStart + 3] == QLatin1Char('s')
+ && m_chars[m_tokenStart + 4] == QLatin1Char('t')) {
+ tok = ConstToken;
+ }
+ break;
+ case 8:
+ if (m_chars[m_tokenStart] == QLatin1Char('v')
+ && m_chars[m_tokenStart + 1] == QLatin1Char('o')
+ && m_chars[m_tokenStart + 2] == QLatin1Char('l')
+ && m_chars[m_tokenStart + 3] == QLatin1Char('a')
+ && m_chars[m_tokenStart + 4] == QLatin1Char('t')
+ && m_chars[m_tokenStart + 5] == QLatin1Char('i')
+ && m_chars[m_tokenStart + 6] == QLatin1Char('l')
+ && m_chars[m_tokenStart + 7] == QLatin1Char('e')) {
+ tok = VolatileToken;
+ }
+ break;
+ }
}
return tok;
@@ -167,6 +185,7 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage)
bool colon_prefix = false;
bool in_array = false;
QString array;
+ bool seenStar = false;
Scanner::Token tok = scanner.nextToken(errorMessage);
while (tok != Scanner::NoToken) {
@@ -191,7 +210,8 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage)
switch (tok) {
case Scanner::StarToken:
- ++stack.top()->m_indirections;
+ seenStar = true;
+ stack.top()->addIndirection(Indirection::Pointer);
break;
case Scanner::AmpersandToken:
@@ -212,14 +232,14 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage)
}
break;
case Scanner::LessThanToken:
- stack.top()->m_arguments << TypeInfo();
- stack.push(&stack.top()->m_arguments.last());
+ stack.top()->m_instantiations << TypeInfo();
+ stack.push(&stack.top()->m_instantiations.last());
break;
case Scanner::CommaToken:
stack.pop();
- stack.top()->m_arguments << TypeInfo();
- stack.push(&stack.top()->m_arguments.last());
+ stack.top()->m_instantiations << TypeInfo();
+ stack.push(&stack.top()->m_instantiations.last());
break;
case Scanner::GreaterThanToken:
@@ -231,7 +251,16 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage)
break;
case Scanner::ConstToken:
- stack.top()->m_constant = true;
+ if (seenStar) { // "int *const": Last indirection is const.
+ Q_ASSERT(!stack.top()->m_indirections.isEmpty());
+ *stack.top()->m_indirections.rbegin() = Indirection::ConstPointer;
+ } else {
+ stack.top()->m_constant = true;
+ }
+ break;
+
+ case Scanner::VolatileToken:
+ stack.top()->m_volatile = true;
break;
case Scanner::OpenParenToken: // function pointers not supported
diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp
index baaec6d30..70563286c 100644
--- a/sources/shiboken2/ApiExtractor/typesystem.cpp
+++ b/sources/shiboken2/ApiExtractor/typesystem.cpp
@@ -35,29 +35,62 @@
#include <QtCore/QFileInfo>
#include <QtCore/QRegularExpression>
#include <QtCore/QSet>
+#include <QtCore/QStringView>
+#include <QtCore/QStringAlgorithms>
#include <QtCore/QXmlStreamAttributes>
#include <QtCore/QXmlStreamReader>
+#include <algorithm>
+
static QString strings_Object = QLatin1String("Object");
static QString strings_String = QLatin1String("String");
static QString strings_char = QLatin1String("char");
static QString strings_jchar = QLatin1String("jchar");
static QString strings_jobject = QLatin1String("jobject");
+static inline QString allowThreadAttribute() { return QStringLiteral("allow-thread"); }
static inline QString colonColon() { return QStringLiteral("::"); }
+static inline QString copyableAttribute() { return QStringLiteral("copyable"); }
+static inline QString accessAttribute() { return QStringLiteral("access"); }
+static inline QString actionAttribute() { return QStringLiteral("action"); }
static inline QString quoteAfterLineAttribute() { return QStringLiteral("quote-after-line"); }
static inline QString quoteBeforeLineAttribute() { return QStringLiteral("quote-before-line"); }
static inline QString textAttribute() { return QStringLiteral("text"); }
static inline QString nameAttribute() { return QStringLiteral("name"); }
static inline QString sinceAttribute() { return QStringLiteral("since"); }
+static inline QString defaultSuperclassAttribute() { return QStringLiteral("default-superclass"); }
+static inline QString deleteInMainThreadAttribute() { return QStringLiteral("delete-in-main-thread"); }
+static inline QString deprecatedAttribute() { return QStringLiteral("deprecated"); }
+static inline QString extensibleAttribute() { return QStringLiteral("extensible"); }
static inline QString flagsAttribute() { return QStringLiteral("flags"); }
+static inline QString forceAbstractAttribute() { return QStringLiteral("force-abstract"); }
+static inline QString forceIntegerAttribute() { return QStringLiteral("force-integer"); }
+static inline QString formatAttribute() { return QStringLiteral("format"); }
static inline QString classAttribute() { return QStringLiteral("class"); }
-static inline QString functionNameAttribute() { return QStringLiteral("function-name"); }
-static inline QString fieldNameAttribute() { return QStringLiteral("field-name"); }
-static inline QString enumNameAttribute() { return QStringLiteral("enum-name"); }
-static inline QString argumentTypeAttribute() { return QStringLiteral("argument-type"); }
-static inline QString returnTypeAttribute() { return QStringLiteral("return-type"); }
+static inline QString generateAttribute() { return QStringLiteral("generate"); }
+static inline QString genericClassAttribute() { return QStringLiteral("generic-class"); }
+static inline QString indexAttribute() { return QStringLiteral("index"); }
+static inline QString invalidateAfterUseAttribute() { return QStringLiteral("invalidate-after-use"); }
+static inline QString locationAttribute() { return QStringLiteral("location"); }
+static inline QString modifiedTypeAttribute() { return QStringLiteral("modified-type"); }
+static inline QString modifierAttribute() { return QStringLiteral("modifier"); }
+static inline QString ownershipAttribute() { return QStringLiteral("owner"); }
+static inline QString packageAttribute() { return QStringLiteral("package"); }
+static inline QString positionAttribute() { return QStringLiteral("position"); }
+static inline QString preferredConversionAttribute() { return QStringLiteral("preferred-conversion"); }
+static inline QString preferredTargetLangTypeAttribute() { return QStringLiteral("preferred-target-lang-type"); }
+static inline QString removeAttribute() { return QStringLiteral("remove"); }
+static inline QString renameAttribute() { return QStringLiteral("rename"); }
+static inline QString readAttribute() { return QStringLiteral("read"); }
+static inline QString writeAttribute() { return QStringLiteral("write"); }
+static inline QString replaceAttribute() { return QStringLiteral("replace"); }
+static inline QString toAttribute() { return QStringLiteral("to"); }
+static inline QString signatureAttribute() { return QStringLiteral("signature"); }
+static inline QString staticAttribute() { return QStringLiteral("static"); }
+static inline QString threadAttribute() { return QStringLiteral("thread"); }
+static inline QString streamAttribute() { return QStringLiteral("stream"); }
static inline QString xPathAttribute() { return QStringLiteral("xpath"); }
+static inline QString virtualSlotAttribute() { return QStringLiteral("virtual-slot"); }
static inline QString enumIdentifiedByValueAttribute() { return QStringLiteral("identified-by-value"); }
static inline QString noAttributeValue() { return QStringLiteral("no"); }
@@ -90,49 +123,258 @@ static bool setRejectionRegularExpression(const QString &patternIn,
return true;
}
-static bool addRejection(TypeDatabase *database, const QHash<QString, QString> &attributes,
- QString *errorMessage)
+template <class EnumType, Qt::CaseSensitivity cs = Qt::CaseInsensitive>
+struct EnumLookup
{
- typedef QPair<QString, TypeRejection::MatchType> AttributeMatchTypePair;
+ QStringView name;
+ EnumType value;
+};
- TypeRejection rejection;
+template <class EnumType, Qt::CaseSensitivity cs>
+bool operator==(const EnumLookup<EnumType, cs> &e1, const EnumLookup<EnumType, cs> &e2)
+{
+#ifdef QTBUG_69389_FIXED
+ return e1.name.compare(e2.name, cs) == 0;
+#else
+ return QtPrivate::compareStrings(e1.name, e2.name, cs) == 0;
+#endif
+}
- const QString className = attributes.value(classAttribute());
- if (!setRejectionRegularExpression(className, &rejection.className, errorMessage))
- return false;
+template <class EnumType, Qt::CaseSensitivity cs>
+bool operator<(const EnumLookup<EnumType, cs> &e1, const EnumLookup<EnumType, cs> &e2)
+{
+#ifdef QTBUG_69389_FIXED
+ return e1.name.compare(e2.name, cs) < 0;
+#else
+ return QtPrivate::compareStrings(e1.name, e2.name, cs) < 0;
+#endif
+}
- static const AttributeMatchTypePair attributeMatchTypeMapping[] =
- {{functionNameAttribute(), TypeRejection::Function},
- {fieldNameAttribute(), TypeRejection::Field},
- {enumNameAttribute(), TypeRejection::Enum},
- {argumentTypeAttribute(), TypeRejection::ArgumentType},
- {returnTypeAttribute(), TypeRejection::ReturnType}
+// Helper macros to define lookup functions that take a QStringView needle
+// and an optional default return value.
+#define ENUM_LOOKUP_BEGIN(EnumType, caseSensitivity, functionName, defaultReturnValue) \
+static EnumType functionName(QStringView needle, EnumType defaultValue = defaultReturnValue) \
+{ \
+ typedef EnumLookup<EnumType, caseSensitivity> HaystackEntry; \
+ static const HaystackEntry haystack[] =
+
+#define ENUM_LOOKUP_LINEAR_SEARCH() \
+ const auto end = haystack + sizeof(haystack) / sizeof(haystack[0]); \
+ const auto it = std::find(haystack, end, HaystackEntry{needle, defaultValue}); \
+ return it != end ? it->value : defaultValue; \
+}
+
+#define ENUM_LOOKUP_BINARY_SEARCH() \
+ const auto end = haystack + sizeof(haystack) / sizeof(haystack[0]); \
+ const HaystackEntry needleEntry{needle, defaultValue}; \
+ const auto lb = std::lower_bound(haystack, end, needleEntry); \
+ return lb != end && *lb == needleEntry ? lb->value : defaultValue; \
+}
+
+ENUM_LOOKUP_BEGIN(TypeSystem::Language, Qt::CaseInsensitive,
+ languageFromAttribute, TypeSystem::NoLanguage)
+ {
+ {QStringViewLiteral("all"), TypeSystem::All}, // sorted!
+ {QStringViewLiteral("constructors"), TypeSystem::Constructors},
+ {QStringViewLiteral("destructor-function"), TypeSystem::DestructorFunction},
+ {QStringViewLiteral("interface"), TypeSystem::Interface},
+ {QStringViewLiteral("library-initializer"), TypeSystem::PackageInitializer},
+ {QStringViewLiteral("native"), TypeSystem::NativeCode}, // em algum lugar do cpp
+ {QStringViewLiteral("shell"), TypeSystem::ShellCode}, // coloca no header, mas antes da declaracao da classe
+ {QStringViewLiteral("shell-declaration"), TypeSystem::ShellDeclaration},
+ {QStringViewLiteral("target"), TypeSystem::TargetLangCode} // em algum lugar do cpp
};
+ENUM_LOOKUP_BINARY_SEARCH()
- // Search for non-empty attribute (function, field, enum)
- const auto aend = attributes.cend();
- for (const AttributeMatchTypePair &mapping : attributeMatchTypeMapping) {
- const auto it = attributes.constFind(mapping.first);
- if (it != aend && !it.value().isEmpty()) {
- if (!setRejectionRegularExpression(it.value(), &rejection.pattern, errorMessage))
- return false;
- rejection.matchType = mapping.second;
- database->addRejection(rejection);
- return true;
- }
- }
+ENUM_LOOKUP_BEGIN(TypeSystem::Ownership, Qt::CaseInsensitive,
+ ownershipFromFromAttribute, TypeSystem::InvalidOwnership)
+ {
+ {QStringViewLiteral("target"), TypeSystem::TargetLangOwnership},
+ {QStringViewLiteral("c++"), TypeSystem::CppOwnership},
+ {QStringViewLiteral("default"), TypeSystem::DefaultOwnership}
+ };
+ENUM_LOOKUP_LINEAR_SEARCH()
- // Special case: When all fields except class are empty, completely exclude class
- if (className == QLatin1String("*")) {
- *errorMessage = QLatin1String("bad reject entry, neither 'class', 'function-name'"
- " nor 'field' specified");
- return false;
+ENUM_LOOKUP_BEGIN(AddedFunction::Access, Qt::CaseInsensitive,
+ addedFunctionAccessFromAttribute, AddedFunction::InvalidAccess)
+ {
+ {QStringViewLiteral("public"), AddedFunction::Public},
+ {QStringViewLiteral("protected"), AddedFunction::Protected},
+ };
+ENUM_LOOKUP_LINEAR_SEARCH()
+
+ENUM_LOOKUP_BEGIN(Modification::Modifiers, Qt::CaseSensitive,
+ modifierFromAttribute, Modification::InvalidModifier)
+ {
+ {QStringViewLiteral("private"), Modification::Private},
+ {QStringViewLiteral("public"), Modification::Public},
+ {QStringViewLiteral("protected"), Modification::Protected},
+ {QStringViewLiteral("friendly"), Modification::Friendly},
+ {QStringViewLiteral("rename"), Modification::Rename},
+ {QStringViewLiteral("final"), Modification::Final},
+ {QStringViewLiteral("non-final"), Modification::NonFinal}
+ };
+ENUM_LOOKUP_LINEAR_SEARCH()
+
+ENUM_LOOKUP_BEGIN(ReferenceCount::Action, Qt::CaseInsensitive,
+ referenceCountFromAttribute, ReferenceCount::Invalid)
+ {
+ {QStringViewLiteral("add"), ReferenceCount::Add},
+ {QStringViewLiteral("add-all"), ReferenceCount::AddAll},
+ {QStringViewLiteral("remove"), ReferenceCount::Remove},
+ {QStringViewLiteral("set"), ReferenceCount::Set},
+ {QStringViewLiteral("ignore"), ReferenceCount::Ignore}
+ };
+ENUM_LOOKUP_LINEAR_SEARCH()
+
+ENUM_LOOKUP_BEGIN(ArgumentOwner::Action, Qt::CaseInsensitive,
+ argumentOwnerActionFromAttribute, ArgumentOwner::Invalid)
+ {
+ {QStringViewLiteral("add"), ArgumentOwner::Add},
+ {QStringViewLiteral("remove"), ArgumentOwner::Remove}
+ };
+ENUM_LOOKUP_LINEAR_SEARCH()
+
+ENUM_LOOKUP_BEGIN(TypeSystem::CodeSnipPosition, Qt::CaseInsensitive,
+ codeSnipPositionFromAttribute, TypeSystem::CodeSnipPositionInvalid)
+ {
+ {QStringViewLiteral("beginning"), TypeSystem::CodeSnipPositionBeginning},
+ {QStringViewLiteral("end"), TypeSystem::CodeSnipPositionEnd},
+ {QStringViewLiteral("declaration"), TypeSystem::CodeSnipPositionDeclaration},
+ {QStringViewLiteral("prototype-initialization"), TypeSystem::CodeSnipPositionPrototypeInitialization},
+ {QStringViewLiteral("constructor-initialization"), TypeSystem::CodeSnipPositionConstructorInitialization},
+ {QStringViewLiteral("constructor"), TypeSystem::CodeSnipPositionConstructor}
+ };
+ENUM_LOOKUP_LINEAR_SEARCH()
+
+ENUM_LOOKUP_BEGIN(Include::IncludeType, Qt::CaseInsensitive,
+ locationFromAttribute, Include::InvalidInclude)
+ {
+ {QStringViewLiteral("global"), Include::IncludePath},
+ {QStringViewLiteral("local"), Include::LocalPath},
+ {QStringViewLiteral("target"), Include::TargetLangImport}
+ };
+ENUM_LOOKUP_LINEAR_SEARCH()
+
+ENUM_LOOKUP_BEGIN(TypeSystem::DocModificationMode, Qt::CaseInsensitive,
+ docModificationFromAttribute, TypeSystem::DocModificationInvalid)
+ {
+ {QStringViewLiteral("append"), TypeSystem::DocModificationAppend},
+ {QStringViewLiteral("prepend"), TypeSystem::DocModificationPrepend},
+ {QStringViewLiteral("replace"), TypeSystem::DocModificationReplace}
+ };
+ENUM_LOOKUP_LINEAR_SEARCH()
+
+ENUM_LOOKUP_BEGIN(ContainerTypeEntry::Type, Qt::CaseSensitive,
+ containerTypeFromAttribute, ContainerTypeEntry::NoContainer)
+ {
+ {QStringViewLiteral("list"), ContainerTypeEntry::ListContainer},
+ {QStringViewLiteral("string-list"), ContainerTypeEntry::StringListContainer},
+ {QStringViewLiteral("linked-list"), ContainerTypeEntry::LinkedListContainer},
+ {QStringViewLiteral("vector"), ContainerTypeEntry::VectorContainer},
+ {QStringViewLiteral("stack"), ContainerTypeEntry::StackContainer},
+ {QStringViewLiteral("queue"), ContainerTypeEntry::QueueContainer},
+ {QStringViewLiteral("set"), ContainerTypeEntry::SetContainer},
+ {QStringViewLiteral("map"), ContainerTypeEntry::MapContainer},
+ {QStringViewLiteral("multi-map"), ContainerTypeEntry::MultiMapContainer},
+ {QStringViewLiteral("hash"), ContainerTypeEntry::HashContainer},
+ {QStringViewLiteral("multi-hash"), ContainerTypeEntry::MultiHashContainer},
+ {QStringViewLiteral("pair"), ContainerTypeEntry::PairContainer}
+ };
+ENUM_LOOKUP_LINEAR_SEARCH()
+
+ENUM_LOOKUP_BEGIN(TypeRejection::MatchType, Qt::CaseSensitive,
+ typeRejectionFromAttribute, TypeRejection::Invalid)
+ {
+ {QStringViewLiteral("class"), TypeRejection::ExcludeClass},
+ {QStringViewLiteral("function-name"), TypeRejection::Function},
+ {QStringViewLiteral("field-name"), TypeRejection::Field},
+ {QStringViewLiteral("enum-name"), TypeRejection::Enum },
+ {QStringViewLiteral("argument-type"), TypeRejection::ArgumentType},
+ {QStringViewLiteral("return-type"), TypeRejection::ReturnType}
+ };
+ENUM_LOOKUP_LINEAR_SEARCH()
+
+ENUM_LOOKUP_BEGIN(StackElement::ElementType, Qt::CaseInsensitive,
+ elementFromTag, StackElement::None)
+ {
+ {QStringViewLiteral("access"), StackElement::Access}, // sorted!
+ {QStringViewLiteral("add-conversion"), StackElement::AddConversion},
+ {QStringViewLiteral("add-function"), StackElement::AddFunction},
+ {QStringViewLiteral("argument-map"), StackElement::ArgumentMap},
+ {QStringViewLiteral("array"), StackElement::Array},
+ {QStringViewLiteral("container-type"), StackElement::ContainerTypeEntry},
+ {QStringViewLiteral("conversion-rule"), StackElement::ConversionRule},
+ {QStringViewLiteral("custom-constructor"), StackElement::CustomMetaConstructor},
+ {QStringViewLiteral("custom-destructor"), StackElement::CustomMetaDestructor},
+ {QStringViewLiteral("custom-type"), StackElement::CustomTypeEntry},
+ {QStringViewLiteral("define-ownership"), StackElement::DefineOwnership},
+ {QStringViewLiteral("enum-type"), StackElement::EnumTypeEntry},
+ {QStringViewLiteral("extra-includes"), StackElement::ExtraIncludes},
+ {QStringViewLiteral("function"), StackElement::FunctionTypeEntry},
+ {QStringViewLiteral("include"), StackElement::Include},
+ {QStringViewLiteral("inject-code"), StackElement::InjectCode},
+ {QStringViewLiteral("inject-documentation"), StackElement::InjectDocumentation},
+ {QStringViewLiteral("insert-template"), StackElement::TemplateInstanceEnum},
+ {QStringViewLiteral("interface-type"), StackElement::InterfaceTypeEntry},
+ {QStringViewLiteral("load-typesystem"), StackElement::LoadTypesystem},
+ {QStringViewLiteral("modify-argument"), StackElement::ModifyArgument},
+ {QStringViewLiteral("modify-documentation"), StackElement::ModifyDocumentation},
+ {QStringViewLiteral("modify-field"), StackElement::ModifyField},
+ {QStringViewLiteral("modify-function"), StackElement::ModifyFunction},
+ {QStringViewLiteral("namespace-type"), StackElement::NamespaceTypeEntry},
+ {QStringViewLiteral("native-to-target"), StackElement::NativeToTarget},
+ {QStringViewLiteral("no-null-pointer"), StackElement::NoNullPointers},
+ {QStringViewLiteral("object-type"), StackElement::ObjectTypeEntry},
+ {QStringViewLiteral("parent"), StackElement::ParentOwner},
+ {QStringViewLiteral("primitive-type"), StackElement::PrimitiveTypeEntry},
+ {QStringViewLiteral("reference-count"), StackElement::ReferenceCount},
+ {QStringViewLiteral("reject-enum-value"), StackElement::RejectEnumValue},
+ {QStringViewLiteral("rejection"), StackElement::Rejection},
+ {QStringViewLiteral("remove"), StackElement::Removal},
+ {QStringViewLiteral("remove-argument"), StackElement::RemoveArgument},
+ {QStringViewLiteral("remove-default-expression"), StackElement::RemoveDefaultExpression},
+ {QStringViewLiteral("rename"), StackElement::Rename},
+ {QStringViewLiteral("replace"), StackElement::Replace},
+ {QStringViewLiteral("replace-default-expression"), StackElement::ReplaceDefaultExpression},
+ {QStringViewLiteral("replace-type"), StackElement::ReplaceType},
+ {QStringViewLiteral("smart-pointer-type"), StackElement::SmartPointerTypeEntry},
+ {QStringViewLiteral("suppress-warning"), StackElement::SuppressedWarning},
+ {QStringViewLiteral("target-to-native"), StackElement::TargetToNative},
+ {QStringViewLiteral("template"), StackElement::Template},
+ {QStringViewLiteral("typesystem"), StackElement::Root},
+ {QStringViewLiteral("value-type"), StackElement::ValueTypeEntry},
+ };
+ENUM_LOOKUP_BINARY_SEARCH()
+
+static int indexOfAttribute(const QXmlStreamAttributes &atts,
+ QStringView name)
+{
+ for (int i = 0, size = atts.size(); i < size; ++i) {
+ if (atts.at(i).qualifiedName() == name)
+ return i;
}
- rejection.matchType = TypeRejection::ExcludeClass;
- database->addRejection(rejection);
- return true;
+ return -1;
}
+static QString msgMissingAttribute(const QString &a)
+{
+ return QLatin1String("Required attribute '") + a
+ + QLatin1String("' missing.");
+}
+
+static QString msgUnusedAttributes(const QStringRef &tag, const QXmlStreamAttributes &attributes)
+{
+ QString result;
+ QTextStream str(&result);
+ str << attributes.size() << " attributes(s) unused on <" << tag << ">: ";
+ for (int i = 0, size = attributes.size(); i < size; ++i) {
+ if (i)
+ str << ", ";
+ str << attributes.at(i).qualifiedName() << "=\"" << attributes.at(i).value() << '"';
+ }
+ return result;
+}
Handler::Handler(TypeDatabase* database, bool generate)
: m_database(database), m_generate(generate ? TypeEntry::GenerateAll : TypeEntry::GenerateForSubclass)
@@ -142,53 +384,6 @@ Handler::Handler(TypeDatabase* database, bool generate)
m_currentDroppedEntry = 0;
m_currentDroppedEntryDepth = 0;
m_ignoreDepth = 0;
-
- tagNames.insert(QLatin1String("rejection"), StackElement::Rejection);
- tagNames.insert(QLatin1String("custom-type"), StackElement::CustomTypeEntry);
- tagNames.insert(QLatin1String("primitive-type"), StackElement::PrimitiveTypeEntry);
- tagNames.insert(QLatin1String("container-type"), StackElement::ContainerTypeEntry);
- tagNames.insert(QLatin1String("object-type"), StackElement::ObjectTypeEntry);
- tagNames.insert(QLatin1String("value-type"), StackElement::ValueTypeEntry);
- tagNames.insert(QLatin1String("interface-type"), StackElement::InterfaceTypeEntry);
- tagNames.insert(QLatin1String("namespace-type"), StackElement::NamespaceTypeEntry);
- tagNames.insert(QLatin1String("enum-type"), StackElement::EnumTypeEntry);
- tagNames.insert(QLatin1String("smart-pointer-type"), StackElement::SmartPointerTypeEntry);
- tagNames.insert(QLatin1String("function"), StackElement::FunctionTypeEntry);
- tagNames.insert(QLatin1String("extra-includes"), StackElement::ExtraIncludes);
- tagNames.insert(QLatin1String("include"), StackElement::Include);
- tagNames.insert(QLatin1String("inject-code"), StackElement::InjectCode);
- tagNames.insert(QLatin1String("modify-function"), StackElement::ModifyFunction);
- tagNames.insert(QLatin1String("modify-field"), StackElement::ModifyField);
- tagNames.insert(QLatin1String("access"), StackElement::Access);
- tagNames.insert(QLatin1String("remove"), StackElement::Removal);
- tagNames.insert(QLatin1String("rename"), StackElement::Rename);
- tagNames.insert(QLatin1String("typesystem"), StackElement::Root);
- tagNames.insert(QLatin1String("custom-constructor"), StackElement::CustomMetaConstructor);
- tagNames.insert(QLatin1String("custom-destructor"), StackElement::CustomMetaDestructor);
- tagNames.insert(QLatin1String("argument-map"), StackElement::ArgumentMap);
- tagNames.insert(QLatin1String("suppress-warning"), StackElement::SuppressedWarning);
- tagNames.insert(QLatin1String("load-typesystem"), StackElement::LoadTypesystem);
- tagNames.insert(QLatin1String("define-ownership"), StackElement::DefineOwnership);
- tagNames.insert(QLatin1String("replace-default-expression"), StackElement::ReplaceDefaultExpression);
- tagNames.insert(QLatin1String("reject-enum-value"), StackElement::RejectEnumValue);
- tagNames.insert(QLatin1String("replace-type"), StackElement::ReplaceType);
- tagNames.insert(QLatin1String("conversion-rule"), StackElement::ConversionRule);
- tagNames.insert(QLatin1String("native-to-target"), StackElement::NativeToTarget);
- tagNames.insert(QLatin1String("target-to-native"), StackElement::TargetToNative);
- tagNames.insert(QLatin1String("add-conversion"), StackElement::AddConversion);
- tagNames.insert(QLatin1String("modify-argument"), StackElement::ModifyArgument);
- tagNames.insert(QLatin1String("remove-argument"), StackElement::RemoveArgument);
- tagNames.insert(QLatin1String("remove-default-expression"), StackElement::RemoveDefaultExpression);
- tagNames.insert(QLatin1String("template"), StackElement::Template);
- tagNames.insert(QLatin1String("insert-template"), StackElement::TemplateInstanceEnum);
- tagNames.insert(QLatin1String("replace"), StackElement::Replace);
- tagNames.insert(QLatin1String("no-null-pointer"), StackElement::NoNullPointers);
- tagNames.insert(QLatin1String("reference-count"), StackElement::ReferenceCount);
- tagNames.insert(QLatin1String("parent"), StackElement::ParentOwner);
- tagNames.insert(QLatin1String("array"), StackElement::Array);
- tagNames.insert(QLatin1String("inject-documentation"), StackElement::InjectDocumentation);
- tagNames.insert(QLatin1String("modify-documentation"), StackElement::ModifyDocumentation);
- tagNames.insert(QLatin1String("add-function"), StackElement::AddFunction);
}
static QString readerFileName(const QXmlStreamReader &reader)
@@ -197,22 +392,31 @@ static QString readerFileName(const QXmlStreamReader &reader)
return file != nullptr ? file->fileName() : QString();
}
-static QString msgReaderError(const QXmlStreamReader &reader, const QString &what)
+static QString msgReaderMessage(const QXmlStreamReader &reader,
+ const char *type,
+ const QString &what)
{
QString message;
QTextStream str(&message);
- str << "Error: ";
+ str << type << ": ";
const QString fileName = readerFileName(reader);
- if (!fileName.isEmpty())
- str << "file=" << QDir::toNativeSeparators(fileName) << ", ";
- str << "line=" << reader.lineNumber() << ", column=" << reader.columnNumber()
- << ", message=" << what;
+ if (fileName.isEmpty())
+ str << "<stdin>:";
+ else
+ str << QDir::toNativeSeparators(fileName) << ':';
+ str << reader.lineNumber() << ':' << reader.columnNumber()
+ << ": " << what;
return message;
}
-static QString msgReaderError(const QXmlStreamReader &reader)
+static QString msgReaderWarning(const QXmlStreamReader &reader, const QString &what)
+{
+ return msgReaderMessage(reader, "Warning", what);
+}
+
+static QString msgReaderError(const QXmlStreamReader &reader, const QString &what)
{
- return msgReaderError(reader, reader.errorString());
+ return msgReaderMessage(reader, "Error", what);
}
static QString msgInvalidVersion(const QStringRef &version, const QString &package = QString())
@@ -226,6 +430,53 @@ static QString msgInvalidVersion(const QStringRef &version, const QString &packa
return result;
}
+static bool addRejection(TypeDatabase *database, QXmlStreamAttributes *attributes,
+ QString *errorMessage)
+{
+ const int classIndex = indexOfAttribute(*attributes, classAttribute());
+ if (classIndex == -1) {
+ *errorMessage = msgMissingAttribute(classAttribute());
+ return false;
+ }
+
+ TypeRejection rejection;
+ const QString className = attributes->takeAt(classIndex).value().toString();
+ if (!setRejectionRegularExpression(className, &rejection.className, errorMessage))
+ return false;
+
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ const TypeRejection::MatchType type = typeRejectionFromAttribute(name);
+ switch (type) {
+ case TypeRejection::Function:
+ case TypeRejection::Field:
+ case TypeRejection::Enum:
+ case TypeRejection::ArgumentType:
+ case TypeRejection::ReturnType: {
+ const QString pattern = attributes->takeAt(i).value().toString();
+ if (!setRejectionRegularExpression(pattern, &rejection.pattern, errorMessage))
+ return false;
+ rejection.matchType = type;
+ database->addRejection(rejection);
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Special case: When all fields except class are empty, completely exclude class
+ if (className == QLatin1String("*")) {
+ *errorMessage = QLatin1String("bad reject entry, neither 'class', 'function-name'"
+ " nor 'field' specified");
+ return false;
+ }
+ rejection.matchType = TypeRejection::ExcludeClass;
+ database->addRejection(rejection);
+ return true;
+}
+
bool Handler::parse(QXmlStreamReader &reader)
{
m_error.clear();
@@ -238,10 +489,10 @@ bool Handler::parse(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::NoToken:
case QXmlStreamReader::Invalid:
- qCWarning(lcShiboken).noquote().nospace() << msgReaderError(reader);
+ m_error = msgReaderError(reader, reader.errorString());
return false;
case QXmlStreamReader::StartElement:
- if (!startElement(reader.name(), reader.attributes())) {
+ if (!startElement(reader)) {
m_error = msgReaderError(reader, m_error);
return false;
}
@@ -271,22 +522,6 @@ bool Handler::parse(QXmlStreamReader &reader)
return true;
}
-void Handler::fetchAttributeValues(const QString &name, const QXmlStreamAttributes &atts,
- QHash<QString, QString> *acceptedAttributes)
-{
- Q_ASSERT(acceptedAttributes);
-
- for (int i = 0; i < atts.length(); ++i) {
- const QString key = atts.at(i).name().toString().toLower();
- if (!acceptedAttributes->contains(key)) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("Unknown attribute for '%1': '%2'").arg(name, key);
- } else {
- acceptedAttributes->insert(key, atts.at(i).value().toString());
- }
- }
-}
-
bool Handler::endElement(const QStringRef &localName)
{
if (m_ignoreDepth) {
@@ -551,8 +786,9 @@ bool Handler::importFileElement(const QXmlStreamAttributes &atts)
return true;
}
-static bool convertBoolean(const QString &value, const QString &attributeName, bool defaultValue)
+static bool convertBoolean(QStringView value, const QString &attributeName, bool defaultValue)
{
+#ifdef QTBUG_69389_FIXED
if (value.compare(trueAttributeValue(), Qt::CaseInsensitive) == 0
|| value.compare(yesAttributeValue(), Qt::CaseInsensitive) == 0) {
return true;
@@ -561,28 +797,47 @@ static bool convertBoolean(const QString &value, const QString &attributeName, b
|| value.compare(noAttributeValue(), Qt::CaseInsensitive) == 0) {
return false;
}
+#else
+ if (QtPrivate::compareStrings(value, trueAttributeValue(), Qt::CaseInsensitive) == 0
+ || QtPrivate::compareStrings(value, yesAttributeValue(), Qt::CaseInsensitive) == 0) {
+ return true;
+ }
+ if (QtPrivate::compareStrings(value, falseAttributeValue(), Qt::CaseInsensitive) == 0
+ || QtPrivate::compareStrings(value, noAttributeValue(), Qt::CaseInsensitive) == 0) {
+ return false;
+ }
+#endif
const QString warn = QStringLiteral("Boolean value '%1' not supported in attribute '%2'. Use 'yes' or 'no'. Defaulting to '%3'.")
- .arg(value, attributeName,
+ .arg(value)
+ .arg(attributeName,
defaultValue ? yesAttributeValue() : noAttributeValue());
qCWarning(lcShiboken).noquote().nospace() << warn;
return defaultValue;
}
-static bool convertRemovalAttribute(const QString& removalAttribute, Modification& mod, QString& errorMsg)
+static bool convertRemovalAttribute(QStringView remove, Modification& mod, QString& errorMsg)
{
- QString remove = removalAttribute.toLower();
- if (!remove.isEmpty()) {
- if (remove == QLatin1String("all")) {
- mod.removal = TypeSystem::All;
- } else if (remove == QLatin1String("target")) {
- mod.removal = TypeSystem::TargetLangAndNativeCode;
- } else {
- errorMsg = QString::fromLatin1("Bad removal type '%1'").arg(remove);
- return false;
- }
+ if (remove.isEmpty())
+ return true;
+#ifdef QTBUG_69389_FIXED
+ if (remove.compare(QStringViewLiteral("all"), Qt::CaseInsensitive) == 0) {
+#else
+ if (QtPrivate::compareStrings(remove, QStringViewLiteral("all"), Qt::CaseInsensitive) == 0) {
+#endif
+ mod.removal = TypeSystem::All;
+ return true;
}
- return true;
+#ifdef QTBUG_69389_FIXED
+ if (remove.compare(QStringViewLiteral("target"), Qt::CaseInsensitive) == 0) {
+#else
+ if (QtPrivate::compareStrings(remove, QStringViewLiteral("target"), Qt::CaseInsensitive) == 0) {
+#endif
+ mod.removal = TypeSystem::TargetLangAndNativeCode;
+ return true;
+ }
+ errorMsg = QString::fromLatin1("Bad removal type '%1'").arg(remove);
+ return false;
}
static void getNamePrefixRecursive(StackElement* element, QStringList& names)
@@ -615,98 +870,1354 @@ static QString checkSignatureError(const QString& signature, const QString& tag)
return QString();
}
-void Handler::addFlags(const QString &name, QString flagName,
- const QHash<QString, QString> &attributes,
- const QVersionNumber &since)
+void Handler::applyCommonAttributes(TypeEntry *type, QXmlStreamAttributes *attributes) const
+{
+ type->setCodeGeneration(m_generate);
+ const int revisionIndex =
+ indexOfAttribute(*attributes, QStringViewLiteral("revision"));
+ if (revisionIndex != -1)
+ type->setRevision(attributes->takeAt(revisionIndex).value().toInt());
+}
+
+FlagsTypeEntry *
+ Handler::parseFlagsEntry(const QXmlStreamReader &,
+ EnumTypeEntry *enumEntry,
+ const QString &name, QString flagName,
+ const QVersionNumber &since,
+ QXmlStreamAttributes *attributes)
+
{
FlagsTypeEntry *ftype = new FlagsTypeEntry(QLatin1String("QFlags<") + name + QLatin1Char('>'), since);
- ftype->setOriginator(m_currentEnum);
+ ftype->setOriginator(enumEntry);
+ ftype->setTargetLangPackage(enumEntry->targetLangPackage());
// Try to get the guess the qualified flag name
const int lastSepPos = name.lastIndexOf(colonColon());
if (lastSepPos >= 0 && !flagName.contains(colonColon()))
flagName.prepend(name.left(lastSepPos + 2));
ftype->setOriginalName(flagName);
- ftype->setCodeGeneration(m_generate);
+ applyCommonAttributes(ftype, attributes);
QString n = ftype->originalName();
QStringList lst = n.split(colonColon());
- if (QStringList(lst.mid(0, lst.size() - 1)).join(colonColon()) != m_currentEnum->targetLangQualifier()) {
+ const QString &targetLangQualifier = enumEntry->targetLangQualifier();
+ if (QStringList(lst.mid(0, lst.size() - 1)).join(colonColon()) != targetLangQualifier) {
qCWarning(lcShiboken).noquote().nospace()
<< QStringLiteral("enum %1 and flags %2 differ in qualifiers")
- .arg(m_currentEnum->targetLangQualifier(), lst.constFirst());
+ .arg(targetLangQualifier, lst.constFirst());
}
ftype->setFlagsName(lst.constLast());
- m_currentEnum->setFlags(ftype);
+ enumEntry->setFlags(ftype);
m_database->addFlagsType(ftype);
m_database->addType(ftype);
- QString revision = attributes.value(QLatin1String("flags-revision"));
- if (revision.isEmpty())
- revision = attributes.value(QLatin1String("revision"));
- setTypeRevision(ftype, revision.toInt());
-}
+ const int revisionIndex =
+ indexOfAttribute(*attributes, QStringViewLiteral("flags-revision"));
+ ftype->setRevision(revisionIndex != -1
+ ? attributes->takeAt(revisionIndex).value().toInt()
+ : enumEntry->revision());
+ return ftype;
+}
+
+SmartPointerTypeEntry *
+ Handler::parseSmartPointerEntry(const QXmlStreamReader &,
+ const QString &name, const QVersionNumber &since,
+ QXmlStreamAttributes *attributes)
+{
+ QString smartPointerType;
+ QString getter;
+ QString refCountMethodName;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == QLatin1String("type")) {
+ smartPointerType = attributes->takeAt(i).value().toString();
+ } else if (name == QLatin1String("getter")) {
+ getter = attributes->takeAt(i).value().toString();
+ } else if (name == QLatin1String("ref-count-method")) {
+ refCountMethodName = attributes->takeAt(i).value().toString();
+ }
+ }
-bool Handler::handleSmartPointerEntry(StackElement *element,
- QHash<QString, QString> &attributes,
- const QString &name,
- const QVersionNumber &since)
-{
- QString smartPointerType = attributes[QLatin1String("type")];
if (smartPointerType.isEmpty()) {
m_error = QLatin1String("No type specified for the smart pointer. Currently supported types: 'shared',");
- return false;
+ return nullptr;
}
if (smartPointerType != QLatin1String("shared")) {
m_error = QLatin1String("Currently only the 'shared' type is supported.");
- return false;
+ return nullptr;
}
- QString getter = attributes[QLatin1String("getter")];
if (getter.isEmpty()) {
m_error = QLatin1String("No function getter name specified for getting the raw pointer held by the smart pointer.");
- return false;
+ return nullptr;
}
- QString refCountMethodName = attributes[QLatin1String("ref-count-method")];
QString signature = getter + QLatin1String("()");
-
signature = TypeDatabase::normalizedSignature(signature);
if (signature.isEmpty()) {
m_error = QLatin1String("No signature for the smart pointer getter found.");
- return false;
+ return nullptr;
}
QString errorString = checkSignatureError(signature,
QLatin1String("smart-pointer-type"));
if (!errorString.isEmpty()) {
m_error = errorString;
- return false;
+ return nullptr;
+ }
+
+ SmartPointerTypeEntry *type =
+ new SmartPointerTypeEntry(name, getter, smartPointerType, refCountMethodName, since);
+ applyCommonAttributes(type, attributes);
+ return type;
+}
+
+PrimitiveTypeEntry *
+ Handler::parsePrimitiveTypeEntry(const QXmlStreamReader &,
+ const QString &name, const QVersionNumber &since,
+ QXmlStreamAttributes *attributes)
+{
+ PrimitiveTypeEntry *type = new PrimitiveTypeEntry(name, since);
+ applyCommonAttributes(type, attributes);
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == QLatin1String("target-lang-name")) {
+ type->setTargetLangName(attributes->takeAt(i).value().toString());
+ } else if (name == QLatin1String("target-lang-api-name")) {
+ type->setTargetLangApiName(attributes->takeAt(i).value().toString());
+ } else if (name == preferredConversionAttribute()) {
+ const bool v = convertBoolean(attributes->takeAt(i).value(),
+ preferredConversionAttribute(), true);
+ type->setPreferredConversion(v);
+ } else if (name == preferredTargetLangTypeAttribute()) {
+ const bool v = convertBoolean(attributes->takeAt(i).value(),
+ preferredTargetLangTypeAttribute(), true);
+ type->setPreferredTargetLangType(v);
+ } else if (name == QLatin1String("default-constructor")) {
+ type->setDefaultConstructor(attributes->takeAt(i).value().toString());
+ }
}
- SmartPointerTypeEntry *type = new SmartPointerTypeEntry(name,
- getter,
- smartPointerType,
- refCountMethodName,
- since);
+ if (type->targetLangName().isEmpty())
+ type->setTargetLangName(type->name());
+ if (type->targetLangApiName().isEmpty())
+ type->setTargetLangApiName(type->name());
type->setTargetLangPackage(m_defaultPackage);
- type->setCodeGeneration(m_generate);
- element->entry = type;
+ return type;
+}
+
+ContainerTypeEntry *
+ Handler::parseContainerTypeEntry(const QXmlStreamReader &,
+ const QString &name, const QVersionNumber &since,
+ QXmlStreamAttributes *attributes)
+{
+ const int typeIndex = indexOfAttribute(*attributes, QStringViewLiteral("type"));
+ if (typeIndex == -1) {
+ m_error = QLatin1String("no 'type' attribute specified");
+ return nullptr;
+ }
+ const QStringRef typeName = attributes->takeAt(typeIndex).value();
+ ContainerTypeEntry::Type containerType = containerTypeFromAttribute(typeName);
+ if (containerType == ContainerTypeEntry::NoContainer) {
+ m_error = QLatin1String("there is no container of type ") + typeName.toString();
+ return nullptr;
+ }
+ ContainerTypeEntry *type = new ContainerTypeEntry(name, containerType, since);
+ applyCommonAttributes(type, attributes);
+ return type;
+}
+
+EnumTypeEntry *
+ Handler::parseEnumTypeEntry(const QXmlStreamReader &reader,
+ const QString &fullName, const QVersionNumber &since,
+ QXmlStreamAttributes *attributes)
+{
+ QString scope;
+ QString name = fullName;
+ const int sep = fullName.lastIndexOf(colonColon());
+ if (sep != -1) {
+ scope = fullName.left(sep);
+ name = fullName.right(fullName.size() - sep - 2);
+ }
+ EnumTypeEntry *entry = new EnumTypeEntry(scope, name, since);
+ applyCommonAttributes(entry, attributes);
+ entry->setTargetLangPackage(m_defaultPackage);
+
+ QString flagNames;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == QLatin1String("upper-bound")) {
+ entry->setUpperBound(attributes->takeAt(i).value().toString());
+ } else if (name == QLatin1String("lower-bound")) {
+ entry->setLowerBound(attributes->takeAt(i).value().toString());
+ } else if (name == forceIntegerAttribute()) {
+ const bool v = convertBoolean(attributes->takeAt(i).value(),
+ forceIntegerAttribute(), false);
+ entry->setForceInteger(v);
+ } else if (name == extensibleAttribute()) {
+ const bool v = convertBoolean(attributes->takeAt(i).value(),
+ extensibleAttribute(), false);
+ entry->setExtensible(v);
+ } else if (name == flagsAttribute()) {
+ flagNames = attributes->takeAt(i).value().toString();
+ }
+ }
+
+ // put in the flags parallel...
+ if (!flagNames.isEmpty()) {
+ const QStringList &flagNameList = flagNames.split(QLatin1Char(','));
+ for (const QString &flagName : flagNameList)
+ parseFlagsEntry(reader, entry, fullName, flagName.trimmed(), since, attributes);
+ }
+ return entry;
+}
+
+ObjectTypeEntry *
+ Handler::parseInterfaceTypeEntry(const QXmlStreamReader &,
+ const QString &name, const QVersionNumber &since,
+ QXmlStreamAttributes *attributes)
+{
+ ObjectTypeEntry *otype = new ObjectTypeEntry(name, since);
+ applyCommonAttributes(otype, attributes);
+ QString targetLangName = name;
+ bool generate = true;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == QLatin1String("target-lang-name")) {
+ targetLangName = attributes->takeAt(i).value().toString();
+ } else if (name == generateAttribute()) {
+ generate = convertBoolean(attributes->takeAt(i).value(),
+ generateAttribute(), true);
+ }
+ }
+
+ InterfaceTypeEntry *itype =
+ new InterfaceTypeEntry(InterfaceTypeEntry::interfaceName(targetLangName), since);
+
+ if (generate)
+ itype->setCodeGeneration(m_generate);
+ else
+ itype->setCodeGeneration(TypeEntry::GenerateForSubclass);
+
+ otype->setDesignatedInterface(itype);
+ itype->setOrigin(otype);
+ return otype;
+}
+
+ValueTypeEntry *
+ Handler::parseValueTypeEntry(const QXmlStreamReader &,
+ const QString &name, const QVersionNumber &since,
+ QXmlStreamAttributes *attributes)
+{
+ ValueTypeEntry *typeEntry = new ValueTypeEntry(name, since);
+ applyCommonAttributes(typeEntry, attributes);
+ const int defaultCtIndex =
+ indexOfAttribute(*attributes, QStringViewLiteral("default-constructor"));
+ if (defaultCtIndex != -1)
+ typeEntry->setDefaultConstructor(attributes->takeAt(defaultCtIndex).value().toString());
+ return typeEntry;
+}
+
+FunctionTypeEntry *
+ Handler::parseFunctionTypeEntry(const QXmlStreamReader &,
+ const QString &name, const QVersionNumber &since,
+ QXmlStreamAttributes *attributes)
+{
+ const int signatureIndex = indexOfAttribute(*attributes, signatureAttribute());
+ if (signatureIndex == -1) {
+ m_error = msgMissingAttribute(signatureAttribute());
+ return nullptr;
+ }
+ const QString signature =
+ TypeDatabase::normalizedSignature(attributes->takeAt(signatureIndex).value().toString());
+
+ TypeEntry *existingType = m_database->findType(name);
+
+ if (!existingType) {
+ FunctionTypeEntry *result = new FunctionTypeEntry(name, signature, since);
+ applyCommonAttributes(result, attributes);
+ return result;
+ }
+
+ if (existingType->type() != TypeEntry::FunctionType) {
+ m_error = QStringLiteral("%1 expected to be a function, but isn't! Maybe it was already declared as a class or something else.")
+ .arg(name);
+ return nullptr;
+ }
+
+ FunctionTypeEntry *result = reinterpret_cast<FunctionTypeEntry *>(existingType);
+ result->addSignature(signature);
+ return result;
+}
+
+void Handler::applyComplexTypeAttributes(const QXmlStreamReader &,
+ ComplexTypeEntry *ctype,
+ QXmlStreamAttributes *attributes) const
+{
+ bool generate = true;
+ ctype->setCopyable(ComplexTypeEntry::Unknown);
+
+ QString package = m_defaultPackage;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == streamAttribute()) {
+ ctype->setStream(convertBoolean(attributes->takeAt(i).value(), streamAttribute(), false));
+ } else if (name == generateAttribute()) {
+ generate = convertBoolean(attributes->takeAt(i).value(), generateAttribute(), true);
+ } else if (name ==packageAttribute()) {
+ package = attributes->takeAt(i).value().toString();
+ } else if (name == defaultSuperclassAttribute()) {
+ ctype->setDefaultSuperclass(attributes->takeAt(i).value().toString());
+ } else if (name == genericClassAttribute()) {
+ const bool v = convertBoolean(attributes->takeAt(i).value(), genericClassAttribute(), false);
+ ctype->setGenericClass(v);
+ } else if (name == QLatin1String("target-lang-name")) {
+ ctype->setTargetLangName(attributes->takeAt(i).value().toString());
+ } else if (name == QLatin1String("polymorphic-base")) {
+ ctype->setPolymorphicIdValue(attributes->takeAt(i).value().toString());
+ } else if (name == QLatin1String("polymorphic-id-expression")) {
+ ctype->setPolymorphicIdValue(attributes->takeAt(i).value().toString());
+ } else if (name == copyableAttribute()) {
+ const bool v = convertBoolean(attributes->takeAt(i).value(), copyableAttribute(), false);
+ ctype->setCopyable(v ? ComplexTypeEntry::CopyableSet : ComplexTypeEntry::NonCopyableSet);
+ } else if (name == QLatin1String("held-type")) {
+ ctype->setHeldType(attributes->takeAt(i).value().toString());
+ } else if (name == QLatin1String("hash-function")) {
+ ctype->setHashFunction(attributes->takeAt(i).value().toString());
+ } else if (name == forceAbstractAttribute()) {
+ if (convertBoolean(attributes->takeAt(i).value(), forceAbstractAttribute(), false))
+ ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::ForceAbstract);
+ } else if (name == deprecatedAttribute()) {
+ if (convertBoolean(attributes->takeAt(i).value(), deprecatedAttribute(), false))
+ ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::Deprecated);
+ } else if (name == deleteInMainThreadAttribute()) {
+ if (convertBoolean(attributes->takeAt(i).value(), deleteInMainThreadAttribute(), false))
+ ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::DeleteInMainThread);
+ } else if (name == QLatin1String("target-type")) {
+ ctype->setTargetType(attributes->takeAt(i).value().toString());
+ }
+ }
+
+ // The generator code relies on container's package being empty.
+ if (ctype->type() != TypeEntry::ContainerType)
+ ctype->setTargetLangPackage(package);
+
+ if (InterfaceTypeEntry *di = ctype->designatedInterface())
+ di->setTargetLangPackage(package);
+
+ if (generate)
+ ctype->setCodeGeneration(m_generate);
+ else
+ ctype->setCodeGeneration(TypeEntry::GenerateForSubclass);
+}
+
+bool Handler::parseRenameFunction(const QXmlStreamReader &,
+ QString *name, QXmlStreamAttributes *attributes)
+{
+ QString signature;
+ QString rename;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == signatureAttribute()) {
+ // Do not remove as it is needed for the type entry later on
+ signature = attributes->at(i).value().toString();
+ } else if (name == renameAttribute()) {
+ rename = attributes->takeAt(i).value().toString();
+ }
+ }
+
+ if (signature.isEmpty()) {
+ m_error = msgMissingAttribute(signatureAttribute());
+ return false;
+ }
+
+ *name = signature.left(signature.indexOf(QLatin1Char('('))).trimmed();
+
+ QString errorString = checkSignatureError(signature, QLatin1String("function"));
+ if (!errorString.isEmpty()) {
+ m_error = errorString;
+ return false;
+ }
+
+ if (!rename.isEmpty()) {
+ static const QRegularExpression functionNameRegExp(QLatin1String("^[a-zA-Z_][a-zA-Z0-9_]*$"));
+ Q_ASSERT(functionNameRegExp.isValid());
+ if (!functionNameRegExp.match(rename).hasMatch()) {
+ m_error = QLatin1String("can not rename '") + signature + QLatin1String("', '")
+ + rename + QLatin1String("' is not a valid function name");
+ return false;
+ }
+ FunctionModification mod;
+ if (!mod.setSignature(signature, &m_error))
+ return false;
+ mod.renamedToName = rename;
+ mod.modifiers |= Modification::Rename;
+ m_contextStack.top()->functionMods << mod;
+ }
+ return true;
+}
+
+bool Handler::parseInjectDocumentation(const QXmlStreamReader &,
+ QXmlStreamAttributes *attributes)
+{
+ const int validParent = StackElement::TypeEntryMask
+ | StackElement::ModifyFunction
+ | StackElement::ModifyField;
+ if (!m_current->parent || (m_current->parent->type & validParent) == 0) {
+ m_error = QLatin1String("inject-documentation must be inside modify-function, "
+ "modify-field or other tags that creates a type");
+ return false;
+ }
+
+ TypeSystem::DocModificationMode mode = TypeSystem::DocModificationReplace;
+ TypeSystem::Language lang = TypeSystem::NativeCode;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == QLatin1String("mode")) {
+ const QStringRef modeName = attributes->takeAt(i).value();
+ mode = docModificationFromAttribute(modeName);
+ if (mode == TypeSystem::DocModificationInvalid) {
+ m_error = QLatin1String("Unknown documentation injection mode: ") + modeName;
+ return false;
+ }
+ } else if (name == formatAttribute()) {
+ const QStringRef format = attributes->takeAt(i).value();
+ lang = languageFromAttribute(format);
+ if (lang != TypeSystem::TargetLangCode && lang != TypeSystem::NativeCode) {
+ m_error = QStringLiteral("unsupported class attribute: '%1'").arg(format);
+ return false;
+ }
+ }
+ }
+
+ QString signature = m_current->type & StackElement::TypeEntryMask
+ ? QString() : m_currentSignature;
+ DocModification mod(mode, signature);
+ mod.setFormat(lang);
+ m_contextStack.top()->docModifications << mod;
+ return true;
+}
+
+bool Handler::parseModifyDocumentation(const QXmlStreamReader &,
+ QXmlStreamAttributes *attributes)
+{
+ const int validParent = StackElement::TypeEntryMask
+ | StackElement::ModifyFunction
+ | StackElement::ModifyField;
+ if (!m_current->parent || (m_current->parent->type & validParent) == 0) {
+ m_error = QLatin1String("modify-documentation must be inside modify-function, "
+ "modify-field or other tags that creates a type");
+ return false;
+ }
+
+ const int xpathIndex = indexOfAttribute(*attributes, xPathAttribute());
+ if (xpathIndex == -1) {
+ m_error = msgMissingAttribute(xPathAttribute());
+ return false;
+ }
+
+ const QString xpath = attributes->takeAt(xpathIndex).value().toString();
+ QString signature = (m_current->type & StackElement::TypeEntryMask) ? QString() : m_currentSignature;
+ m_contextStack.top()->docModifications
+ << DocModification(xpath, signature);
+ return true;
+}
+
+TypeSystemTypeEntry *Handler::parseRootElement(const QXmlStreamReader &,
+ const QVersionNumber &since,
+ QXmlStreamAttributes *attributes)
+{
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == packageAttribute())
+ m_defaultPackage = attributes->takeAt(i).value().toString();
+ else if (name == defaultSuperclassAttribute())
+ m_defaultSuperclass = attributes->takeAt(i).value().toString();
+ }
+
+ TypeSystemTypeEntry* moduleEntry =
+ reinterpret_cast<TypeSystemTypeEntry*>(m_database->findType(m_defaultPackage));
+ if (!moduleEntry)
+ moduleEntry = new TypeSystemTypeEntry(m_defaultPackage, since);
+ moduleEntry->setCodeGeneration(m_generate);
+
+ if ((m_generate == TypeEntry::GenerateForSubclass ||
+ m_generate == TypeEntry::GenerateNothing) && !m_defaultPackage.isEmpty())
+ TypeDatabase::instance()->addRequiredTargetImport(m_defaultPackage);
+
+ if (!moduleEntry->qualifiedCppName().isEmpty())
+ m_database->addType(moduleEntry);
+ return moduleEntry;
+}
+
+bool Handler::loadTypesystem(const QXmlStreamReader &,
+ QXmlStreamAttributes *attributes)
+{
+ QString typeSystemName;
+ bool generateChild = true;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == nameAttribute())
+ typeSystemName = attributes->takeAt(i).value().toString();
+ else if (name == generateAttribute())
+ generateChild = convertBoolean(attributes->takeAt(i).value(), generateAttribute(), true);
+ }
+ if (typeSystemName.isEmpty()) {
+ m_error = QLatin1String("No typesystem name specified");
+ return false;
+ }
+ const bool result =
+ m_database->parseFile(typeSystemName, m_currentPath, generateChild
+ && m_generate == TypeEntry::GenerateAll);
+ if (!result)
+ m_error = QStringLiteral("Failed to parse: '%1'").arg(typeSystemName);
+ return result;
+}
+
+bool Handler::parseRejectEnumValue(const QXmlStreamReader &,
+ QXmlStreamAttributes *attributes)
+{
+ if (!m_currentEnum) {
+ m_error = QLatin1String("<reject-enum-value> node must be used inside a <enum-type> node");
+ return false;
+ }
+ const int nameIndex = indexOfAttribute(*attributes, nameAttribute());
+ if (nameIndex == -1) {
+ m_error = msgMissingAttribute(nameAttribute());
+ return false;
+ }
+ m_currentEnum->addEnumValueRejection(attributes->takeAt(nameIndex).value().toString());
+ return true;
+}
+
+bool Handler::parseReplaceArgumentType(const QXmlStreamReader &,
+ const StackElement &topElement,
+ QXmlStreamAttributes *attributes)
+{
+ if (topElement.type != StackElement::ModifyArgument) {
+ m_error = QLatin1String("Type replacement can only be specified for argument modifications");
+ return false;
+ }
+ const int modifiedTypeIndex = indexOfAttribute(*attributes, modifiedTypeAttribute());
+ if (modifiedTypeIndex == -1) {
+ m_error = QLatin1String("Type replacement requires 'modified-type' attribute");
+ return false;
+ }
+ m_contextStack.top()->functionMods.last().argument_mods.last().modified_type =
+ attributes->takeAt(modifiedTypeIndex).value().toString();
+ return true;
+}
+
+bool Handler::parseCustomConversion(const QXmlStreamReader &,
+ const StackElement &topElement,
+ QXmlStreamAttributes *attributes)
+{
+ if (topElement.type != StackElement::ModifyArgument
+ && topElement.type != StackElement::ValueTypeEntry
+ && topElement.type != StackElement::PrimitiveTypeEntry
+ && topElement.type != StackElement::ContainerTypeEntry) {
+ m_error = QLatin1String("Conversion rules can only be specified for argument modification, "
+ "value-type, primitive-type or container-type conversion.");
+ return false;
+ }
+
+ QString sourceFile;
+ TypeSystem::Language lang = TypeSystem::NativeCode;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == classAttribute()) {
+ const QStringRef languageAttribute = attributes->takeAt(i).value();
+ lang = languageFromAttribute(languageAttribute);
+ if (lang != TypeSystem::TargetLangCode && lang != TypeSystem::NativeCode) {
+ m_error = QStringLiteral("unsupported class attribute: '%1'").arg(languageAttribute);
+ return false;
+ }
+ } else if (name == QLatin1String("file")) {
+ sourceFile = attributes->takeAt(i).value().toString();
+ }
+ }
+
+ if (topElement.type == StackElement::ModifyArgument) {
+ CodeSnip snip;
+ snip.language = lang;
+ m_contextStack.top()->functionMods.last().argument_mods.last().conversion_rules.append(snip);
+ return true;
+ }
+
+ if (topElement.entry->hasConversionRule() || topElement.entry->hasCustomConversion()) {
+ m_error = QLatin1String("Types can have only one conversion rule");
+ return false;
+ }
+
+ // The old conversion rule tag that uses a file containing the conversion
+ // will be kept temporarily for compatibility reasons.
+ if (!sourceFile.isEmpty()) {
+ if (m_generate != TypeEntry::GenerateForSubclass
+ && m_generate != TypeEntry::GenerateNothing) {
+
+ const char* conversionFlag = NATIVE_CONVERSION_RULE_FLAG;
+ if (lang == TypeSystem::TargetLangCode)
+ conversionFlag = TARGET_CONVERSION_RULE_FLAG;
+
+ QFile conversionSource(sourceFile);
+ if (conversionSource.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ topElement.entry->setConversionRule(QLatin1String(conversionFlag) + QString::fromUtf8(conversionSource.readAll()));
+ } else {
+ qCWarning(lcShiboken).noquote().nospace()
+ << "File containing conversion code for "
+ << topElement.entry->name() << " type does not exist or is not readable: "
+ << sourceFile;
+ }
+ }
+ }
+
+ CustomConversion* customConversion = new CustomConversion(m_current->entry);
+ customConversionsForReview.append(customConversion);
+ return true;
+}
+
+bool Handler::parseAddConversion(const QXmlStreamReader &,
+ const StackElement &topElement,
+ QXmlStreamAttributes *attributes)
+{
+ if (topElement.type != StackElement::TargetToNative) {
+ m_error = QLatin1String("Target to Native conversions can only be added inside 'target-to-native' tags.");
+ return false;
+ }
+ QString sourceTypeName;
+ QString typeCheck;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == QLatin1String("type"))
+ sourceTypeName = attributes->takeAt(i).value().toString();
+ else if (name == QLatin1String("check"))
+ typeCheck = attributes->takeAt(i).value().toString();
+ }
+ if (sourceTypeName.isEmpty()) {
+ m_error = QLatin1String("Target to Native conversions must specify the input type with the 'type' attribute.");
+ return false;
+ }
+ m_current->entry->customConversion()->addTargetToNativeConversion(sourceTypeName, typeCheck);
+ m_contextStack.top()->codeSnips << CodeSnip();
+ return true;
+}
+
+static bool parseIndex(const QString &index, int *result, QString *errorMessage)
+{
+ bool ok = false;
+ *result = index.toInt(&ok);
+ if (!ok)
+ *errorMessage = QStringLiteral("Cannot convert '%1' to integer").arg(index);
+ return ok;
+}
+
+static bool parseArgumentIndex(const QString &index, int *result, QString *errorMessage)
+{
+ if (index == QLatin1String("return")) {
+ *result = 0;
+ return true;
+ }
+ if (index == QLatin1String("this")) {
+ *result = -1;
+ return true;
+ }
+ return parseIndex(index, result, errorMessage);
+}
+
+bool Handler::parseModifyArgument(const QXmlStreamReader &,
+ const StackElement &topElement, QXmlStreamAttributes *attributes)
+{
+ if (topElement.type != StackElement::ModifyFunction
+ && topElement.type != StackElement::AddFunction) {
+ m_error = QString::fromLatin1("argument modification requires function"
+ " modification as parent, was %1")
+ .arg(topElement.type, 0, 16);
+ return false;
+ }
+
+ QString index;
+ QString replaceValue;
+ bool resetAfterUse = false;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == indexAttribute()) {
+ index = attributes->takeAt(i).value().toString();
+ } else if (name == QLatin1String("replace-value")) {
+ replaceValue = attributes->takeAt(i).value().toString();
+ } else if (name == invalidateAfterUseAttribute()) {
+ resetAfterUse = convertBoolean(attributes->takeAt(i).value(),
+ invalidateAfterUseAttribute(), false);
+ }
+ }
+
+ if (index.isEmpty()) {
+ m_error = msgMissingAttribute(indexAttribute());
+ return false;
+ }
+
+ int idx;
+ if (!parseArgumentIndex(index, &idx, &m_error))
+ return false;
+
+ if (!replaceValue.isEmpty() && idx) {
+ m_error = QLatin1String("replace-value is only supported for return values (index=0).");
+ return false;
+ }
+
+ ArgumentModification argumentModification = ArgumentModification(idx);
+ argumentModification.replace_value = replaceValue;
+ argumentModification.resetAfterUse = resetAfterUse;
+ m_contextStack.top()->functionMods.last().argument_mods.append(argumentModification);
+ return true;
+}
+
+bool Handler::parseNoNullPointer(const QXmlStreamReader &,
+ const StackElement &topElement, QXmlStreamAttributes *attributes)
+{
+ if (topElement.type != StackElement::ModifyArgument) {
+ m_error = QLatin1String("no-null-pointer requires argument modification as parent");
+ return false;
+ }
+
+ ArgumentModification &lastArgMod = m_contextStack.top()->functionMods.last().argument_mods.last();
+ lastArgMod.noNullPointers = true;
+
+ const int defaultValueIndex =
+ indexOfAttribute(*attributes, QStringViewLiteral("default-value"));
+ if (defaultValueIndex != -1) {
+ if (lastArgMod.index == 0) {
+ lastArgMod.nullPointerDefaultValue =
+ attributes->takeAt(defaultValueIndex).value().toString();
+ } else {
+ qCWarning(lcShiboken)
+ << "default values for null pointer guards are only effective for return values";
+ }
+ }
+ return true;
+}
+
+bool Handler::parseDefineOwnership(const QXmlStreamReader &,
+ const StackElement &topElement,
+ QXmlStreamAttributes *attributes)
+{
+ if (topElement.type != StackElement::ModifyArgument) {
+ m_error = QLatin1String("define-ownership requires argument modification as parent");
+ return false;
+ }
+
+ TypeSystem::Language lang = TypeSystem::TargetLangCode;
+ QString ownership;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == classAttribute()) {
+ const QStringRef className = attributes->takeAt(i).value();
+ lang = languageFromAttribute(className);
+ if (lang != TypeSystem::TargetLangCode && lang != TypeSystem::NativeCode) {
+ m_error = QStringLiteral("unsupported class attribute: '%1'").arg(className);
+ return false;
+ }
+ } else if (name == ownershipAttribute()) {
+ ownership = attributes->takeAt(i).value().toString();
+ }
+ }
+ const TypeSystem::Ownership owner = ownershipFromFromAttribute(ownership);
+ if (owner == TypeSystem::InvalidOwnership) {
+ m_error = QStringLiteral("unsupported owner attribute: '%1'").arg(ownership);
+ return false;
+ }
+ m_contextStack.top()->functionMods.last().argument_mods.last().ownerships[lang] = owner;
+ return true;
+}
+
+bool Handler::parseArgumentMap(const QXmlStreamReader &,
+ const StackElement &topElement,
+ QXmlStreamAttributes *attributes)
+{
+ if (!(topElement.type & StackElement::CodeSnipMask)) {
+ m_error = QLatin1String("Argument maps requires code injection as parent");
+ return false;
+ }
+
+ int pos = 1;
+ QString metaName;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == indexAttribute()) {
+ if (!parseIndex(attributes->takeAt(i).value().toString(), &pos, &m_error))
+ return false;
+ if (pos <= 0) {
+ m_error = QStringLiteral("Argument position %1 must be a positive number").arg(pos);
+ return false;
+ }
+ } else if (name == QLatin1String("meta-name")) {
+ metaName = attributes->takeAt(i).value().toString();
+ }
+ }
+
+ if (metaName.isEmpty())
+ qCWarning(lcShiboken) << "Empty meta name in argument map";
+
+ if (topElement.type == StackElement::InjectCodeInFunction) {
+ m_contextStack.top()->functionMods.last().snips.last().argumentMap[pos] = metaName;
+ } else {
+ qCWarning(lcShiboken) << "Argument maps are only useful for injection of code "
+ "into functions.";
+ }
+ return true;
+}
+
+bool Handler::parseRemoval(const QXmlStreamReader &,
+ const StackElement &topElement,
+ QXmlStreamAttributes *attributes)
+{
+ if (topElement.type != StackElement::ModifyFunction) {
+ m_error = QLatin1String("Function modification parent required");
+ return false;
+ }
+
+ TypeSystem::Language lang = TypeSystem::All;
+ const int classIndex = indexOfAttribute(*attributes, classAttribute());
+ if (classIndex != -1) {
+ const QStringRef value = attributes->takeAt(classIndex).value();
+ lang = languageFromAttribute(value);
+ if (lang == TypeSystem::TargetLangCode) // "target" means TargetLangAndNativeCode here
+ lang = TypeSystem::TargetLangAndNativeCode;
+ if (lang != TypeSystem::TargetLangAndNativeCode && lang != TypeSystem::All) {
+ m_error = QStringLiteral("unsupported class attribute: '%1'").arg(value);
+ return false;
+ }
+ }
+ m_contextStack.top()->functionMods.last().removal = lang;
+ return true;
+}
+
+bool Handler::parseRename(const QXmlStreamReader &,
+ StackElement::ElementType type,
+ const StackElement &topElement,
+ QXmlStreamAttributes *attributes)
+{
+ if (topElement.type != StackElement::ModifyField
+ && topElement.type != StackElement::ModifyFunction
+ && topElement.type != StackElement::ModifyArgument) {
+ m_error = QLatin1String("Function, field or argument modification parent required");
+ return false;
+ }
+
+ Modification *mod = nullptr;
+ if (topElement.type == StackElement::ModifyFunction)
+ mod = &m_contextStack.top()->functionMods.last();
+ else if (topElement.type == StackElement::ModifyField)
+ mod = &m_contextStack.top()->fieldMods.last();
+
+ Modification::Modifiers modifierFlag = Modification::Rename;
+ if (type == StackElement::Rename) {
+ const int toIndex = indexOfAttribute(*attributes, toAttribute());
+ if (toIndex == -1) {
+ m_error = msgMissingAttribute(toAttribute());
+ return false;
+ }
+ const QString renamed_to = attributes->takeAt(toIndex).value().toString();
+ if (topElement.type == StackElement::ModifyFunction)
+ mod->setRenamedTo(renamed_to);
+ else if (topElement.type == StackElement::ModifyField)
+ mod->setRenamedTo(renamed_to);
+ else
+ m_contextStack.top()->functionMods.last().argument_mods.last().renamed_to = renamed_to;
+ } else {
+ const int modifierIndex = indexOfAttribute(*attributes, modifierAttribute());
+ if (modifierIndex == -1) {
+ m_error = msgMissingAttribute(modifierAttribute());
+ return false;
+ }
+ const QStringRef modifier = attributes->takeAt(modifierIndex).value();
+ modifierFlag = modifierFromAttribute(modifier);
+ if (modifierFlag == Modification::InvalidModifier) {
+ m_error = QStringLiteral("Unknown access modifier: '%1'").arg(modifier);
+ return false;
+ }
+ }
+
+ if (mod)
+ mod->modifiers |= modifierFlag;
+ return true;
+}
+
+bool Handler::parseModifyField(const QXmlStreamReader &,
+ QXmlStreamAttributes *attributes)
+{
+ FieldModification fm;
+ fm.modifiers = FieldModification::Readable | FieldModification::Writable;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == nameAttribute()) {
+ fm.name = attributes->takeAt(i).value().toString();
+ } else if (name == removeAttribute()) {
+ if (!convertRemovalAttribute(attributes->takeAt(i).value(), fm, m_error))
+ return false;
+ } else if (name == readAttribute()) {
+ if (!convertBoolean(attributes->takeAt(i).value(), readAttribute(), true))
+ fm.modifiers &= ~FieldModification::Readable;
+ } else if (name == writeAttribute()) {
+ if (!convertBoolean(attributes->takeAt(i).value(), writeAttribute(), true))
+ fm.modifiers &= ~FieldModification::Writable;
+ }
+ }
+ if (fm.name.isEmpty()) {
+ m_error = msgMissingAttribute(nameAttribute());
+ return false;
+ }
+ m_contextStack.top()->fieldMods << fm;
+ return true;
+}
+
+bool Handler::parseAddFunction(const QXmlStreamReader &,
+ const StackElement &topElement,
+ QXmlStreamAttributes *attributes)
+{
+ if (!(topElement.type & (StackElement::ComplexTypeEntryMask | StackElement::Root))) {
+ m_error = QString::fromLatin1("Add function requires a complex type or a root tag as parent"
+ ", was=%1").arg(topElement.type, 0, 16);
+ return false;
+ }
+ QString originalSignature;
+ QString returnType = QLatin1String("void");
+ bool staticFunction = false;
+ QString access;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == QLatin1String("signature")) {
+ originalSignature = attributes->takeAt(i).value().toString();
+ } else if (name == QLatin1String("return-type")) {
+ returnType = attributes->takeAt(i).value().toString();
+ } else if (name == staticAttribute()) {
+ staticFunction = convertBoolean(attributes->takeAt(i).value(),
+ staticAttribute(), false);
+ } else if (name == accessAttribute()) {
+ access = attributes->takeAt(i).value().toString();
+ }
+ }
+
+ QString signature = TypeDatabase::normalizedSignature(originalSignature);
+ if (signature.isEmpty()) {
+ m_error = QLatin1String("No signature for the added function");
+ return false;
+ }
+
+ QString errorString = checkSignatureError(signature, QLatin1String("add-function"));
+ if (!errorString.isEmpty()) {
+ m_error = errorString;
+ return false;
+ }
+
+ AddedFunction func(signature, returnType);
+ func.setStatic(staticFunction);
+ if (!signature.contains(QLatin1Char('(')))
+ signature += QLatin1String("()");
+ m_currentSignature = signature;
+
+ if (!access.isEmpty()) {
+ const AddedFunction::Access a = addedFunctionAccessFromAttribute(access);
+ if (a == AddedFunction::InvalidAccess) {
+ m_error = QString::fromLatin1("Bad access type '%1'").arg(access);
+ return false;
+ }
+ func.setAccess(a);
+ }
+
+ m_contextStack.top()->addedFunctions << func;
+
+ FunctionModification mod;
+ if (!mod.setSignature(m_currentSignature, &m_error))
+ return false;
+ mod.setOriginalSignature(originalSignature);
+ m_contextStack.top()->functionMods << mod;
+ return true;
+}
+
+bool Handler::parseModifyFunction(const QXmlStreamReader &,
+ const StackElement &topElement,
+ QXmlStreamAttributes *attributes)
+{
+ if (!(topElement.type & StackElement::ComplexTypeEntryMask)) {
+ m_error = QString::fromLatin1("Modify function requires complex type as parent"
+ ", was=%1").arg(topElement.type, 0, 16);
+ return false;
+ }
+
+ QString originalSignature;
+ QString access;
+ QString removal;
+ QString rename;
+ QString association;
+ bool deprecated = false;
+ bool isThread = false;
+ bool allowThread = false;
+ bool virtualSlot = false;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == QLatin1String("signature")) {
+ originalSignature = attributes->takeAt(i).value().toString();
+ } else if (name == accessAttribute()) {
+ access = attributes->takeAt(i).value().toString();
+ } else if (name == renameAttribute()) {
+ rename = attributes->takeAt(i).value().toString();
+ } else if (name == QLatin1String("associated-to")) {
+ association = attributes->takeAt(i).value().toString();
+ } else if (name == removeAttribute()) {
+ removal = attributes->takeAt(i).value().toString();
+ } else if (name == deprecatedAttribute()) {
+ deprecated = convertBoolean(attributes->takeAt(i).value(),
+ deprecatedAttribute(), false);
+ } else if (name == threadAttribute()) {
+ isThread = convertBoolean(attributes->takeAt(i).value(),
+ threadAttribute(), false);
+ } else if (name == allowThreadAttribute()) {
+ allowThread = convertBoolean(attributes->takeAt(i).value(),
+ allowThreadAttribute(), false);
+ } else if (name == virtualSlotAttribute()) {
+ virtualSlot = convertBoolean(attributes->takeAt(i).value(),
+ virtualSlotAttribute(), false);
+ }
+ }
+
+ const QString signature = TypeDatabase::normalizedSignature(originalSignature);
+ if (signature.isEmpty()) {
+ m_error = QLatin1String("No signature for modified function");
+ return false;
+ }
+
+ QString errorString = checkSignatureError(signature, QLatin1String("modify-function"));
+ if (!errorString.isEmpty()) {
+ m_error = errorString;
+ return false;
+ }
+
+ FunctionModification mod;
+ if (!mod.setSignature(signature, &m_error))
+ return false;
+ mod.setOriginalSignature(originalSignature);
+ m_currentSignature = signature;
+
+ if (!access.isEmpty()) {
+ const Modification::Modifiers m = modifierFromAttribute(access);
+ if ((m & (Modification::AccessModifierMask | Modification::FinalMask)) == 0) {
+ m_error = QString::fromLatin1("Bad access type '%1'").arg(access);
+ return false;
+ }
+ mod.modifiers |= m;
+ }
+
+ if (deprecated)
+ mod.modifiers |= Modification::Deprecated;
+
+ if (!removal.isEmpty() && !convertRemovalAttribute(removal, mod, m_error))
+ return false;
+
+ if (!rename.isEmpty()) {
+ mod.renamedToName = rename;
+ mod.modifiers |= Modification::Rename;
+ }
+
+ if (!association.isEmpty())
+ mod.association = association;
+
+ mod.setIsThread(isThread);
+ mod.setAllowThread(allowThread);
+ if (virtualSlot)
+ mod.modifiers |= Modification::VirtualSlot;
+
+ m_contextStack.top()->functionMods << mod;
+ return true;
+}
+
+bool Handler::parseReplaceDefaultExpression(const QXmlStreamReader &,
+ const StackElement &topElement,
+ QXmlStreamAttributes *attributes)
+{
+ if (!(topElement.type & StackElement::ModifyArgument)) {
+ m_error = QLatin1String("Replace default expression only allowed as child of argument modification");
+ return false;
+ }
+ const int withIndex = indexOfAttribute(*attributes, QStringViewLiteral("with"));
+ if (withIndex == -1 || attributes->at(withIndex).value().isEmpty()) {
+ m_error = QLatin1String("Default expression replaced with empty string. Use remove-default-expression instead.");
+ return false;
+ }
+
+ m_contextStack.top()->functionMods.last().argument_mods.last().replacedDefaultExpression =
+ attributes->takeAt(withIndex).value().toString();
+ return true;
+}
+
+CustomFunction *
+ Handler::parseCustomMetaConstructor(const QXmlStreamReader &,
+ StackElement::ElementType type,
+ const StackElement &topElement,
+ QXmlStreamAttributes *attributes)
+{
+ QString functionName = topElement.entry->name().toLower()
+ + (type == StackElement::CustomMetaConstructor
+ ? QLatin1String("_create") : QLatin1String("_delete"));
+ QString paramName = QLatin1String("copy");
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == nameAttribute())
+ functionName = attributes->takeAt(i).value().toString();
+ else if (name == QLatin1String("param-name"))
+ paramName = attributes->takeAt(i).value().toString();
+ }
+ CustomFunction *func = new CustomFunction(functionName);
+ func->paramName = paramName;
+ return func;
+}
+
+bool Handler::parseReferenceCount(const QXmlStreamReader &,
+ const StackElement &topElement,
+ QXmlStreamAttributes *attributes)
+{
+ if (topElement.type != StackElement::ModifyArgument) {
+ m_error = QLatin1String("reference-count must be child of modify-argument");
+ return false;
+ }
+
+ ReferenceCount rc;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == actionAttribute()) {
+ const QStringRef action = attributes->takeAt(i).value();
+ rc.action = referenceCountFromAttribute(action);
+ if (rc.action == ReferenceCount::Invalid) {
+ m_error = QLatin1String("unrecognized value '") + action
+ + QLatin1String("' for action attribute.");
+ return false;
+ }
+ } else if (name == QLatin1String("variable-name")) {
+ rc.varName = attributes->takeAt(i).value().toString();
+ }
+ }
+
+ m_contextStack.top()->functionMods.last().argument_mods.last().referenceCounts.append(rc);
+ return true;
+}
+
+bool Handler::parseParentOwner(const QXmlStreamReader &,
+ const StackElement &topElement,
+ QXmlStreamAttributes *attributes)
+{
+ if (topElement.type != StackElement::ModifyArgument) {
+ m_error = QLatin1String("parent-policy must be child of modify-argument");
+ return false;
+ }
+ ArgumentOwner ao;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == indexAttribute()) {
+ const QString index = attributes->takeAt(i).value().toString();
+ if (!parseArgumentIndex(index, &ao.index, &m_error))
+ return false;
+ } else if (name == actionAttribute()) {
+ const QStringRef action = attributes->takeAt(i).value();
+ ao.action = argumentOwnerActionFromAttribute(action);
+ if (ao.action == ArgumentOwner::Invalid) {
+ m_error = QLatin1String("Invalid parent actionr '") + action + QLatin1String("'.");
+ return false;
+ }
+ }
+ }
+ m_contextStack.top()->functionMods.last().argument_mods.last().owner = ao;
+ return true;
+}
+
+bool Handler::parseInjectCode(const QXmlStreamReader &,
+ const StackElement &topElement,
+ StackElement* element, QXmlStreamAttributes *attributes)
+{
+ if (!(topElement.type & StackElement::ComplexTypeEntryMask)
+ && (topElement.type != StackElement::AddFunction)
+ && (topElement.type != StackElement::ModifyFunction)
+ && (topElement.type != StackElement::Root)) {
+ m_error = QLatin1String("wrong parent type for code injection");
+ return false;
+ }
+
+ TypeSystem::CodeSnipPosition position = TypeSystem::CodeSnipPositionBeginning;
+ TypeSystem::Language lang = TypeSystem::TargetLangCode;
+ QString fileName;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == classAttribute()) {
+ const QStringRef className = attributes->takeAt(i).value();
+ lang = languageFromAttribute(className);
+ if (lang == TypeSystem::NoLanguage) {
+ m_error = QStringLiteral("Invalid class specifier: '%1'").arg(className);
+ return false;
+ }
+ } else if (name == positionAttribute()) {
+ const QStringRef value = attributes->takeAt(i).value();
+ position = codeSnipPositionFromAttribute(value);
+ if (position == TypeSystem::CodeSnipPositionInvalid) {
+ m_error = QStringLiteral("Invalid position: '%1'").arg(value);
+ return false;
+ }
+ } else if (name == QLatin1String("file")) {
+ fileName = attributes->takeAt(i).value().toString();
+ }
+ }
+
+ CodeSnip snip;
+ snip.position = position;
+ snip.language = lang;
+ bool in_file = false;
+
+ // Handler constructor....
+ if (m_generate != TypeEntry::GenerateForSubclass &&
+ m_generate != TypeEntry::GenerateNothing &&
+ !fileName.isEmpty()) {
+ const QString resolved = m_database->modifiedTypesystemFilepath(fileName, m_currentPath);
+ if (QFile::exists(resolved)) {
+ QFile codeFile(resolved);
+ if (codeFile.open(QIODevice::Text | QIODevice::ReadOnly)) {
+ QString content = QLatin1String("// ========================================================================\n"
+ "// START of custom code block [file: ");
+ content += fileName;
+ content += QLatin1String("]\n");
+ content += QString::fromUtf8(codeFile.readAll());
+ content += QLatin1String("\n// END of custom code block [file: ");
+ content += fileName;
+ content += QLatin1String("]\n// ========================================================================\n");
+ snip.addCode(content);
+ in_file = true;
+ }
+ } else {
+ qCWarning(lcShiboken).noquote().nospace()
+ << "File for inject code not exist: " << QDir::toNativeSeparators(fileName);
+ }
+
+ }
+
+ if (snip.language == TypeSystem::Interface
+ && topElement.type != StackElement::InterfaceTypeEntry) {
+ m_error = QLatin1String("Interface code injections must be direct child of an interface type entry");
+ return false;
+ }
+
+ if (topElement.type == StackElement::ModifyFunction
+ || topElement.type == StackElement::AddFunction) {
+ if (snip.language == TypeSystem::ShellDeclaration) {
+ m_error = QLatin1String("no function implementation in shell declaration in which to inject code");
+ return false;
+ }
+
+ FunctionModification &mod = m_contextStack.top()->functionMods.last();
+ mod.snips << snip;
+ if (in_file)
+ mod.modifiers |= FunctionModification::CodeInjection;
+ element->type = StackElement::InjectCodeInFunction;
+ } else if (topElement.type == StackElement::Root) {
+ element->entry->addCodeSnip(snip);
+ } else if (topElement.type != StackElement::Root) {
+ m_contextStack.top()->codeSnips << snip;
+ }
+ return true;
+}
+
+bool Handler::parseInclude(const QXmlStreamReader &,
+ const StackElement &topElement,
+ TypeEntry *entry, QXmlStreamAttributes *attributes)
+{
+ QString fileName;
+ QString location;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == QLatin1String("file-name"))
+ fileName = attributes->takeAt(i).value().toString();
+ else if (name == locationAttribute())
+ location = attributes->takeAt(i).value().toString();
+ }
+ const Include::IncludeType loc = locationFromAttribute(location);
+ if (loc == Include::InvalidInclude) {
+ m_error = QStringLiteral("Location not recognized: '%1'").arg(location);
+ return false;
+ }
+
+ Include inc(loc, fileName);
+ if (topElement.type
+ & (StackElement::ComplexTypeEntryMask | StackElement::PrimitiveTypeEntry)) {
+ entry->setInclude(inc);
+ } else if (topElement.type == StackElement::ExtraIncludes) {
+ entry->addExtraInclude(inc);
+ } else {
+ m_error = QLatin1String("Only supported parent tags are primitive-type, complex types or extra-includes");
+ return false;
+ }
+ if (InterfaceTypeEntry *di = entry->designatedInterface()) {
+ di->setInclude(entry->include());
+ di->setExtraIncludes(entry->extraIncludes());
+ }
+ return true;
+}
+
+TemplateInstance *
+ Handler::parseTemplateInstanceEnum(const QXmlStreamReader &,
+ const StackElement &topElement,
+ QXmlStreamAttributes *attributes)
+{
+ if (!(topElement.type & StackElement::CodeSnipMask) &&
+ (topElement.type != StackElement::Template) &&
+ (topElement.type != StackElement::CustomMetaConstructor) &&
+ (topElement.type != StackElement::CustomMetaDestructor) &&
+ (topElement.type != StackElement::NativeToTarget) &&
+ (topElement.type != StackElement::AddConversion) &&
+ (topElement.type != StackElement::ConversionRule)) {
+ m_error = QLatin1String("Can only insert templates into code snippets, templates, custom-constructors, "\
+ "custom-destructors, conversion-rule, native-to-target or add-conversion tags.");
+ return nullptr;
+ }
+ const int nameIndex = indexOfAttribute(*attributes, nameAttribute());
+ if (nameIndex == -1) {
+ m_error = msgMissingAttribute(nameAttribute());
+ return nullptr;
+ }
+ return new TemplateInstance(attributes->takeAt(nameIndex).value().toString());
+}
+
+bool Handler::parseReplace(const QXmlStreamReader &,
+ const StackElement &topElement,
+ StackElement *element, QXmlStreamAttributes *attributes)
+{
+ if (topElement.type != StackElement::TemplateInstanceEnum) {
+ m_error = QLatin1String("Can only insert replace rules into insert-template.");
+ return false;
+ }
+ QString from;
+ QString to;
+ for (int i = attributes->size() - 1; i >= 0; --i) {
+ const QStringRef name = attributes->at(i).qualifiedName();
+ if (name == QLatin1String("from"))
+ from = attributes->takeAt(i).value().toString();
+ else if (name == toAttribute())
+ to = attributes->takeAt(i).value().toString();
+ }
+ element->parent->value.templateInstance->addReplaceRule(from, to);
return true;
}
-bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts)
+bool Handler::startElement(const QXmlStreamReader &reader)
{
if (m_ignoreDepth) {
++m_ignoreDepth;
return true;
}
+ const QStringRef tagName = reader.name();
+ QXmlStreamAttributes attributes = reader.attributes();
+
QVersionNumber since(0, 0);
- const QStringRef sinceSpec = atts.value(sinceAttribute());
- if (!sinceSpec.isNull()) {
+ int index = indexOfAttribute(attributes, sinceAttribute());
+ if (index != -1) {
+ const QStringRef sinceSpec = attributes.takeAt(index).value();
since = QVersionNumber::fromString(sinceSpec.toString());
if (since.isNull()) {
m_error = msgInvalidVersion(sinceSpec, m_defaultPackage);
@@ -722,12 +2233,11 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts
}
}
- const QString tagName = n.toString().toLower();
- if (tagName == QLatin1String("import-file"))
- return importFileElement(atts);
+ if (tagName.compare(QLatin1String("import-file"), Qt::CaseInsensitive) == 0)
+ return importFileElement(attributes);
- const QHash<QString, StackElement::ElementType>::const_iterator tit = tagNames.constFind(tagName);
- if (tit == tagNames.constEnd()) {
+ const StackElement::ElementType elementType = elementFromTag(tagName);
+ if (elementType == StackElement::None) {
m_error = QStringLiteral("Unknown tag name: '%1'").arg(tagName);
return false;
}
@@ -738,7 +2248,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts
}
StackElement* element = new StackElement(m_current);
- element->type = tit.value();
+ element->type = elementType;
if (element->type == StackElement::Root && m_generate == TypeEntry::GenerateAll)
customConversionsForReview.clear();
@@ -753,77 +2263,22 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts
}
if (element->type & StackElement::TypeEntryMask) {
- QHash<QString, QString> attributes;
- attributes.insert(nameAttribute(), QString());
- attributes.insert(QLatin1String("revision"), QLatin1String("0"));
- attributes.insert(sinceAttribute(), QString()); // dummy for matching allowed attributes
-
- switch (element->type) {
- case StackElement::PrimitiveTypeEntry:
- attributes.insert(QLatin1String("target-lang-name"), QString());
- attributes.insert(QLatin1String("target-lang-api-name"), QString());
- attributes.insert(QLatin1String("preferred-conversion"), yesAttributeValue());
- attributes.insert(QLatin1String("preferred-target-lang-type"), yesAttributeValue());
- attributes.insert(QLatin1String("default-constructor"), QString());
- break;
- case StackElement::ContainerTypeEntry:
- attributes.insert(QLatin1String("type"), QString());
- break;
- case StackElement::SmartPointerTypeEntry:
- attributes.insert(QLatin1String("type"), QString());
- attributes.insert(QLatin1String("getter"), QString());
- attributes.insert(QLatin1String("ref-count-method"), QString());
- break;
- case StackElement::EnumTypeEntry:
- attributes.insert(flagsAttribute(), QString());
- attributes.insert(QLatin1String("flags-revision"), QString());
- attributes.insert(QLatin1String("upper-bound"), QString());
- attributes.insert(QLatin1String("lower-bound"), QString());
- attributes.insert(QLatin1String("force-integer"), noAttributeValue());
- attributes.insert(QLatin1String("extensible"), noAttributeValue());
- attributes.insert(enumIdentifiedByValueAttribute(), QString());
- attributes.insert(classAttribute(), falseAttributeValue());
- break;
- case StackElement::ValueTypeEntry:
- attributes.insert(QLatin1String("default-constructor"), QString());
- Q_FALLTHROUGH();
- case StackElement::ObjectTypeEntry:
- attributes.insert(QLatin1String("force-abstract"), noAttributeValue());
- attributes.insert(QLatin1String("deprecated"), noAttributeValue());
- attributes.insert(QLatin1String("hash-function"), QString());
- attributes.insert(QLatin1String("stream"), noAttributeValue());
- Q_FALLTHROUGH();
- case StackElement::InterfaceTypeEntry:
- attributes[QLatin1String("default-superclass")] = m_defaultSuperclass;
- attributes.insert(QLatin1String("polymorphic-id-expression"), QString());
- attributes.insert(QLatin1String("delete-in-main-thread"), noAttributeValue());
- attributes.insert(QLatin1String("held-type"), QString());
- attributes.insert(QLatin1String("copyable"), QString());
- Q_FALLTHROUGH();
- case StackElement::NamespaceTypeEntry:
- attributes.insert(QLatin1String("target-lang-name"), QString());
- attributes[QLatin1String("package")] = m_defaultPackage;
- attributes.insert(QLatin1String("expense-cost"), QLatin1String("1"));
- attributes.insert(QLatin1String("expense-limit"), QLatin1String("none"));
- attributes.insert(QLatin1String("polymorphic-base"), noAttributeValue());
- attributes.insert(QLatin1String("generate"), yesAttributeValue());
- attributes.insert(QLatin1String("target-type"), QString());
- attributes.insert(QLatin1String("generic-class"), noAttributeValue());
- break;
- case StackElement::FunctionTypeEntry:
- attributes.insert(QLatin1String("signature"), QString());
- attributes.insert(QLatin1String("rename"), QString());
- break;
- default:
- { } // nada
- };
-
- fetchAttributeValues(tagName, atts, &attributes);
- QString name = attributes[nameAttribute()];
+ QString name;
+ if (element->type != StackElement::FunctionTypeEntry) {
+ const int nameIndex = indexOfAttribute(attributes, nameAttribute());
+ if (nameIndex != -1) {
+ name = attributes.takeAt(nameIndex).value().toString();
+ } else if (element->type != StackElement::EnumTypeEntry) { // anonymous enum?
+ m_error = msgMissingAttribute(nameAttribute());
+ return false;
+ }
+ }
if (m_database->hasDroppedTypeEntries()) {
QString identifier = getNamePrefix(element) + QLatin1Char('.');
- identifier += (element->type == StackElement::FunctionTypeEntry ? attributes[QLatin1String("signature")] : name);
+ identifier += element->type == StackElement::FunctionTypeEntry
+ ? attributes.value(signatureAttribute()).toString()
+ : name;
if (m_database->shouldDropTypeEntry(identifier)) {
m_currentDroppedEntry = element;
m_currentDroppedEntryDepth = 1;
@@ -837,30 +2292,9 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts
// The top level tag 'function' has only the 'signature' tag
// and we should extract the 'name' value from it.
- if (element->type == StackElement::FunctionTypeEntry) {
- QString signature = attributes[QLatin1String("signature")];
- name = signature.left(signature.indexOf(QLatin1Char('('))).trimmed();
- QString errorString = checkSignatureError(signature, QLatin1String("function"));
- if (!errorString.isEmpty()) {
- m_error = errorString;
+ if (element->type == StackElement::FunctionTypeEntry
+ && !parseRenameFunction(reader, &name, &attributes)) {
return false;
- }
- QString rename = attributes[QLatin1String("rename")];
- if (!rename.isEmpty()) {
- static const QRegularExpression functionNameRegExp(QLatin1String("^[a-zA-Z_][a-zA-Z0-9_]*$"));
- Q_ASSERT(functionNameRegExp.isValid());
- if (!functionNameRegExp.match(rename).hasMatch()) {
- m_error = QLatin1String("can not rename '") + signature + QLatin1String("', '")
- + rename + QLatin1String("' is not a valid function name");
- return false;
- }
- FunctionModification mod;
- if (!mod.setSignature(signature, &m_error))
- return false;
- mod.renamedToName = attributes[QLatin1String("rename")];
- mod.modifiers |= Modification::Rename;
- m_contextStack.top()->functionMods << mod;
- }
}
// We need to be able to have duplicate primitive type entries,
@@ -875,7 +2309,9 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts
}
if (element->type == StackElement::EnumTypeEntry) {
- const QString identifiedByValue = attributes.value(enumIdentifiedByValueAttribute());
+ const int enumIdentifiedByIndex = indexOfAttribute(attributes, enumIdentifiedByValueAttribute());
+ const QString identifiedByValue = enumIdentifiedByIndex != -1
+ ? attributes.takeAt(enumIdentifiedByIndex).value().toString() : QString();
if (name.isEmpty()) {
name = identifiedByValue;
} else if (!identifiedByValue.isEmpty()) {
@@ -900,281 +2336,83 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts
case StackElement::CustomTypeEntry:
element->entry = new TypeEntry(name, TypeEntry::CustomType, since);
break;
- case StackElement::PrimitiveTypeEntry: {
- QString targetLangName = attributes[QLatin1String("target-lang-name")];
- QString targetLangApiName = attributes[QLatin1String("target-lang-api-name")];
- QString preferredConversion = attributes[QLatin1String("preferred-conversion")].toLower();
- QString preferredTargetLangType = attributes[QLatin1String("preferred-target-lang-type")].toLower();
- QString defaultConstructor = attributes[QLatin1String("default-constructor")];
-
- if (targetLangName.isEmpty())
- targetLangName = name;
- if (targetLangApiName.isEmpty())
- targetLangApiName = name;
-
- PrimitiveTypeEntry *type = new PrimitiveTypeEntry(name, since);
- type->setCodeGeneration(m_generate);
- type->setTargetLangName(targetLangName);
- type->setTargetLangApiName(targetLangApiName);
- type->setTargetLangPackage(m_defaultPackage);
- type->setDefaultConstructor(defaultConstructor);
-
- bool preferred;
- preferred = convertBoolean(preferredConversion, QLatin1String("preferred-conversion"), true);
- type->setPreferredConversion(preferred);
- preferred = convertBoolean(preferredTargetLangType,
- QLatin1String("preferred-target-lang-type"), true);
- type->setPreferredTargetLangType(preferred);
-
- element->entry = type;
- }
- break;
-
- case StackElement::ContainerTypeEntry: {
- QString typeName = attributes[QLatin1String("type")];
- ContainerTypeEntry::Type containerType =
- ContainerTypeEntry::containerTypeFromString(typeName);
- if (typeName.isEmpty()) {
- m_error = QLatin1String("no 'type' attribute specified");
+ case StackElement::PrimitiveTypeEntry:
+ element->entry = parsePrimitiveTypeEntry(reader, name, since, &attributes);
+ if (Q_UNLIKELY(!element->entry))
return false;
- } else if (containerType == ContainerTypeEntry::NoContainer) {
- m_error = QLatin1String("there is no container of type ") + typeName;
+ break;
+ case StackElement::ContainerTypeEntry:
+ if (ContainerTypeEntry *ce = parseContainerTypeEntry(reader, name, since, &attributes)) {
+ applyComplexTypeAttributes(reader, ce, &attributes);
+ element->entry = ce;
+ } else {
return false;
}
+ break;
- ContainerTypeEntry *type = new ContainerTypeEntry(name, containerType, since);
- type->setCodeGeneration(m_generate);
- element->entry = type;
- }
- break;
-
- case StackElement::SmartPointerTypeEntry: {
- bool result = handleSmartPointerEntry(element, attributes, name, since);
- if (!result)
- return result;
- }
- break;
-
- case StackElement::EnumTypeEntry: {
- QStringList names = name.split(colonColon());
- if (names.size() == 1)
- m_currentEnum = new EnumTypeEntry(QString(), name, since);
- else
- m_currentEnum =
- new EnumTypeEntry(QStringList(names.mid(0, names.size() - 1)).join(colonColon()),
- names.constLast(), since);
- element->entry = m_currentEnum;
- m_currentEnum->setCodeGeneration(m_generate);
- m_currentEnum->setTargetLangPackage(m_defaultPackage);
- m_currentEnum->setUpperBound(attributes[QLatin1String("upper-bound")]);
- m_currentEnum->setLowerBound(attributes[QLatin1String("lower-bound")]);
- m_currentEnum->setForceInteger(convertBoolean(attributes[QLatin1String("force-integer")], QLatin1String("force-integer"), false));
- m_currentEnum->setExtensible(convertBoolean(attributes[QLatin1String("extensible")], QLatin1String("extensible"), false));
-
- // put in the flags parallel...
- const QString flagNames = attributes.value(flagsAttribute());
- if (!flagNames.isEmpty()) {
- const QStringList &flagNameList = flagNames.split(QLatin1Char(','));
- for (const QString &flagName : flagNameList)
- addFlags(name, flagName.trimmed(), attributes, since);
+ case StackElement::SmartPointerTypeEntry:
+ if (SmartPointerTypeEntry *se = parseSmartPointerEntry(reader, name, since, &attributes)) {
+ applyComplexTypeAttributes(reader, se, &attributes);
+ element->entry = se;
+ } else {
+ return false;
}
- }
- break;
+ break;
+ case StackElement::EnumTypeEntry:
+ m_currentEnum = parseEnumTypeEntry(reader, name, since, &attributes);
+ if (Q_UNLIKELY(!m_currentEnum))
+ return false;
+ element->entry = m_currentEnum;
+ break;
- case StackElement::InterfaceTypeEntry: {
- ObjectTypeEntry *otype = new ObjectTypeEntry(name, since);
- QString targetLangName = attributes[QLatin1String("target-lang-name")];
- if (targetLangName.isEmpty())
- targetLangName = name;
- InterfaceTypeEntry *itype =
- new InterfaceTypeEntry(InterfaceTypeEntry::interfaceName(targetLangName), since);
-
- if (!convertBoolean(attributes[QLatin1String("generate")], QLatin1String("generate"), true))
- itype->setCodeGeneration(TypeEntry::GenerateForSubclass);
- else
- itype->setCodeGeneration(m_generate);
- otype->setDesignatedInterface(itype);
- itype->setOrigin(otype);
- element->entry = otype;
- }
- Q_FALLTHROUGH();
- case StackElement::ValueTypeEntry: {
- if (!element->entry) {
- ValueTypeEntry* typeEntry = new ValueTypeEntry(name, since);
- QString defaultConstructor = attributes[QLatin1String("default-constructor")];
- if (!defaultConstructor.isEmpty())
- typeEntry->setDefaultConstructor(defaultConstructor);
- element->entry = typeEntry;
+ case StackElement::InterfaceTypeEntry:
+ if (ObjectTypeEntry *oe = parseInterfaceTypeEntry(reader, name, since, &attributes)) {
+ applyComplexTypeAttributes(reader, oe, &attributes);
+ element->entry = oe;
+ } else {
+ return false;
}
-
- Q_FALLTHROUGH();
+ break;
+ case StackElement::ValueTypeEntry:
+ if (ValueTypeEntry *ve = parseValueTypeEntry(reader, name, since, &attributes)) {
+ applyComplexTypeAttributes(reader, ve, &attributes);
+ element->entry = ve;
+ } else {
+ return false;
+ }
+ break;
case StackElement::NamespaceTypeEntry:
- if (!element->entry)
- element->entry = new NamespaceTypeEntry(name, since);
-
- Q_FALLTHROUGH();
+ element->entry = new NamespaceTypeEntry(name, since);
+ applyCommonAttributes(element->entry, &attributes);
+ applyComplexTypeAttributes(reader, static_cast<ComplexTypeEntry *>(element->entry), &attributes);
+ break;
case StackElement::ObjectTypeEntry:
- if (!element->entry)
- element->entry = new ObjectTypeEntry(name, since);
-
- element->entry->setStream(attributes[QLatin1String("stream")] == yesAttributeValue());
-
- ComplexTypeEntry *ctype = static_cast<ComplexTypeEntry *>(element->entry);
- ctype->setTargetLangPackage(attributes[QLatin1String("package")]);
- ctype->setDefaultSuperclass(attributes[QLatin1String("default-superclass")]);
- ctype->setGenericClass(convertBoolean(attributes[QLatin1String("generic-class")], QLatin1String("generic-class"), false));
-
- if (!convertBoolean(attributes[QLatin1String("generate")], QLatin1String("generate"), true))
- element->entry->setCodeGeneration(TypeEntry::GenerateForSubclass);
- else
- element->entry->setCodeGeneration(m_generate);
-
- QString targetLangName = attributes[QLatin1String("target-lang-name")];
- if (!targetLangName.isEmpty())
- ctype->setTargetLangName(targetLangName);
-
- ctype->setIsPolymorphicBase(convertBoolean(attributes[QLatin1String("polymorphic-base")], QLatin1String("polymorphic-base"), false));
- ctype->setPolymorphicIdValue(attributes[QLatin1String("polymorphic-id-expression")]);
- //Copyable
- if (attributes[QLatin1String("copyable")].isEmpty())
- ctype->setCopyable(ComplexTypeEntry::Unknown);
- else {
- if (convertBoolean(attributes[QLatin1String("copyable")], QLatin1String("copyable"), false))
- ctype->setCopyable(ComplexTypeEntry::CopyableSet);
- else
- ctype->setCopyable(ComplexTypeEntry::NonCopyableSet);
-
- }
-
- if (element->type == StackElement::ObjectTypeEntry || element->type == StackElement::ValueTypeEntry)
- ctype->setHashFunction(attributes[QLatin1String("hash-function")]);
-
-
- ctype->setHeldType(attributes[QLatin1String("held-type")]);
-
- if (element->type == StackElement::ObjectTypeEntry
- || element->type == StackElement::ValueTypeEntry) {
- if (convertBoolean(attributes[QLatin1String("force-abstract")], QLatin1String("force-abstract"), false))
- ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::ForceAbstract);
- if (convertBoolean(attributes[QLatin1String("deprecated")], QLatin1String("deprecated"), false))
- ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::Deprecated);
- }
-
- if (element->type == StackElement::InterfaceTypeEntry
- || element->type == StackElement::ValueTypeEntry
- || element->type == StackElement::ObjectTypeEntry) {
- if (convertBoolean(attributes[QLatin1String("delete-in-main-thread")], QLatin1String("delete-in-main-thread"), false))
- ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::DeleteInMainThread);
- }
-
- QString targetType = attributes[QLatin1String("target-type")];
- if (!targetType.isEmpty() && element->entry->isComplex())
- static_cast<ComplexTypeEntry *>(element->entry)->setTargetType(targetType);
-
- // ctype->setInclude(Include(Include::IncludePath, ctype->name()));
- ctype = ctype->designatedInterface();
- if (ctype)
- ctype->setTargetLangPackage(attributes[QLatin1String("package")]);
-
- }
- break;
- case StackElement::FunctionTypeEntry: {
- QString signature = attributes[QLatin1String("signature")];
- signature = TypeDatabase::normalizedSignature(signature);
- element->entry = m_database->findType(name);
- if (element->entry) {
- if (element->entry->type() == TypeEntry::FunctionType) {
- reinterpret_cast<FunctionTypeEntry*>(element->entry)->addSignature(signature);
- } else {
- m_error = QStringLiteral("%1 expected to be a function, but isn't! Maybe it was already declared as a class or something else.")
- .arg(name);
- return false;
- }
- } else {
- element->entry = new FunctionTypeEntry(name, signature, since);
- element->entry->setCodeGeneration(m_generate);
- }
- }
- break;
+ element->entry = new ObjectTypeEntry(name, since);
+ applyCommonAttributes(element->entry, &attributes);
+ applyComplexTypeAttributes(reader, static_cast<ComplexTypeEntry *>(element->entry), &attributes);
+ break;
+ case StackElement::FunctionTypeEntry:
+ element->entry = parseFunctionTypeEntry(reader, name, since, &attributes);
+ if (Q_UNLIKELY(!element->entry))
+ return false;
+ break;
default:
Q_ASSERT(false);
};
if (element->entry) {
m_database->addType(element->entry);
- setTypeRevision(element->entry, attributes[QLatin1String("revision")].toInt());
} else {
qCWarning(lcShiboken).noquote().nospace()
<< QStringLiteral("Type: %1 was rejected by typesystem").arg(name);
}
} else if (element->type == StackElement::InjectDocumentation) {
- // check the XML tag attributes
- QHash<QString, QString> attributes;
- attributes.insert(QLatin1String("mode"), QLatin1String("replace"));
- attributes.insert(QLatin1String("format"), QLatin1String("native"));
- attributes.insert(sinceAttribute(), QString()); // dummy for matching allowed attributes
-
- fetchAttributeValues(tagName, atts, &attributes);
-
- const int validParent = StackElement::TypeEntryMask
- | StackElement::ModifyFunction
- | StackElement::ModifyField;
- if (m_current->parent && m_current->parent->type & validParent) {
- QString modeName = attributes[QLatin1String("mode")];
- TypeSystem::DocModificationMode mode;
- if (modeName == QLatin1String("append")) {
- mode = TypeSystem::DocModificationAppend;
- } else if (modeName == QLatin1String("prepend")) {
- mode = TypeSystem::DocModificationPrepend;
- } else if (modeName == QLatin1String("replace")) {
- mode = TypeSystem::DocModificationReplace;
- } else {
- m_error = QLatin1String("Unknow documentation injection mode: ") + modeName;
- return false;
- }
-
- static QHash<QString, TypeSystem::Language> languageNames;
- if (languageNames.isEmpty()) {
- languageNames[QLatin1String("target")] = TypeSystem::TargetLangCode;
- languageNames[QLatin1String("native")] = TypeSystem::NativeCode;
- }
-
- QString format = attributes[QLatin1String("format")].toLower();
- TypeSystem::Language lang = languageNames.value(format, TypeSystem::NoLanguage);
- if (lang == TypeSystem::NoLanguage) {
- m_error = QStringLiteral("unsupported class attribute: '%1'").arg(format);
- return false;
- }
-
- QString signature = m_current->type & StackElement::TypeEntryMask ? QString() : m_currentSignature;
- DocModification mod(mode, signature);
- mod.setFormat(lang);
- m_contextStack.top()->docModifications << mod;
- } else {
- m_error = QLatin1String("inject-documentation must be inside modify-function, "
- "modify-field or other tags that creates a type");
+ if (!parseInjectDocumentation(reader, &attributes))
return false;
- }
} else if (element->type == StackElement::ModifyDocumentation) {
- // check the XML tag attributes
- QHash<QString, QString> attributes;
- attributes.insert(xPathAttribute(), QString());
- attributes.insert(sinceAttribute(), QString()); // dummy for matching allowed attributes
- fetchAttributeValues(tagName, atts, &attributes);
-
- const int validParent = StackElement::TypeEntryMask
- | StackElement::ModifyFunction
- | StackElement::ModifyField;
- if (m_current->parent && m_current->parent->type & validParent) {
- QString signature = (m_current->type & StackElement::TypeEntryMask) ? QString() : m_currentSignature;
- m_contextStack.top()->docModifications
- << DocModification(attributes.value(xPathAttribute()), signature);
- } else {
- m_error = QLatin1String("modify-documentation must be inside modify-function, "
- "modify-field or other tags that creates a type");
+ if (!parseModifyDocumentation(reader, &attributes))
return false;
- }
} else if (element->type != StackElement::None) {
bool topLevel = element->type == StackElement::Root
|| element->type == StackElement::SuppressedWarning
@@ -1194,494 +2432,87 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts
StackElement topElement = !m_current ? StackElement(0) : *m_current;
element->entry = topElement.entry;
- QHash<QString, QString> attributes;
- attributes.insert(sinceAttribute(), QString()); // dummy for matching allowed attributes
switch (element->type) {
case StackElement::Root:
- attributes.insert(QLatin1String("package"), QString());
- attributes.insert(QLatin1String("default-superclass"), QString());
+ element->entry = parseRootElement(reader, since, &attributes);
+ element->type = StackElement::Root;
break;
case StackElement::LoadTypesystem:
- attributes.insert(nameAttribute(), QString());
- attributes.insert(QLatin1String("generate"), yesAttributeValue());
- break;
- case StackElement::NoNullPointers:
- attributes.insert(QLatin1String("default-value"), QString());
- break;
- case StackElement::SuppressedWarning:
- attributes.insert(textAttribute(), QString());
- break;
- case StackElement::ReplaceDefaultExpression:
- attributes.insert(QLatin1String("with"), QString());
- break;
- case StackElement::DefineOwnership:
- attributes.insert(QLatin1String("class"), QLatin1String("target"));
- attributes.insert(QLatin1String("owner"), QString());
- break;
- case StackElement::AddFunction:
- attributes.insert(QLatin1String("signature"), QString());
- attributes.insert(QLatin1String("return-type"), QLatin1String("void"));
- attributes.insert(QLatin1String("access"), QLatin1String("public"));
- attributes.insert(QLatin1String("static"), noAttributeValue());
- break;
- case StackElement::ModifyFunction:
- attributes.insert(QLatin1String("signature"), QString());
- attributes.insert(QLatin1String("access"), QString());
- attributes.insert(QLatin1String("remove"), QString());
- attributes.insert(QLatin1String("rename"), QString());
- attributes.insert(QLatin1String("deprecated"), noAttributeValue());
- attributes.insert(QLatin1String("associated-to"), QString());
- attributes.insert(QLatin1String("virtual-slot"), noAttributeValue());
- attributes.insert(QLatin1String("thread"), noAttributeValue());
- attributes.insert(QLatin1String("allow-thread"), noAttributeValue());
- break;
- case StackElement::ModifyArgument:
- attributes.insert(QLatin1String("index"), QString());
- attributes.insert(QLatin1String("replace-value"), QString());
- attributes.insert(QLatin1String("invalidate-after-use"), noAttributeValue());
- break;
- case StackElement::ModifyField:
- attributes.insert(nameAttribute(), QString());
- attributes.insert(QLatin1String("write"), trueAttributeValue());
- attributes.insert(QLatin1String("read"), trueAttributeValue());
- attributes.insert(QLatin1String("remove"), QString());
- break;
- case StackElement::Access:
- attributes.insert(QLatin1String("modifier"), QString());
- break;
- case StackElement::Include:
- attributes.insert(QLatin1String("file-name"), QString());
- attributes.insert(QLatin1String("location"), QString());
- break;
- case StackElement::CustomMetaConstructor:
- attributes[nameAttribute()] = topElement.entry->name().toLower() + QLatin1String("_create");
- attributes.insert(QLatin1String("param-name"), QLatin1String("copy"));
+ if (!loadTypesystem(reader, &attributes))
+ return false;
break;
- case StackElement::CustomMetaDestructor:
- attributes[nameAttribute()] = topElement.entry->name().toLower() + QLatin1String("_delete");
- attributes.insert(QLatin1String("param-name"), QLatin1String("copy"));
+ case StackElement::RejectEnumValue:
+ if (!parseRejectEnumValue(reader, &attributes))
+ return false;
break;
case StackElement::ReplaceType:
- attributes.insert(QLatin1String("modified-type"), QString());
- break;
- case StackElement::InjectCode:
- attributes.insert(QLatin1String("class"), QLatin1String("target"));
- attributes.insert(QLatin1String("position"), QLatin1String("beginning"));
- attributes.insert(QLatin1String("file"), QString());
+ if (!parseReplaceArgumentType(reader, topElement, &attributes))
+ return false;
break;
case StackElement::ConversionRule:
- attributes.insert(QLatin1String("class"), QString());
- attributes.insert(QLatin1String("file"), QString());
- break;
- case StackElement::TargetToNative:
- attributes.insert(QLatin1String("replace"), yesAttributeValue());
- break;
- case StackElement::AddConversion:
- attributes.insert(QLatin1String("type"), QString());
- attributes.insert(QLatin1String("check"), QString());
- break;
- case StackElement::RejectEnumValue:
- attributes.insert(nameAttribute(), QString());
- break;
- case StackElement::ArgumentMap:
- attributes.insert(QLatin1String("index"), QLatin1String("1"));
- attributes.insert(QLatin1String("meta-name"), QString());
- break;
- case StackElement::Rename:
- attributes.insert(QLatin1String("to"), QString());
- break;
- case StackElement::Rejection:
- attributes.insert(classAttribute(), QString());
- attributes.insert(functionNameAttribute(), QString());
- attributes.insert(fieldNameAttribute(), QString());
- attributes.insert(enumNameAttribute(), QString());
- attributes.insert(argumentTypeAttribute(), QString());
- attributes.insert(returnTypeAttribute(), QString());
- break;
- case StackElement::Removal:
- attributes.insert(QLatin1String("class"), QLatin1String("all"));
- break;
- case StackElement::Template:
- attributes.insert(nameAttribute(), QString());
- break;
- case StackElement::TemplateInstanceEnum:
- attributes.insert(nameAttribute(), QString());
- break;
- case StackElement::Replace:
- attributes.insert(QLatin1String("from"), QString());
- attributes.insert(QLatin1String("to"), QString());
- break;
- case StackElement::ReferenceCount:
- attributes.insert(QLatin1String("action"), QString());
- attributes.insert(QLatin1String("variable-name"), QString());
- break;
- case StackElement::ParentOwner:
- attributes.insert(QLatin1String("index"), QString());
- attributes.insert(QLatin1String("action"), QString());
- break;
- case StackElement::Array:
- break;
- default:
- { };
- };
-
- if (!attributes.isEmpty())
- fetchAttributeValues(tagName, atts, &attributes);
-
- switch (element->type) {
- case StackElement::Root:
- m_defaultPackage = attributes[QLatin1String("package")];
- m_defaultSuperclass = attributes[QLatin1String("default-superclass")];
- element->type = StackElement::Root;
- {
- TypeSystemTypeEntry* moduleEntry = reinterpret_cast<TypeSystemTypeEntry*>(
- m_database->findType(m_defaultPackage));
- element->entry = moduleEntry ? moduleEntry : new TypeSystemTypeEntry(m_defaultPackage, since);
- element->entry->setCodeGeneration(m_generate);
- }
-
- if ((m_generate == TypeEntry::GenerateForSubclass ||
- m_generate == TypeEntry::GenerateNothing) && !m_defaultPackage.isEmpty())
- TypeDatabase::instance()->addRequiredTargetImport(m_defaultPackage);
-
- if (!element->entry->qualifiedCppName().isEmpty())
- m_database->addType(element->entry);
- break;
- case StackElement::LoadTypesystem: {
- QString name = attributes[nameAttribute()];
- if (name.isEmpty()) {
- m_error = QLatin1String("No typesystem name specified");
- return false;
- }
- bool generateChild = (convertBoolean(attributes[QLatin1String("generate")], QLatin1String("generate"), true) && (m_generate == TypeEntry::GenerateAll));
- if (!m_database->parseFile(name, m_currentPath, generateChild)) {
- m_error = QStringLiteral("Failed to parse: '%1'").arg(name);
- return false;
- }
- }
- break;
- case StackElement::RejectEnumValue:
- if (!m_currentEnum) {
- m_error = QLatin1String("<reject-enum-value> node must be used inside a <enum-type> node");
- return false;
- }
- break;
- case StackElement::ReplaceType: {
- if (topElement.type != StackElement::ModifyArgument) {
- m_error = QLatin1String("Type replacement can only be specified for argument modifications");
- return false;
- }
-
- if (attributes[QLatin1String("modified-type")].isEmpty()) {
- m_error = QLatin1String("Type replacement requires 'modified-type' attribute");
+ if (!Handler::parseCustomConversion(reader, topElement, &attributes))
return false;
- }
-
- m_contextStack.top()->functionMods.last().argument_mods.last().modified_type = attributes[QLatin1String("modified-type")];
- }
- break;
- case StackElement::ConversionRule: {
- if (topElement.type != StackElement::ModifyArgument
- && topElement.type != StackElement::ValueTypeEntry
- && topElement.type != StackElement::PrimitiveTypeEntry
- && topElement.type != StackElement::ContainerTypeEntry) {
- m_error = QLatin1String("Conversion rules can only be specified for argument modification, "
- "value-type, primitive-type or container-type conversion.");
- return false;
- }
-
- static QHash<QString, TypeSystem::Language> languageNames;
- if (languageNames.isEmpty()) {
- languageNames[QLatin1String("target")] = TypeSystem::TargetLangCode;
- languageNames[QLatin1String("native")] = TypeSystem::NativeCode;
- }
-
- QString languageAttribute = attributes[QLatin1String("class")].toLower();
- TypeSystem::Language lang = languageNames.value(languageAttribute, TypeSystem::NoLanguage);
-
- if (topElement.type == StackElement::ModifyArgument) {
- if (lang == TypeSystem::NoLanguage) {
- m_error = QStringLiteral("unsupported class attribute: '%1'").arg(lang);
- return false;
- }
-
- CodeSnip snip;
- snip.language = lang;
- m_contextStack.top()->functionMods.last().argument_mods.last().conversion_rules.append(snip);
- } else {
- if (topElement.entry->hasConversionRule() || topElement.entry->hasCustomConversion()) {
- m_error = QLatin1String("Types can have only one conversion rule");
- return false;
- }
-
- // The old conversion rule tag that uses a file containing the conversion
- // will be kept temporarily for compatibility reasons.
- QString sourceFile = attributes[QLatin1String("file")];
- if (!sourceFile.isEmpty()) {
- if (m_generate != TypeEntry::GenerateForSubclass
- && m_generate != TypeEntry::GenerateNothing) {
-
- const char* conversionFlag = NATIVE_CONVERSION_RULE_FLAG;
- if (lang == TypeSystem::TargetLangCode)
- conversionFlag = TARGET_CONVERSION_RULE_FLAG;
-
- QFile conversionSource(sourceFile);
- if (conversionSource.open(QIODevice::ReadOnly | QIODevice::Text)) {
- topElement.entry->setConversionRule(QLatin1String(conversionFlag) + QString::fromUtf8(conversionSource.readAll()));
- } else {
- qCWarning(lcShiboken).noquote().nospace()
- << "File containing conversion code for "
- << topElement.entry->name() << " type does not exist or is not readable: "
- << sourceFile;
- }
- }
- }
-
- CustomConversion* customConversion = new CustomConversion(static_cast<TypeEntry*>(m_current->entry));
- customConversionsForReview.append(customConversion);
- }
- }
- break;
- case StackElement::NativeToTarget: {
+ break;
+ case StackElement::NativeToTarget:
if (topElement.type != StackElement::ConversionRule) {
m_error = QLatin1String("Native to Target conversion code can only be specified for custom conversion rules.");
return false;
}
m_contextStack.top()->codeSnips << CodeSnip();
- }
- break;
+ break;
case StackElement::TargetToNative: {
if (topElement.type != StackElement::ConversionRule) {
m_error = QLatin1String("Target to Native conversions can only be specified for custom conversion rules.");
return false;
}
- bool replace = attributes[QLatin1String("replace")] == yesAttributeValue();
- static_cast<TypeEntry*>(m_current->entry)->customConversion()->setReplaceOriginalTargetToNativeConversions(replace);
- }
- break;
- case StackElement::AddConversion: {
- if (topElement.type != StackElement::TargetToNative) {
- m_error = QLatin1String("Target to Native conversions can only be added inside 'target-to-native' tags.");
- return false;
- }
- QString sourceTypeName = attributes[QLatin1String("type")];
- if (sourceTypeName.isEmpty()) {
- m_error = QLatin1String("Target to Native conversions must specify the input type with the 'type' attribute.");
- return false;
- }
- QString typeCheck = attributes[QLatin1String("check")];
- static_cast<TypeEntry*>(m_current->entry)->customConversion()->addTargetToNativeConversion(sourceTypeName, typeCheck);
- m_contextStack.top()->codeSnips << CodeSnip();
- }
- break;
- case StackElement::ModifyArgument: {
- if (topElement.type != StackElement::ModifyFunction
- && topElement.type != StackElement::AddFunction) {
- m_error = QString::fromLatin1("argument modification requires function"
- " modification as parent, was %1")
- .arg(topElement.type, 0, 16);
- return false;
- }
-
- QString index = attributes[QLatin1String("index")];
- if (index == QLatin1String("return"))
- index = QLatin1String("0");
- else if (index == QLatin1String("this"))
- index = QLatin1String("-1");
-
- bool ok = false;
- int idx = index.toInt(&ok);
- if (!ok) {
- m_error = QStringLiteral("Cannot convert '%1' to integer").arg(index);
- return false;
- }
-
- QString replace_value = attributes[QLatin1String("replace-value")];
-
- if (!replace_value.isEmpty() && idx) {
- m_error = QLatin1String("replace-value is only supported for return values (index=0).");
- return false;
- }
-
- ArgumentModification argumentModification = ArgumentModification(idx);
- argumentModification.replace_value = replace_value;
- argumentModification.resetAfterUse = convertBoolean(attributes[QLatin1String("invalidate-after-use")], QLatin1String("invalidate-after-use"), false);
- m_contextStack.top()->functionMods.last().argument_mods.append(argumentModification);
+ const int replaceIndex = indexOfAttribute(attributes, replaceAttribute());
+ const bool replace = replaceIndex == -1
+ || convertBoolean(attributes.takeAt(replaceIndex).value(),
+ replaceAttribute(), true);
+ m_current->entry->customConversion()->setReplaceOriginalTargetToNativeConversions(replace);
}
break;
- case StackElement::NoNullPointers: {
- if (topElement.type != StackElement::ModifyArgument) {
- m_error = QLatin1String("no-null-pointer requires argument modification as parent");
+ case StackElement::AddConversion:
+ if (!parseAddConversion(reader, topElement, &attributes))
return false;
- }
-
- m_contextStack.top()->functionMods.last().argument_mods.last().noNullPointers = true;
- if (!m_contextStack.top()->functionMods.last().argument_mods.last().index)
- m_contextStack.top()->functionMods.last().argument_mods.last().nullPointerDefaultValue = attributes[QLatin1String("default-value")];
- else if (!attributes[QLatin1String("default-value")].isEmpty())
- qCWarning(lcShiboken) << "default values for null pointer guards are only effective for return values";
-
- }
- break;
- case StackElement::DefineOwnership: {
- if (topElement.type != StackElement::ModifyArgument) {
- m_error = QLatin1String("define-ownership requires argument modification as parent");
+ break;
+ case StackElement::ModifyArgument:
+ if (!parseModifyArgument(reader, topElement, &attributes))
return false;
- }
-
- static QHash<QString, TypeSystem::Language> languageNames;
- if (languageNames.isEmpty()) {
- languageNames[QLatin1String("target")] = TypeSystem::TargetLangCode;
- languageNames[QLatin1String("native")] = TypeSystem::NativeCode;
- }
-
- QString classAttribute = attributes[QLatin1String("class")].toLower();
- TypeSystem::Language lang = languageNames.value(classAttribute, TypeSystem::NoLanguage);
- if (lang == TypeSystem::NoLanguage) {
- m_error = QStringLiteral("unsupported class attribute: '%1'").arg(classAttribute);
+ break;
+ case StackElement::NoNullPointers:
+ if (!parseNoNullPointer(reader, topElement, &attributes))
return false;
- }
-
- static QHash<QString, TypeSystem::Ownership> ownershipNames;
- if (ownershipNames.isEmpty()) {
- ownershipNames[QLatin1String("target")] = TypeSystem::TargetLangOwnership;
- ownershipNames[QLatin1String("c++")] = TypeSystem::CppOwnership;
- ownershipNames[QLatin1String("default")] = TypeSystem::DefaultOwnership;
- }
-
- QString ownershipAttribute = attributes[QLatin1String("owner")].toLower();
- TypeSystem::Ownership owner = ownershipNames.value(ownershipAttribute, TypeSystem::InvalidOwnership);
- if (owner == TypeSystem::InvalidOwnership) {
- m_error = QStringLiteral("unsupported owner attribute: '%1'").arg(ownershipAttribute);
+ break;
+ case StackElement::DefineOwnership:
+ if (!parseDefineOwnership(reader, topElement, &attributes))
return false;
- }
-
- m_contextStack.top()->functionMods.last().argument_mods.last().ownerships[lang] = owner;
- }
- break;
+ break;
case StackElement::SuppressedWarning: {
- const QString suppressedWarning = attributes.value(textAttribute());
- if (suppressedWarning.isEmpty()) {
+ const int textIndex = indexOfAttribute(attributes, textAttribute());
+ if (textIndex == -1) {
qCWarning(lcShiboken) << "Suppressed warning with no text specified";
} else {
+ const QString suppressedWarning =
+ attributes.takeAt(textIndex).value().toString();
if (!m_database->addSuppressedWarning(suppressedWarning, &m_error))
return false;
}
}
break;
- case StackElement::ArgumentMap: {
- if (!(topElement.type & StackElement::CodeSnipMask)) {
- m_error = QLatin1String("Argument maps requires code injection as parent");
- return false;
- }
-
- bool ok;
- int pos = attributes[QLatin1String("index")].toInt(&ok);
- if (!ok) {
- m_error = QStringLiteral("Can't convert position '%1' to integer")
- .arg(attributes[QLatin1String("position")]);
- return false;
- }
-
- if (pos <= 0) {
- m_error = QStringLiteral("Argument position %1 must be a positive number").arg(pos);
- return false;
- }
-
- QString meta_name = attributes[QLatin1String("meta-name")];
- if (meta_name.isEmpty())
- qCWarning(lcShiboken) << "Empty meta name in argument map";
-
-
- if (topElement.type == StackElement::InjectCodeInFunction)
- m_contextStack.top()->functionMods.last().snips.last().argumentMap[pos] = meta_name;
- else {
- qCWarning(lcShiboken) << "Argument maps are only useful for injection of code "
- "into functions.";
- }
- }
- break;
- case StackElement::Removal: {
- if (topElement.type != StackElement::ModifyFunction) {
- m_error = QLatin1String("Function modification parent required");
+ case StackElement::ArgumentMap:
+ if (!parseArgumentMap(reader, topElement, &attributes))
return false;
- }
-
- static QHash<QString, TypeSystem::Language> languageNames;
- if (languageNames.isEmpty()) {
- languageNames.insert(QLatin1String("target"), TypeSystem::TargetLangAndNativeCode);
- languageNames.insert(QLatin1String("all"), TypeSystem::All);
- }
-
- QString languageAttribute = attributes[QLatin1String("class")].toLower();
- TypeSystem::Language lang = languageNames.value(languageAttribute, TypeSystem::NoLanguage);
- if (lang == TypeSystem::NoLanguage) {
- m_error = QStringLiteral("unsupported class attribute: '%1'").arg(languageAttribute);
+ break;
+ case StackElement::Removal:
+ if (!parseRemoval(reader, topElement, &attributes))
return false;
- }
-
- m_contextStack.top()->functionMods.last().removal = lang;
- }
- break;
+ break;
case StackElement::Rename:
- case StackElement::Access: {
- if (topElement.type != StackElement::ModifyField
- && topElement.type != StackElement::ModifyFunction
- && topElement.type != StackElement::ModifyArgument) {
- m_error = QLatin1String("Function, field or argument modification parent required");
- return false;
- }
-
- Modification *mod = 0;
- if (topElement.type == StackElement::ModifyFunction)
- mod = &m_contextStack.top()->functionMods.last();
- else if (topElement.type == StackElement::ModifyField)
- mod = &m_contextStack.top()->fieldMods.last();
-
- QString modifier;
- if (element->type == StackElement::Rename) {
- modifier = QLatin1String("rename");
- QString renamed_to = attributes[QLatin1String("to")];
- if (renamed_to.isEmpty()) {
- m_error = QLatin1String("Rename modifier requires 'to' attribute");
- return false;
- }
-
- if (topElement.type == StackElement::ModifyFunction)
- mod->setRenamedTo(renamed_to);
- else if (topElement.type == StackElement::ModifyField)
- mod->setRenamedTo(renamed_to);
- else
- m_contextStack.top()->functionMods.last().argument_mods.last().renamed_to = renamed_to;
- } else
- modifier = attributes[QLatin1String("modifier")].toLower();
-
-
- if (modifier.isEmpty()) {
- m_error = QLatin1String("No access modification specified");
- return false;
- }
-
- static QHash<QString, FunctionModification::Modifiers> modifierNames;
- if (modifierNames.isEmpty()) {
- modifierNames[QLatin1String("private")] = Modification::Private;
- modifierNames[QLatin1String("public")] = Modification::Public;
- modifierNames[QLatin1String("protected")] = Modification::Protected;
- modifierNames[QLatin1String("friendly")] = Modification::Friendly;
- modifierNames[QLatin1String("rename")] = Modification::Rename;
- modifierNames[QLatin1String("final")] = Modification::Final;
- modifierNames[QLatin1String("non-final")] = Modification::NonFinal;
- }
-
- if (!modifierNames.contains(modifier)) {
- m_error = QStringLiteral("Unknown access modifier: '%1'").arg(modifier);
+ case StackElement::Access:
+ if (!parseRename(reader, element->type, topElement, &attributes))
return false;
- }
-
- if (mod)
- mod->modifiers |= modifierNames[modifier];
- }
- break;
+ break;
case StackElement::RemoveArgument:
if (topElement.type != StackElement::ModifyArgument) {
m_error = QLatin1String("Removing argument requires argument modification as parent");
@@ -1691,229 +2522,38 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts
m_contextStack.top()->functionMods.last().argument_mods.last().removed = true;
break;
- case StackElement::ModifyField: {
- QString name = attributes[nameAttribute()];
- if (name.isEmpty())
- break;
- FieldModification fm;
- fm.name = name;
- fm.modifiers = 0;
-
- if (!convertRemovalAttribute(attributes[QLatin1String("remove")], fm, m_error))
- return false;
-
- QString read = attributes[QLatin1String("read")];
- QString write = attributes[QLatin1String("write")];
-
- if (read == trueAttributeValue()) fm.modifiers |= FieldModification::Readable;
- if (write == trueAttributeValue()) fm.modifiers |= FieldModification::Writable;
-
- m_contextStack.top()->fieldMods << fm;
- }
- break;
- case StackElement::AddFunction: {
- if (!(topElement.type & (StackElement::ComplexTypeEntryMask | StackElement::Root))) {
- m_error = QString::fromLatin1("Add function requires a complex type or a root tag as parent"
- ", was=%1").arg(topElement.type, 0, 16);
- return false;
- }
- const QString originalSignature = attributes[QLatin1String("signature")];
-
- QString signature = TypeDatabase::normalizedSignature(originalSignature);
- if (signature.isEmpty()) {
- m_error = QLatin1String("No signature for the added function");
- return false;
- }
-
- QString errorString = checkSignatureError(signature, QLatin1String("add-function"));
- if (!errorString.isEmpty()) {
- m_error = errorString;
- return false;
- }
-
- AddedFunction func(signature, attributes[QLatin1String("return-type")]);
- func.setStatic(attributes[QLatin1String("static")] == yesAttributeValue());
- if (!signature.contains(QLatin1Char('(')))
- signature += QLatin1String("()");
- m_currentSignature = signature;
-
- QString access = attributes[QLatin1String("access")].toLower();
- if (!access.isEmpty()) {
- if (access == QLatin1String("protected")) {
- func.setAccess(AddedFunction::Protected);
- } else if (access == QLatin1String("public")) {
- func.setAccess(AddedFunction::Public);
- } else {
- m_error = QString::fromLatin1("Bad access type '%1'").arg(access);
- return false;
- }
- }
-
- m_contextStack.top()->addedFunctions << func;
-
- FunctionModification mod;
- if (!mod.setSignature(m_currentSignature, &m_error))
- return false;
- mod.setOriginalSignature(originalSignature);
- m_contextStack.top()->functionMods << mod;
- }
- break;
- case StackElement::ModifyFunction: {
- if (!(topElement.type & StackElement::ComplexTypeEntryMask)) {
- m_error = QString::fromLatin1("Modify function requires complex type as parent"
- ", was=%1").arg(topElement.type, 0, 16);
- return false;
- }
- const QString originalSignature = attributes[QLatin1String("signature")];
-
- const QString signature = TypeDatabase::normalizedSignature(originalSignature);
- if (signature.isEmpty()) {
- m_error = QLatin1String("No signature for modified function");
- return false;
- }
-
- QString errorString = checkSignatureError(signature, QLatin1String("modify-function"));
- if (!errorString.isEmpty()) {
- m_error = errorString;
+ case StackElement::ModifyField:
+ if (!parseModifyField(reader, &attributes))
return false;
- }
-
- FunctionModification mod;
- if (!mod.setSignature(signature, &m_error))
+ break;
+ case StackElement::AddFunction:
+ if (!parseAddFunction(reader, topElement, &attributes))
return false;
- mod.setOriginalSignature(originalSignature);
- m_currentSignature = signature;
-
- QString access = attributes[QLatin1String("access")].toLower();
- if (!access.isEmpty()) {
- if (access == QLatin1String("private"))
- mod.modifiers |= Modification::Private;
- else if (access == QLatin1String("protected"))
- mod.modifiers |= Modification::Protected;
- else if (access == QLatin1String("public"))
- mod.modifiers |= Modification::Public;
- else if (access == QLatin1String("final"))
- mod.modifiers |= Modification::Final;
- else if (access == QLatin1String("non-final"))
- mod.modifiers |= Modification::NonFinal;
- else {
- m_error = QString::fromLatin1("Bad access type '%1'").arg(access);
- return false;
- }
- }
-
- if (convertBoolean(attributes[QLatin1String("deprecated")], QLatin1String("deprecated"), false))
- mod.modifiers |= Modification::Deprecated;
-
- if (!convertRemovalAttribute(attributes[QLatin1String("remove")], mod, m_error))
+ break;
+ case StackElement::ModifyFunction:
+ if (!parseModifyFunction(reader, topElement, &attributes))
return false;
-
- QString rename = attributes[QLatin1String("rename")];
- if (!rename.isEmpty()) {
- mod.renamedToName = rename;
- mod.modifiers |= Modification::Rename;
- }
-
- QString association = attributes[QLatin1String("associated-to")];
- if (!association.isEmpty())
- mod.association = association;
-
- mod.setIsThread(convertBoolean(attributes[QLatin1String("thread")], QLatin1String("thread"), false));
- mod.setAllowThread(convertBoolean(attributes[QLatin1String("allow-thread")], QLatin1String("allow-thread"), false));
-
- mod.modifiers |= (convertBoolean(attributes[QLatin1String("virtual-slot")], QLatin1String("virtual-slot"), false) ? Modification::VirtualSlot : 0);
-
- m_contextStack.top()->functionMods << mod;
- }
- break;
+ break;
case StackElement::ReplaceDefaultExpression:
- if (!(topElement.type & StackElement::ModifyArgument)) {
- m_error = QLatin1String("Replace default expression only allowed as child of argument modification");
- return false;
- }
-
- if (attributes[QLatin1String("with")].isEmpty()) {
- m_error = QLatin1String("Default expression replaced with empty string. Use remove-default-expression instead.");
+ if (!parseReplaceDefaultExpression(reader, topElement, &attributes))
return false;
- }
-
- m_contextStack.top()->functionMods.last().argument_mods.last().replacedDefaultExpression = attributes[QLatin1String("with")];
break;
case StackElement::RemoveDefaultExpression:
m_contextStack.top()->functionMods.last().argument_mods.last().removedDefaultExpression = true;
break;
case StackElement::CustomMetaConstructor:
- case StackElement::CustomMetaDestructor: {
- CustomFunction *func = new CustomFunction(attributes[nameAttribute()]);
- func->paramName = attributes[QLatin1String("param-name")];
- element->value.customFunction = func;
- }
- break;
- case StackElement::ReferenceCount: {
- if (topElement.type != StackElement::ModifyArgument) {
- m_error = QLatin1String("reference-count must be child of modify-argument");
- return false;
- }
-
- ReferenceCount rc;
-
- static QHash<QString, ReferenceCount::Action> actions;
- if (actions.isEmpty()) {
- actions[QLatin1String("add")] = ReferenceCount::Add;
- actions[QLatin1String("add-all")] = ReferenceCount::AddAll;
- actions[QLatin1String("remove")] = ReferenceCount::Remove;
- actions[QLatin1String("set")] = ReferenceCount::Set;
- actions[QLatin1String("ignore")] = ReferenceCount::Ignore;
- }
- rc.action = actions.value(attributes[QLatin1String("action")].toLower(), ReferenceCount::Invalid);
- rc.varName = attributes[QLatin1String("variable-name")];
-
- if (rc.action == ReferenceCount::Invalid) {
- m_error = QLatin1String("unrecognized value for action attribute. supported actions:");
- for (QHash<QString, ReferenceCount::Action>::const_iterator it = actions.cbegin(), end = actions.cend(); it != end; ++it)
- m_error += QLatin1Char(' ') + it.key();
- }
-
- m_contextStack.top()->functionMods.last().argument_mods.last().referenceCounts.append(rc);
- }
- break;
-
- case StackElement::ParentOwner: {
- if (topElement.type != StackElement::ModifyArgument) {
- m_error = QLatin1String("parent-policy must be child of modify-argument");
- return false;
- }
-
- ArgumentOwner ao;
-
- QString index = attributes[QLatin1String("index")];
- if (index == QLatin1String("return"))
- index = QLatin1String("0");
- else if (index == QLatin1String("this"))
- index = QLatin1String("-1");
-
- bool ok = false;
- int idx = index.toInt(&ok);
- if (!ok) {
- m_error = QStringLiteral("Cannot convert '%1' to integer").arg(index);
+ case StackElement::CustomMetaDestructor:
+ element->value.customFunction =
+ parseCustomMetaConstructor(reader, element->type, topElement, &attributes);
+ break;
+ case StackElement::ReferenceCount:
+ if (!parseReferenceCount(reader, topElement, &attributes))
return false;
- }
-
- static QHash<QString, ArgumentOwner::Action> actions;
- if (actions.isEmpty()) {
- actions[QLatin1String("add")] = ArgumentOwner::Add;
- actions[QLatin1String("remove")] = ArgumentOwner::Remove;
- }
-
- ao.action = actions.value(attributes[QLatin1String("action")].toLower(), ArgumentOwner::Invalid);
- if (!ao.action) {
- m_error = QLatin1String("Invalid parent actionr");
+ break;
+ case StackElement::ParentOwner:
+ if (!parseParentOwner(reader, topElement, &attributes))
return false;
- }
- ao.index = idx;
- m_contextStack.top()->functionMods.last().argument_mods.last().owner = ao;
- }
- break;
+ break;
case StackElement::Array:
if (topElement.type != StackElement::ModifyArgument) {
m_error = QLatin1String("array must be child of modify-argument");
@@ -1921,178 +2561,48 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts
}
m_contextStack.top()->functionMods.last().argument_mods.last().array = true;
break;
- case StackElement::InjectCode: {
- if (!(topElement.type & StackElement::ComplexTypeEntryMask)
- && (topElement.type != StackElement::AddFunction)
- && (topElement.type != StackElement::ModifyFunction)
- && (topElement.type != StackElement::Root)) {
- m_error = QLatin1String("wrong parent type for code injection");
- return false;
- }
-
- static QHash<QString, TypeSystem::Language> languageNames;
- if (languageNames.isEmpty()) {
- languageNames[QLatin1String("target")] = TypeSystem::TargetLangCode; // em algum lugar do cpp
- languageNames[QLatin1String("native")] = TypeSystem::NativeCode; // em algum lugar do cpp
- languageNames[QLatin1String("shell")] = TypeSystem::ShellCode; // coloca no header, mas antes da declaracao da classe
- languageNames[QLatin1String("shell-declaration")] = TypeSystem::ShellDeclaration; // coloca no header, dentro da declaracao da classe
- languageNames[QLatin1String("library-initializer")] = TypeSystem::PackageInitializer;
- languageNames[QLatin1String("destructor-function")] = TypeSystem::DestructorFunction;
- languageNames[QLatin1String("constructors")] = TypeSystem::Constructors;
- languageNames[QLatin1String("interface")] = TypeSystem::Interface;
- }
-
- QString className = attributes[QLatin1String("class")].toLower();
- if (!languageNames.contains(className)) {
- m_error = QStringLiteral("Invalid class specifier: '%1'").arg(className);
- return false;
- }
-
-
- static QHash<QString, TypeSystem::CodeSnipPosition> positionNames;
- if (positionNames.isEmpty()) {
- positionNames.insert(QLatin1String("beginning"), TypeSystem::CodeSnipPositionBeginning);
- positionNames.insert(QLatin1String("end"), TypeSystem::CodeSnipPositionEnd);
- // QtScript
- positionNames.insert(QLatin1String("declaration"), TypeSystem::CodeSnipPositionDeclaration);
- positionNames.insert(QLatin1String("prototype-initialization"), TypeSystem::CodeSnipPositionPrototypeInitialization);
- positionNames.insert(QLatin1String("constructor-initialization"), TypeSystem::CodeSnipPositionConstructorInitialization);
- positionNames.insert(QLatin1String("constructor"), TypeSystem::CodeSnipPositionConstructor);
- }
-
- QString position = attributes[QLatin1String("position")].toLower();
- if (!positionNames.contains(position)) {
- m_error = QStringLiteral("Invalid position: '%1'").arg(position);
+ case StackElement::InjectCode:
+ if (!parseInjectCode(reader, topElement, element, &attributes))
return false;
- }
-
- CodeSnip snip;
- snip.language = languageNames[className];
- snip.position = positionNames[position];
- bool in_file = false;
-
- QString file_name = attributes[QLatin1String("file")];
-
- //Handler constructor....
- if (m_generate != TypeEntry::GenerateForSubclass &&
- m_generate != TypeEntry::GenerateNothing &&
- !file_name.isEmpty()) {
- const QString resolved = m_database->modifiedTypesystemFilepath(file_name, m_currentPath);
- if (QFile::exists(resolved)) {
- QFile codeFile(resolved);
- if (codeFile.open(QIODevice::Text | QIODevice::ReadOnly)) {
- QString content = QLatin1String("// ========================================================================\n"
- "// START of custom code block [file: ");
- content += file_name;
- content += QLatin1String("]\n");
- content += QString::fromUtf8(codeFile.readAll());
- content += QLatin1String("\n// END of custom code block [file: ");
- content += file_name;
- content += QLatin1String("]\n// ========================================================================\n");
- snip.addCode(content);
- in_file = true;
- }
- } else {
- qCWarning(lcShiboken).noquote().nospace()
- << "File for inject code not exist: " << QDir::toNativeSeparators(file_name);
- }
-
- }
-
- if (snip.language == TypeSystem::Interface && topElement.type != StackElement::InterfaceTypeEntry) {
- m_error = QLatin1String("Interface code injections must be direct child of an interface type entry");
+ break;
+ case StackElement::Include:
+ if (!parseInclude(reader, topElement, element->entry, &attributes))
return false;
- }
-
- if (topElement.type == StackElement::ModifyFunction || topElement.type == StackElement::AddFunction) {
- FunctionModification mod = m_contextStack.top()->functionMods.constLast();
- if (snip.language == TypeSystem::ShellDeclaration) {
- m_error = QLatin1String("no function implementation in shell declaration in which to inject code");
- return false;
- }
-
- m_contextStack.top()->functionMods.last().snips << snip;
- if (in_file)
- m_contextStack.top()->functionMods.last().modifiers |= FunctionModification::CodeInjection;
- element->type = StackElement::InjectCodeInFunction;
- } else if (topElement.type == StackElement::Root) {
- element->entry->addCodeSnip(snip);
- } else if (topElement.type != StackElement::Root) {
- m_contextStack.top()->codeSnips << snip;
- }
-
- }
- break;
- case StackElement::Include: {
- QString location = attributes[QLatin1String("location")].toLower();
-
- static QHash<QString, Include::IncludeType> locationNames;
- if (locationNames.isEmpty()) {
- locationNames[QLatin1String("global")] = Include::IncludePath;
- locationNames[QLatin1String("local")] = Include::LocalPath;
- locationNames[QLatin1String("target")] = Include::TargetLangImport;
- }
-
- if (!locationNames.contains(location)) {
- m_error = QStringLiteral("Location not recognized: '%1'").arg(location);
+ break;
+ case StackElement::Rejection:
+ if (!addRejection(m_database, &attributes, &m_error))
return false;
- }
-
- Include::IncludeType loc = locationNames[location];
- Include inc(loc, attributes[QLatin1String("file-name")]);
-
- ComplexTypeEntry *ctype = static_cast<ComplexTypeEntry *>(element->entry);
- if (topElement.type & (StackElement::ComplexTypeEntryMask | StackElement::PrimitiveTypeEntry)) {
- element->entry->setInclude(inc);
- } else if (topElement.type == StackElement::ExtraIncludes) {
- element->entry->addExtraInclude(inc);
- } else {
- m_error = QLatin1String("Only supported parent tags are primitive-type, complex types or extra-includes");
+ break;
+ case StackElement::Template: {
+ const int nameIndex = indexOfAttribute(attributes, nameAttribute());
+ if (nameIndex == -1) {
+ m_error = msgMissingAttribute(nameAttribute());
return false;
}
-
- inc = ctype->include();
- IncludeList lst = ctype->extraIncludes();
- ctype = ctype->designatedInterface();
- if (ctype) {
- ctype->setExtraIncludes(lst);
- ctype->setInclude(inc);
- }
+ element->value.templateEntry =
+ new TemplateEntry(attributes.takeAt(nameIndex).value().toString());
}
- break;
- case StackElement::Rejection:
- if (!addRejection(m_database, attributes, &m_error))
- return false;
- break;
- case StackElement::Template:
- element->value.templateEntry = new TemplateEntry(attributes.value(nameAttribute()));
break;
case StackElement::TemplateInstanceEnum:
- if (!(topElement.type & StackElement::CodeSnipMask) &&
- (topElement.type != StackElement::Template) &&
- (topElement.type != StackElement::CustomMetaConstructor) &&
- (topElement.type != StackElement::CustomMetaDestructor) &&
- (topElement.type != StackElement::NativeToTarget) &&
- (topElement.type != StackElement::AddConversion) &&
- (topElement.type != StackElement::ConversionRule)) {
- m_error = QLatin1String("Can only insert templates into code snippets, templates, custom-constructors, "\
- "custom-destructors, conversion-rule, native-to-target or add-conversion tags.");
+ element->value.templateInstance =
+ parseTemplateInstanceEnum(reader, topElement, &attributes);
+ if (!element->value.templateInstance)
return false;
- }
- element->value.templateInstance = new TemplateInstance(attributes.value(nameAttribute()));
break;
case StackElement::Replace:
- if (topElement.type != StackElement::TemplateInstanceEnum) {
- m_error = QLatin1String("Can only insert replace rules into insert-template.");
+ if (!parseReplace(reader, topElement, element, &attributes))
return false;
- }
- element->parent->value.templateInstance->addReplaceRule(attributes[QLatin1String("from")], attributes[QLatin1String("to")]);
break;
default:
break; // nada
};
}
+ if (!attributes.isEmpty()) {
+ const QString message = msgUnusedAttributes(tagName, attributes);
+ qCWarning(lcShiboken, "%s", qPrintable(msgReaderWarning(reader, message)));
+ }
+
m_current = element;
return true;
}
@@ -2120,10 +2630,7 @@ PrimitiveTypeEntry *PrimitiveTypeEntry::basicReferencedTypeEntry() const
return 0;
PrimitiveTypeEntry *baseReferencedTypeEntry = m_referencedTypeEntry->basicReferencedTypeEntry();
- if (baseReferencedTypeEntry)
- return baseReferencedTypeEntry;
- else
- return m_referencedTypeEntry;
+ return baseReferencedTypeEntry ? baseReferencedTypeEntry : m_referencedTypeEntry;
}
bool PrimitiveTypeEntry::preferredConversion() const
@@ -2136,20 +2643,6 @@ void PrimitiveTypeEntry::setPreferredConversion(bool b)
m_preferredConversion = b;
}
-typedef QHash<const PrimitiveTypeEntry*, QString> PrimitiveTypeEntryTargetLangPackageMap;
-Q_GLOBAL_STATIC(PrimitiveTypeEntryTargetLangPackageMap, primitiveTypeEntryTargetLangPackages);
-
-void PrimitiveTypeEntry::setTargetLangPackage(const QString& package)
-{
- primitiveTypeEntryTargetLangPackages()->insert(this, package);
-}
-QString PrimitiveTypeEntry::targetLangPackage() const
-{
- if (!primitiveTypeEntryTargetLangPackages()->contains(this))
- return this->::TypeEntry::targetLangPackage();
- return primitiveTypeEntryTargetLangPackages()->value(this);
-}
-
CodeSnipList TypeEntry::codeSnips() const
{
return m_codeSnips;
@@ -2186,40 +2679,23 @@ FieldModification ComplexTypeEntry::fieldModification(const QString &name) const
return mod;
}
-QString ComplexTypeEntry::targetLangPackage() const
-{
- return m_package;
-}
-
QString ComplexTypeEntry::targetLangName() const
{
return m_targetLangName.isEmpty() ?
TypeEntry::targetLangName() : m_targetLangName;
}
-// The things we do not to break the ABI...
-typedef QHash<const ComplexTypeEntry*, QString> ComplexTypeEntryDefaultConstructorMap;
-Q_GLOBAL_STATIC(ComplexTypeEntryDefaultConstructorMap, complexTypeEntryDefaultConstructors);
-
void ComplexTypeEntry::setDefaultConstructor(const QString& defaultConstructor)
{
- if (!defaultConstructor.isEmpty())
- complexTypeEntryDefaultConstructors()->insert(this, defaultConstructor);
+ m_defaultConstructor = defaultConstructor;
}
QString ComplexTypeEntry::defaultConstructor() const
{
- if (!complexTypeEntryDefaultConstructors()->contains(this))
- return QString();
- return complexTypeEntryDefaultConstructors()->value(this);
+ return m_defaultConstructor;
}
bool ComplexTypeEntry::hasDefaultConstructor() const
{
- return complexTypeEntryDefaultConstructors()->contains(this);
-}
-
-QString ContainerTypeEntry::targetLangPackage() const
-{
- return QString();
+ return !m_defaultConstructor.isEmpty();
}
QString ContainerTypeEntry::targetLangName() const
@@ -2255,10 +2731,7 @@ QString ContainerTypeEntry::qualifiedCppName() const
QString EnumTypeEntry::targetLangQualifier() const
{
TypeEntry *te = TypeDatabase::instance()->findType(m_qualifier);
- if (te)
- return te->targetLangName();
- else
- return m_qualifier;
+ return te ? te->targetLangName() : m_qualifier;
}
QString EnumTypeEntry::qualifiedTargetLangName() const
@@ -2296,11 +2769,6 @@ bool FlagsTypeEntry::preferredConversion() const
return false;
}
-QString FlagsTypeEntry::targetLangPackage() const
-{
- return m_enum->targetLangPackage();
-}
-
QString FlagsTypeEntry::qualifiedTargetLangName() const
{
return targetLangPackage() + QLatin1Char('.') + m_enum->targetLangQualifier()
@@ -2320,7 +2788,7 @@ QString fixCppTypeName(const QString &name)
{
if (name == QLatin1String("long long"))
return QLatin1String("qint64");
- else if (name == QLatin1String("unsigned long long"))
+ if (name == QLatin1String("unsigned long long"))
return QLatin1String("quint64");
return name;
}
@@ -2341,11 +2809,9 @@ QString TemplateInstance::expandCode() const
result += code;
result += QLatin1String("\n// TEMPLATE - ") + m_name + QLatin1String(" - END");
return result;
- } else {
- qCWarning(lcShiboken).noquote().nospace()
- << "insert-template referring to non-existing template '" << m_name << '\'';
}
-
+ qCWarning(lcShiboken).noquote().nospace()
+ << "insert-template referring to non-existing template '" << m_name << '\'';
return QString();
}
@@ -2361,10 +2827,7 @@ QString CodeSnipAbstract::code() const
QString CodeSnipFragment::code() const
{
- if (m_instance)
- return m_instance->expandCode();
- else
- return m_code;
+ return m_instance ? m_instance->expandCode() : m_code;
}
bool FunctionModification::setSignature(const QString &s, QString *errorMessage)
@@ -2578,71 +3041,6 @@ QString ComplexTypeEntry::targetLangApiName() const
{
return strings_jobject;
}
-QString StringTypeEntry::targetLangApiName() const
-{
- return strings_jobject;
-}
-QString StringTypeEntry::targetLangName() const
-{
- return strings_String;
-}
-QString StringTypeEntry::targetLangPackage() const
-{
- return QString();
-}
-
-bool StringTypeEntry::isNativeIdBased() const
-{
- return false;
-}
-
-CharTypeEntry::CharTypeEntry(const QString &name, const QVersionNumber &vr) :
- ValueTypeEntry(name, CharType, vr)
-{
- setCodeGeneration(GenerateNothing);
-}
-
-QString CharTypeEntry::targetLangApiName() const
-{
- return strings_jchar;
-}
-QString CharTypeEntry::targetLangName() const
-{
- return strings_char;
-}
-
-QString CharTypeEntry::targetLangPackage() const
-{
- return QString();
-}
-
-bool CharTypeEntry::isNativeIdBased() const
-{
- return false;
-}
-
-VariantTypeEntry::VariantTypeEntry(const QString &name, const QVersionNumber &vr) :
- ValueTypeEntry(name, VariantType, vr)
-{
-}
-
-QString VariantTypeEntry::targetLangApiName() const
-{
- return strings_jobject;
-}
-QString VariantTypeEntry::targetLangName() const
-{
- return strings_Object;
-}
-QString VariantTypeEntry::targetLangPackage() const
-{
- return QString();
-}
-
-bool VariantTypeEntry::isNativeIdBased() const
-{
- return false;
-}
QString ContainerTypeEntry::typeName() const
{
@@ -2706,10 +3104,6 @@ bool TypeEntry::isCppPrimitive() const
return typeName.contains(QLatin1Char(' ')) || primitiveCppTypes().contains(typeName);
}
-// Again, stuff to avoid ABI breakage.
-typedef QHash<const TypeEntry*, CustomConversion*> TypeEntryCustomConversionMap;
-Q_GLOBAL_STATIC(TypeEntryCustomConversionMap, typeEntryCustomConversionMap);
-
TypeEntry::TypeEntry(const QString &name, TypeEntry::Type t, const QVersionNumber &vr) :
m_name(name),
m_type(t),
@@ -2719,29 +3113,22 @@ TypeEntry::TypeEntry(const QString &name, TypeEntry::Type t, const QVersionNumbe
TypeEntry::~TypeEntry()
{
- if (typeEntryCustomConversionMap()->contains(this)) {
- CustomConversion* customConversion = typeEntryCustomConversionMap()->value(this);
- typeEntryCustomConversionMap()->remove(this);
- delete customConversion;
- }
+ delete m_customConversion;
}
bool TypeEntry::hasCustomConversion() const
{
- return typeEntryCustomConversionMap()->contains(this);
+ return m_customConversion != nullptr;
}
+
void TypeEntry::setCustomConversion(CustomConversion* customConversion)
{
- if (customConversion)
- typeEntryCustomConversionMap()->insert(this, customConversion);
- else if (typeEntryCustomConversionMap()->contains(this))
- typeEntryCustomConversionMap()->remove(this);
+ m_customConversion = customConversion;
}
+
CustomConversion* TypeEntry::customConversion() const
{
- if (typeEntryCustomConversionMap()->contains(this))
- return typeEntryCustomConversionMap()->value(this);
- return 0;
+ return m_customConversion;
}
TypeSystemTypeEntry::TypeSystemTypeEntry(const QString &name, const QVersionNumber &vr) :
@@ -2778,10 +3165,9 @@ QString ArrayTypeEntry::targetLangName() const
QString ArrayTypeEntry::targetLangApiName() const
{
- if (m_nestedType->isPrimitive())
- return m_nestedType->targetLangApiName() + QLatin1String("Array");
- else
- return QLatin1String("jobjectArray");
+ return m_nestedType->isPrimitive()
+ ? m_nestedType->targetLangApiName() + QLatin1String("Array")
+ : QLatin1String("jobjectArray");
}
EnumTypeEntry::EnumTypeEntry(const QString &nspace, const QString &enumName,
@@ -2793,16 +3179,6 @@ EnumTypeEntry::EnumTypeEntry(const QString &nspace, const QString &enumName,
{
}
-QString EnumTypeEntry::targetLangPackage() const
-{
- return m_packageName;
-}
-
-void EnumTypeEntry::setTargetLangPackage(const QString &package)
-{
- m_packageName = package;
-}
-
QString EnumTypeEntry::targetLangName() const
{
return m_targetLangName;
@@ -2867,31 +3243,6 @@ ValueTypeEntry::ValueTypeEntry(const QString &name, Type t, const QVersionNumber
{
}
-StringTypeEntry::StringTypeEntry(const QString &name, const QVersionNumber &vr) :
- ValueTypeEntry(name, StringType, vr)
-{
- setCodeGeneration(GenerateNothing);
-}
-
-/*
-static void injectCode(ComplexTypeEntry *e,
- const char *signature,
- const QByteArray &code,
- const ArgumentMap &args)
-{
- CodeSnip snip;
- snip.language = TypeSystem::NativeCode;
- snip.position = CodeSnip::Beginning;
- snip.addCode(QString::fromLatin1(code));
- snip.argumentMap = args;
-
- FunctionModification mod;
- mod.signature = QMetaObject::normalizedSignature(signature);
- mod.snips << snip;
- mod.modifiers = Modification::CodeInjection;
-}
-*/
-
struct CustomConversion::CustomConversionPrivate
{
CustomConversionPrivate(const TypeEntry* ownerType)
diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h
index 186c4b24d..13805d47e 100644
--- a/sources/shiboken2/ApiExtractor/typesystem.h
+++ b/sources/shiboken2/ApiExtractor/typesystem.h
@@ -237,6 +237,7 @@ struct ArgumentModification
struct Modification
{
enum Modifiers {
+ InvalidModifier = 0x0000,
Private = 0x0001,
Protected = 0x0002,
Public = 0x0003,
@@ -398,6 +399,7 @@ struct AddedFunction
{
/// Function access types.
enum Access {
+ InvalidAccess = 0,
Protected = 0x1,
Public = 0x2
};
@@ -715,6 +717,11 @@ public:
&& m_codeGeneration != TypeEntry::GenerateNothing;
}
+ int revision() const { return m_revision; }
+ void setRevision(int r); // see typedatabase.cpp
+ int sbkIndex() const;
+ void setSbkIndex(int i) { m_sbkIndex = i; }
+
virtual QString qualifiedCppName() const
{
return m_name;
@@ -747,10 +754,8 @@ public:
}
// The package
- virtual QString targetLangPackage() const
- {
- return QString();
- }
+ QString targetLangPackage() const { return m_targetLangPackage; }
+ void setTargetLangPackage(const QString &p) { m_targetLangPackage = p; }
virtual QString qualifiedTargetLangName() const
{
@@ -889,8 +894,13 @@ public:
bool hasCustomConversion() const;
void setCustomConversion(CustomConversion* customConversion);
CustomConversion* customConversion() const;
+
+#ifndef QT_NO_DEBUG_STREAM
+ virtual void formatDebug(QDebug &d) const;
+#endif
private:
QString m_name;
+ QString m_targetLangPackage;
Type m_type;
uint m_codeGeneration = GenerateAll;
CustomFunction m_customConstructor;
@@ -904,6 +914,9 @@ private:
QString m_conversionRule;
bool m_stream = false;
QVersionNumber m_version;
+ CustomConversion *m_customConversion = nullptr;
+ int m_revision = 0;
+ int m_sbkIndex = 0;
};
class TypeSystemTypeEntry : public TypeEntry
@@ -1031,8 +1044,6 @@ public:
m_preferredTargetLangType = b;
}
- void setTargetLangPackage(const QString& package);
- QString targetLangPackage() const override;
private:
QString m_targetLangName;
QString m_targetLangApiName;
@@ -1048,9 +1059,6 @@ public:
explicit EnumTypeEntry(const QString &nspace, const QString &enumName,
const QVersionNumber &vr);
- QString targetLangPackage() const override;
- void setTargetLangPackage(const QString &package);
-
QString targetLangName() const override;
QString targetLangQualifier() const;
QString qualifiedTargetLangName() const override;
@@ -1131,6 +1139,9 @@ public:
m_forceInteger = force;
}
+#ifndef QT_NO_DEBUG_STREAM
+ void formatDebug(QDebug &d) const override;
+#endif
private:
QString m_packageName;
QString m_qualifier;
@@ -1203,8 +1214,6 @@ public:
m_enum = e;
}
- QString targetLangPackage() const override;
-
private:
QString m_originalName;
QString m_targetLangName;
@@ -1288,12 +1297,6 @@ public:
return m_fieldMods;
}
- QString targetLangPackage() const override;
- void setTargetLangPackage(const QString &package)
- {
- m_package = package;
- }
-
bool isQObject() const
{
return m_qobject;
@@ -1401,11 +1404,14 @@ public:
void setDefaultConstructor(const QString& defaultConstructor);
bool hasDefaultConstructor() const;
+#ifndef QT_NO_DEBUG_STREAM
+ void formatDebug(QDebug &d) const override;
+#endif
private:
AddedFunctionList m_addedFunctions;
FunctionModificationList m_functionMods;
FieldModificationList m_fieldMods;
- QString m_package;
+ QString m_defaultConstructor;
QString m_defaultSuperclass;
QString m_qualifiedCppName;
QString m_targetLangName;
@@ -1455,29 +1461,8 @@ public:
QString typeName() const;
QString targetLangName() const override;
- QString targetLangPackage() const override;
QString qualifiedCppName() const override;
- static Type containerTypeFromString(QString typeName)
- {
- static QHash<QString, Type> m_stringToContainerType;
- if (m_stringToContainerType.isEmpty()) {
- m_stringToContainerType.insert(QLatin1String("list"), ListContainer);
- m_stringToContainerType.insert(QLatin1String("string-list"), StringListContainer);
- m_stringToContainerType.insert(QLatin1String("linked-list"), LinkedListContainer);
- m_stringToContainerType.insert(QLatin1String("vector"), VectorContainer);
- m_stringToContainerType.insert(QLatin1String("stack"), StackContainer);
- m_stringToContainerType.insert(QLatin1String("queue"), QueueContainer);
- m_stringToContainerType.insert(QLatin1String("set"), SetContainer);
- m_stringToContainerType.insert(QLatin1String("map"), MapContainer);
- m_stringToContainerType.insert(QLatin1String("multi-map"), MultiMapContainer);
- m_stringToContainerType.insert(QLatin1String("hash"), HashContainer);
- m_stringToContainerType.insert(QLatin1String("multi-hash"), MultiHashContainer);
- m_stringToContainerType.insert(QLatin1String("pair"), PairContainer);
- }
- return m_stringToContainerType.value(typeName, NoContainer);
- }
-
private:
Type m_type;
};
@@ -1527,44 +1512,6 @@ protected:
explicit ValueTypeEntry(const QString &name, Type t, const QVersionNumber &vr);
};
-
-class StringTypeEntry : public ValueTypeEntry
-{
-public:
- explicit StringTypeEntry(const QString &name, const QVersionNumber &vr);
-
- QString targetLangApiName() const override;
- QString targetLangName() const override;
- QString targetLangPackage() const override;
-
- bool isNativeIdBased() const override;
-};
-
-class CharTypeEntry : public ValueTypeEntry
-{
-public:
- explicit CharTypeEntry(const QString &name, const QVersionNumber &vr);
-
- QString targetLangApiName() const override;
- QString targetLangName() const override;
- QString targetLangPackage() const override;
-
- bool isNativeIdBased() const override;
-};
-
-class VariantTypeEntry: public ValueTypeEntry
-{
-public:
- explicit VariantTypeEntry(const QString &name, const QVersionNumber &vr);
-
- QString targetLangApiName() const override;
- QString targetLangName() const override;
- QString targetLangPackage() const override;
-
- bool isNativeIdBased() const override;
-};
-
-
class InterfaceTypeEntry : public ComplexTypeEntry
{
public:
@@ -1641,7 +1588,8 @@ struct TypeRejection
Field, // Match className and field name
Enum, // Match className and enum name
ArgumentType, // Match className and argument type
- ReturnType // Match className and return type
+ ReturnType, // Match className and return type
+ Invalid
};
QRegularExpression className;
diff --git a/sources/shiboken2/ApiExtractor/typesystem_enums.h b/sources/shiboken2/ApiExtractor/typesystem_enums.h
index 6bfc94368..62ae8feb2 100644
--- a/sources/shiboken2/ApiExtractor/typesystem_enums.h
+++ b/sources/shiboken2/ApiExtractor/typesystem_enums.h
@@ -71,14 +71,16 @@ enum CodeSnipPosition {
CodeSnipPositionPrototypeInitialization,
CodeSnipPositionConstructorInitialization,
CodeSnipPositionConstructor,
- CodeSnipPositionAny
+ CodeSnipPositionAny,
+ CodeSnipPositionInvalid
};
enum DocModificationMode {
DocModificationAppend,
DocModificationPrepend,
DocModificationReplace,
- DocModificationXPathReplace
+ DocModificationXPathReplace,
+ DocModificationInvalid
};
} // namespace TypeSystem
diff --git a/sources/shiboken2/ApiExtractor/typesystem_p.h b/sources/shiboken2/ApiExtractor/typesystem_p.h
index 882cf3fab..d54c4cb65 100644
--- a/sources/shiboken2/ApiExtractor/typesystem_p.h
+++ b/sources/shiboken2/ApiExtractor/typesystem_p.h
@@ -140,22 +140,96 @@ public:
bool parse(QXmlStreamReader &reader);
+ QString errorString() const { return m_error; }
+
private:
- bool startElement(const QStringRef& localName, const QXmlStreamAttributes& atts);
- bool handleSmartPointerEntry(StackElement *element,
- QHash<QString, QString> &attributes,
- const QString &name,
- const QVersionNumber &since);
+ bool startElement(const QXmlStreamReader &reader);
+ SmartPointerTypeEntry *parseSmartPointerEntry(const QXmlStreamReader &,
+ const QString &name,
+ const QVersionNumber &since,
+ QXmlStreamAttributes *attributes);
bool endElement(const QStringRef& localName);
template <class String> // QString/QStringRef
bool characters(const String &ch);
- void fetchAttributeValues(const QString &name, const QXmlStreamAttributes &atts,
- QHash<QString, QString> *acceptedAttributes);
bool importFileElement(const QXmlStreamAttributes &atts);
- void addFlags(const QString &name, QString flagName,
- const QHash<QString, QString> &attributes,
- const QVersionNumber &since);
+
+ void applyCommonAttributes(TypeEntry *type, QXmlStreamAttributes *attributes) const;
+ PrimitiveTypeEntry *
+ parsePrimitiveTypeEntry(const QXmlStreamReader &, const QString &name,
+ const QVersionNumber &since, QXmlStreamAttributes *);
+ ContainerTypeEntry *
+ parseContainerTypeEntry(const QXmlStreamReader &, const QString &name,
+ const QVersionNumber &since, QXmlStreamAttributes *);
+ EnumTypeEntry *
+ parseEnumTypeEntry(const QXmlStreamReader &, const QString &name,
+ const QVersionNumber &since, QXmlStreamAttributes *);
+ FlagsTypeEntry *
+ parseFlagsEntry(const QXmlStreamReader &, EnumTypeEntry *enumEntry,
+ const QString &name, QString flagName,
+ const QVersionNumber &since, QXmlStreamAttributes *);
+ ObjectTypeEntry *
+ parseInterfaceTypeEntry(const QXmlStreamReader &, const QString &name,
+ const QVersionNumber &since, QXmlStreamAttributes *);
+ ValueTypeEntry *
+ parseValueTypeEntry(const QXmlStreamReader &, const QString &name,
+ const QVersionNumber &since, QXmlStreamAttributes *);
+ FunctionTypeEntry *
+ parseFunctionTypeEntry(const QXmlStreamReader &, const QString &name,
+ const QVersionNumber &since, QXmlStreamAttributes *);
+ void applyComplexTypeAttributes(const QXmlStreamReader &, ComplexTypeEntry *ctype,
+ QXmlStreamAttributes *) const;
+ bool parseRenameFunction(const QXmlStreamReader &, QString *name,
+ QXmlStreamAttributes *);
+ bool parseInjectDocumentation(const QXmlStreamReader &, QXmlStreamAttributes *);
+ bool parseModifyDocumentation(const QXmlStreamReader &, QXmlStreamAttributes *);
+ TypeSystemTypeEntry *
+ parseRootElement(const QXmlStreamReader &, const QVersionNumber &since,
+ QXmlStreamAttributes *);
+ bool loadTypesystem(const QXmlStreamReader &, QXmlStreamAttributes *);
+ bool parseRejectEnumValue(const QXmlStreamReader &, QXmlStreamAttributes *);
+ bool parseReplaceArgumentType(const QXmlStreamReader &, const StackElement &topElement,
+ QXmlStreamAttributes *);
+ bool parseCustomConversion(const QXmlStreamReader &, const StackElement &topElement,
+ QXmlStreamAttributes *);
+ bool parseAddConversion(const QXmlStreamReader &, const StackElement &topElement,
+ QXmlStreamAttributes *);
+ bool parseModifyArgument(const QXmlStreamReader &, const StackElement &topElement,
+ QXmlStreamAttributes *attributes);
+ bool parseNoNullPointer(const QXmlStreamReader &, const StackElement &topElement,
+ QXmlStreamAttributes *attributes);
+ bool parseDefineOwnership(const QXmlStreamReader &, const StackElement &topElement,
+ QXmlStreamAttributes *);
+ bool parseArgumentMap(const QXmlStreamReader &, const StackElement &topElement,
+ QXmlStreamAttributes *);
+ bool parseRemoval(const QXmlStreamReader &, const StackElement &topElement,
+ QXmlStreamAttributes *);
+ bool parseRename(const QXmlStreamReader &, StackElement::ElementType type,
+ const StackElement &topElement, QXmlStreamAttributes *);
+ bool parseModifyField(const QXmlStreamReader &, QXmlStreamAttributes *);
+ bool parseAddFunction(const QXmlStreamReader &, const StackElement &topElement,
+ QXmlStreamAttributes *);
+ bool parseModifyFunction(const QXmlStreamReader &, const StackElement &topElement,
+ QXmlStreamAttributes *);
+ bool parseReplaceDefaultExpression(const QXmlStreamReader &,
+ const StackElement &topElement, QXmlStreamAttributes *);
+ CustomFunction *
+ parseCustomMetaConstructor(const QXmlStreamReader &,
+ StackElement::ElementType type,
+ const StackElement &topElement, QXmlStreamAttributes *);
+ bool parseReferenceCount(const QXmlStreamReader &, const StackElement &topElement,
+ QXmlStreamAttributes *);
+ bool parseParentOwner(const QXmlStreamReader &, const StackElement &topElement,
+ QXmlStreamAttributes *);
+ bool parseInjectCode(const QXmlStreamReader &, const StackElement &topElement,
+ StackElement* element, QXmlStreamAttributes *);
+ bool parseInclude(const QXmlStreamReader &, const StackElement &topElement,
+ TypeEntry *entry, QXmlStreamAttributes *);
+ TemplateInstance
+ *parseTemplateInstanceEnum(const QXmlStreamReader &, const StackElement &topElement,
+ QXmlStreamAttributes *);
+ bool parseReplace(const QXmlStreamReader &, const StackElement &topElement,
+ StackElement *element, QXmlStreamAttributes *);
TypeDatabase* m_database;
StackElement* m_current;
@@ -170,7 +244,6 @@ private:
EnumTypeEntry* m_currentEnum;
QStack<StackElementContext*> m_contextStack;
- QHash<QString, StackElement::ElementType> tagNames;
QString m_currentSignature;
QString m_currentPath;
};