201 lines
7.0 KiB
C++
201 lines
7.0 KiB
C++
|
|
|
|
#include "GeneratorGrantleeBase.h"
|
|
|
|
#include "GrantleeWrappers.h"
|
|
#include "XmlReader.h"
|
|
|
|
#include <NGLLogger/NGLLoggerBootstrap.h>
|
|
#include <QtCore/QFile>
|
|
#include <QtCore/QRegularExpression>
|
|
|
|
using namespace CodeGen;
|
|
|
|
GeneratorGrantleeBase::GeneratorGrantleeBase(const char* loggerName)
|
|
: m_engine(new KTextTemplate::Engine)
|
|
, m_ctx(new KTextTemplate::Context)
|
|
, m_structBuilder(nullptr)
|
|
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger(loggerName))
|
|
{
|
|
// Add KTextTemplate plugin path for loading default tags/filters
|
|
// KTextTemplate plugins are in /usr/lib/x86_64-linux-gnu/qt6/plugins/kf6/ktexttemplate
|
|
// QT_PLUGIN_PATH should point to the parent directory containing the category folders
|
|
m_engine->addPluginPath(QStringLiteral("/usr/lib/x86_64-linux-gnu/qt6/plugins"));
|
|
}
|
|
|
|
GeneratorGrantleeBase::~GeneratorGrantleeBase()
|
|
{
|
|
delete m_engine;
|
|
delete m_ctx;
|
|
}
|
|
|
|
bool GeneratorGrantleeBase::initInternal(const XmlReader* reader, StructBuilder* structBuilder)
|
|
{
|
|
m_structBuilder = structBuilder;
|
|
|
|
if (reader)
|
|
{
|
|
m_ctx->insert(QStringLiteral("namespace"), reader->getServiceNamespace());
|
|
m_ctx->insert(QStringLiteral("namespace_abbr"), reader->getServiceAbbr().toLower());
|
|
m_ctx->insert(QStringLiteral("namespace_abbr_upper"), reader->getServiceAbbr().toUpper());
|
|
if (reader->getServiceNamespace() == QLatin1String("Core"))
|
|
m_ctx->insert(QStringLiteral("include_prefix"),
|
|
QStringLiteral("DDS/%1").arg(reader->getServiceNamespace()));
|
|
else
|
|
m_ctx->insert(QStringLiteral("include_prefix"), reader->getServiceNamespace());
|
|
m_ctx->insert(QStringLiteral("custom_record_replay"), reader->hasCustomRecordReplayPlugin());
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool GeneratorGrantleeBase::setTemplate(const QString& templateName, const QString& tmpl)
|
|
{
|
|
m_template = m_engine->newTemplate(tmpl, QStringLiteral("myTemplate"));
|
|
if (m_template->error())
|
|
{
|
|
WARNING_LOG(m_logger) << "Error parsing template '" << templateName << "': " << m_template->errorString();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
QString GeneratorGrantleeBase::render() const
|
|
{
|
|
QString out = m_template->render(m_ctx);
|
|
const QRegularExpression rx(QLatin1String(";\\n([ ]+\\n)*"));
|
|
out = out.replace(rx, QStringLiteral(";\n"));
|
|
return out;
|
|
}
|
|
|
|
QString GeneratorGrantleeBase::errorString() const
|
|
{
|
|
return m_template->errorString();
|
|
}
|
|
|
|
bool GeneratorGrantleeBase::generateData(const QString& templateName, const QString& outDirectory)
|
|
{
|
|
QString content;
|
|
if (!readFile(templateName, content))
|
|
return false;
|
|
if (!setTemplate(templateName, content))
|
|
return false;
|
|
|
|
content = render();
|
|
|
|
QString outFilename;
|
|
if (!getFilenameFromData(content, outFilename))
|
|
return false;
|
|
|
|
QFile f(outDirectory + QLatin1Char('/') + outFilename);
|
|
if (!f.open(QIODevice::WriteOnly))
|
|
{
|
|
ERROR_LOG(m_logger) << "Error opening file '" << f.fileName() << "' for writing: " << f.errorString() << "("
|
|
<< f.error() << ")";
|
|
return false;
|
|
}
|
|
const QByteArray outData = content.toUtf8();
|
|
f.write(outData);
|
|
f.close();
|
|
|
|
DEBUG_LOG(m_logger) << "Written data to " << f.fileName();
|
|
return true;
|
|
}
|
|
|
|
bool GeneratorGrantleeBase::readFile(const QString& filename, QString& data) const
|
|
{
|
|
QFile f(filename);
|
|
if (!f.open(QIODevice::ReadOnly))
|
|
{
|
|
ERROR_LOG(m_logger) << "Error opening file " << filename << " - error: " << f.errorString();
|
|
return false;
|
|
}
|
|
data = QString::fromUtf8(f.readAll());
|
|
f.close();
|
|
return true;
|
|
}
|
|
|
|
bool GeneratorGrantleeBase::getFilenameFromData(const QString& dataToParse, QString& filename) const
|
|
{
|
|
|
|
const QString filenameMarker(QStringLiteral("// filename:"));
|
|
int idx = dataToParse.indexOf(filenameMarker);
|
|
if (idx < 0)
|
|
{
|
|
ERROR_LOG(m_logger) << "Could not find marker '" << filenameMarker << "' in data!";
|
|
return false;
|
|
}
|
|
idx += filenameMarker.length() + 1;
|
|
int endIdx = dataToParse.indexOf(QLatin1Char('\n'), idx);
|
|
if (endIdx < 0)
|
|
{
|
|
ERROR_LOG(m_logger) << "Could not find end marker '\\n' in data!";
|
|
return false;
|
|
}
|
|
filename = dataToParse.mid(idx, endIdx - idx).trimmed();
|
|
|
|
return true;
|
|
}
|
|
|
|
void GeneratorGrantleeBase::addCustomFunctions(const QVector<CustomServiceFunctionInformation>& customFunctions)
|
|
{
|
|
|
|
QVariantList vlCustomDbFunctions;
|
|
QVariantList vlCustomDtcFunctions;
|
|
vlCustomDbFunctions.reserve(customFunctions.size());
|
|
vlCustomDtcFunctions.reserve(customFunctions.size());
|
|
for (const CustomServiceFunctionInformation& csfi : customFunctions)
|
|
{
|
|
const QString signature(csfi.returnValue + QLatin1Char(' ') + csfi.methodName + QLatin1Char('(') +
|
|
csfi.signature + QLatin1Char(')') +
|
|
(csfi.isConst ? QStringLiteral(" const") : QString()));
|
|
CustomFunctionWrapper* customFunctionWrapper(new CustomFunctionWrapper(signature, this));
|
|
switch (csfi.type)
|
|
{
|
|
case CustomServiceFunctionInformation::Type::Db:
|
|
vlCustomDbFunctions += QVariant::fromValue(customFunctionWrapper);
|
|
break;
|
|
case CustomServiceFunctionInformation::Type::Dtc:
|
|
vlCustomDtcFunctions += QVariant::fromValue(customFunctionWrapper);
|
|
break;
|
|
case CustomServiceFunctionInformation::Type::DbNotify:
|
|
|
|
WARNING_LOG(m_logger) << "Internal error - Trying to handle DbNotify in addCustomFunctions(): "
|
|
<< csfi.methodName;
|
|
delete customFunctionWrapper;
|
|
break;
|
|
}
|
|
DEBUG_LOG(m_logger) << "Added custom db function " << csfi.methodName;
|
|
}
|
|
m_ctx->insert(QStringLiteral("custom_dtc_procs"), vlCustomDtcFunctions);
|
|
m_ctx->insert(QStringLiteral("custom_db_procs"), vlCustomDbFunctions);
|
|
}
|
|
|
|
void GeneratorGrantleeBase::exportUsedServices(const XmlReader* reader)
|
|
{
|
|
IdlServicesWrapper* idlServicesWrapper(new IdlServicesWrapper(QString(), this));
|
|
const QMap<QString, bool> usedServices = reader->usedServices();
|
|
for (auto it = usedServices.begin(); it != usedServices.end(); ++it)
|
|
{
|
|
|
|
if (!it.value())
|
|
continue;
|
|
const QString& svc = it.key();
|
|
const QString fullPath = reader->idlFileForService(svc);
|
|
const int idx = fullPath.lastIndexOf(QLatin1Char('.'));
|
|
if (idx < 0)
|
|
{
|
|
ERROR_LOG(m_logger) << "Could not parse file path: " << fullPath;
|
|
continue;
|
|
}
|
|
const QString idlFile = fullPath.left(idx);
|
|
if (idlFile.isEmpty())
|
|
{
|
|
WARNING_LOG(m_logger) << "Could not find idl file for service " << svc;
|
|
continue;
|
|
}
|
|
idlServicesWrapper->addService(svc, idlFile);
|
|
DEBUG_LOG(m_logger) << "Added service " << svc;
|
|
}
|
|
m_ctx->insert(QStringLiteral("ext_services"), idlServicesWrapper);
|
|
}
|