mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-25 11:22:55 +00:00
371 lines
18 KiB
C++
371 lines
18 KiB
C++
/* This file is part of KDevelop
|
|
Copyright 2007-2009 David Nolden <david.nolden.kdevelop@art-master.de>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License version 2 as published by the Free Software Foundation.
|
|
|
|
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.
|
|
*/
|
|
|
|
#ifndef TEMPLATEDECLARATION_H
|
|
#define TEMPLATEDECLARATION_H
|
|
|
|
#include <QMutex>
|
|
|
|
#include <language/duchain/forwarddeclaration.h>
|
|
#include <language/duchain/duchainbase.h>
|
|
#include <language/duchain/duchainpointer.h>
|
|
#include <language/duchain/ducontext.h>
|
|
#include "cppduchainexport.h"
|
|
#include <language/duchain/instantiationinformation.h>
|
|
|
|
using namespace KDevelop;
|
|
|
|
namespace KTextEditor {
|
|
class Range;
|
|
}
|
|
namespace KDevelop {
|
|
class DUContext;
|
|
class Declaration;
|
|
class DeclarationId;
|
|
class DelayedType;
|
|
class TopDUContext;
|
|
}
|
|
|
|
namespace Cpp {
|
|
using KDevelop::InstantiationInformation;
|
|
using KDevelop::IndexedInstantiationInformation;
|
|
template<class Base>
|
|
class CppDUContext;
|
|
|
|
struct KDEVCPPDUCHAIN_EXPORT TemplateDeclarationData {
|
|
TemplateDeclarationData() {
|
|
}
|
|
TemplateDeclarationData(const TemplateDeclarationData& rhs) : m_parameterContext(rhs.m_parameterContext) {
|
|
}
|
|
//The context in which the template-parameters are declared
|
|
KDevelop::IndexedDUContext m_parameterContext;
|
|
};
|
|
|
|
//Represents the template-part of a template-class'es or template-function's template-part
|
|
class KDEVCPPDUCHAIN_EXPORT TemplateDeclaration {
|
|
public:
|
|
typedef QHash<IndexedInstantiationInformation, TemplateDeclaration*> InstantiationsHash;
|
|
|
|
///Copy-constructor for cloning
|
|
TemplateDeclaration(const TemplateDeclaration& rhs);
|
|
TemplateDeclaration();
|
|
virtual ~TemplateDeclaration();
|
|
|
|
void setTemplateParameterContext(KDevelop::DUContext* context);
|
|
KDevelop::DUContext* templateParameterContext() const;
|
|
|
|
TemplateDeclaration* instantiatedFrom() const;
|
|
|
|
///Marks this template-declaration as a instantiation of the given one. This also means that this declaration will be deleted when the here given is deleted.
|
|
///from can also be zero, then the declaration will just be marked as a specialization(instantiatedWith is set)
|
|
void setInstantiatedFrom(TemplateDeclaration* from, const InstantiationInformation& instantiatedWith);
|
|
|
|
/**
|
|
* Either finds the existing instance instantiated with the given template-arguments, or creates a new one.
|
|
* The template-arguments must chained up with the template-arguments of the parent, if the parent is a template class.
|
|
* @param source the top-context from which ones perspective the instantiation should happen. If @p topContext is zero, only existing specializations are returned
|
|
* @param forceLocal if this is true, it is this exact declaration that is instantiated. Else, this declaration is instantiated again.
|
|
* */
|
|
KDevelop::Declaration* instantiate(const InstantiationInformation& templateArguments,
|
|
const KDevelop::TopDUContext* source, bool forceLocal = false );
|
|
|
|
///Returns true if this class is a direct instantiation of the given class. Not if it is an instantiation of a specialization of the given class.
|
|
bool isInstantiatedFrom(const TemplateDeclaration* other) const;
|
|
|
|
void setSpecializedFrom(TemplateDeclaration* other);
|
|
|
|
IndexedInstantiationInformation instantiatedWith() const;
|
|
|
|
///Marks that a declaration is currently instantiated with the given instantiation-information.
|
|
///A zero instantiation is inserted into the cache to make sure that we don't instantiate the same declaration again in the meantime.
|
|
void reserveInstantiation(const IndexedInstantiationInformation& info);
|
|
|
|
///An instantiation is an additional temporary version of this declaration that was created given some template-parameters.
|
|
///Opposed to that a specialization is a real declaration that was created by the user, that specializes this declaration.
|
|
///Returns all current instantiations of this declaration
|
|
///@warning Some instantiations may have the value zero when an instantiation is currently happening.
|
|
InstantiationsHash instantiations() const;
|
|
|
|
IndexedInstantiationInformation specialization() const;
|
|
|
|
DeclarationId id(bool forceDirect) const;
|
|
|
|
Declaration* specialize(const IndexedInstantiationInformation& specialization,
|
|
const TopDUContext* topContext, int upDistance);
|
|
|
|
//Duchain must be write-locked
|
|
void deleteAllInstantiations();
|
|
|
|
///Returns the template-context that belongs to this template declaration, or zero
|
|
DUContext* templateContext(const TopDUContext* source) const;
|
|
|
|
///@return The declaration this one was explicitly specialized from.
|
|
///Zero, or a non-specialized (thus also non-instantiated) template-class, which this was explicitly specialized from.
|
|
virtual IndexedDeclaration specializedFrom() = 0;
|
|
virtual const IndexedDeclaration* specializations() const = 0;
|
|
virtual uint specializationsSize() const = 0;
|
|
|
|
///These are internal, do not use them. They have to be public so they are visible from SpecialTemplateDeclaration.
|
|
virtual void setSpecializedFromInternal(const IndexedDeclaration& decl) = 0;
|
|
virtual void addSpecializationInternal(const IndexedDeclaration& decl) = 0;
|
|
virtual void removeSpecializationInternal(const IndexedDeclaration& decl) = 0;
|
|
|
|
virtual void setSpecializedWith(const IndexedInstantiationInformation& info) = 0;
|
|
virtual IndexedInstantiationInformation specializedWith() const = 0;
|
|
|
|
protected:
|
|
//If the given info matches a specialization, returns the instantiated specialization
|
|
TemplateDeclaration *instantiateSpecialization(const InstantiationInformation& info, const TopDUContext *source);
|
|
//Matches the given instantiation-information to this declaration's specialization information and returns a score
|
|
uint matchInstantiation(IndexedInstantiationInformation indexedInfo, const TopDUContext* topCtxt,
|
|
InstantiationInformation& instantiateWith, bool& instantiationRequired) const;
|
|
|
|
virtual TemplateDeclarationData* dynamicTemplateData() = 0;
|
|
virtual const TemplateDeclarationData* templateData() const = 0;
|
|
|
|
TemplateDeclaration* m_instantiatedFrom;
|
|
|
|
IndexedInstantiationInformation m_instantiatedWith;
|
|
|
|
static QMutex instantiationsMutex;
|
|
///Every access to m_instantiations must be serialized through instantiationsMutex!
|
|
typedef QHash<IndexedInstantiationInformation, IndexedInstantiationInformation> DefaultParameterInstantiationHash;
|
|
DefaultParameterInstantiationHash m_defaultParameterInstantiations;
|
|
InstantiationsHash m_instantiations; ///Every declaration nested within a template declaration knows all its instantiations.
|
|
// recursion counter
|
|
int m_instantiationDepth;
|
|
};
|
|
|
|
|
|
KDEVCPPDUCHAIN_EXPORT DECLARE_LIST_MEMBER_HASH(SpecialTemplateDeclarationData, m_specializations, IndexedDeclaration)
|
|
|
|
template<class Base>
|
|
class SpecialTemplateDeclarationData : public Base, public TemplateDeclarationData
|
|
{
|
|
public:
|
|
SpecialTemplateDeclarationData() {
|
|
initializeAppendedLists();
|
|
}
|
|
|
|
~SpecialTemplateDeclarationData() {
|
|
freeAppendedLists();
|
|
}
|
|
|
|
SpecialTemplateDeclarationData(const SpecialTemplateDeclarationData& rhs) : Base(rhs), TemplateDeclarationData(rhs) {
|
|
initializeAppendedLists();
|
|
copyListsFrom(rhs);
|
|
m_specializedFrom = rhs.m_specializedFrom;
|
|
m_specializedWith = rhs.m_specializedWith;
|
|
}
|
|
|
|
uint classSize() const {
|
|
return Base::classSize();
|
|
}
|
|
|
|
IndexedDeclaration m_specializedFrom;
|
|
IndexedInstantiationInformation m_specializedWith;
|
|
|
|
START_APPENDED_LISTS_BASE(SpecialTemplateDeclarationData, Base);
|
|
APPENDED_LIST_FIRST(SpecialTemplateDeclarationData, IndexedDeclaration, m_specializations);
|
|
END_APPENDED_LISTS(SpecialTemplateDeclarationData, m_specializations);
|
|
|
|
//Just for visibility
|
|
static bool appendedListDynamicDefault() {
|
|
return Base::appendedListDynamicDefault();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Use this to merge any type of declaration with a TemplateDeclaration.
|
|
* This allows wrapping template-declaration's over any kind of declaration, without changing the basic structure of types.
|
|
* Necessary because we have at least 3 different declaration-classes that are not derived from each other, and that can
|
|
* be TemplateDeclarations.
|
|
*/
|
|
template<class BaseDeclaration>
|
|
class KDEVCPPDUCHAIN_EXPORT SpecialTemplateDeclaration : public BaseDeclaration, public TemplateDeclaration {
|
|
public:
|
|
template<class Data>
|
|
SpecialTemplateDeclaration(Data& data) : BaseDeclaration(data) {
|
|
}
|
|
|
|
typedef SpecialTemplateDeclarationData<typename BaseDeclaration::Data> Data;
|
|
|
|
///Copy-constructor for cloning
|
|
SpecialTemplateDeclaration(const SpecialTemplateDeclaration<BaseDeclaration>& rhs) : BaseDeclaration(*new SpecialTemplateDeclarationData<typename BaseDeclaration::Data>(*rhs.d_func())), TemplateDeclaration(rhs) {
|
|
DUChainBaseData* data = static_cast<DUChainBase*>(this)->d_func_dynamic();
|
|
data->setClassId(this);
|
|
//To keep link-consistency these specialization links are cleared in copies/instantiations
|
|
static_cast<Data*>(data)->m_specializedFrom = IndexedDeclaration();
|
|
static_cast<Data*>(data)->m_specializationsList().clear();
|
|
}
|
|
///Arguments are passed to the base
|
|
SpecialTemplateDeclaration( const KDevelop::RangeInRevision& range, KDevelop::DUContext* context ) : BaseDeclaration(*new SpecialTemplateDeclarationData<typename BaseDeclaration::Data>()) {
|
|
static_cast<DUChainBase*>(this)->d_func_dynamic()->setClassId(this);
|
|
|
|
this->setRange(range);
|
|
|
|
if(context)
|
|
this->setContext(context);
|
|
}
|
|
|
|
~SpecialTemplateDeclaration() {
|
|
TopDUContext* top = this->topContext();
|
|
Q_ASSERT(top);
|
|
|
|
//This actually belongs into ~TemplateDeclaration, but we do it here because here we do not need to go through virtual
|
|
//functions or dynamic casts, because those are not guaranteed to work from within destructors.
|
|
if(!top->deleting() || !top->isOnDisk()) {
|
|
///When the declaration is being deleted, disconnect the links on both sides
|
|
Declaration* specializedFromDeclaration = static_cast<const Data*>(this->DUChainBase::d_func())->m_specializedFrom.data();
|
|
if(TemplateDeclaration* specializedFromTemplate = dynamic_cast<TemplateDeclaration*>(specializedFromDeclaration))
|
|
specializedFromTemplate->removeSpecializationInternal(IndexedDeclaration(this));
|
|
|
|
FOREACH_FUNCTION(IndexedDeclaration decl, static_cast<const Data*>(this->DUChainBase::d_func())->m_specializations) {
|
|
TemplateDeclaration* tDecl = dynamic_cast<TemplateDeclaration*>(decl.data());
|
|
if(tDecl)
|
|
tDecl->setSpecializedFrom(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual IndexedDeclaration specializedFrom() {
|
|
return static_cast<const Data*>(this->DUChainBase::d_func())->m_specializedFrom;
|
|
}
|
|
virtual const IndexedDeclaration* specializations() const {
|
|
return static_cast<const Data*>(this->DUChainBase::d_func())->m_specializations();
|
|
}
|
|
virtual uint specializationsSize() const {
|
|
return static_cast<const Data*>(this->DUChainBase::d_func())->m_specializationsSize();
|
|
}
|
|
virtual IndexedInstantiationInformation specializedWith() const {
|
|
return static_cast<const Data*>(this->DUChainBase::d_func())->m_specializedWith;
|
|
}
|
|
virtual bool inDUChain() const {
|
|
return instantiatedFrom() || BaseDeclaration::inDUChain();
|
|
}
|
|
|
|
virtual uint additionalIdentity() const {
|
|
return BaseDeclaration::additionalIdentity() + 101;
|
|
}
|
|
virtual Declaration* specialize(const IndexedInstantiationInformation& specialization,
|
|
const TopDUContext* topContext, int upDistance) {
|
|
return TemplateDeclaration::specialize(specialization, topContext, upDistance);
|
|
}
|
|
|
|
virtual IndexedInstantiationInformation specialization() const {
|
|
return TemplateDeclaration::specialization();
|
|
}
|
|
|
|
virtual DeclarationId id(bool forceDirect) const {
|
|
return TemplateDeclaration::id(forceDirect);
|
|
}
|
|
|
|
//Is specialized for ForwardDeclaration in templatedeclaration.cpp to actively instantiate template forward declarations
|
|
virtual Declaration* resolve(const TopDUContext* /*topContext*/) const {
|
|
Q_ASSERT(0);
|
|
return 0;
|
|
}
|
|
|
|
enum {
|
|
Identity = BaseDeclaration::Identity + 50
|
|
};
|
|
|
|
private:
|
|
virtual void setSpecializedFromInternal(const IndexedDeclaration& decl) {
|
|
static_cast<Data*>(this->DUChainBase::d_func_dynamic())->m_specializedFrom = decl;
|
|
}
|
|
virtual void addSpecializationInternal(const IndexedDeclaration& decl) {
|
|
static_cast<Data*>(this->DUChainBase::d_func_dynamic())->m_specializationsList().append(decl);
|
|
}
|
|
virtual void removeSpecializationInternal(const IndexedDeclaration& decl) {
|
|
bool result = static_cast<Data*>(this->DUChainBase::d_func_dynamic())->m_specializationsList().removeOne(decl);
|
|
Q_ASSERT(result);
|
|
Q_UNUSED(result);
|
|
}
|
|
virtual void setSpecializedWith(const IndexedInstantiationInformation& info) {
|
|
static_cast<Data*>(this->DUChainBase::d_func_dynamic())->m_specializedWith = info;
|
|
}
|
|
|
|
virtual TemplateDeclarationData* dynamicTemplateData() {
|
|
return d_func_dynamic();
|
|
}
|
|
|
|
virtual const TemplateDeclarationData* templateData() const {
|
|
return d_func();
|
|
}
|
|
|
|
virtual void activateSpecialization()
|
|
{
|
|
BaseDeclaration::activateSpecialization();
|
|
|
|
if(specialization().index()) {
|
|
//Also register parents
|
|
DUContext* context = this->context();
|
|
if(context->owner() && context->owner()->specialization().index()) {
|
|
context->owner()->activateSpecialization(); //will also add to the background-parser
|
|
}else{
|
|
// context->topContext()->setHasUses(false); //Force re-building of the uses
|
|
// ICore::self()->languageController()->backgroundParser()->addDocument( KUrl(this->url().str()) );
|
|
}
|
|
}
|
|
}
|
|
|
|
inline SpecialTemplateDeclarationData<typename BaseDeclaration::Data>* d_func_dynamic() { this->makeDynamic(); return reinterpret_cast<SpecialTemplateDeclarationData<typename BaseDeclaration::Data>*>(this->d_ptr); }
|
|
inline const SpecialTemplateDeclarationData<typename BaseDeclaration::Data>* d_func() const { return reinterpret_cast<const SpecialTemplateDeclarationData<typename BaseDeclaration::Data>*>(this->d_ptr); }
|
|
virtual KDevelop::Declaration* clonePrivate() const {
|
|
return new SpecialTemplateDeclaration(*this);
|
|
}
|
|
};
|
|
|
|
bool KDEVCPPDUCHAIN_EXPORT isTemplateDeclaration(const KDevelop::Declaration*);
|
|
|
|
/**
|
|
* If this is used to instantiate a declaration, it should be called BEFORE the Declaration's types DelayedType's are resolved,
|
|
* because those are needed to resolve missing base-classes.
|
|
*
|
|
* The given context should be one that, on some level, imports a template-parameter-declaration context.
|
|
* The given declaration will be registered anonymously, the same for the created contexts.
|
|
* @param parentContext he parent-context everything should be created in(instantiatedDeclaration will be moved into that context anonymously)
|
|
* @param inclusionTrace a trace as used in findDeclarationsInternal(..)
|
|
* @param context A du-context that will be copied and used as internal context for declaration. If this is zero, no context will be copied.
|
|
* @param templateArguments The template-arguments that will be used to instantiate the input-context. If this is empty, the intersting context will be only copied without specialization. If it contains exactly one argument, and that argument is invalid, the context is instantiated without arguments(default-arguments are used). Default-arguments will be used if needed.
|
|
* @param instantiatedDeclaration The copied declaration this should belong to. If this is set, the created context will be made the given declaration's internal-context, and its parent-context will be set to the given context's parent-context. Also delayed types in the declaration will be resolved(The declaration will be changed)
|
|
* @param instantiatedFrom The declaration instantiatedDeclaration should be/is instantiated from. This is needed to eventually change the declaration of in IdentifiedType. The instantiation has to be reserved before calling instantiateDeclarationAndContext!
|
|
* @param doNotRegister If this is true, the context will not be registered anywhere, and can be deleted at will.
|
|
*
|
|
* The DU-Context must be read-locked but not write-locked when this is called.
|
|
* */
|
|
KDEVCPPDUCHAIN_EXPORT CppDUContext<KDevelop::DUContext>* instantiateDeclarationAndContext( KDevelop::DUContext* parentContext, const KDevelop::TopDUContext* source, KDevelop::DUContext* context, const InstantiationInformation& templateArguments, KDevelop::Declaration* instantiatedDeclaration, KDevelop::Declaration* instantiatedFrom, bool doNotRegister = false );
|
|
|
|
/**
|
|
* Returns whether any count of reference/pointer-types are followed by a delayed type
|
|
* */
|
|
KDEVCPPDUCHAIN_EXPORT TypePtr<DelayedType> containsDelayedType(AbstractType::Ptr type);
|
|
|
|
/**
|
|
* Eventually creates a copy of the given type, where all DelayedTypes that can be resolved in the given context are resolved.
|
|
* */
|
|
KDEVCPPDUCHAIN_EXPORT AbstractType::Ptr resolveDelayedTypes( AbstractType::Ptr type, const KDevelop::DUContext* context, const KDevelop::TopDUContext* source, KDevelop::DUContext::SearchFlags searchFlags = KDevelop::DUContext::NoUndefinedTemplateParams );
|
|
|
|
template<>
|
|
Declaration* SpecialTemplateDeclaration<ForwardDeclaration>::resolve(const TopDUContext* topContext) const;
|
|
|
|
}
|
|
|
|
#endif
|
|
|