mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-26 11:52:54 +00:00
243 lines
7.5 KiB
C++
243 lines
7.5 KiB
C++
/* This is part of KDevelop
|
|
Copyright 2006 Hamish Rodda <rodda@kde.org>
|
|
Copyright 2007/2008 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.
|
|
*/
|
|
|
|
#include "duchainbase.h"
|
|
|
|
#include <QMutexLocker>
|
|
#include <QThreadStorage>
|
|
|
|
#include "duchainpointer.h"
|
|
#include "parsingenvironment.h"
|
|
#include "indexedstring.h"
|
|
#include "topducontext.h"
|
|
#include "duchainregister.h"
|
|
#include <editor/simplerange.h>
|
|
#include <interfaces/foregroundlock.h>
|
|
#include <interfaces/icore.h>
|
|
#include <interfaces/ilanguagecontroller.h>
|
|
#include <backgroundparser/backgroundparser.h>
|
|
#include <backgroundparser/documentchangetracker.h>
|
|
#include <ktexteditor/movinginterface.h>
|
|
#include <editor/persistentmovingrange.h>
|
|
|
|
namespace KDevelop
|
|
{
|
|
REGISTER_DUCHAIN_ITEM(DUChainBase);
|
|
|
|
uint DUChainBaseData::classSize() const {
|
|
return DUChainItemSystem::self().dataClassSize(*this);
|
|
}
|
|
|
|
DUChainBase::DUChainBase(const RangeInRevision& range)
|
|
: d_ptr(new DUChainBaseData), m_ptr( 0L )
|
|
{
|
|
d_func_dynamic()->m_range = range;
|
|
d_func_dynamic()->setClassId(this);
|
|
}
|
|
|
|
DUChainBase::DUChainBase( DUChainBaseData & dd, const RangeInRevision& range )
|
|
: d_ptr( &dd ), m_ptr( 0 )
|
|
{
|
|
d_func_dynamic()->m_range = range;
|
|
}
|
|
|
|
DUChainBase::DUChainBase( DUChainBaseData & dd )
|
|
: d_ptr( &dd ), m_ptr( 0 )
|
|
{
|
|
}
|
|
|
|
DUChainBase::DUChainBase( DUChainBase& rhs )
|
|
: d_ptr( new DUChainBaseData(*rhs.d_func()) ), m_ptr( 0 )
|
|
{
|
|
d_func_dynamic()->setClassId(this);
|
|
}
|
|
|
|
IndexedString DUChainBase::url() const
|
|
{
|
|
TopDUContext* top = topContext();
|
|
if(top)
|
|
return top->TopDUContext::url();
|
|
else
|
|
return IndexedString();
|
|
}
|
|
|
|
void DUChainBase::setData(DUChainBaseData* data, bool constructorCalled)
|
|
{
|
|
Q_ASSERT(data);
|
|
Q_ASSERT(d_ptr);
|
|
|
|
if(constructorCalled)
|
|
KDevelop::DUChainItemSystem::self().callDestructor(static_cast<DUChainBaseData*>(d_ptr));
|
|
|
|
if(d_ptr->m_dynamic) // If the data object isn't dynamic, then it is part of a central repository, and cannot be deleted here.
|
|
delete d_ptr;
|
|
|
|
d_ptr = data;
|
|
}
|
|
|
|
DUChainBase::~DUChainBase()
|
|
{
|
|
if (m_ptr)
|
|
m_ptr->m_base = 0;
|
|
|
|
if(d_ptr->m_dynamic)
|
|
{
|
|
KDevelop::DUChainItemSystem::self().callDestructor(d_ptr);
|
|
delete d_ptr;
|
|
d_ptr = 0;
|
|
}
|
|
}
|
|
|
|
TopDUContext* DUChainBase::topContext() const
|
|
{
|
|
///@todo Move the reference to the top-context right into this class, as it's common to all inheriters
|
|
return 0;
|
|
}
|
|
|
|
namespace {
|
|
QMutex weakPointerMutex;
|
|
};
|
|
|
|
const KSharedPtr<DUChainPointerData>& DUChainBase::weakPointer() const
|
|
{
|
|
if (!m_ptr) {
|
|
QMutexLocker lock(&weakPointerMutex); // The mutex is used to make sure we don't create m_ptr twice at the same time
|
|
m_ptr = new DUChainPointerData(const_cast<DUChainBase*>(this));
|
|
m_ptr->m_base = const_cast<DUChainBase*>(this);
|
|
}
|
|
|
|
return m_ptr;
|
|
}
|
|
|
|
void DUChainBase::rebuildDynamicData(DUContext* parent, uint ownIndex)
|
|
{
|
|
Q_UNUSED(parent)
|
|
Q_UNUSED(ownIndex)
|
|
}
|
|
|
|
void DUChainBase::makeDynamic() {
|
|
Q_ASSERT(d_ptr);
|
|
if(!d_func()->m_dynamic) {
|
|
Q_ASSERT(d_func()->classId);
|
|
DUChainBaseData* newData = DUChainItemSystem::self().cloneData(*d_func());
|
|
enableDUChainReferenceCounting(d_ptr, DUChainItemSystem::self().dynamicSize(*static_cast<DUChainBaseData*>(d_ptr)));
|
|
//We don't delete the previous data, because it's embedded in the top-context when it isn't dynamic.
|
|
//However we do call the destructor, to keep semantic stuff like reference-counting within the data class working correctly.
|
|
KDevelop::DUChainItemSystem::self().callDestructor(static_cast<DUChainBaseData*>(d_ptr));
|
|
disableDUChainReferenceCounting(d_ptr);
|
|
d_ptr = newData;
|
|
Q_ASSERT(d_ptr);
|
|
Q_ASSERT(d_func()->m_dynamic);
|
|
Q_ASSERT(d_func()->classId);
|
|
}
|
|
}
|
|
|
|
RangeInRevision DUChainBase::range() const
|
|
{
|
|
return d_func()->m_range;
|
|
}
|
|
|
|
SimpleRange DUChainBase::rangeInCurrentRevision() const
|
|
{
|
|
DocumentChangeTracker* tracker = ICore::self()->languageController()->backgroundParser()->trackerForUrl(url());
|
|
|
|
if(tracker && topContext() && topContext()->parsingEnvironmentFile())
|
|
{
|
|
qint64 revision = topContext()->parsingEnvironmentFile()->modificationRevision().revision;
|
|
return tracker->transformToCurrentRevision(d_func()->m_range, revision);
|
|
}
|
|
|
|
// If the document is not open, we can simply cast the range over, as no translation can be done
|
|
return d_func()->m_range.castToSimpleRange();
|
|
}
|
|
|
|
PersistentMovingRange::Ptr DUChainBase::createRangeMoving() const
|
|
{
|
|
VERIFY_FOREGROUND_LOCKED
|
|
return PersistentMovingRange::Ptr(new PersistentMovingRange(rangeInCurrentRevision(), url()));
|
|
}
|
|
|
|
CursorInRevision DUChainBase::transformToLocalRevision(const KDevelop::SimpleCursor& cursor) const
|
|
{
|
|
DocumentChangeTracker* tracker = ICore::self()->languageController()->backgroundParser()->trackerForUrl(url());
|
|
|
|
if(tracker && topContext() && topContext()->parsingEnvironmentFile())
|
|
{
|
|
qint64 revision = topContext()->parsingEnvironmentFile()->modificationRevision().revision;
|
|
return tracker->transformToRevision(cursor, revision);
|
|
}
|
|
|
|
return CursorInRevision::castFromSimpleCursor(cursor);
|
|
}
|
|
|
|
RangeInRevision DUChainBase::transformToLocalRevision(const KDevelop::SimpleRange& range) const
|
|
{
|
|
DocumentChangeTracker* tracker = ICore::self()->languageController()->backgroundParser()->trackerForUrl(url());
|
|
|
|
if(tracker && topContext() && topContext()->parsingEnvironmentFile())
|
|
{
|
|
qint64 revision = topContext()->parsingEnvironmentFile()->modificationRevision().revision;
|
|
return tracker->transformToRevision(range, revision);
|
|
}
|
|
|
|
return RangeInRevision::castFromSimpleRange(range);
|
|
}
|
|
|
|
SimpleRange DUChainBase::transformFromLocalRevision(const KDevelop::RangeInRevision& range) const
|
|
{
|
|
DocumentChangeTracker* tracker = ICore::self()->languageController()->backgroundParser()->trackerForUrl(url());
|
|
|
|
if(tracker && topContext() && topContext()->parsingEnvironmentFile())
|
|
{
|
|
qint64 revision = topContext()->parsingEnvironmentFile()->modificationRevision().revision;
|
|
return tracker->transformToCurrentRevision(range, revision);
|
|
}
|
|
|
|
return range.castToSimpleRange();
|
|
}
|
|
|
|
SimpleCursor DUChainBase::transformFromLocalRevision(const KDevelop::CursorInRevision& cursor) const
|
|
{
|
|
DocumentChangeTracker* tracker = ICore::self()->languageController()->backgroundParser()->trackerForUrl(url());
|
|
|
|
if(tracker && topContext() && topContext()->parsingEnvironmentFile())
|
|
{
|
|
qint64 revision = topContext()->parsingEnvironmentFile()->modificationRevision().revision;
|
|
return tracker->transformToCurrentRevision(cursor, revision);
|
|
}
|
|
|
|
return cursor.castToSimpleCursor();
|
|
}
|
|
|
|
void DUChainBase::setRange(const RangeInRevision& range)
|
|
{
|
|
d_func_dynamic()->m_range = range;
|
|
}
|
|
|
|
QThreadStorage<bool> shouldCreateConstantDataStorage;
|
|
|
|
bool& DUChainBaseData::shouldCreateConstantData()
|
|
{
|
|
return shouldCreateConstantDataStorage.localData();
|
|
}
|
|
|
|
}
|
|
|
|
// kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on
|
|
|