ClassView: Use only const pointers to ParserTreeItems

There is no need to use non-const pointers anymore. This also
ensures, that after generating the tree data in the non-gui
thread no-one modifies already created items.

Task-number: QTCREATORBUG-25317
Change-Id: I91f63da8f57ae9798587265adc029ebd0c68504e
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
Jarek Kobus
2021-02-16 16:04:50 +01:00
parent d4fe3fdb15
commit 8c5dc305ae
4 changed files with 35 additions and 36 deletions

View File

@@ -92,12 +92,12 @@ public:
struct DocumentCache { struct DocumentCache {
unsigned treeRevision = 0; unsigned treeRevision = 0;
ParserTreeItem::Ptr tree; ParserTreeItem::ConstPtr tree;
CPlusPlus::Document::Ptr document; CPlusPlus::Document::Ptr document;
}; };
struct ProjectCache { struct ProjectCache {
unsigned treeRevision = 0; unsigned treeRevision = 0;
ParserTreeItem::Ptr tree; ParserTreeItem::ConstPtr tree;
QStringList fileList; QStringList fileList;
}; };
@@ -180,7 +180,7 @@ ParserTreeItem::ConstPtr Parser::parse()
timer->start(); timer->start();
} }
QHash<SymbolInformation, ParserTreeItem::Ptr> projectTrees; QHash<SymbolInformation, ParserTreeItem::ConstPtr> projectTrees;
// TODO: move a call to SessionManager::projects() out of this thread // TODO: move a call to SessionManager::projects() out of this thread
for (const Project *prj : SessionManager::projects()) { for (const Project *prj : SessionManager::projects()) {
@@ -188,13 +188,13 @@ ParserTreeItem::ConstPtr Parser::parse()
const QString prjType = prj->projectFilePath().toString(); const QString prjType = prj->projectFilePath().toString();
const SymbolInformation inf(prjName, prjType); const SymbolInformation inf(prjName, prjType);
ParserTreeItem::Ptr item = addFlatTree(prj); ParserTreeItem::ConstPtr item = addFlatTree(prj);
if (item.isNull()) if (item.isNull())
continue; continue;
projectTrees.insert(inf, item); projectTrees.insert(inf, item);
} }
ParserTreeItem::Ptr rootItem(new ParserTreeItem(projectTrees)); ParserTreeItem::ConstPtr rootItem(new ParserTreeItem(projectTrees));
if (debug) { if (debug) {
qDebug() << "Class View:" << QDateTime::currentDateTime().toString() qDebug() << "Class View:" << QDateTime::currentDateTime().toString()
@@ -210,7 +210,7 @@ ParserTreeItem::ConstPtr Parser::parse()
project. project.
*/ */
ParserTreeItem::Ptr Parser::getParseProjectTree(const QStringList &fileList, ParserTreeItem::ConstPtr Parser::getParseProjectTree(const QStringList &fileList,
const QString &projectId) const QString &projectId)
{ {
//! \todo Way to optimize - for documentUpdate - use old cached project and subtract //! \todo Way to optimize - for documentUpdate - use old cached project and subtract
@@ -231,7 +231,7 @@ ParserTreeItem::Ptr Parser::getParseProjectTree(const QStringList &fileList,
docTrees.append(docTree); docTrees.append(docTree);
} }
ParserTreeItem::Ptr item = ParserTreeItem::mergeTrees(Utils::FilePath::fromString(projectId), docTrees); ParserTreeItem::ConstPtr item = ParserTreeItem::mergeTrees(Utils::FilePath::fromString(projectId), docTrees);
// update the cache // update the cache
if (!projectId.isEmpty()) { if (!projectId.isEmpty()) {
@@ -248,7 +248,7 @@ ParserTreeItem::Ptr Parser::getParseProjectTree(const QStringList &fileList,
Updates the internal cached tree for this project. Updates the internal cached tree for this project.
*/ */
ParserTreeItem::Ptr Parser::getCachedOrParseProjectTree(const QStringList &fileList, ParserTreeItem::ConstPtr Parser::getCachedOrParseProjectTree(const QStringList &fileList,
const QString &projectId) const QString &projectId)
{ {
const auto it = d->m_projectCache.constFind(projectId); const auto it = d->m_projectCache.constFind(projectId);
@@ -286,7 +286,7 @@ ParserTreeItem::ConstPtr Parser::getParseDocumentTree(const CPlusPlus::Document:
if (!d->fileList.contains(fileName)) if (!d->fileList.contains(fileName))
return ParserTreeItem::ConstPtr(); return ParserTreeItem::ConstPtr();
ParserTreeItem::Ptr itemPtr = ParserTreeItem::parseDocument(doc); ParserTreeItem::ConstPtr itemPtr = ParserTreeItem::parseDocument(doc);
d->m_documentCache.insert(fileName, { doc->revision(), itemPtr, doc } ); d->m_documentCache.insert(fileName, { doc->revision(), itemPtr, doc } );
return itemPtr; return itemPtr;
@@ -426,7 +426,7 @@ QStringList Parser::getAllFiles(const Project *project)
} }
// TODO: don't use Project class in this thread // TODO: don't use Project class in this thread
ParserTreeItem::Ptr Parser::addFlatTree(const Project *project) ParserTreeItem::ConstPtr Parser::addFlatTree(const Project *project)
{ {
if (!project) if (!project)
return {}; return {};

View File

@@ -68,13 +68,13 @@ private:
ParserTreeItem::ConstPtr getParseDocumentTree(const CPlusPlus::Document::Ptr &doc); ParserTreeItem::ConstPtr getParseDocumentTree(const CPlusPlus::Document::Ptr &doc);
ParserTreeItem::ConstPtr getCachedOrParseDocumentTree(const CPlusPlus::Document::Ptr &doc); ParserTreeItem::ConstPtr getCachedOrParseDocumentTree(const CPlusPlus::Document::Ptr &doc);
ParserTreeItem::Ptr getParseProjectTree(const QStringList &fileList, const QString &projectId); ParserTreeItem::ConstPtr getParseProjectTree(const QStringList &fileList, const QString &projectId);
ParserTreeItem::Ptr getCachedOrParseProjectTree(const QStringList &fileList, ParserTreeItem::ConstPtr getCachedOrParseProjectTree(const QStringList &fileList,
const QString &projectId); const QString &projectId);
ParserTreeItem::ConstPtr parse(); ParserTreeItem::ConstPtr parse();
QStringList getAllFiles(const ProjectExplorer::Project *project); QStringList getAllFiles(const ProjectExplorer::Project *project);
ParserTreeItem::Ptr addFlatTree(const ProjectExplorer::Project *project); ParserTreeItem::ConstPtr addFlatTree(const ProjectExplorer::Project *project);
//! Private class data pointer //! Private class data pointer
ParserPrivate *d; ParserPrivate *d;

View File

@@ -66,9 +66,9 @@ class ParserTreeItemPrivate
public: public:
void mergeWith(const ParserTreeItem::ConstPtr &target); void mergeWith(const ParserTreeItem::ConstPtr &target);
void mergeSymbol(const CPlusPlus::Symbol *symbol); void mergeSymbol(const CPlusPlus::Symbol *symbol);
ParserTreeItem::Ptr cloneTree() const; ParserTreeItem::ConstPtr cloneTree() const;
QHash<SymbolInformation, ParserTreeItem::Ptr> m_symbolInformations; QHash<SymbolInformation, ParserTreeItem::ConstPtr> m_symbolInformations;
QSet<SymbolLocation> m_symbolLocations; QSet<SymbolLocation> m_symbolLocations;
const Utils::FilePath m_projectFilePath; const Utils::FilePath m_projectFilePath;
}; };
@@ -84,13 +84,13 @@ void ParserTreeItemPrivate::mergeWith(const ParserTreeItem::ConstPtr &target)
for (auto it = target->d->m_symbolInformations.cbegin(); for (auto it = target->d->m_symbolInformations.cbegin();
it != target->d->m_symbolInformations.cend(); ++it) { it != target->d->m_symbolInformations.cend(); ++it) {
const SymbolInformation &inf = it.key(); const SymbolInformation &inf = it.key();
const ParserTreeItem::Ptr &targetChild = it.value(); const ParserTreeItem::ConstPtr &targetChild = it.value();
ParserTreeItem::Ptr child = m_symbolInformations.value(inf); ParserTreeItem::ConstPtr child = m_symbolInformations.value(inf);
if (!child.isNull()) { if (!child.isNull()) {
child->d->mergeWith(targetChild); child->d->mergeWith(targetChild);
} else { } else {
const ParserTreeItem::Ptr clone = targetChild.isNull() ? ParserTreeItem::Ptr() const ParserTreeItem::ConstPtr clone = targetChild.isNull() ? ParserTreeItem::ConstPtr()
: targetChild->d->cloneTree(); : targetChild->d->cloneTree();
m_symbolInformations.insert(inf, clone); m_symbolInformations.insert(inf, clone);
} }
@@ -128,10 +128,10 @@ void ParserTreeItemPrivate::mergeSymbol(const CPlusPlus::Symbol *symbol)
// If next line will be removed, 5% speed up for the initial parsing. // If next line will be removed, 5% speed up for the initial parsing.
// But there might be a problem for some files ??? // But there might be a problem for some files ???
// Better to improve qHash timing // Better to improve qHash timing
ParserTreeItem::Ptr childItem = m_symbolInformations.value(information); ParserTreeItem::ConstPtr childItem = m_symbolInformations.value(information);
if (childItem.isNull()) if (childItem.isNull())
childItem = ParserTreeItem::Ptr(new ParserTreeItem()); childItem = ParserTreeItem::ConstPtr(new ParserTreeItem());
// locations have 1-based column in Symbol, use the same here. // locations have 1-based column in Symbol, use the same here.
SymbolLocation location(QString::fromUtf8(symbol->fileName() , symbol->fileNameLength()), SymbolLocation location(QString::fromUtf8(symbol->fileName() , symbol->fileNameLength()),
@@ -163,9 +163,9 @@ void ParserTreeItemPrivate::mergeSymbol(const CPlusPlus::Symbol *symbol)
/*! /*!
Creates a deep clone of this tree. Creates a deep clone of this tree.
*/ */
ParserTreeItem::Ptr ParserTreeItemPrivate::cloneTree() const ParserTreeItem::ConstPtr ParserTreeItemPrivate::cloneTree() const
{ {
ParserTreeItem::Ptr newItem(new ParserTreeItem(m_projectFilePath)); ParserTreeItem::ConstPtr newItem(new ParserTreeItem(m_projectFilePath));
newItem->d->m_symbolLocations = m_symbolLocations; newItem->d->m_symbolLocations = m_symbolLocations;
for (auto it = m_symbolInformations.cbegin(); it != m_symbolInformations.cend(); ++it) { for (auto it = m_symbolInformations.cbegin(); it != m_symbolInformations.cend(); ++it) {
@@ -197,7 +197,7 @@ ParserTreeItem::ParserTreeItem(const Utils::FilePath &projectFilePath)
{ {
} }
ParserTreeItem::ParserTreeItem(const QHash<SymbolInformation, Ptr> &children) ParserTreeItem::ParserTreeItem(const QHash<SymbolInformation, ConstPtr> &children)
: d(new ParserTreeItemPrivate({children, {}, {}})) : d(new ParserTreeItemPrivate({children, {}, {}}))
{ {
} }
@@ -226,7 +226,7 @@ QSet<SymbolLocation> ParserTreeItem::symbolLocations() const
Returns the child item specified by \a inf symbol information. Returns the child item specified by \a inf symbol information.
*/ */
ParserTreeItem::Ptr ParserTreeItem::child(const SymbolInformation &inf) const ParserTreeItem::ConstPtr ParserTreeItem::child(const SymbolInformation &inf) const
{ {
return d->m_symbolInformations.value(inf); return d->m_symbolInformations.value(inf);
} }
@@ -240,9 +240,9 @@ int ParserTreeItem::childCount() const
return d->m_symbolInformations.count(); return d->m_symbolInformations.count();
} }
ParserTreeItem::Ptr ParserTreeItem::parseDocument(const CPlusPlus::Document::Ptr &doc) ParserTreeItem::ConstPtr ParserTreeItem::parseDocument(const CPlusPlus::Document::Ptr &doc)
{ {
Ptr item(new ParserTreeItem()); ConstPtr item(new ParserTreeItem());
const unsigned total = doc->globalSymbolCount(); const unsigned total = doc->globalSymbolCount();
for (unsigned i = 0; i < total; ++i) for (unsigned i = 0; i < total; ++i)
@@ -251,10 +251,10 @@ ParserTreeItem::Ptr ParserTreeItem::parseDocument(const CPlusPlus::Document::Ptr
return item; return item;
} }
ParserTreeItem::Ptr ParserTreeItem::mergeTrees(const Utils::FilePath &projectFilePath, ParserTreeItem::ConstPtr ParserTreeItem::mergeTrees(const Utils::FilePath &projectFilePath,
const QList<ConstPtr> &docTrees) const QList<ConstPtr> &docTrees)
{ {
Ptr item(new ParserTreeItem(projectFilePath)); ConstPtr item(new ParserTreeItem(projectFilePath));
for (const ConstPtr &docTree : docTrees) for (const ConstPtr &docTree : docTrees)
item->d->mergeWith(docTree); item->d->mergeWith(docTree);
@@ -299,13 +299,13 @@ void ParserTreeItem::fetchMore(QStandardItem *item) const
return; return;
// convert to map - to sort it // convert to map - to sort it
QMap<SymbolInformation, Ptr> map; QMap<SymbolInformation, ConstPtr> map;
for (auto it = d->m_symbolInformations.cbegin(); it != d->m_symbolInformations.cend(); ++it) for (auto it = d->m_symbolInformations.cbegin(); it != d->m_symbolInformations.cend(); ++it)
map.insert(it.key(), it.value()); map.insert(it.key(), it.value());
for (auto it = map.cbegin(); it != map.cend(); ++it) { for (auto it = map.cbegin(); it != map.cend(); ++it) {
const SymbolInformation &inf = it.key(); const SymbolInformation &inf = it.key();
Ptr ptr = it.value(); ConstPtr ptr = it.value();
auto add = new QStandardItem; auto add = new QStandardItem;
add->setData(inf.name(), Constants::SymbolNameRole); add->setData(inf.name(), Constants::SymbolNameRole);
@@ -340,7 +340,7 @@ void ParserTreeItem::debugDump(int indent) const
{ {
for (auto it = d->m_symbolInformations.cbegin(); it != d->m_symbolInformations.cend(); ++it) { for (auto it = d->m_symbolInformations.cbegin(); it != d->m_symbolInformations.cend(); ++it) {
const SymbolInformation &inf = it.key(); const SymbolInformation &inf = it.key();
const Ptr &child = it.value(); const ConstPtr &child = it.value();
qDebug() << QString(2 * indent, QLatin1Char(' ')) << inf.iconType() << inf.name() qDebug() << QString(2 * indent, QLatin1Char(' ')) << inf.iconType() << inf.name()
<< inf.type() << child.isNull(); << inf.type() << child.isNull();
if (!child.isNull()) if (!child.isNull())

View File

@@ -43,21 +43,20 @@ class ParserTreeItemPrivate;
class ParserTreeItem class ParserTreeItem
{ {
public: public:
using Ptr = QSharedPointer<ParserTreeItem>;
using ConstPtr = QSharedPointer<const ParserTreeItem>; using ConstPtr = QSharedPointer<const ParserTreeItem>;
public: public:
ParserTreeItem(); ParserTreeItem();
ParserTreeItem(const Utils::FilePath &projectFilePath); ParserTreeItem(const Utils::FilePath &projectFilePath);
ParserTreeItem(const QHash<SymbolInformation, Ptr> &children); ParserTreeItem(const QHash<SymbolInformation, ConstPtr> &children);
~ParserTreeItem(); ~ParserTreeItem();
static Ptr parseDocument(const CPlusPlus::Document::Ptr &doc); static ConstPtr parseDocument(const CPlusPlus::Document::Ptr &doc);
static Ptr mergeTrees(const Utils::FilePath &projectFilePath, const QList<ConstPtr> &docTrees); static ConstPtr mergeTrees(const Utils::FilePath &projectFilePath, const QList<ConstPtr> &docTrees);
Utils::FilePath projectFilePath() const; Utils::FilePath projectFilePath() const;
QSet<SymbolLocation> symbolLocations() const; QSet<SymbolLocation> symbolLocations() const;
Ptr child(const SymbolInformation &inf) const; ConstPtr child(const SymbolInformation &inf) const;
int childCount() const; int childCount() const;
// Make sure that below two methods are called only from the GUI thread // Make sure that below two methods are called only from the GUI thread