diff options
author | Tomaz Canabrava <tcanabrava@kde.org> | 2020-01-17 10:03:43 +0000 |
---|---|---|
committer | Tomaz Canabrava <tcanabrava@kde.org> | 2020-01-17 10:03:43 +0000 |
commit | 5f8c2ce63499d05dfb4753eb1acc21dccf21d434 (patch) | |
tree | fed718a3c8f4c4974411d612a79c4125ae3fffd8 /src/kconfig_compiler/KConfigSourceGenerator.cpp | |
parent | 98c32e29f50465d4d4e16bafdf0491edbfb422b0 (diff) | |
download | kconfig-5f8c2ce63499d05dfb4753eb1acc21dccf21d434.tar.gz kconfig-5f8c2ce63499d05dfb4753eb1acc21dccf21d434.tar.bz2 |
Revert "WIP: Refactor KConfigXT"
This reverts commit 98c32e29f50465d4d4e16bafdf0491edbfb422b0.
This broke kdevelop and kmymoney. I'm workin on the fixes and more
unittests for them.
Diffstat (limited to 'src/kconfig_compiler/KConfigSourceGenerator.cpp')
-rw-r--r-- | src/kconfig_compiler/KConfigSourceGenerator.cpp | 657 |
1 files changed, 0 insertions, 657 deletions
diff --git a/src/kconfig_compiler/KConfigSourceGenerator.cpp b/src/kconfig_compiler/KConfigSourceGenerator.cpp deleted file mode 100644 index 1949b420..00000000 --- a/src/kconfig_compiler/KConfigSourceGenerator.cpp +++ /dev/null @@ -1,657 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org) - Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> - Copyright (c) 2003 Waldo Bastian <bastian@kde.org> - Copyright (c) 2003 Zack Rusin <zack@kde.org> - Copyright (c) 2006 MichaĆ«l Larouche <michael.larouche@kdemail.net> - Copyright (c) 2008 Allen Winter <winter@kde.org> - Copyright (C) 2020 Tomaz Cananbrava (tcanabrava@kde.org) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "KConfigSourceGenerator.h" -#include "KConfigCommonStructs.h" - - -KConfigSourceGenerator::KConfigSourceGenerator( - const QString& inputFile, - const QString& baseDir, - const KConfigXTParameters &cfg, - ParseResult &parseResult) - : KConfigCodeGeneratorBase(inputFile, baseDir, baseDir + cfg.baseName + QLatin1Char('.') + cfg.sourceExtension, cfg, parseResult) -{ -} - -void KConfigSourceGenerator::start() -{ - KConfigCodeGeneratorBase::start(); - stream << endl; - createHeaders(); - - if (!cfg.nameSpace.isEmpty()) { - stream << "using namespace " << cfg.nameSpace << ";"; - stream << endl << endl; - } - - createPrivateDPointerImplementation(); - createSingletonImplementation(); - createPreamble(); - doConstructor(); - doGetterSetterDPointerMode(); - createDefaultValueGetterSetter(); - createDestructor(); - createNonModifyingSignalsHelper(); - createSignalFlagsHandler(); - includeMoc(); -} - -void KConfigSourceGenerator::createHeaders() -{ - QString headerName = cfg.baseName + QLatin1Char('.') + cfg.headerExtension; - - // TODO: Make addQuotes return a string instead of replacing it inplace. - addQuotes(headerName); - - addHeaders({ headerName }); - stream << endl; - - addHeaders(cfg.sourceIncludes); - if (cfg.setUserTexts && cfg.translationSystem == KConfigXTParameters::KdeTranslation) { - addHeaders({QStringLiteral("klocalizedstring.h")}); - stream << endl; - } - - // Header required by singleton implementation - if (cfg.singleton) { - addHeaders({QStringLiteral("qglobal.h"), QStringLiteral("QFile")}); - - // HACK: Add single line to fix test. - if (cfg.singleton && parseResult.cfgFileNameArg) { - stream << endl; - } - } - - if (cfg.singleton && parseResult.cfgFileNameArg) { - addHeaders({QStringLiteral("QDebug")}); - } - - if (cfg.singleton) { - stream << endl; - } -} - -void KConfigSourceGenerator::createPrivateDPointerImplementation() -{ - // private class implementation - if (!cfg.dpointer) { - return; - } - - QString group; - beginNamespaces(); - stream << "class " << cfg.className << "Private" << endl; - stream << "{" << endl; - stream << " public:" << endl; - - // Create Members - for (auto *entry : qAsConst(parseResult.entries)) { - if (entry->group != group) { - group = entry->group; - stream << endl; - stream << " // " << group << endl; - } - stream << " " << cppType(entry->type) << " " << varName(entry->name, cfg); - if (!entry->param.isEmpty()) { - stream << QStringLiteral("[%1]").arg(entry->paramMax + 1); - } - stream << ";" << endl; - } - stream << endl << " // items" << endl; - - // Create Items. - for (auto *entry : qAsConst(parseResult.entries)) { - const QString declType = entry->signalList.isEmpty() - ? QString(cfg.inherits + QStringLiteral("::Item") + itemType(entry->type)) - : QStringLiteral("KConfigCompilerSignallingItem"); - - stream << " " << declType << " *" << itemVar( entry, cfg ); - if (!entry->param.isEmpty()) { - stream << QStringLiteral("[%1]").arg(entry->paramMax + 1); - } - stream << ";" << endl; - } - - if (parseResult.hasNonModifySignals) { - stream << " uint " << varName(QStringLiteral("settingsChanged"), cfg) << ";" << endl; - } - - stream << "};" << endl << endl; - endNamespaces(); -} - -void KConfigSourceGenerator::createSingletonImplementation() -{ - // Singleton implementation - if (!cfg.singleton) { - return; - } - - beginNamespaces(); - stream << "class " << cfg.className << "Helper" << endl; - stream << '{' << endl; - stream << " public:" << endl; - stream << " " << cfg.className << "Helper() : q(nullptr) {}" << endl; - stream << " ~" << cfg.className << "Helper() { delete q; }" << endl; - stream << " " << cfg.className << "Helper(const " << cfg.className << "Helper&) = delete;" << endl; - stream << " " << cfg.className << "Helper& operator=(const " << cfg.className << "Helper&) = delete;" << endl; - stream << " " << cfg.className << " *q;" << endl; - stream << "};" << endl; - endNamespaces(); - - stream << "Q_GLOBAL_STATIC(" << cfg.className << "Helper, s_global" << cfg.className << ")" << endl; - - stream << cfg.className << " *" << cfg.className << "::self()" << endl; - stream << "{" << endl; - if (parseResult.cfgFileNameArg) { - stream << " if (!s_global" << cfg.className << "()->q)" << endl; - stream << " qFatal(\"you need to call " << cfg.className << "::instance before using\");" << endl; - } else { - stream << " if (!s_global" << cfg.className << "()->q) {" << endl; - stream << " new " << cfg.className << ';' << endl; - stream << " s_global" << cfg.className << "()->q->read();" << endl; - stream << " }" << endl << endl; - } - stream << " return s_global" << cfg.className << "()->q;" << endl; - stream << "}" << endl << endl; - - if (parseResult.cfgFileNameArg) { - auto instance = [this] (const QString &type, const QString &arg, bool isString) { - stream << "void " << cfg.className << "::instance(" << type << " " << arg << ")" << endl; - stream << "{" << endl; - stream << " if (s_global" << cfg.className << "()->q) {" << endl; - stream << " qDebug() << \"" << cfg.className << "::instance called after the first use - ignoring\";" << endl; - stream << " return;" << endl; - stream << " }" << endl; - stream << " new " << cfg.className << "("; - if (isString) { - stream << "KSharedConfig::openConfig(" << arg << ")"; - } else { - stream << "std::move(" << arg << ")"; - } - stream << ");" << endl; - stream << " s_global" << cfg.className << "()->q->read();" << endl; - stream << "}" << endl << endl; - }; - instance(QStringLiteral("const QString&"), QStringLiteral("cfgfilename"), true); - instance(QStringLiteral("KSharedConfig::Ptr"), QStringLiteral("config"), false); - } -} - -void KConfigSourceGenerator::createPreamble() -{ - QString cppPreamble; - for (const auto entry : qAsConst(parseResult.entries)) { - if (entry->paramValues.isEmpty()) { - continue; - } - - cppPreamble += QStringLiteral("const char* const ") + cfg.className + QStringLiteral("::") + enumName(entry->param); - cppPreamble += cfg.globalEnums - ? QStringLiteral("ToString[] = { \"") + entry->paramValues.join(QStringLiteral("\", \"")) + QStringLiteral("\" };\n") - : QStringLiteral("::enumToString[] = { \"") + entry->paramValues.join(QStringLiteral("\", \"")) + QStringLiteral("\" };\n"); - } - - if (!cppPreamble.isEmpty()) { - stream << cppPreamble << endl; - } -} - -void KConfigSourceGenerator::createConstructorParameterList() -{ - if (parseResult.cfgFileNameArg) { - if (!cfg.forceStringFilename) { - stream << " KSharedConfig::Ptr config"; - } else { - stream << " const QString& config"; - } - stream << (parseResult.parameters.isEmpty() ? "" : ","); - } - - for (QList<Param>::ConstIterator it = parseResult.parameters.constBegin(); - it != parseResult.parameters.constEnd(); ++it) { - if (it != parseResult.parameters.constBegin()) { - stream << ","; - } - stream << " " << param((*it).type) << " " << (*it).name; - } - - if (cfg.parentInConstructor) { - if (parseResult.cfgFileNameArg || !parseResult.parameters.isEmpty()) { - stream << ","; - } - stream << " QObject *parent"; - } - -} - -void KConfigSourceGenerator::createParentConstructorCall() -{ - stream << cfg.inherits << "("; - if (!parseResult.cfgFileName.isEmpty()) { - stream << " QStringLiteral( \"" << parseResult.cfgFileName << "\" "; - } - if (parseResult.cfgFileNameArg) { - if (! cfg.forceStringFilename) { - stream << " std::move( config ) "; - } else { - stream << " config "; - } - } - if (!parseResult.cfgFileName.isEmpty()) { - stream << ") "; - } - stream << ")" << endl; -} - -void KConfigSourceGenerator::createInitializerList() -{ - for (const auto ¶meter : qAsConst(parseResult.parameters)) { - stream << " , mParam" << parameter.name << "(" << parameter.name << ")" << endl; - } - - if (parseResult.hasNonModifySignals && !cfg.dpointer) { - stream << " , " << varName(QStringLiteral("settingsChanged"), cfg) << "(0)" << endl; - } -} - -void KConfigSourceGenerator::createEnums(const CfgEntry *entry) -{ - if (entry->type != QLatin1String("Enum")) { - return; - } - stream << " QList<" << cfg.inherits << "::ItemEnum::Choice> values" << entry->name << ";" << endl; - - for (const auto &choice : qAsConst(entry->choices.choices)) { - stream << " {" << endl; - stream << " " << cfg.inherits << "::ItemEnum::Choice choice;" << endl; - stream << " choice.name = QStringLiteral(\"" << choice.name << "\");" << endl; - if (cfg.setUserTexts) { - if (!choice.label.isEmpty()) { - stream << " choice.label = " - << translatedString(cfg, choice.label, choice.context) - << ";" << endl; - } - if (!choice.toolTip.isEmpty()) { - stream << " choice.toolTip = " - << translatedString(cfg, choice.toolTip, choice.context) - << ";" << endl; - } - if (!choice.whatsThis.isEmpty()) { - stream << " choice.whatsThis = " - << translatedString(cfg, choice.whatsThis, choice.context) - << ";" << endl; - } - } - stream << " values" << entry->name << ".append( choice );" << endl; - stream << " }" << endl; - } -} - -void KConfigSourceGenerator::createNormalEntry(const CfgEntry *entry, const QString& key) -{ - stream << " " << itemPath(entry, cfg) << " = " - << newItem(entry, key, entry->defaultValue, cfg) << endl; - - if (!entry->min.isEmpty()) { - stream << " " << itemPath(entry, cfg) << "->setMinValue(" << entry->min << ");" << endl; - } - if (!entry->max.isEmpty()) { - stream << " " << itemPath(entry, cfg) << "->setMaxValue(" << entry->max << ");" << endl; - } - - if (cfg.setUserTexts) { - stream << userTextsFunctions(entry, cfg); - } - - if (cfg.allNotifiers || cfg.notifiers.contains(entry->name)) { - stream << " " << itemPath(entry, cfg) << "->setWriteFlags(KConfigBase::Notify);" << endl; - } - - stream << " addItem( " << itemPath(entry, cfg); - QString quotedName = entry->name; - addQuotes(quotedName); - if (quotedName != key) { - stream << ", QStringLiteral( \"" << entry->name << "\" )"; - } - stream << " );" << endl; -} - -void KConfigSourceGenerator::createIndexedEntry(const CfgEntry *entry, const QString& key) -{ - for (int i = 0; i <= entry->paramMax; i++) { - QString itemVarStr(itemPath(entry, cfg) + QStringLiteral("[%1]").arg(i)); - - QString defaultStr = !entry->paramDefaultValues[i].isEmpty() ? entry->paramDefaultValues[i] - : !entry->defaultValue.isEmpty() ? paramString(entry->defaultValue, entry, i) - : defaultValue(entry->type); - - stream << " " << itemVarStr << " = " - << newItem(entry, paramString(key, entry, i), defaultStr, cfg, QStringLiteral("[%1]").arg(i)) << endl; - - if (cfg.setUserTexts) { - stream << userTextsFunctions(entry, cfg, itemVarStr, entry->paramName); - } - - // Make mutators for enum parameters work by adding them with $(..) replaced by the - // param name. The check for isImmutable in the set* functions doesn't have the param - // name available, just the corresponding enum value (int), so we need to store the - // param names in a separate static list!. - const bool isEnum = entry->paramType == QLatin1String("Enum"); - const QString arg = isEnum ? entry->paramValues[i] : QString::number(i); - - QString paramName = entry->paramName; - - stream << " addItem( " << itemVarStr << ", QStringLiteral( \""; - stream << paramName.replace(QStringLiteral("$(") + entry->param + QLatin1Char(')'), QLatin1String("%1")).arg( arg ); - stream << "\" ) );" << endl; - } -} - -void KConfigSourceGenerator::handleCurrentGroupChange(const CfgEntry *entry) -{ - if (entry->group == mCurrentGroup) { - return; - } - - // HACK: This fixes one spacing line in the diff. Remove this in the future and adapt the testcases. - static bool first = true; - if (!entry->group.isEmpty()) { - if (!first) { - stream << endl; - } - first = false; - } - - mCurrentGroup = entry->group; - stream << " setCurrentGroup( " << paramString(mCurrentGroup, parseResult.parameters) << " );"; - stream << endl << endl; -} - -void KConfigSourceGenerator::doConstructor() -{ - // Constructor - stream << cfg.className << "::" << cfg.className << "("; - createConstructorParameterList(); - stream << " )" << endl; - stream << " : "; - createParentConstructorCall(); - createInitializerList(); - - stream << "{" << endl; - - if (cfg.parentInConstructor) { - stream << " setParent(parent);" << endl; - } - - if (cfg.dpointer) { - stream << " d = new " << cfg.className << "Private;" << endl; - if (parseResult.hasNonModifySignals) { - stream << " " << varPath(QStringLiteral("settingsChanged"), cfg) << " = 0;" << endl; - } - } - - // Needed in case the singleton class is used as baseclass for - // another singleton. - if (cfg.singleton) { - stream << " Q_ASSERT(!s_global" << cfg.className << "()->q);" << endl; - stream << " s_global" << cfg.className << "()->q = this;" << endl; - } - - if (!parseResult.signalList.isEmpty()) { - // this cast to base-class pointer-to-member is valid C++ - // https://stackoverflow.com/questions/4272909/is-it-safe-to-upcast-a-method-pointer-and-use-it-with-base-class-pointer/ - stream << " KConfigCompilerSignallingItem::NotifyFunction notifyFunction =" - << " static_cast<KConfigCompilerSignallingItem::NotifyFunction>(&" - << cfg.className << "::itemChanged);" << endl; - - stream << endl; - } - - for (auto *entry : qAsConst(parseResult.entries)) { - handleCurrentGroupChange(entry); - - const QString key = paramString(entry->key, parseResult.parameters); - if (!entry->code.isEmpty()) { - stream << entry->code << endl; - } - createEnums(entry); - - if (!cfg.dpointer) { - stream << itemDeclaration(entry, cfg); - } - - if (entry->param.isEmpty()) { - createNormalEntry(entry, key); - } else { - createIndexedEntry(entry, key); - } - } - - stream << "}" << endl << endl; -} - -void KConfigSourceGenerator::createGetterDPointerMode(const CfgEntry *entry) -{ - // Accessor - if (cfg.useEnumTypes && entry->type == QLatin1String("Enum")) { - stream << enumType(entry, cfg.globalEnums); - } else { - stream << cppType(entry->type); - } - - stream << " " << getFunction(entry->name, cfg.className) << "("; - if (!entry->param.isEmpty()) { - stream << " " << cppType(entry->paramType) << " i "; - } - stream << ")" << Const << endl; - - // function body inline only if not using dpointer - // for BC mode - startScope(); - // HACK: Fix memberAccessorBody - stream << " " << memberAccessorBody(entry, cfg.globalEnums); - endScope(); - stream << endl; -} - -void KConfigSourceGenerator::createSetterDPointerMode(const CfgEntry *entry) -{ - // Manipulator - if (!(cfg.allMutators || cfg.mutators.contains(entry->name))) { - return; - } - - stream << "void " << setFunction(entry->name, cfg.className) << "( "; - if (!entry->param.isEmpty()) { - stream << cppType(entry->paramType) << " i, "; - } - - if (cfg.useEnumTypes && entry->type == QLatin1String("Enum")) { - stream << enumType(entry, cfg.globalEnums); - } else { - stream << param(entry->type); - } - stream << " v )" << endl; - - // function body inline only if not using dpointer - // for BC mode - startScope(); - memberMutatorBody(entry); - endScope(); - stream << endl; -} - -void KConfigSourceGenerator::createItemGetterDPointerMode(const CfgEntry *entry) -{ - // Item accessor - if (!cfg.itemAccessors) { - return; - } - stream << endl; - stream << cfg.inherits << "::Item" << itemType(entry->type) << " *" - << getFunction(entry->name, cfg.className) << "Item("; - if (!entry->param.isEmpty()) { - stream << " " << cppType(entry->paramType) << " i "; - } - stream << ")" << endl; - startScope(); - stream << " " << itemAccessorBody(entry, cfg); - endScope(); -} - -void KConfigSourceGenerator::doGetterSetterDPointerMode() -{ - if (!cfg.dpointer) { - return; - } - - // setters and getters go in Cpp if in dpointer mode - for (auto *entry : qAsConst(parseResult.entries)) { - createSetterDPointerMode(entry); - createGetterDPointerMode(entry); - createItemGetterDPointerMode(entry); - stream << endl; - } -} - -void KConfigSourceGenerator::createDefaultValueGetterSetter() -{ - // default value getters always go in Cpp - for (auto *entry : qAsConst(parseResult.entries)) { - QString n = entry->name; - QString t = entry->type; - - // Default value Accessor, as "helper" function - if ((cfg.allDefaultGetters || cfg.defaultGetters.contains(n)) && !entry->defaultValue.isEmpty()) { - stream << cppType(t) << " " << getDefaultFunction(n, cfg.className) << "_helper("; - if (!entry->param.isEmpty()) { - stream << " " << cppType(entry->paramType) << " i "; - } - stream << ")" << Const << endl; - startScope(); - stream << memberGetDefaultBody(entry) << endl; - endScope(); - stream << endl; - } - } -} - -void KConfigSourceGenerator::createDestructor() -{ - stream << cfg.className << "::~" << cfg.className << "()" << endl; - startScope(); - if (cfg.dpointer) { - stream << " delete d;" << endl; - } - if (cfg.singleton) { - stream << " s_global" << cfg.className << "()->q = nullptr;" << endl; - } - endScope(); - stream << endl; -} - -void KConfigSourceGenerator::createNonModifyingSignalsHelper() -{ - if (!parseResult.hasNonModifySignals) { - return; - } - stream << "bool " << cfg.className << "::" << "usrSave()" << endl; - startScope(); - stream << " const bool res = " << cfg.inherits << "::usrSave();" << endl; - stream << " if (!res) return false;" << endl << endl; - for (const Signal &signal : qAsConst(parseResult.signalList)) { - if (signal.modify) { - continue; - } - - stream << " if ( " << varPath(QStringLiteral("settingsChanged"), cfg) << " & " << signalEnumName(signal.name) << " )" << endl; - stream << " Q_EMIT " << signal.name << "("; - QList<Param>::ConstIterator it, itEnd = signal.arguments.constEnd(); - for (it = signal.arguments.constBegin(); it != itEnd;) { - Param argument = *it; - bool cast = false; - if (cfg.useEnumTypes && argument.type == QLatin1String("Enum")) { - for (int i = 0, end = parseResult.entries.count(); i < end; ++i) { - if (parseResult.entries.at(i)->name == argument.name) { - stream << "static_cast<" << enumType(parseResult.entries.at(i), cfg.globalEnums) << ">("; - cast = true; - break; - } - } - } - stream << varPath(argument.name, cfg); - if (cast) { - stream << ")"; - } - if (++it != itEnd) { - stream << ", "; - } - } - - stream << ");" << endl; - } - - stream << " " << varPath(QStringLiteral("settingsChanged"), cfg) << " = 0;" << endl; - stream << " return true;" << endl; - endScope(); -} - -void KConfigSourceGenerator::createSignalFlagsHandler() -{ - if (parseResult.signalList.isEmpty()) { - return; - } - - stream << endl; - stream << "void " << cfg.className << "::" << "itemChanged(quint64 flags) {" << endl; - if (parseResult.hasNonModifySignals) - stream << " " << varPath(QStringLiteral("settingsChanged"), cfg) << " |= flags;" << endl; - - if (!parseResult.signalList.isEmpty()) - stream << endl; - - for (const Signal &signal : qAsConst(parseResult.signalList)) { - if (signal.modify) { - stream << " if ( flags & " << signalEnumName(signal.name) << " ) {" << endl; - stream << " Q_EMIT " << signal.name << "();" << endl; - stream << " }" << endl; - } - } - - stream << "}" << endl; -} - -void KConfigSourceGenerator::includeMoc() { - const QString mocFileName = cfg.baseName + QStringLiteral(".moc"); - - if (parseResult.signalList.count() || cfg.generateProperties) { - // Add includemoc if they are signals defined. - stream << endl; - stream << "#include \"" << mocFileName << "\"" << endl; - stream << endl; - } -} |