mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-27 04:13:05 +00:00
339 lines
9.2 KiB
C++
339 lines
9.2 KiB
C++
![]() |
/* This file is part of KDevelop
|
||
|
Copyright 2012 Miha Čančula <miha@noughmad.eu>
|
||
|
|
||
|
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 "templateclassgenerator.h"
|
||
|
#include "archivetemplateloader.h"
|
||
|
|
||
|
#include "interfaces/icore.h"
|
||
|
#include <interfaces/iprojectcontroller.h>
|
||
|
#include <interfaces/iproject.h>
|
||
|
#include "language/codegen/documentchangeset.h"
|
||
|
#include "codedescription.h"
|
||
|
#include "templaterenderer.h"
|
||
|
#include "sourcefiletemplate.h"
|
||
|
#include "templateengine.h"
|
||
|
#include <duchain/duchainlock.h>
|
||
|
#include <duchain/persistentsymboltable.h>
|
||
|
#include <duchain/types/structuretype.h>
|
||
|
#include <project/interfaces/iprojectfilemanager.h>
|
||
|
#include <project/interfaces/ibuildsystemmanager.h>
|
||
|
#include <project/projectmodel.h>
|
||
|
|
||
|
#include <KComponentData>
|
||
|
#include <KStandardDirs>
|
||
|
|
||
|
#include <QFileInfo>
|
||
|
|
||
|
using namespace KDevelop;
|
||
|
|
||
|
/// @param base String such as 'public QObject' or 'QObject'
|
||
|
InheritanceDescription descriptionFromString(const QString& base)
|
||
|
{
|
||
|
QStringList splitBase = base.split(' ');
|
||
|
QString identifier = splitBase.takeLast();
|
||
|
QString inheritanceMode = splitBase.join(" ");
|
||
|
|
||
|
InheritanceDescription desc;
|
||
|
desc.baseType = identifier;
|
||
|
desc.inheritanceMode = inheritanceMode;
|
||
|
return desc;
|
||
|
}
|
||
|
|
||
|
class KDevelop::TemplateClassGeneratorPrivate
|
||
|
{
|
||
|
public:
|
||
|
SourceFileTemplate fileTemplate;
|
||
|
KUrl baseUrl;
|
||
|
TemplateRenderer renderer;
|
||
|
|
||
|
QString name;
|
||
|
QString identifier;
|
||
|
QStringList namespaces;
|
||
|
QString license;
|
||
|
|
||
|
QHash<QString, KUrl> fileUrls;
|
||
|
QHash<QString, SimpleCursor> filePositions;
|
||
|
ClassDescription description;
|
||
|
|
||
|
QList<DeclarationPointer> directBaseClasses;
|
||
|
QList<DeclarationPointer> allBaseClasses;
|
||
|
|
||
|
void fetchSuperClasses(const DeclarationPointer& declaration);
|
||
|
};
|
||
|
|
||
|
void TemplateClassGeneratorPrivate::fetchSuperClasses(const DeclarationPointer& declaration)
|
||
|
{
|
||
|
DUChainReadLocker lock;
|
||
|
|
||
|
//Prevent duplicity
|
||
|
if(allBaseClasses.contains(declaration))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
allBaseClasses << declaration;
|
||
|
|
||
|
DUContext* context = declaration->internalContext();
|
||
|
if (context) {
|
||
|
foreach (const DUContext::Import& import, context->importedParentContexts()) {
|
||
|
if (DUContext * parentContext = import.context(context->topContext())) {
|
||
|
if (parentContext->type() == DUContext::Class) {
|
||
|
fetchSuperClasses( DeclarationPointer(parentContext->owner()) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
TemplateClassGenerator::TemplateClassGenerator(const KUrl& baseUrl)
|
||
|
: d(new TemplateClassGeneratorPrivate)
|
||
|
{
|
||
|
d->baseUrl = baseUrl;
|
||
|
d->renderer.setEmptyLinesPolicy(TemplateRenderer::TrimEmptyLines);
|
||
|
}
|
||
|
|
||
|
TemplateClassGenerator::~TemplateClassGenerator()
|
||
|
{
|
||
|
delete d;
|
||
|
}
|
||
|
|
||
|
void TemplateClassGenerator::setTemplateDescription(const SourceFileTemplate& fileTemplate)
|
||
|
{
|
||
|
d->fileTemplate = fileTemplate;
|
||
|
Q_ASSERT(fileTemplate.isValid());
|
||
|
}
|
||
|
|
||
|
DocumentChangeSet TemplateClassGenerator::generate()
|
||
|
{
|
||
|
return d->renderer.renderFileTemplate(d->fileTemplate, d->baseUrl, fileUrls());
|
||
|
}
|
||
|
|
||
|
QHash<QString, QString> TemplateClassGenerator::fileLabels() const
|
||
|
{
|
||
|
Q_ASSERT(d->fileTemplate.isValid());
|
||
|
QHash<QString,QString> labels;
|
||
|
|
||
|
foreach (const SourceFileTemplate::OutputFile& outputFile, d->fileTemplate.outputFiles())
|
||
|
{
|
||
|
labels.insert(outputFile.identifier, outputFile.label);
|
||
|
}
|
||
|
|
||
|
return labels;
|
||
|
}
|
||
|
|
||
|
TemplateClassGenerator::UrlHash TemplateClassGenerator::fileUrls() const
|
||
|
{
|
||
|
if (d->fileUrls.isEmpty())
|
||
|
{
|
||
|
foreach (const SourceFileTemplate::OutputFile& outputFile, d->fileTemplate.outputFiles())
|
||
|
{
|
||
|
KUrl url(d->baseUrl);
|
||
|
QString outputName = d->renderer.render(outputFile.outputName, outputFile.identifier);
|
||
|
url.addPath(outputName);
|
||
|
d->fileUrls.insert(outputFile.identifier, url);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return d->fileUrls;
|
||
|
}
|
||
|
|
||
|
KUrl TemplateClassGenerator::baseUrl() const
|
||
|
{
|
||
|
return d->baseUrl;
|
||
|
}
|
||
|
|
||
|
KUrl TemplateClassGenerator::fileUrl(const QString& outputFile) const
|
||
|
{
|
||
|
return fileUrls().value(outputFile);
|
||
|
}
|
||
|
|
||
|
void TemplateClassGenerator::setFileUrl(const QString& outputFile, const KUrl& url)
|
||
|
{
|
||
|
d->fileUrls.insert(outputFile, url);
|
||
|
d->renderer.addVariable("output_file_" + outputFile.toLower(), KUrl::relativeUrl(d->baseUrl, url));
|
||
|
d->renderer.addVariable("output_file_" + outputFile.toLower() + "_absolute", url.toLocalFile());
|
||
|
}
|
||
|
|
||
|
SimpleCursor TemplateClassGenerator::filePosition(const QString& outputFile) const
|
||
|
{
|
||
|
return d->filePositions.value(outputFile);
|
||
|
}
|
||
|
|
||
|
void TemplateClassGenerator::setFilePosition(const QString& outputFile, const SimpleCursor& position)
|
||
|
{
|
||
|
d->filePositions.insert(outputFile, position);
|
||
|
}
|
||
|
|
||
|
void TemplateClassGenerator::addVariables(const QVariantHash& variables)
|
||
|
{
|
||
|
d->renderer.addVariables(variables);
|
||
|
}
|
||
|
|
||
|
QString TemplateClassGenerator::renderString(const QString& text) const
|
||
|
{
|
||
|
return d->renderer.render(text);
|
||
|
}
|
||
|
|
||
|
SourceFileTemplate TemplateClassGenerator::sourceFileTemplate() const
|
||
|
{
|
||
|
return d->fileTemplate;
|
||
|
}
|
||
|
|
||
|
TemplateRenderer* TemplateClassGenerator::renderer() const
|
||
|
{
|
||
|
return &(d->renderer);
|
||
|
}
|
||
|
|
||
|
|
||
|
QString TemplateClassGenerator::name() const
|
||
|
{
|
||
|
return d->name;
|
||
|
}
|
||
|
|
||
|
void TemplateClassGenerator::setName(const QString& newName)
|
||
|
{
|
||
|
d->name = newName;
|
||
|
d->renderer.addVariable("name", newName);
|
||
|
}
|
||
|
|
||
|
QString TemplateClassGenerator::identifier() const
|
||
|
{
|
||
|
return name();
|
||
|
}
|
||
|
|
||
|
void TemplateClassGenerator::setIdentifier(const QString& identifier)
|
||
|
{
|
||
|
d->renderer.addVariable("identifier", identifier);;
|
||
|
QStringList separators;
|
||
|
separators << "::" << "." << ":" << "\\" << "/";
|
||
|
QStringList ns;
|
||
|
foreach (const QString& separator, separators)
|
||
|
{
|
||
|
ns = identifier.split(separator);
|
||
|
if (ns.size() > 1)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
setName(ns.takeLast());
|
||
|
setNamespaces(ns);
|
||
|
}
|
||
|
|
||
|
QStringList TemplateClassGenerator::namespaces() const
|
||
|
{
|
||
|
return d->namespaces;
|
||
|
}
|
||
|
|
||
|
void TemplateClassGenerator::setNamespaces(const QStringList& namespaces) const
|
||
|
{
|
||
|
d->namespaces = namespaces;
|
||
|
d->renderer.addVariable("namespaces", namespaces);
|
||
|
}
|
||
|
|
||
|
|
||
|
/// Specify license for this class
|
||
|
void TemplateClassGenerator::setLicense(const QString& license)
|
||
|
{
|
||
|
kDebug() << "New Class: " << d->name << "Set license: " << d->license;
|
||
|
d->license = license;
|
||
|
d->renderer.addVariable("license", license);
|
||
|
}
|
||
|
|
||
|
/// Get the license specified for this classes
|
||
|
QString TemplateClassGenerator::license() const
|
||
|
{
|
||
|
return d->license;
|
||
|
}
|
||
|
|
||
|
void TemplateClassGenerator::setDescription(const ClassDescription& description)
|
||
|
{
|
||
|
d->description = description;
|
||
|
|
||
|
QVariantHash variables;
|
||
|
variables["description"] = QVariant::fromValue(description);
|
||
|
variables["members"] = CodeDescription::toVariantList(description.members);
|
||
|
variables["functions"] = CodeDescription::toVariantList(description.methods);
|
||
|
variables["base_classes"] = CodeDescription::toVariantList(description.baseClasses);
|
||
|
d->renderer.addVariables(variables);
|
||
|
}
|
||
|
|
||
|
ClassDescription TemplateClassGenerator::description() const
|
||
|
{
|
||
|
return d->description;
|
||
|
}
|
||
|
|
||
|
void TemplateClassGenerator::addBaseClass(const QString& base)
|
||
|
{
|
||
|
const InheritanceDescription desc = descriptionFromString(base);
|
||
|
|
||
|
ClassDescription cd = description();
|
||
|
cd.baseClasses << desc;
|
||
|
setDescription(cd);
|
||
|
|
||
|
DUChainReadLocker lock;
|
||
|
|
||
|
PersistentSymbolTable::Declarations decl = PersistentSymbolTable::self().getDeclarations(IndexedQualifiedIdentifier(QualifiedIdentifier(desc.baseType)));
|
||
|
|
||
|
//Search for all super classes
|
||
|
for(PersistentSymbolTable::Declarations::Iterator it = decl.iterator(); it; ++it)
|
||
|
{
|
||
|
DeclarationPointer declaration = DeclarationPointer(it->declaration());
|
||
|
if(declaration->isForwardDeclaration())
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Check if it's a class/struct/etc
|
||
|
if(declaration->type<StructureType>())
|
||
|
{
|
||
|
d->fetchSuperClasses(declaration);
|
||
|
d->directBaseClasses << declaration;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void TemplateClassGenerator::setBaseClasses(const QList<QString>& bases)
|
||
|
{
|
||
|
// clear
|
||
|
ClassDescription cd = description();
|
||
|
cd.baseClasses.clear();
|
||
|
setDescription(cd);
|
||
|
|
||
|
d->directBaseClasses.clear();
|
||
|
d->allBaseClasses.clear();
|
||
|
|
||
|
// add all bases
|
||
|
foreach (const QString& base, bases) {
|
||
|
addBaseClass(base);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
QList< DeclarationPointer > TemplateClassGenerator::directBaseClasses() const
|
||
|
{
|
||
|
return d->directBaseClasses;
|
||
|
}
|
||
|
|
||
|
QList< DeclarationPointer > TemplateClassGenerator::allBaseClasses() const
|
||
|
{
|
||
|
return d->allBaseClasses;
|
||
|
}
|
||
|
|