diff options
Diffstat (limited to 'sources/shiboken6_generator/ApiExtractor/abstractmetabuilder.cpp')
| -rw-r--r-- | sources/shiboken6_generator/ApiExtractor/abstractmetabuilder.cpp | 214 |
1 files changed, 119 insertions, 95 deletions
diff --git a/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder.cpp index deb6acbec..2413cc1ad 100644 --- a/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder.cpp @@ -160,6 +160,14 @@ const QMultiHash<QString, QString> &AbstractMetaBuilder::typedefTargetToName() c return d->m_typedefTargetToName; } +static inline bool warnAboutConstMismatch(const AbstractMetaFunctionCPtr &function, + const QString &signature) +{ + return function->isConstant() && !signature.startsWith(u'^') && signature.endsWith(u')') + // An operator synthesized from a free operator? + && !(function->isOperatorOverload() && signature.contains(u',')); +} + // Check whether a function modification can be found in a class, else // warn with candidates. static void checkModification(const FunctionModification &modification, @@ -176,7 +184,7 @@ static void checkModification(const FunctionModification &modification, const QString &signature = modification.signature(); auto it = std::find_if(functions.cbegin(), functions.cend(), modificationPredicate); if (it != functions.cend()) { - if ((*it)->isConstant() && signature.endsWith(u')')) // Warn about missing const + if (warnAboutConstMismatch(*it, signature)) qCWarning(lcShiboken, "%s", qPrintable(msgModificationConstMismatch(*it, signature))); return; } @@ -348,6 +356,8 @@ void AbstractMetaBuilderPrivate::traverseFreeOperatorFunction(const FunctionMode flags.setFlag(InternalFunctionFlag::OperatorClassArgumentByValue); } metaFunction->setFlags(flags); + if (metaFunction->isComparisonOperator()) + metaFunction->setConstant(true); metaFunction->setAccess(Access::Public); AbstractMetaClass::addFunction(baseoperandClass, metaFunction); ReportHandler::addGeneralMessage(msgSynthesizedFunction(metaFunction, item)); @@ -1273,7 +1283,10 @@ void AbstractMetaBuilderPrivate::traverseScopeMembers(const ScopeModelItem &item { // Classes/Namespace members traverseFields(item, metaClass); - traverseFunctions(item, metaClass); + if (item->kind() == _CodeModelItem::Kind_Class) + traverseClassFunctions(item, metaClass); + else + traverseNameSpaceFunctions(item, metaClass); // Inner classes const ClassList &innerClasses = item->classes(); @@ -1442,113 +1455,126 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(const Abstrac metaFunction->setType(metaType); } -AbstractMetaFunctionList - AbstractMetaBuilderPrivate::classFunctionList(const ScopeModelItem &scopeItem, - AbstractMetaClass::Attributes *constructorAttributes, - const AbstractMetaClassPtr ¤tClass) +void AbstractMetaBuilderPrivate::traverseNameSpaceFunctions(const ScopeModelItem& scopeItem, + const AbstractMetaClassPtr ¤tClass) + { - *constructorAttributes = {}; - AbstractMetaFunctionList result; + Q_ASSERT(currentClass); + AbstractMetaFunctionList functions; const FunctionList &scopeFunctionList = scopeItem->functions(); - result.reserve(scopeFunctionList.size()); - const bool isNamespace = currentClass->isNamespace(); + functions.reserve(scopeFunctionList.size()); for (const FunctionModelItem &function : scopeFunctionList) { - if (isNamespace && function->isOperator()) { + if (function->isOperator()) { traverseFreeOperatorFunction(function, currentClass); - } else if (function->isSpaceshipOperator() && !function->isDeleted()) { - if (currentClass) { - AbstractMetaClass::addSynthesizedComparisonOperators(currentClass, - InternalFunctionFlag::OperatorCpp20Spaceship); - } } else if (auto metaFunction = traverseFunction(function, currentClass)) { - result.append(metaFunction); - } else if (!function->isDeleted() && function->functionType() == CodeModel::Constructor) { - // traverseFunction() failed: mark rejected constructors - auto arguments = function->arguments(); - *constructorAttributes |= AbstractMetaClass::HasRejectedConstructor; - if (arguments.isEmpty() || arguments.constFirst()->defaultValue()) - *constructorAttributes |= AbstractMetaClass::HasRejectedDefaultConstructor; + metaFunction->setCppAttribute(FunctionAttribute::Static); + functions.append(metaFunction); + AbstractMetaClass::addFunction(currentClass, metaFunction); + applyFunctionModifications(metaFunction); } } - return result; + fillAddedFunctions(currentClass); } -void AbstractMetaBuilderPrivate::traverseFunctions(const ScopeModelItem& scopeItem, - const AbstractMetaClassPtr &metaClass) +void AbstractMetaBuilderPrivate::traverseClassFunction(const AbstractMetaFunctionPtr &metaFunction, + const AbstractMetaClassPtr &metaClass) { - AbstractMetaClass::Attributes constructorAttributes; - const AbstractMetaFunctionList functions = - classFunctionList(scopeItem, &constructorAttributes, metaClass); - metaClass->setAttributes(metaClass->attributes() | constructorAttributes); - - for (const auto &metaFunction : functions) { - if (metaClass->isNamespace()) - metaFunction->setCppAttribute(FunctionAttribute::Static); - - const auto propertyFunction = metaClass->searchPropertyFunction(metaFunction->name()); - if (propertyFunction.index >= 0) { - QPropertySpec prop = metaClass->propertySpecs().at(propertyFunction.index); - switch (propertyFunction.function) { - case AbstractMetaClass::PropertyFunction::Read: - // Property reader must be in the form "<type> name()" - if (!metaFunction->isSignal() - && prop.typeEntry() == metaFunction->type().typeEntry() - && metaFunction->arguments().isEmpty()) { - *metaFunction += AbstractMetaFunction::PropertyReader; - metaFunction->setPropertySpecIndex(propertyFunction.index); - } - break; - case AbstractMetaClass::PropertyFunction::Write: - // Property setter must be in the form "void name(<type>)" - // Make sure the function was created with all arguments; some - // argument can be missing during the parsing because of errors - // in the typesystem. - if (metaFunction->isVoid() && metaFunction->arguments().size() == 1 - && (prop.typeEntry() == metaFunction->arguments().at(0).type().typeEntry())) { - *metaFunction += AbstractMetaFunction::PropertyWriter; - metaFunction->setPropertySpecIndex(propertyFunction.index); - } - break; - case AbstractMetaClass::PropertyFunction::Reset: - // Property resetter must be in the form "void name()" - if (metaFunction->isVoid() && metaFunction->arguments().isEmpty()) { - *metaFunction += AbstractMetaFunction::PropertyResetter; - metaFunction->setPropertySpecIndex(propertyFunction.index); - } - break; - case AbstractMetaClass::PropertyFunction::Notify: - if (metaFunction->isSignal()) { - *metaFunction += AbstractMetaFunction::PropertyNotify; - metaFunction->setPropertySpecIndex(propertyFunction.index); - } + const auto propertyFunction = metaClass->searchPropertyFunction(metaFunction->name()); + if (propertyFunction.index >= 0) { + QPropertySpec prop = metaClass->propertySpecs().at(propertyFunction.index); + switch (propertyFunction.function) { + case AbstractMetaClass::PropertyFunction::Read: + // Property reader must be in the form "<type> name()" + if (!metaFunction->isSignal() + && prop.typeEntry() == metaFunction->type().typeEntry() + && metaFunction->arguments().isEmpty()) { + *metaFunction += AbstractMetaFunction::PropertyReader; + metaFunction->setPropertySpecIndex(propertyFunction.index); + } + break; + case AbstractMetaClass::PropertyFunction::Write: + // Property setter must be in the form "void name(<type>)" + // Make sure the function was created with all arguments; some + // argument can be missing during the parsing because of errors + // in the typesystem. + if (metaFunction->isVoid() && metaFunction->arguments().size() == 1 + && (prop.typeEntry() == metaFunction->arguments().at(0).type().typeEntry())) { + *metaFunction += AbstractMetaFunction::PropertyWriter; + metaFunction->setPropertySpecIndex(propertyFunction.index); + } + break; + case AbstractMetaClass::PropertyFunction::Reset: + // Property resetter must be in the form "void name()" + if (metaFunction->isVoid() && metaFunction->arguments().isEmpty()) { + *metaFunction += AbstractMetaFunction::PropertyResetter; + metaFunction->setPropertySpecIndex(propertyFunction.index); + } + break; + case AbstractMetaClass::PropertyFunction::Notify: + if (metaFunction->isSignal()) { + *metaFunction += AbstractMetaFunction::PropertyNotify; + metaFunction->setPropertySpecIndex(propertyFunction.index); } } + } - if (metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction - && metaFunction->isPrivate()) { - metaClass->setHasPrivateConstructor(true); - } - if (metaFunction->isConstructor() && !metaFunction->isPrivate()) // Including Copy CT - metaClass->setHasNonPrivateConstructor(true); + if (metaFunction->isPrivate() && metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction) { + metaClass->setHasPrivateConstructor(true); + return; + } - if (!metaFunction->isDestructor() - && !(metaFunction->isPrivate() && metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction)) { + if (metaFunction->isConstructor() && !metaFunction->isPrivate()) // Including Copy CT + metaClass->setHasNonPrivateConstructor(true); - if (metaFunction->isSignal() && metaClass->hasSignal(metaFunction.get())) - ReportHandler::addGeneralMessage(msgSignalOverloaded(metaClass, metaFunction.get())); + if (metaFunction->isDestructor()) { + metaClass->setHasPrivateDestructor(metaFunction->isPrivate()); + metaClass->setHasProtectedDestructor(metaFunction->isProtected()); + metaClass->setHasVirtualDestructor(metaFunction->isVirtual()); + return; + } - if (metaFunction->isConversionOperator()) - fixReturnTypeOfConversionOperator(metaFunction); + if (metaFunction->isSignal() && metaClass->hasSignal(metaFunction.get())) + ReportHandler::addGeneralMessage(msgSignalOverloaded(metaClass, metaFunction.get())); - AbstractMetaClass::addFunction(metaClass, metaFunction); - applyFunctionModifications(metaFunction); - } else if (metaFunction->isDestructor()) { - metaClass->setHasPrivateDestructor(metaFunction->isPrivate()); - metaClass->setHasProtectedDestructor(metaFunction->isProtected()); - metaClass->setHasVirtualDestructor(metaFunction->isVirtual()); + if (metaFunction->isConversionOperator()) + fixReturnTypeOfConversionOperator(metaFunction); + + AbstractMetaClass::addFunction(metaClass, metaFunction); + applyFunctionModifications(metaFunction); +} + +void AbstractMetaBuilderPrivate::traverseClassFunction(const ScopeModelItem& scopeItem, + const FunctionModelItem &function, + const AbstractMetaFunctionPtr &metaFunction, + const AbstractMetaClassPtr &metaClass) const +{ + Q_UNUSED(scopeItem) + Q_UNUSED(function) + traverseClassFunction(metaFunction, metaClass); +} + +void AbstractMetaBuilderPrivate::traverseClassFunctions(const ScopeModelItem& scopeItem, + const AbstractMetaClassPtr &metaClass) +{ + Q_ASSERT(metaClass); + AbstractMetaClass::Attributes constructorAttributes; + for (const FunctionModelItem &function : scopeItem->functions()) { + if (function->isSpaceshipOperator() && !function->isDeleted()) { + AbstractMetaClass::addSynthesizedComparisonOperators(metaClass, + InternalFunctionFlag::OperatorCpp20Spaceship); + } else if (auto metaFunction = traverseFunction(function, metaClass)) { + traverseClassFunction(scopeItem, function, metaFunction, metaClass); + } else if (!function->isDeleted() && function->functionType() == CodeModel::Constructor) { + // traverseFunction() failed: mark rejected constructors + auto arguments = function->arguments(); + constructorAttributes |= AbstractMetaClass::HasRejectedConstructor; + if (arguments.isEmpty() || arguments.constFirst()->defaultValue()) + constructorAttributes |= AbstractMetaClass::HasRejectedDefaultConstructor; } } + metaClass->setAttributes(metaClass->attributes() | constructorAttributes); + fillAddedFunctions(metaClass); } @@ -1803,12 +1829,10 @@ AbstractMetaFunctionPtr // Check if it's a reverse operator if (metaArguments[1].type().typeEntry() == metaClass->typeEntry()) { metaFunction->setReverseOperator(true); - // we need to call these two function to cache the old signature (with two args) - // we do this buggy behaviour to comply with the original apiextractor buggy behaviour. - metaFunction->signature(); - metaFunction->minimalSignature(); - metaArguments.removeLast(); - metaFunction->setArguments(metaArguments); + // Cache the old signature (with two args) for modifications + QString minimalSignature = metaFunction->minimalSignature(); + metaFunction->takeArgument(1); + metaFunction->setUnresolvedSignatures({minimalSignature}); } else { qCWarning(lcShiboken) << "Operator overload can have two arguments only if it's a reverse operator!"; } |
