mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-25 03:12:53 +00:00
220 lines
6.2 KiB
C++
220 lines
6.2 KiB
C++
![]() |
/*
|
||
|
* KDevelop C++ Language Support
|
||
|
*
|
||
|
* Copyright 2008 Hamish Rodda <rodda@kde.org>
|
||
|
* Copyright 2012 Miha Čančula <miha@noughmad.eu>
|
||
|
*
|
||
|
* This program 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 program 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 General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public
|
||
|
* License along with this program; if not, write to the
|
||
|
* Free Software Foundation, Inc.,
|
||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
*/
|
||
|
|
||
|
#include "cppclasshelper.h"
|
||
|
#include <codecompletion/missingincludeitem.h>
|
||
|
#include <language/duchain/declaration.h>
|
||
|
#include <language/codegen/documentchangeset.h>
|
||
|
#include <language/codegen/codedescription.h>
|
||
|
|
||
|
#include <KTemporaryFile>
|
||
|
|
||
|
using namespace KDevelop;
|
||
|
|
||
|
CppClassHelper::CppClassHelper()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
CppClassHelper::~CppClassHelper()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
TemplateClassGenerator* CppClassHelper::createGenerator(const KUrl& baseUrl)
|
||
|
{
|
||
|
return new CppTemplateNewClass(baseUrl);
|
||
|
}
|
||
|
|
||
|
QList<DeclarationPointer> CppClassHelper::defaultMethods(const QString& name) const
|
||
|
{
|
||
|
KTemporaryFile file;
|
||
|
file.setSuffix( ".cpp" );
|
||
|
file.setAutoRemove(false);
|
||
|
file.open();
|
||
|
QTextStream stream(&file);
|
||
|
stream << "class " << name << " {\n"
|
||
|
<< " public:\n"
|
||
|
// default ctor
|
||
|
<< " " << name << "();\n"
|
||
|
// copy ctor
|
||
|
<< " " << name << "(const " << name << "& other);\n"
|
||
|
// default dtor
|
||
|
<< " ~" << name << "();\n"
|
||
|
// assignment operator
|
||
|
<< " " << name << "& operator=(const " << name << "& other);\n"
|
||
|
// equality operator
|
||
|
<< " bool operator==(const " << name << "& other) const;\n"
|
||
|
<< "};\n";
|
||
|
file.close();
|
||
|
ReferencedTopDUContext context(DUChain::self()->waitForUpdate( IndexedString(file.fileName()),
|
||
|
TopDUContext::AllDeclarationsAndContexts ));
|
||
|
DUChainReadLocker lock;
|
||
|
|
||
|
QList<DeclarationPointer> methods;
|
||
|
|
||
|
if (context && context->childContexts().size() == 1) {
|
||
|
foreach (Declaration* declaration, context->childContexts().first()->localDeclarations())
|
||
|
{
|
||
|
methods << DeclarationPointer(declaration);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
file.remove();
|
||
|
return methods;
|
||
|
}
|
||
|
|
||
|
CppTemplateNewClass::CppTemplateNewClass(const KUrl& url)
|
||
|
: TemplateClassGenerator(url)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
CppTemplateNewClass::~CppTemplateNewClass()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
QVariantHash CppTemplateNewClass::extraVariables()
|
||
|
{
|
||
|
QVariantHash variables;
|
||
|
|
||
|
QMap<QString, VariableDescriptionList> variableDescriptions;
|
||
|
|
||
|
QMap<QString, FunctionDescriptionList> functionDescriptions;
|
||
|
QMap<QString, FunctionDescriptionList> slotDescriptions;
|
||
|
FunctionDescriptionList signalDescriptions;
|
||
|
|
||
|
foreach (const FunctionDescription& function, description().methods)
|
||
|
{
|
||
|
QString access = function.access;
|
||
|
if (access.isEmpty())
|
||
|
{
|
||
|
access = "public";
|
||
|
}
|
||
|
if (function.isSignal)
|
||
|
{
|
||
|
signalDescriptions << function;
|
||
|
}
|
||
|
else if (function.isSlot)
|
||
|
{
|
||
|
slotDescriptions[access] << function;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
functionDescriptions[access] << function;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
foreach (const VariableDescription& variable, description().members)
|
||
|
{
|
||
|
QString access = variable.access;
|
||
|
if (access.isEmpty())
|
||
|
{
|
||
|
access = "public";
|
||
|
}
|
||
|
variableDescriptions[access] << variable;
|
||
|
}
|
||
|
|
||
|
QMap<QString, VariableDescriptionList>::const_iterator vit, vend;
|
||
|
vit = variableDescriptions.constBegin();
|
||
|
vend = variableDescriptions.constEnd();
|
||
|
for (; vit != vend; ++vit)
|
||
|
{
|
||
|
variables[vit.key() + "_members"] = CodeDescription::toVariantList(vit.value());
|
||
|
}
|
||
|
|
||
|
QMap<QString, FunctionDescriptionList>::const_iterator fit, fend;
|
||
|
fit = functionDescriptions.constBegin();
|
||
|
fend = functionDescriptions.constEnd();
|
||
|
for (; fit != fend; ++fit)
|
||
|
{
|
||
|
variables[fit.key() + "_functions"] = CodeDescription::toVariantList(fit.value());
|
||
|
}
|
||
|
|
||
|
fit = slotDescriptions.constBegin();
|
||
|
fend = slotDescriptions.constEnd();
|
||
|
for (; fit != fend; ++fit)
|
||
|
{
|
||
|
variables[fit.key() + "_slots"] = CodeDescription::toVariantList(fit.value());
|
||
|
}
|
||
|
|
||
|
variables["signals"] = CodeDescription::toVariantList(signalDescriptions);
|
||
|
variables["needs_qobject_macro"] = !slotDescriptions.isEmpty() || !signalDescriptions.isEmpty();
|
||
|
|
||
|
QStringList includedFiles;
|
||
|
DUChainReadLocker locker(DUChain::lock());
|
||
|
|
||
|
KUrl sourceUrl;
|
||
|
QHash<QString, KUrl> urls = fileUrls();
|
||
|
if (!urls.isEmpty())
|
||
|
{
|
||
|
sourceUrl = urls.constBegin().value();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// includeDirectiveFromUrl() expects a header URL
|
||
|
sourceUrl = baseUrl();
|
||
|
sourceUrl.addPath(name().toLower() + ".h");
|
||
|
}
|
||
|
|
||
|
foreach (const DeclarationPointer& base, directBaseClasses())
|
||
|
{
|
||
|
if (!base)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
kDebug() << "Looking for includes for class" << base->identifier().toString();
|
||
|
KSharedPtr<Cpp::MissingIncludeCompletionItem> item = Cpp::includeDirectiveFromUrl(sourceUrl, IndexedDeclaration(base.data()));
|
||
|
if(item)
|
||
|
{
|
||
|
kDebug() << "Found one in" << item->m_canonicalPath;
|
||
|
includedFiles << item->m_addedInclude;
|
||
|
}
|
||
|
}
|
||
|
variables["included_files"] = includedFiles;
|
||
|
|
||
|
return variables;
|
||
|
}
|
||
|
|
||
|
|
||
|
DocumentChangeSet CppTemplateNewClass::generate()
|
||
|
{
|
||
|
addVariables(extraVariables());
|
||
|
return TemplateClassGenerator::generate();
|
||
|
}
|
||
|
|
||
|
void CppTemplateNewClass::addBaseClass(const QString& base)
|
||
|
{
|
||
|
//strip access specifier
|
||
|
QStringList splitBase = base.split(' ', QString::SkipEmptyParts);
|
||
|
|
||
|
//if no access specifier is found use public by default
|
||
|
if(splitBase.size() == 1)
|
||
|
{
|
||
|
splitBase.prepend("public");
|
||
|
}
|
||
|
|
||
|
//Call base function with the access specifier
|
||
|
TemplateClassGenerator::addBaseClass(splitBase.join(" "));
|
||
|
}
|