aboutsummaryrefslogtreecommitdiffstats
path: root/generator
diff options
context:
space:
mode:
authorMarcelo Lira <marcelo.lira@openbossa.org>2011-08-02 17:01:40 -0300
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-08 16:17:07 -0300
commitf9e9189be4b622b74d0df2787a09f93fe7a5d0ae (patch)
tree37e5c07fb73a638e65a13352cb3c50304135d6e7 /generator
parent3e8c945bdc731fb7c9eaff0007abc02bfa1e5c37 (diff)
Disassembled ShibokenGenerator's writeCodeSnips method.
Also added writeConversionRule methods to CppGenerator. Reviewed by Hugo Parente <hugo.lima@openbossa.org> Reviewed by Luciano Wolf <luciano.wolf@openbossa.org> Reviewed by Renato Araújo <renato.filho@openbossa.org>
Diffstat (limited to 'generator')
-rw-r--r--generator/cppgenerator.cpp103
-rw-r--r--generator/cppgenerator.h5
-rw-r--r--generator/shibokengenerator.cpp450
-rw-r--r--generator/shibokengenerator.h39
4 files changed, 301 insertions, 296 deletions
diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp
index 6845d4f4f..827ec28e3 100644
--- a/generator/cppgenerator.cpp
+++ b/generator/cppgenerator.cpp
@@ -39,49 +39,6 @@ QHash<QString, QString> CppGenerator::m_mpFuncs = QHash<QString, QString>();
int CppGenerator::m_currentErrorCode = 0;
// utility functions
-inline CodeSnipList getConversionRule(TypeSystem::Language lang, const AbstractMetaFunction *function)
-{
- CodeSnipList list;
-
- foreach(AbstractMetaArgument *arg, function->arguments()) {
- QString convRule = function->conversionRule(lang, arg->argumentIndex() + 1);
- if (!convRule.isEmpty()) {
- CodeSnip snip(0, TypeSystem::TargetLangCode);
- snip.position = CodeSnip::Beginning;
-
- convRule.replace("%in", arg->name());
- convRule.replace("%out", arg->name() + "_out");
-
- snip.addCode(convRule);
- list << snip;
- }
-
- }
- return list;
-}
-
-inline CodeSnipList getReturnConversionRule(TypeSystem::Language lang,
- const AbstractMetaFunction *function,
- const QString& inputName,
- const QString& outputName)
-{
- CodeSnipList list;
-
- QString convRule = function->conversionRule(lang, 0);
- if (!convRule.isEmpty()) {
- CodeSnip snip(0, lang);
- snip.position = CodeSnip::Beginning;
-
- convRule.replace("%in", inputName);
- convRule.replace("%out", outputName);
-
- snip.addCode(convRule);
- list << snip;
- }
-
- return list;
-}
-
inline AbstractMetaType* getTypeWithoutContainer(AbstractMetaType* arg)
{
if (arg && arg->typeEntry()->isContainer()) {
@@ -339,7 +296,7 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl
// class inject-code native/beginning
if (!metaClass->typeEntry()->codeSnips().isEmpty()) {
- writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), CodeSnip::Beginning, TypeSystem::NativeCode, 0, 0, metaClass);
+ writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), CodeSnip::Beginning, TypeSystem::NativeCode, metaClass);
s << endl;
}
@@ -570,7 +527,7 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl
// class inject-code native/end
if (!metaClass->typeEntry()->codeSnips().isEmpty()) {
- writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), CodeSnip::End, TypeSystem::NativeCode, 0, 0, metaClass);
+ writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), CodeSnip::End, TypeSystem::NativeCode, metaClass);
s << endl;
}
}
@@ -734,9 +691,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun
s << ';' << endl;
s << INDENT << '}' << endl << endl;
- CodeSnipList convRules = getConversionRule(TypeSystem::TargetLangCode, func);
- if (convRules.size())
- writeCodeSnips(s, convRules, CodeSnip::Beginning, TypeSystem::TargetLangCode, func);
+ writeConversionRule(s, func, TypeSystem::TargetLangCode);
s << INDENT << "Shiboken::AutoDecRef " PYTHON_ARGS "(";
@@ -859,8 +814,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun
if (!func->conversionRule(TypeSystem::NativeCode, 0).isEmpty()) {
// Has conversion rule.
- CodeSnipList convRule = getReturnConversionRule(TypeSystem::NativeCode, func, "", CPP_RETURN_VAR);
- writeCodeSnips(s, convRule, CodeSnip::Any, TypeSystem::NativeCode, func);
+ writeConversionRule(s, func, CPP_RETURN_VAR);
} else if (!injectedCodeHasReturnValueAttribution(func, TypeSystem::NativeCode)) {
writePythonToCppTypeConversion(s, func->type(), PYTHON_RETURN_VAR, CPP_RETURN_VAR, func->implementingClass());
}
@@ -1624,6 +1578,45 @@ void CppGenerator::writePythonToCppTypeConversion(QTextStream& s,
s << INDENT << typeName << " " << cppOut << " = " << conversion << ';' << endl;
}
+static void addConversionRuleCodeSnippet(CodeSnipList& snippetList, QString& rule,
+ TypeSystem::Language conversionLanguage,
+ TypeSystem::Language snippetLanguage,
+ QString outputName = QString(),
+ QString inputName = QString())
+{
+ if (rule.isEmpty())
+ return;
+ if (snippetLanguage == TypeSystem::TargetLangCode) {
+ rule.replace("%in", inputName);
+ rule.replace("%out", QString("%1_out").arg(outputName));
+ } else {
+ rule.replace("%out", outputName);
+ }
+ CodeSnip snip(0, snippetLanguage);
+ snip.position = (snippetLanguage == TypeSystem::NativeCode) ? CodeSnip::Any : CodeSnip::Beginning;
+ snip.addCode(rule);
+ snippetList << snip;
+}
+
+void CppGenerator::writeConversionRule(QTextStream& s, const AbstractMetaFunction* func, TypeSystem::Language language)
+{
+ CodeSnipList snippets;
+ foreach (AbstractMetaArgument* arg, func->arguments()) {
+ QString rule = func->conversionRule(language, arg->argumentIndex() + 1);
+ addConversionRuleCodeSnippet(snippets, rule, language, TypeSystem::TargetLangCode,
+ arg->name(), arg->name());
+ }
+ writeCodeSnips(s, snippets, CodeSnip::Beginning, TypeSystem::TargetLangCode, func);
+}
+
+void CppGenerator::writeConversionRule(QTextStream& s, const AbstractMetaFunction* func, const QString& outputVar)
+{
+ CodeSnipList snippets;
+ QString rule = func->conversionRule(TypeSystem::NativeCode, 0);
+ addConversionRuleCodeSnippet(snippets, rule, TypeSystem::NativeCode, TypeSystem::NativeCode, outputVar);
+ writeCodeSnips(s, snippets, CodeSnip::Any, TypeSystem::NativeCode, func);
+}
+
void CppGenerator::writeNoneReturn(QTextStream& s, const AbstractMetaFunction* func, bool thereIsReturnValue)
{
if (thereIsReturnValue && (!func->type() || func->argumentRemoved(0)) && !injectedCodeHasReturnValueAttribution(func)) {
@@ -2018,9 +2011,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f
s << endl;
}
- CodeSnipList convRules = getConversionRule(TypeSystem::NativeCode, func);
- if (convRules.size())
- writeCodeSnips(s, convRules, CodeSnip::Beginning, TypeSystem::TargetLangCode, func);
+ writeConversionRule(s, func, TypeSystem::NativeCode);
if (!func->isUserAdded()) {
bool badModifications = false;
@@ -2682,7 +2673,7 @@ void CppGenerator::writeMappingMethods(QTextStream& s, const AbstractMetaClass*
writeCppSelfDefinition(s, func);
const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last();
- writeCodeSnips(s, snips,CodeSnip::Any, TypeSystem::TargetLangCode, func, lastArg);
+ writeCodeSnips(s, snips, CodeSnip::Any, TypeSystem::TargetLangCode, func, lastArg);
s << '}' << endl << endl;
}
}
@@ -3495,7 +3486,7 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m
// class inject-code target/beginning
if (!classTypeEntry->codeSnips().isEmpty()) {
- writeCodeSnips(s, classTypeEntry->codeSnips(), CodeSnip::Beginning, TypeSystem::TargetLangCode, 0, 0, metaClass);
+ writeCodeSnips(s, classTypeEntry->codeSnips(), CodeSnip::Beginning, TypeSystem::TargetLangCode, metaClass);
s << endl;
}
@@ -3544,7 +3535,7 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m
// class inject-code target/end
if (!classTypeEntry->codeSnips().isEmpty()) {
s << endl;
- writeCodeSnips(s, classTypeEntry->codeSnips(), CodeSnip::End, TypeSystem::TargetLangCode, 0, 0, metaClass);
+ writeCodeSnips(s, classTypeEntry->codeSnips(), CodeSnip::End, TypeSystem::TargetLangCode, metaClass);
}
if (!metaClass->isNamespace())
diff --git a/generator/cppgenerator.h b/generator/cppgenerator.h
index c6cda3184..4dea57bd2 100644
--- a/generator/cppgenerator.h
+++ b/generator/cppgenerator.h
@@ -109,6 +109,11 @@ private:
const AbstractMetaClass* context = 0,
const QString& defaultValue = QString());
+ /// Writes the conversion rule for arguments of regular and virtual methods.
+ void writeConversionRule(QTextStream& s, const AbstractMetaFunction* func, TypeSystem::Language language);
+ /// Writes the conversion rule for the return value of a virtual method.
+ void writeConversionRule(QTextStream& s, const AbstractMetaFunction* func, const QString& outputVar);
+
/**
* Set the Python method wrapper return value variable to Py_None if
* there are return types different from void in any of the other overloads
diff --git a/generator/shibokengenerator.cpp b/generator/shibokengenerator.cpp
index b3fb89b16..3bb2d579d 100644
--- a/generator/shibokengenerator.cpp
+++ b/generator/shibokengenerator.cpp
@@ -1165,265 +1165,269 @@ static QString getArgumentsFromMethodCall(const QString& str)
return str.mid(begin, pos-begin-1);
}
-void ShibokenGenerator::writeCodeSnips(QTextStream& s,
- const CodeSnipList& codeSnips,
- CodeSnip::Position position,
- TypeSystem::Language language,
- const AbstractMetaFunction* func,
- const AbstractMetaArgument* lastArg,
- const AbstractMetaClass* context)
+QString ShibokenGenerator::getCodeSnippets(const CodeSnipList& codeSnips,
+ CodeSnip::Position position,
+ TypeSystem::Language language)
{
- static QRegExp pyArgsRegex("%PYARG_(\\d+)");
-
- // detect is we should use pyargs instead of args as variable name for python arguments
- bool usePyArgs = false;
- if (func) {
- // calc num of real arguments.
- int argsRemoved = 0;
- for (int i = 0; i < func->arguments().size(); i++) {
- if (func->argumentRemoved(i+1))
- argsRemoved++;
- }
- OverloadData od(getFunctionGroups(func->implementingClass())[func->name()], this);
- usePyArgs = pythonFunctionWrapperUsesListOfArguments(od);
- }
-
+ QString code;
+ QTextStream c(&code);
foreach (CodeSnip snip, codeSnips) {
if ((position != CodeSnip::Any && snip.position != position) || !(snip.language & language))
continue;
+ QString snipCode;
+ QTextStream sc(&snipCode);
+ formatCode(sc, snip.code(), INDENT);
+ c << snipCode;
+ }
+ return code;
+}
+void ShibokenGenerator::processCodeSnip(QString& code, const AbstractMetaClass* context)
+{
+ if (context) {
+ // Replace template variable by the Python Type object
+ // for the class context in which the variable is used.
+ code.replace("%PYTHONTYPEOBJECT", cpythonTypeName(context) + ".super.ht_type");
+ code.replace("%TYPE", wrapperName(context));
+ code.replace("%CPPTYPE", context->name());
+ }
- QString code;
- QTextStream tmpStream(&code);
- formatCode(tmpStream, snip.code(), INDENT);
+ // replace "toPython" converters
+ replaceConvertToPythonTypeSystemVariable(code);
- if (context) {
- // replace template variable for the Python Type object for the
- // class context in which the variable is used
- code.replace("%PYTHONTYPEOBJECT", cpythonTypeName(context) + ".super.ht_type");
- code.replace("%TYPE", wrapperName(context));
- code.replace("%CPPTYPE", context->name());
- }
+ // replace "toCpp" converters
+ replaceConvertToCppTypeSystemVariable(code);
- if (func) {
- // replace %PYARG_# variables
- code.replace("%PYARG_0", PYTHON_RETURN_VAR);
- if (snip.language == TypeSystem::TargetLangCode) {
- if (usePyArgs) {
- code.replace(pyArgsRegex, PYTHON_ARGS"[\\1-1]");
- } else {
- static QRegExp pyArgsRegexCheck("%PYARG_([2-9]+)");
- if (pyArgsRegexCheck.indexIn(code) != -1) {
- ReportHandler::warning("Wrong index for %PYARG variable ("+pyArgsRegexCheck.cap(1)+") on "+func->signature());
- return;
- }
- code.replace("%PYARG_1", PYTHON_ARG);
- }
- } else {
- // Replaces the simplest case of attribution to a Python argument
- // on the binding virtual method.
- static QRegExp pyArgsAttributionRegex("%PYARG_(\\d+)\\s*=[^=]\\s*([^;]+)");
- code.replace(pyArgsAttributionRegex, "PyTuple_SET_ITEM(" PYTHON_ARGS ", \\1-1, \\2)");
- code.replace(pyArgsRegex, "PyTuple_GET_ITEM(" PYTHON_ARGS ", \\1-1)");
- }
+ // replace "isConvertible" check
+ replaceConvertibleToCppTypeSystemVariable(code);
- // replace %ARG#_TYPE variables
- foreach (const AbstractMetaArgument* arg, func->arguments()) {
- QString argTypeVar = QString("%ARG%1_TYPE").arg(arg->argumentIndex() + 1);
- QString argTypeVal = arg->type()->cppSignature();
- code.replace(argTypeVar, argTypeVal);
- }
+ // replace "checkType" check
+ replaceTypeCheckTypeSystemVariable(code);
+}
- static QRegExp cppArgTypeRegexCheck("%ARG(\\d+)_TYPE");
- int pos = 0;
- while ((pos = cppArgTypeRegexCheck.indexIn(code, pos)) != -1) {
- ReportHandler::warning("Wrong index for %ARG#_TYPE variable ("+cppArgTypeRegexCheck.cap(1)+") on "+func->signature());
- pos += cppArgTypeRegexCheck.matchedLength();
+QMap<int, QString> ShibokenGenerator::getArgumentReplacement(const AbstractMetaFunction* func,
+ bool usePyArgs, TypeSystem::Language language,
+ const AbstractMetaArgument* lastArg)
+{
+ QMap<int, QString> argReplacement;
+ int removed = 0;
+ for (int i = 0; i < func->arguments().size(); ++i) {
+ const AbstractMetaArgument* arg = func->arguments().at(i);
+ QString argValue;
+ if (language == TypeSystem::TargetLangCode) {
+ bool argRemoved = func->argumentRemoved(i+1);
+ removed = removed + (int) argRemoved;
+ if (argRemoved || (lastArg && arg->argumentIndex() > lastArg->argumentIndex()))
+ argValue = arg->defaultValueExpression();
+ if (!argRemoved && argValue.isEmpty()) {
+ if (arg->type()->typeEntry()->isCustom())
+ argValue = usePyArgs ? QString(PYTHON_ARGS"[%1]").arg(i - removed) : PYTHON_ARG;
+ else
+ argValue = QString(CPP_ARG"%1").arg(i - removed);
}
+ } else {
+ argValue = arg->name();
+ }
+ if (!argValue.isEmpty())
+ argReplacement[i+1] = argValue;
+ }
+ return argReplacement;
+}
- // replace template variable for return variable name
- if (func->isConstructor()) {
- code.replace("%0.", QString("%1->").arg("cptr"));
- code.replace("%0", "cptr");
- } else if (func->type()) {
- QString returnValueOp = isPointerToWrapperType(func->type()) ? "%1->" : "%1.";
- if (ShibokenGenerator::isWrapperType(func->type()))
- code.replace("%0.", returnValueOp.arg(CPP_RETURN_VAR));
- code.replace("%0", CPP_RETURN_VAR);
- }
+void ShibokenGenerator::writeCodeSnips(QTextStream& s,
+ const CodeSnipList& codeSnips,
+ CodeSnip::Position position,
+ TypeSystem::Language language,
+ const AbstractMetaClass* context)
+{
+ QString code = getCodeSnippets(codeSnips, position, language);
+ if (code.isEmpty())
+ return;
+ processCodeSnip(code, context);
+ s << INDENT << "// Begin code injection" << endl;
+ s << code;
+ s << INDENT << "// End of code injection" << endl;
+}
- // replace template variable for self Python object
- QString pySelf = (snip.language == TypeSystem::NativeCode) ? "pySelf" : PYTHON_SELF_VAR;
- code.replace("%PYSELF", pySelf);
-
- // replace template variable for pointer to C++ this object
- if (func->implementingClass()) {
- QString cppSelf;
- QString replacement("%1->");
- if (func->isStatic()) {
- cppSelf = func->ownerClass()->qualifiedCppName();
- replacement = "%1::";
- } else if (snip.language == TypeSystem::NativeCode) {
- cppSelf = "this";
- } else {
- cppSelf = "cppSelf";
- }
+void ShibokenGenerator::writeCodeSnips(QTextStream& s,
+ const CodeSnipList& codeSnips,
+ CodeSnip::Position position,
+ TypeSystem::Language language,
+ const AbstractMetaFunction* func,
+ const AbstractMetaArgument* lastArg)
+{
+ QString code = getCodeSnippets(codeSnips, position, language);
+ if (code.isEmpty())
+ return;
- // on comparison operator cppSelf is always a reference.
- if (func->isComparisonOperator())
- replacement = "%1.";
-
- if (func->isVirtual() && !func->isAbstract() && (!avoidProtectedHack() || !func->isProtected())) {
- QString methodCallArgs = getArgumentsFromMethodCall(code);
- if (!methodCallArgs.isNull()) {
- if (func->name() == "metaObject") {
- QString wrapperClassName = wrapperName(func->ownerClass());
- QString cppSelfVar = avoidProtectedHack() ? QString("%CPPSELF") : QString("reinterpret_cast<%1*>(%CPPSELF)").arg(wrapperClassName);
- code.replace(QString("%CPPSELF.%FUNCTION_NAME(%1)").arg(methodCallArgs),
- QString("(Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject*>(%1))"
- " ? %2->::%3::%FUNCTION_NAME(%4)"
- " : %CPPSELF.%FUNCTION_NAME(%4))").arg(pySelf).arg(cppSelfVar).arg(wrapperClassName).arg(methodCallArgs));
- } else {
- code.replace(QString("%CPPSELF.%FUNCTION_NAME(%1)").arg(methodCallArgs),
- QString("(Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject*>(%1))"
- " ? %CPPSELF->::%TYPE::%FUNCTION_NAME(%2)"
- " : %CPPSELF.%FUNCTION_NAME(%2))").arg(pySelf).arg(methodCallArgs));
- }
- }
- }
+ // Calculate the real number of arguments.
+ int argsRemoved = 0;
+ for (int i = 0; i < func->arguments().size(); i++) {
+ if (func->argumentRemoved(i+1))
+ argsRemoved++;
+ }
- code.replace("%CPPSELF.", replacement.arg(cppSelf));
- code.replace("%CPPSELF", cppSelf);
+ OverloadData od(getFunctionGroups(func->implementingClass())[func->name()], this);
+ bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(od);
- if (code.indexOf("%BEGIN_ALLOW_THREADS") > -1) {
- if (code.count("%BEGIN_ALLOW_THREADS") == code.count("%END_ALLOW_THREADS")) {
- code.replace("%BEGIN_ALLOW_THREADS", BEGIN_ALLOW_THREADS);
- code.replace("%END_ALLOW_THREADS", END_ALLOW_THREADS);
- } else {
- ReportHandler::warning("%BEGIN_ALLOW_THREADS and %END_ALLOW_THREADS mismatch");
- }
- }
+ // Replace %PYARG_# variables.
+ code.replace("%PYARG_0", PYTHON_RETURN_VAR);
- // replace template variable for the Python Type object for the
- // class implementing the method in which the code snip is written
- if (func->isStatic()) {
- code.replace("%PYTHONTYPEOBJECT", cpythonTypeName(func->implementingClass()) + ".super.ht_type");
- } else {
- code.replace("%PYTHONTYPEOBJECT.", QString("%1->ob_type->").arg(pySelf));
- code.replace("%PYTHONTYPEOBJECT", QString("%1->ob_type").arg(pySelf));
- }
+ static QRegExp pyArgsRegex("%PYARG_(\\d+)");
+ if (language == TypeSystem::TargetLangCode) {
+ if (usePyArgs) {
+ code.replace(pyArgsRegex, PYTHON_ARGS"[\\1-1]");
+ } else {
+ static QRegExp pyArgsRegexCheck("%PYARG_([2-9]+)");
+ if (pyArgsRegexCheck.indexIn(code) != -1) {
+ ReportHandler::warning("Wrong index for %PYARG variable ("+pyArgsRegexCheck.cap(1)+") on "+func->signature());
+ return;
}
+ code.replace("%PYARG_1", PYTHON_ARG);
+ }
+ } else {
+ // Replaces the simplest case of attribution to a
+ // Python argument on the binding virtual method.
+ static QRegExp pyArgsAttributionRegex("%PYARG_(\\d+)\\s*=[^=]\\s*([^;]+)");
+ code.replace(pyArgsAttributionRegex, "PyTuple_SET_ITEM(" PYTHON_ARGS ", \\1-1, \\2)");
+ code.replace(pyArgsRegex, "PyTuple_GET_ITEM(" PYTHON_ARGS ", \\1-1)");
+ }
- // replace template variables %# for individual arguments
- int removed = 0;
- for (int i = 0; i < func->arguments().size(); i++) {
- const AbstractMetaArgument* arg = func->arguments().at(i);
- QString argReplacement;
- if (snip.language == TypeSystem::TargetLangCode) {
- if (!lastArg || func->argumentRemoved(i+1)) {
- if (!arg->defaultValueExpression().isEmpty())
- argReplacement = arg->defaultValueExpression();
- removed++;
- } else if (lastArg && (arg->argumentIndex() > lastArg->argumentIndex())) {
- argReplacement = arg->defaultValueExpression();
- }
+ // Replace %ARG#_TYPE variables.
+ foreach (const AbstractMetaArgument* arg, func->arguments()) {
+ QString argTypeVar = QString("%ARG%1_TYPE").arg(arg->argumentIndex() + 1);
+ QString argTypeVal = arg->type()->cppSignature();
+ code.replace(argTypeVar, argTypeVal);
+ }
- if (argReplacement.isEmpty()) {
- if (arg->type()->typeEntry()->isCustom()) {
- argReplacement = usePyArgs ? QString(PYTHON_ARGS"[%1]").arg(i - removed) : PYTHON_ARG;
- } else {
- argReplacement = QString(CPP_ARG"%1").arg(i - removed);
- }
- }
- } else {
- argReplacement = arg->name();
- }
- code.replace("%" + QString::number(i+1), argReplacement);
- }
+ int pos = 0;
+ static QRegExp cppArgTypeRegexCheck("%ARG(\\d+)_TYPE");
+ while ((pos = cppArgTypeRegexCheck.indexIn(code, pos)) != -1) {
+ ReportHandler::warning("Wrong index for %ARG#_TYPE variable ("+cppArgTypeRegexCheck.cap(1)+") on "+func->signature());
+ pos += cppArgTypeRegexCheck.matchedLength();
+ }
- // replace template %ARGUMENT_NAMES variable for a list of arguments
- removed = 0;
- QStringList argumentNames;
- foreach (const AbstractMetaArgument* arg, func->arguments()) {
- if (snip.language == TypeSystem::TargetLangCode) {
- if (func->argumentRemoved(arg->argumentIndex() + 1)) {
- if (!arg->defaultValueExpression().isEmpty())
- argumentNames << arg->defaultValueExpression();
- removed++;
- continue;
- }
+ // Replace template variable for return variable name.
+ if (func->isConstructor()) {
+ code.replace("%0.", QString("%1->").arg("cptr"));
+ code.replace("%0", "cptr");
+ } else if (func->type()) {
+ QString returnValueOp = isPointerToWrapperType(func->type()) ? "%1->" : "%1.";
+ if (ShibokenGenerator::isWrapperType(func->type()))
+ code.replace("%0.", returnValueOp.arg(CPP_RETURN_VAR));
+ code.replace("%0", CPP_RETURN_VAR);
+ }
- QString argName;
- if (lastArg && arg->argumentIndex() > lastArg->argumentIndex()) {
- argName = arg->defaultValueExpression();
- } else {
- argName = QString(CPP_ARG"%1").arg(arg->argumentIndex() - removed);
- }
- argumentNames << argName;
+ // Replace template variable for self Python object.
+ QString pySelf = (language == TypeSystem::NativeCode) ? "pySelf" : PYTHON_SELF_VAR;
+ code.replace("%PYSELF", pySelf);
+
+ // Replace template variable for a pointer to C++ of this object.
+ if (func->implementingClass()) {
+ QString replacement = func->isStatic() ? "%1::" : "%1->";
+ QString cppSelf;
+ if (func->isStatic())
+ cppSelf = func->ownerClass()->qualifiedCppName();
+ else if (language == TypeSystem::NativeCode)
+ cppSelf = "this";
+ else
+ cppSelf = CPP_SELF_VAR;
+
+ // On comparison operator CPP_SELF_VAR is always a reference.
+ if (func->isComparisonOperator())
+ replacement = "%1.";
+
+ if (func->isVirtual() && !func->isAbstract() && (!avoidProtectedHack() || !func->isProtected())) {
+ QString methodCallArgs = getArgumentsFromMethodCall(code);
+ if (!methodCallArgs.isNull()) {
+ if (func->name() == "metaObject") {
+ QString wrapperClassName = wrapperName(func->ownerClass());
+ QString cppSelfVar = avoidProtectedHack() ? QString("%CPPSELF") : QString("reinterpret_cast<%1*>(%CPPSELF)").arg(wrapperClassName);
+ code.replace(QString("%CPPSELF.%FUNCTION_NAME(%1)").arg(methodCallArgs),
+ QString("(Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject*>(%1))"
+ " ? %2->::%3::%FUNCTION_NAME(%4)"
+ " : %CPPSELF.%FUNCTION_NAME(%4))").arg(pySelf).arg(cppSelfVar).arg(wrapperClassName).arg(methodCallArgs));
} else {
- argumentNames << arg->name();
+ code.replace(QString("%CPPSELF.%FUNCTION_NAME(%1)").arg(methodCallArgs),
+ QString("(Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject*>(%1))"
+ " ? %CPPSELF->::%TYPE::%FUNCTION_NAME(%2)"
+ " : %CPPSELF.%FUNCTION_NAME(%2))").arg(pySelf).arg(methodCallArgs));
}
}
- code.replace("%ARGUMENT_NAMES", argumentNames.join(", "));
-
- if (snip.language == TypeSystem::NativeCode) {
- // replace template %PYTHON_ARGUMENTS variable for a pointer to the Python tuple
- // containing the converted virtual method arguments received from C++ to be passed
- // to the Python override
- code.replace("%PYTHON_ARGUMENTS", PYTHON_ARGS);
-
- // replace variable %PYTHON_METHOD_OVERRIDE for a pointer to the Python method
- // override for the C++ virtual method in which this piece of code was inserted
- code.replace("%PYTHON_METHOD_OVERRIDE", PYTHON_OVERRIDE_VAR);
- }
+ }
- if (avoidProtectedHack()) {
- // If the function being processed was added by the user via type system,
- // Shiboken needs to find out if there are other overloads for the same method
- // name and if any of them is of the protected visibility. This is used to replace
- // calls to %FUNCTION_NAME on user written custom code for calls to the protected
- // dispatcher.
- bool hasProtectedOverload = false;
- if (func->isUserAdded()) {
- foreach (const AbstractMetaFunction* f, getFunctionOverloads(func->ownerClass(), func->name()))
- hasProtectedOverload |= f->isProtected();
- }
+ code.replace("%CPPSELF.", replacement.arg(cppSelf));
+ code.replace("%CPPSELF", cppSelf);
- if (func->isProtected() || hasProtectedOverload) {
- code.replace("%TYPE::%FUNCTION_NAME",
- QString("%1::%2_protected")
- .arg(wrapperName(func->ownerClass()))
- .arg(func->originalName()));
- code.replace("%FUNCTION_NAME", QString("%1_protected").arg(func->originalName()));
- }
+ if (code.indexOf("%BEGIN_ALLOW_THREADS") > -1) {
+ if (code.count("%BEGIN_ALLOW_THREADS") == code.count("%END_ALLOW_THREADS")) {
+ code.replace("%BEGIN_ALLOW_THREADS", BEGIN_ALLOW_THREADS);
+ code.replace("%END_ALLOW_THREADS", END_ALLOW_THREADS);
+ } else {
+ ReportHandler::warning("%BEGIN_ALLOW_THREADS and %END_ALLOW_THREADS mismatch");
}
+ }
- if (func->isConstructor() && shouldGenerateCppWrapper(func->ownerClass()))
- code.replace("%TYPE", wrapperName(func->ownerClass()));
+ // replace template variable for the Python Type object for the
+ // class implementing the method in which the code snip is written
+ if (func->isStatic()) {
+ code.replace("%PYTHONTYPEOBJECT", cpythonTypeName(func->implementingClass()) + ".super.ht_type");
+ } else {
+ code.replace("%PYTHONTYPEOBJECT.", QString("%1->ob_type->").arg(pySelf));
+ code.replace("%PYTHONTYPEOBJECT", QString("%1->ob_type").arg(pySelf));
+ }
+ }
- if (func->ownerClass())
- code.replace("%CPPTYPE", func->ownerClass()->name());
+ // Replaces template %ARGUMENT_NAMES and %# variables by argument variables and values.
+ // Replaces template variables %# for individual arguments.
+ QMap<int, QString> argReplacements = getArgumentReplacement(func, usePyArgs, language, lastArg);
+ code.replace("%ARGUMENT_NAMES", QStringList(argReplacements.values()).join(", "));
+ foreach (int i, argReplacements.keys())
+ code.replace(QString("%%1").arg(i), argReplacements[i]);
+
+ if (language == TypeSystem::NativeCode) {
+ // Replaces template %PYTHON_ARGUMENTS variable with a pointer to the Python tuple
+ // containing the converted virtual method arguments received from C++ to be passed
+ // to the Python override.
+ code.replace("%PYTHON_ARGUMENTS", PYTHON_ARGS);
+
+ // replace variable %PYTHON_METHOD_OVERRIDE for a pointer to the Python method
+ // override for the C++ virtual method in which this piece of code was inserted
+ code.replace("%PYTHON_METHOD_OVERRIDE", PYTHON_OVERRIDE_VAR);
+ }
- replaceTemplateVariables(code, func);
+ if (avoidProtectedHack()) {
+ // If the function being processed was added by the user via type system,
+ // Shiboken needs to find out if there are other overloads for the same method
+ // name and if any of them is of the protected visibility. This is used to replace
+ // calls to %FUNCTION_NAME on user written custom code for calls to the protected
+ // dispatcher.
+ bool hasProtectedOverload = false;
+ if (func->isUserAdded()) {
+ foreach (const AbstractMetaFunction* f, getFunctionOverloads(func->ownerClass(), func->name()))
+ hasProtectedOverload |= f->isProtected();
}
- // replace "toPython" converters
- replaceConvertToPythonTypeSystemVariable(code);
+ if (func->isProtected() || hasProtectedOverload) {
+ code.replace("%TYPE::%FUNCTION_NAME",
+ QString("%1::%2_protected")
+ .arg(wrapperName(func->ownerClass()))
+ .arg(func->originalName()));
+ code.replace("%FUNCTION_NAME", QString("%1_protected").arg(func->originalName()));
+ }
+ }
- // replace "toCpp" converters
- replaceConvertToCppTypeSystemVariable(code);
+ if (func->isConstructor() && shouldGenerateCppWrapper(func->ownerClass()))
+ code.replace("%TYPE", wrapperName(func->ownerClass()));
- // replace "isConvertible" check
- replaceConvertibleToCppTypeSystemVariable(code);
+ if (func->ownerClass())
+ code.replace("%CPPTYPE", func->ownerClass()->name());
- // replace "checkType" check
- replaceTypeCheckTypeSystemVariable(code);
+ replaceTemplateVariables(code, func);
- if (!code.isEmpty()) {
- s << INDENT << "// Begin code injection" << endl;
- s << code;
- s << INDENT << "// End of code injection" << endl;
- }
- }
+ processCodeSnip(code);
+ s << INDENT << "// Begin code injection" << endl;
+ s << code;
+ s << INDENT << "// End of code injection" << endl;
}
void ShibokenGenerator::replaceConvertToPythonTypeSystemVariable(QString& code)
diff --git a/generator/shibokengenerator.h b/generator/shibokengenerator.h
index 256977690..605b205e6 100644
--- a/generator/shibokengenerator.h
+++ b/generator/shibokengenerator.h
@@ -111,26 +111,31 @@ public:
const AbstractMetaFunction* func,
Options options = NoOption) const;
QString functionReturnType(const AbstractMetaFunction* func, Options options = NoOption) const;
- /**
- * Write a code snip into the buffer \p s.
- * CodeSnip are codes inside inject-code tags.
- * \param s the buffer
- * \param code_snips a list of code snips
- * \param position the position to insert the code snip
- * \param language the kind of code snip
- * \param func the cpp function
- * \param lastArg last argument whose value is available, usually the last;
- * a NULL pointer indicates that no argument will be available,
- * i.e. a call without arguments.
- * \param context the class context for the place where the code snip will be written
- */
- void writeCodeSnips(QTextStream &s,
- const CodeSnipList &code_snips,
+
+ /// Utility function for writeCodeSnips.
+ static QMap<int, QString> getArgumentReplacement(const AbstractMetaFunction* func,
+ bool usePyArgs, TypeSystem::Language language,
+ const AbstractMetaArgument* lastArg);
+
+ /// Write user's custom code snippets at class or module level.
+ void writeCodeSnips(QTextStream& s,
+ const CodeSnipList& codeSnips,
CodeSnip::Position position,
TypeSystem::Language language,
- const AbstractMetaFunction* func = 0,
- const AbstractMetaArgument* lastArg = 0,
const AbstractMetaClass* context = 0);
+ /// Write user's custom code snippets at function level.
+ void writeCodeSnips(QTextStream& s,
+ const CodeSnipList& codeSnips,
+ CodeSnip::Position position,
+ TypeSystem::Language language,
+ const AbstractMetaFunction* func,
+ const AbstractMetaArgument* lastArg = 0);
+
+ /// Returns a string with the user's custom code snippets that comply with \p position and \p language.
+ QString getCodeSnippets(const CodeSnipList& codeSnips, CodeSnip::Position position, TypeSystem::Language language);
+
+ /// Replaces variables for the user's custom code at global or class level.
+ void processCodeSnip(QString& code, const AbstractMetaClass* context = 0);
/// Replaces the %CONVERTTOPYTHON type system variable.
void replaceConvertToPythonTypeSystemVariable(QString& code);