diff --git a/kdevplatform/language/backgroundparser/parsejob.cpp b/kdevplatform/language/backgroundparser/parsejob.cpp --- a/kdevplatform/language/backgroundparser/parsejob.cpp +++ b/kdevplatform/language/backgroundparser/parsejob.cpp @@ -27,41 +27,41 @@ #include #include -#include #include +#include #include #include "backgroundparser.h" -#include #include "duchain/topducontext.h" +#include -#include "duchain/duchainlock.h" #include "duchain/duchain.h" +#include "duchain/duchainlock.h" #include "duchain/parsingenvironment.h" #include "editor/documentrange.h" -#include -#include -#include -#include #include #include +#include #include #include -#include +#include +#include +#include +#include using namespace KTextEditor; static QMutex minimumFeaturesMutex; static QHash> staticMinimumFeatures; -namespace KDevelop { +namespace KDevelop +{ class ParseJobPrivate { public: - - ParseJobPrivate(const IndexedString& url_, ILanguageSupport* languageSupport_) : - url(url_) + ParseJobPrivate(const IndexedString& url_, ILanguageSupport* languageSupport_) + : url(url_) , languageSupport(languageSupport_) , abortRequested(0) , hasReadContents(false) @@ -73,9 +73,7 @@ { } - ~ParseJobPrivate() - { - } + ~ParseJobPrivate() {} ReferencedTopDUContext duContext; @@ -204,21 +202,21 @@ TopDUContext::Features ParseJob::staticMinimumFeatures(const IndexedString& url) { QMutexLocker lock(&minimumFeaturesMutex); - auto features = ( TopDUContext::Features )0; + auto features = (TopDUContext::Features)0; const auto featuresIt = ::staticMinimumFeatures.constFind(url); if (featuresIt != ::staticMinimumFeatures.constEnd()) for (const TopDUContext::Features f : *featuresIt) - features = ( TopDUContext::Features )(features | f); + features = (TopDUContext::Features)(features | f); return features; } TopDUContext::Features ParseJob::minimumFeatures() const { Q_D(const ParseJob); - return ( TopDUContext::Features )(d->features | staticMinimumFeatures(d->url)); + return (TopDUContext::Features)(d->features | staticMinimumFeatures(d->url)); } void ParseJob::setDuChain(const ReferencedTopDUContext& duChain) @@ -238,8 +236,11 @@ bool ParseJob::abortRequested() const { Q_D(const ParseJob); - +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + return d->abortRequested.loadRelaxed(); +#else return d->abortRequested.load(); +#endif } void ParseJob::requestAbort() @@ -292,7 +293,7 @@ d->tracker = ICore::self()->languageController()->backgroundParser()->trackerForUrl(document()); - //Try using an artificial code-representation, which overrides everything else + // Try using an artificial code-representation, which overrides everything else if (artificialCodeRepresentationExists(document())) { CodeRepresentation::Ptr repr = createCodeRepresentation(document()); d->contents.contents = repr->text().toUtf8(); @@ -311,8 +312,8 @@ Q_ASSERT(t->revisionAtLastReset()); d->contents.contents = t->document()->text().toUtf8(); - d->contents.modification = - KDevelop::ModificationRevision(lastModified, t->revisionAtLastReset()->revision()); + d->contents.modification + = KDevelop::ModificationRevision(lastModified, t->revisionAtLastReset()->revision()); d->revision = t->acquireRevision(d->contents.modification.revision); hadTracker = true; @@ -327,10 +328,8 @@ KDevelop::ProblemPointer p(new Problem()); p->setSource(IProblem::Disk); p->setDescription(i18nc("%1: filename", "Skipped file that is too large: '%1'", localFile)); - p->setExplanation(i18nc("%1: file size, %2: limit file size", - "The file is %1 and exceeds the limit of %2.", - f.formatByteSize(fileInfo.size()), - f.formatByteSize(d->maximumFileSize))); + p->setExplanation(i18nc("%1: file size, %2: limit file size", "The file is %1 and exceeds the limit of %2.", + f.formatByteSize(fileInfo.size()), f.formatByteSize(d->maximumFileSize))); p->setFinalLocation(DocumentRange(document(), KTextEditor::Range::invalid())); qCWarning(LANGUAGE) << p->description() << p->explanation(); return p; @@ -381,10 +380,9 @@ return d->contents; } -struct MovingRangeTranslator - : public DUChainVisitor -{ - MovingRangeTranslator(qint64 _source, qint64 _target, MovingInterface* _moving) : source(_source) +struct MovingRangeTranslator : public DUChainVisitor { + MovingRangeTranslator(qint64 _source, qint64 _target, MovingInterface* _moving) + : source(_source) , target(_target) , moving(_moving) { @@ -403,10 +401,7 @@ } } - void visit(Declaration* declaration) override - { - translateRange(declaration); - } + void visit(Declaration* declaration) override { translateRange(declaration); } void translateRange(DUChainBase* object) { @@ -461,8 +456,9 @@ } if (sourceRevision > targetRevision) { - qCDebug(LANGUAGE) << "for document" << document().str() << - ": source revision is higher than target revision:" << sourceRevision << " > " << targetRevision; + qCDebug(LANGUAGE) << "for document" << document().str() + << ": source revision is higher than target revision:" << sourceRevision << " > " + << targetRevision; return; } @@ -474,8 +470,8 @@ } if (sourceRevision != d->previousRevision->revision() || !d->previousRevision->valid()) { - qCDebug(LANGUAGE) << - "not translating because the document revision does not match the tracker start revision (maybe the document was cleared)"; + qCDebug(LANGUAGE) << "not translating because the document revision does not match the tracker start " + "revision (maybe the document was cleared)"; return; } diff --git a/kdevplatform/language/codegen/documentchangeset.cpp b/kdevplatform/language/codegen/documentchangeset.cpp --- a/kdevplatform/language/codegen/documentchangeset.cpp +++ b/kdevplatform/language/codegen/documentchangeset.cpp @@ -23,33 +23,34 @@ #include -#include #include +#include #include #include -#include #include +#include +#include #include #include #include #include -#include #include -#include -#include #include #include +#include +#include #include #include #include -namespace KDevelop { +namespace KDevelop +{ using ChangesList = QList; using ChangesHash = QHash; @@ -67,66 +68,59 @@ DocumentChangeSet::ChangeResult addChange(const DocumentChangePointer& change); DocumentChangeSet::ChangeResult replaceOldText(CodeRepresentation* repr, const QString& newText, const ChangesList& sortedChangesList); - DocumentChangeSet::ChangeResult generateNewText(const IndexedString& file, - ChangesList& sortedChanges, - const CodeRepresentation* repr, - QString& output); - DocumentChangeSet::ChangeResult removeDuplicates(const IndexedString& file, - ChangesList& filteredChanges); + DocumentChangeSet::ChangeResult generateNewText(const IndexedString& file, ChangesList& sortedChanges, + const CodeRepresentation* repr, QString& output); + DocumentChangeSet::ChangeResult removeDuplicates(const IndexedString& file, ChangesList& filteredChanges); void formatChanges(); void updateFiles(); }; // Simple helpers to clear up code clutter -namespace { -inline bool changeIsValid(const DocumentChange& change, const QStringList& textLines) +namespace { - return change.m_range.start() <= change.m_range.end() && - change.m_range.end().line() < textLines.size() && - change.m_range.start().line() >= 0 && - change.m_range.start().column() >= 0 && - change.m_range.start().column() <= textLines[change.m_range.start().line()].length() && - change.m_range.end().column() >= 0 && - change.m_range.end().column() <= textLines[change.m_range.end().line()].length(); -} + inline bool changeIsValid(const DocumentChange& change, const QStringList& textLines) + { + return change.m_range.start() <= change.m_range.end() && change.m_range.end().line() < textLines.size() + && change.m_range.start().line() >= 0 && change.m_range.start().column() >= 0 + && change.m_range.start().column() <= textLines[change.m_range.start().line()].length() + && change.m_range.end().column() >= 0 + && change.m_range.end().column() <= textLines[change.m_range.end().line()].length(); + } -inline bool duplicateChanges(const DocumentChangePointer& previous, const DocumentChangePointer& current) -{ - // Given the option of considering a duplicate two changes in the same range - // but with different old texts to be ignored - return previous->m_range == current->m_range && - previous->m_newText == current->m_newText && - (previous->m_oldText == current->m_oldText || - (previous->m_ignoreOldText && current->m_ignoreOldText)); -} + inline bool duplicateChanges(const DocumentChangePointer& previous, const DocumentChangePointer& current) + { + // Given the option of considering a duplicate two changes in the same range + // but with different old texts to be ignored + return previous->m_range == current->m_range && previous->m_newText == current->m_newText + && (previous->m_oldText == current->m_oldText || (previous->m_ignoreOldText && current->m_ignoreOldText)); + } -inline QString rangeText(const KTextEditor::Range& range, const QStringList& textLines) -{ - QStringList ret; - ret.reserve(range.end().line() - range.start().line() + 1); - for (int line = range.start().line(); line <= range.end().line(); ++line) { - const QString lineText = textLines.at(line); - int startColumn = 0; - int endColumn = lineText.length(); - if (line == range.start().line()) { - startColumn = range.start().column(); - } - if (line == range.end().line()) { - endColumn = range.end().column(); + inline QString rangeText(const KTextEditor::Range& range, const QStringList& textLines) + { + QStringList ret; + ret.reserve(range.end().line() - range.start().line() + 1); + for (int line = range.start().line(); line <= range.end().line(); ++line) { + const QString lineText = textLines.at(line); + int startColumn = 0; + int endColumn = lineText.length(); + if (line == range.start().line()) { + startColumn = range.start().column(); + } + if (line == range.end().line()) { + endColumn = range.end().column(); + } + ret << lineText.mid(startColumn, endColumn - startColumn); } - ret << lineText.mid(startColumn, endColumn - startColumn); - } - return ret.join(QLatin1Char('\n')); -} + return ret.join(QLatin1Char('\n')); + } -// need to have it as otherwise the arguments can exceed the maximum of 10 -static QString printRange(const KTextEditor::Range& r) -{ - return i18nc("text range line:column->line:column", "%1:%2->%3:%4", - r.start().line(), r.start().column(), - r.end().line(), r.end().column()); -} + // need to have it as otherwise the arguments can exceed the maximum of 10 + static QString printRange(const KTextEditor::Range& r) + { + return i18nc("text range line:column->line:column", "%1:%2->%3:%4", r.start().line(), r.start().column(), + r.end().line(), r.end().column()); + } } DocumentChangeSet::DocumentChangeSet() @@ -220,7 +214,12 @@ } QList allFiles; +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + const auto changedFiles = const auto changedFiles + = QSet(d->documentsRename.keys().begin(), d->documentsRename.keys().end()); +#else const auto changedFiles = d->documentsRename.keys().toSet() + d->changes.keys().toSet(); +#endif allFiles.reserve(changedFiles.size()); for (const IndexedString& file : changedFiles) { allFiles << file.toUrl(); @@ -261,12 +260,12 @@ d->changes[idxNewDoc] = value; } } else { - ///FIXME: share code with project manager for the error code string representation + /// FIXME: share code with project manager for the error code string representation return ChangeResult(i18n("Could not rename '%1' to '%2'", url.toDisplayString(QUrl::PreferLocalFile), it.value().str())); } } else { - //TODO: do it outside the project management? + // TODO: do it outside the project management? qCWarning(LANGUAGE) << "tried to rename file not tracked by project - not implemented"; } } else { @@ -305,13 +304,13 @@ QMap oldTexts; - //Apply the changes to the files + // Apply the changes to the files for (const IndexedString& file : files) { oldTexts[file] = codeRepresentations[file]->text(); result = d->replaceOldText(codeRepresentations[file].data(), newTexts[file], filteredSortedChanges[file]); if (!result && d->replacePolicy == StopOnFailedChange) { - //Revert all files + // Revert all files for (auto it = oldTexts.constBegin(), end = oldTexts.constEnd(); it != end; ++it) { const IndexedString& revertFile = it.key(); const QString& oldText = it.value(); @@ -345,36 +344,34 @@ auto* dynamic = dynamic_cast(repr); if (dynamic) { auto transaction = dynamic->makeEditTransaction(); - //Replay the changes one by one + // Replay the changes one by one for (int pos = sortedChangesList.size() - 1; pos >= 0; --pos) { const DocumentChange& change(*sortedChangesList[pos]); if (!dynamic->replace(change.m_range, change.m_oldText, change.m_newText, change.m_ignoreOldText)) { - QString warningString = i18nc( - "Inconsistent change in between , found (encountered ) -> ", - "Inconsistent change in %1 between %2, found %3 (encountered \"%4\") -> \"%5\"", - change.m_document.str(), - printRange(change.m_range), - change.m_oldText, - dynamic->rangeText(change.m_range), - change.m_newText); + QString warningString + = i18nc("Inconsistent change in between , found (encountered " + ") -> ", + "Inconsistent change in %1 between %2, found %3 (encountered \"%4\") -> \"%5\"", + change.m_document.str(), printRange(change.m_range), change.m_oldText, + dynamic->rangeText(change.m_range), change.m_newText); if (replacePolicy == DocumentChangeSet::WarnOnFailedChange) { qCWarning(LANGUAGE) << warningString; } else if (replacePolicy == DocumentChangeSet::StopOnFailedChange) { return DocumentChangeSet::ChangeResult(warningString); } - //If set to ignore failed changes just continue with the others + // If set to ignore failed changes just continue with the others } } return DocumentChangeSet::ChangeResult::successfulResult(); } - //For files on disk + // For files on disk if (!repr->setText(newText)) { - QString warningString = i18n("Could not replace text in the document: %1", - sortedChangesList.begin()->data()->m_document.str()); + QString warningString + = i18n("Could not replace text in the document: %1", sortedChangesList.begin()->data()->m_document.str()); if (replacePolicy == DocumentChangeSet::WarnOnFailedChange) { qCWarning(LANGUAGE) << warningString; } @@ -390,33 +387,37 @@ const CodeRepresentation* repr, QString& output) { - //Create the actual new modified file + // Create the actual new modified file QStringList textLines = repr->text().split(QLatin1Char('\n')); QUrl url = file.toUrl(); QMimeType mime = QMimeDatabase().mimeTypeForUrl(url); auto core = ICore::self(); - ISourceFormatter* formatter = core ? core->sourceFormatterController()->formatterForUrl(file.toUrl(), mime) : nullptr; + ISourceFormatter* formatter + = core ? core->sourceFormatterController()->formatterForUrl(file.toUrl(), mime) : nullptr; QVector removedLines; for (int pos = sortedChanges.size() - 1; pos >= 0; --pos) { DocumentChange& change(*sortedChanges[pos]); QString encountered; - if (changeIsValid(change, textLines) && //We demand this, although it should be fixed + if (changeIsValid(change, textLines) && // We demand this, although it should be fixed ((encountered = rangeText(change.m_range, textLines)) == change.m_oldText || change.m_ignoreOldText)) { - ///Problem: This does not work if the other changes significantly alter the context @todo Use the changed context - QString leftContext = QStringList(textLines.mid(0, change.m_range.start().line() + 1)).join(QLatin1Char( - '\n')); + /// Problem: This does not work if the other changes significantly alter the context @todo Use the changed + /// context + QString leftContext + = QStringList(textLines.mid(0, change.m_range.start().line() + 1)).join(QLatin1Char('\n')); leftContext.chop(textLines[change.m_range.start().line()].length() - change.m_range.start().column()); - QString rightContext = QStringList(textLines.mid(change.m_range.end().line())).join(QLatin1Char('\n')).mid( - change.m_range.end().column()); + QString rightContext = QStringList(textLines.mid(change.m_range.end().line())) + .join(QLatin1Char('\n')) + .mid(change.m_range.end().column()); - if (formatter && (formatPolicy == DocumentChangeSet::AutoFormatChanges - || formatPolicy == DocumentChangeSet::AutoFormatChangesKeepIndentation)) { + if (formatter + && (formatPolicy == DocumentChangeSet::AutoFormatChanges + || formatPolicy == DocumentChangeSet::AutoFormatChangesKeepIndentation)) { QString oldNewText = change.m_newText; change.m_newText = formatter->formatSource(change.m_newText, url, mime, leftContext, rightContext); @@ -452,18 +453,17 @@ change.m_newText = newLines.join(QLatin1Char('\n')); } else { - qCDebug(LANGUAGE) << "Cannot keep the indentation because the line count has changed" << - oldNewText; + qCDebug(LANGUAGE) + << "Cannot keep the indentation because the line count has changed" << oldNewText; } } } QString& line = textLines[change.m_range.start().line()]; if (change.m_range.start().line() == change.m_range.end().line()) { // simply replace existing line content line.replace(change.m_range.start().column(), - change.m_range.end().column() - change.m_range.start().column(), - change.m_newText); + change.m_range.end().column() - change.m_range.start().column(), change.m_newText); } else { // replace first line contents line.replace(change.m_range.start().column(), line.length() - change.m_range.start().column(), @@ -478,18 +478,15 @@ } } } else { - QString warningString = i18nc("Inconsistent change in at " - " = (encountered ) -> ", - "Inconsistent change in %1 at %2" - " = \"%3\"(encountered \"%4\") -> \"%5\"", - file.str(), - printRange(change.m_range), - change.m_oldText, - encountered, - change.m_newText); + QString warningString + = i18nc("Inconsistent change in at " + " = (encountered ) -> ", + "Inconsistent change in %1 at %2" + " = \"%3\"(encountered \"%4\") -> \"%5\"", + file.str(), printRange(change.m_range), change.m_oldText, encountered, change.m_newText); if (replacePolicy == DocumentChangeSet::IgnoreFailedChange) { - //Just don't do the replacement + // Just don't do the replacement } else if (replacePolicy == DocumentChangeSet::WarnOnFailedChange) { qCWarning(LANGUAGE) << warningString; } else { @@ -510,7 +507,7 @@ return DocumentChangeSet::ChangeResult::successfulResult(); } -//Removes all duplicate changes for a single file, and then returns (via filteredChanges) the filtered duplicates +// Removes all duplicate changes for a single file, and then returns (via filteredChanges) the filtered duplicates DocumentChangeSet::ChangeResult DocumentChangeSetPrivate::removeDuplicates(const IndexedString& file, ChangesList& filteredChanges) { @@ -521,47 +518,42 @@ sortedChanges.insert(change->m_range.end(), change); } - //Remove duplicates + // Remove duplicates ChangesMap::iterator previous = sortedChanges.begin(); for (ChangesMap::iterator it = ++sortedChanges.begin(); it != sortedChanges.end();) { if ((*previous) && (*previous)->m_range.end() > (*it)->m_range.start()) { - //intersection + // intersection if (duplicateChanges((*previous), *it)) { - //duplicate, remove one + // duplicate, remove one it = sortedChanges.erase(it); continue; } - //When two changes contain each other, and the container change is set to ignore old text, then it should be safe to - //just ignore the contained change, and apply the bigger change + // When two changes contain each other, and the container change is set to ignore old text, then it should + // be safe to just ignore the contained change, and apply the bigger change else if ((*it)->m_range.contains((*previous)->m_range) && (*it)->m_ignoreOldText) { qCDebug(LANGUAGE) << "Removing change: " << (*previous)->m_oldText << "->" << (*previous)->m_newText - << ", because it is contained by change: " << (*it)->m_oldText << "->" << - (*it)->m_newText; + << ", because it is contained by change: " << (*it)->m_oldText << "->" + << (*it)->m_newText; sortedChanges.erase(previous); } - //This case is for when both have the same end, either of them could be the containing range + // This case is for when both have the same end, either of them could be the containing range else if ((*previous)->m_range.contains((*it)->m_range) && (*previous)->m_ignoreOldText) { qCDebug(LANGUAGE) << "Removing change: " << (*it)->m_oldText << "->" << (*it)->m_newText - << ", because it is contained by change: " << (*previous)->m_oldText - << "->" << (*previous)->m_newText; + << ", because it is contained by change: " << (*previous)->m_oldText << "->" + << (*previous)->m_newText; it = sortedChanges.erase(it); continue; } else { - return DocumentChangeSet::ChangeResult( - i18nc("Inconsistent change-request at :" - "intersecting changes: " - " -> @ & " - " -> @", - "Inconsistent change-request at %1; " - "intersecting changes: " - "\"%2\"->\"%3\"@%4 & \"%5\"->\"%6\"@%7 ", - file.str(), - (*previous)->m_oldText, - (*previous)->m_newText, - printRange((*previous)->m_range), - (*it)->m_oldText, - (*it)->m_newText, - printRange((*it)->m_range))); + return DocumentChangeSet::ChangeResult(i18nc("Inconsistent change-request at :" + "intersecting changes: " + " -> @ & " + " -> @", + "Inconsistent change-request at %1; " + "intersecting changes: " + "\"%2\"->\"%3\"@%4 & \"%5\"->\"%6\"@%7 ", + file.str(), (*previous)->m_oldText, (*previous)->m_newText, + printRange((*previous)->m_range), (*it)->m_oldText, + (*it)->m_newText, printRange((*it)->m_range))); } } previous = it; diff --git a/kdevplatform/language/duchain/duchain.cpp b/kdevplatform/language/duchain/duchain.cpp --- a/kdevplatform/language/duchain/duchain.cpp +++ b/kdevplatform/language/duchain/duchain.cpp @@ -21,137 +21,128 @@ #include "duchainlock.h" #include +#include #include #include +#include #include #include -#include -#include #include -#include +#include #include #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) #include #endif -#include #include +#include #include #include -#include "../interfaces/ilanguagesupport.h" -#include "../interfaces/icodehighlighting.h" #include "../backgroundparser/backgroundparser.h" +#include "../interfaces/icodehighlighting.h" +#include "../interfaces/ilanguagesupport.h" #include +#include "abstractfunctiondeclaration.h" +#include "declaration.h" +#include "definitions.h" +#include "duchainregister.h" +#include "duchainutils.h" +#include "importers.h" #include "language-features.h" +#include "parsingenvironment.h" +#include "persistentsymboltable.h" +#include "serialization/itemrepository.h" #include "topducontext.h" #include "topducontextdata.h" #include "topducontextdynamicdata.h" -#include "parsingenvironment.h" -#include "declaration.h" -#include "definitions.h" -#include "duchainutils.h" #include "use.h" #include "uses.h" -#include "abstractfunctiondeclaration.h" -#include "duchainregister.h" -#include "persistentsymboltable.h" -#include "serialization/itemrepository.h" #include "waitforupdate.h" -#include "importers.h" #if HAVE_MALLOC_TRIM #include "malloc.h" #endif -namespace { -//Additional "soft" cleanup steps that are done before the actual cleanup. -//During "soft" cleanup, the consistency is not guaranteed. The repository is -//marked to be updating during soft cleanup, so if kdevelop crashes, it will be cleared. -//The big advantage of the soft cleanup steps is, that the duchain is always only locked for -//short times, which leads to no lockup in the UI. +namespace +{ +// Additional "soft" cleanup steps that are done before the actual cleanup. +// During "soft" cleanup, the consistency is not guaranteed. The repository is +// marked to be updating during soft cleanup, so if kdevelop crashes, it will be cleared. +// The big advantage of the soft cleanup steps is, that the duchain is always only locked for +// short times, which leads to no lockup in the UI. const int SOFT_CLEANUP_STEPS = 1; // seconds to wait before trying to cleanup the DUChain const uint cleanupEverySeconds = 200; -///Approximate maximum count of top-contexts that are checked during final cleanup +/// Approximate maximum count of top-contexts that are checked during final cleanup const uint maxFinalCleanupCheckContexts = 2000; -const uint minimumFinalCleanupCheckContextsPercentage = 10; //Check at least n% of all top-contexts during cleanup -//Set to true as soon as the duchain is deleted +const uint minimumFinalCleanupCheckContextsPercentage = 10; // Check at least n% of all top-contexts during cleanup +// Set to true as soon as the duchain is deleted } -namespace KDevelop { +namespace KDevelop +{ bool DUChain::m_deleted = false; -///Must be locked through KDevelop::SpinLock before using chainsByIndex -///This lock should be locked only for very short times +/// Must be locked through KDevelop::SpinLock before using chainsByIndex +/// This lock should be locked only for very short times QMutex DUChain::chainsByIndexLock; std::vector DUChain::chainsByIndex; -//This thing is not actually used, but it's needed for compiling +// This thing is not actually used, but it's needed for compiling DEFINE_LIST_MEMBER_HASH(EnvironmentInformationListItem, items, uint) -//An entry for the item-repository that holds some meta-data. Behind this entry, the actual ParsingEnvironmentFileData is stored. +// An entry for the item-repository that holds some meta-data. Behind this entry, the actual ParsingEnvironmentFileData +// is stored. class EnvironmentInformationItem { public: - EnvironmentInformationItem(uint topContext, uint size) : m_topContext(topContext) + EnvironmentInformationItem(uint topContext, uint size) + : m_topContext(topContext) , m_size(size) { } - ~EnvironmentInformationItem() - { - } + ~EnvironmentInformationItem() {} EnvironmentInformationItem& operator=(const EnvironmentInformationItem& rhs) = delete; - unsigned int hash() const - { - return m_topContext; - } + unsigned int hash() const { return m_topContext; } - unsigned int itemSize() const - { - return sizeof(*this) + m_size; - } + unsigned int itemSize() const { return sizeof(*this) + m_size; } uint m_topContext; - uint m_size;//Size of the data behind, that holds the actual item + uint m_size; // Size of the data behind, that holds the actual item }; -struct ItemRepositoryIndexHash -{ - uint - operator()(unsigned int __x) const - { return 173 * (__x >> 2) + 11 * (__x >> 16); } +struct ItemRepositoryIndexHash { + uint operator()(unsigned int __x) const { return 173 * (__x >> 2) + 11 * (__x >> 16); } }; class EnvironmentInformationRequest { public: - - ///This constructor should only be used for lookup - EnvironmentInformationRequest(uint topContextIndex) : m_file(nullptr) + /// This constructor should only be used for lookup + EnvironmentInformationRequest(uint topContextIndex) + : m_file(nullptr) , m_index(topContextIndex) { } - EnvironmentInformationRequest(const ParsingEnvironmentFile* file) : m_file(file) + EnvironmentInformationRequest(const ParsingEnvironmentFile* file) + : m_file(file) , m_index(file->indexedTopContext().index()) { } enum { - AverageSize = 32 //This should be the approximate average size of an Item + AverageSize = 32 // This should be the approximate average size of an Item }; - unsigned int hash() const - { - return m_index; - } + unsigned int hash() const { return m_index; } uint itemSize() const { @@ -162,8 +153,8 @@ { new (item) EnvironmentInformationItem(m_index, DUChainItemSystem::self().dynamicSize(*m_file->d_func())); Q_ASSERT(m_file->d_func()->m_dynamic); - auto* data = - reinterpret_cast(reinterpret_cast(item) + sizeof(EnvironmentInformationItem)); + auto* data + = reinterpret_cast(reinterpret_cast(item) + sizeof(EnvironmentInformationItem)); DUChainItemSystem::self().copy(*m_file->d_func(), *data, true); Q_ASSERT(data->m_range == m_file->d_func()->m_range); Q_ASSERT(data->classId == m_file->d_func()->classId); @@ -173,103 +164,83 @@ static void destroy(EnvironmentInformationItem* item, KDevelop::AbstractItemRepository&) { item->~EnvironmentInformationItem(); - //We don't need to call the destructor, because that's done in DUChainBase::makeDynamic() - //We just need to make sure that every environment-file is dynamic when it's deleted -// DUChainItemSystem::self().callDestructor((DUChainBaseData*)(((char*)item) + sizeof(EnvironmentInformationItem))); + // We don't need to call the destructor, because that's done in DUChainBase::makeDynamic() + // We just need to make sure that every environment-file is dynamic when it's deleted + // DUChainItemSystem::self().callDestructor((DUChainBaseData*)(((char*)item) + + // sizeof(EnvironmentInformationItem))); } static bool persistent(const EnvironmentInformationItem*) { - //Cleanup done separately + // Cleanup done separately return true; } - bool equals(const EnvironmentInformationItem* item) const - { - return m_index == item->m_topContext; - } + bool equals(const EnvironmentInformationItem* item) const { return m_index == item->m_topContext; } const ParsingEnvironmentFile* m_file; uint m_index; }; -///A list of environment-information/top-contexts mapped to a file-name +/// A list of environment-information/top-contexts mapped to a file-name class EnvironmentInformationListItem { public: - EnvironmentInformationListItem() - { - initializeAppendedLists(true); - } + EnvironmentInformationListItem() { initializeAppendedLists(true); } EnvironmentInformationListItem(const EnvironmentInformationListItem& rhs, bool dynamic = true) { initializeAppendedLists(dynamic); m_file = rhs.m_file; copyListsFrom(rhs); } - ~EnvironmentInformationListItem() - { - freeAppendedLists(); - } + ~EnvironmentInformationListItem() { freeAppendedLists(); } EnvironmentInformationListItem& operator=(const EnvironmentInformationListItem& rhs) = delete; unsigned int hash() const { - //We only compare the declaration. This allows us implementing a map, although the item-repository - //originally represents a set. + // We only compare the declaration. This allows us implementing a map, although the item-repository + // originally represents a set. return m_file.hash(); } - unsigned short int itemSize() const - { - return dynamicSize(); - } + unsigned short int itemSize() const { return dynamicSize(); } IndexedString m_file; - uint classSize() const - { - return sizeof(*this); - } + uint classSize() const { return sizeof(*this); } START_APPENDED_LISTS(EnvironmentInformationListItem); - ///Contains the index of each contained environment-item + /// Contains the index of each contained environment-item APPENDED_LIST_FIRST(EnvironmentInformationListItem, uint, items); END_APPENDED_LISTS(EnvironmentInformationListItem, items); }; class EnvironmentInformationListRequest { public: - - ///This constructor should only be used for lookup - EnvironmentInformationListRequest(const IndexedString& file) : m_file(file) + /// This constructor should only be used for lookup + EnvironmentInformationListRequest(const IndexedString& file) + : m_file(file) , m_item(nullptr) { } - ///This is used to actually construct the information in the repository - EnvironmentInformationListRequest(const IndexedString& file, const EnvironmentInformationListItem& item) : m_file( - file) + /// This is used to actually construct the information in the repository + EnvironmentInformationListRequest(const IndexedString& file, const EnvironmentInformationListItem& item) + : m_file(file) , m_item(&item) { } enum { - AverageSize = 160 //This should be the approximate average size of an Item + AverageSize = 160 // This should be the approximate average size of an Item }; - unsigned int hash() const - { - return m_file.hash(); - } + unsigned int hash() const { return m_file.hash(); } - uint itemSize() const - { - return m_item->itemSize(); - } + uint itemSize() const { return m_item->itemSize(); } void createItem(EnvironmentInformationListItem* item) const { @@ -284,14 +255,11 @@ static bool persistent(const EnvironmentInformationListItem*) { - //Cleanup is done separately + // Cleanup is done separately return true; } - bool equals(const EnvironmentInformationListItem* item) const - { - return m_file == item->m_file; - } + bool equals(const EnvironmentInformationListItem* item) const { return m_file == item->m_file; } IndexedString m_file; const EnvironmentInformationListItem* m_item; @@ -301,10 +269,9 @@ static DUChainPrivate* duChainPrivateSelf = nullptr; class DUChainPrivate { - class CleanupThread - : public QThread + class CleanupThread : public QThread { -public: + public: explicit CleanupThread(DUChainPrivate* data) : m_data(data) { @@ -316,25 +283,26 @@ wait(); } -private: + private: void run() override { QTimer timer; connect(&timer, &QTimer::timeout, &timer, [this]() { - Q_ASSERT(QThread::currentThread() == this); - //Just to make sure the cache is cleared periodically - ModificationRevisionSet::clearCache(); + Q_ASSERT(QThread::currentThread() == this); + // Just to make sure the cache is cleared periodically + ModificationRevisionSet::clearCache(); - m_data->doMoreCleanup(SOFT_CLEANUP_STEPS, TryLock); - }); + m_data->doMoreCleanup(SOFT_CLEANUP_STEPS, TryLock); + }); timer.start(cleanupEverySeconds * 1000); exec(); } DUChainPrivate* m_data; }; public: - DUChainPrivate() : m_chainsMutex(QMutex::Recursive) + DUChainPrivate() + : m_chainsMutex(QMutex::Recursive) , m_cleanupMutex(QMutex::Recursive) , instance(nullptr) , m_cleanupDisabled(false) @@ -362,32 +330,33 @@ DUChain::m_deleted = false; - ///Loading of some static data: + /// Loading of some static data: { ///@todo Solve this more duchain-like QFile f(globalItemRepositoryRegistry().path() + QLatin1String("/parsing_environment_data")); bool opened = f.open(QIODevice::ReadOnly); - ///FIXME: ugh, so ugly - ParsingEnvironmentFile::m_staticData = - reinterpret_cast(new char[sizeof(StaticParsingEnvironmentData)]); + /// FIXME: ugh, so ugly + ParsingEnvironmentFile::m_staticData + = reinterpret_cast(new char[sizeof(StaticParsingEnvironmentData)]); if (opened) { qCDebug(LANGUAGE) << "reading parsing-environment static data"; - //Read - f.read(reinterpret_cast(ParsingEnvironmentFile::m_staticData), sizeof(StaticParsingEnvironmentData)); + // Read + f.read(reinterpret_cast(ParsingEnvironmentFile::m_staticData), + sizeof(StaticParsingEnvironmentData)); } else { qCDebug(LANGUAGE) << "creating new parsing-environment static data"; - //Initialize + // Initialize new (ParsingEnvironmentFile::m_staticData) StaticParsingEnvironmentData(); } } - ///Read in the list of available top-context indices + /// Read in the list of available top-context indices { QFile f(globalItemRepositoryRegistry().path() + QLatin1String("/available_top_context_indices")); bool opened = f.open(QIODevice::ReadOnly); if (opened) { Q_ASSERT((f.size() % sizeof(uint)) == 0); - m_availableTopContextIndices.resize(f.size() / ( int )sizeof(uint)); + m_availableTopContextIndices.resize(f.size() / (int)sizeof(uint)); f.read(reinterpret_cast(m_availableTopContextIndices.data()), f.size()); } } @@ -422,8 +391,8 @@ Q_ASSERT(m_chainsByUrl.isEmpty()); } - ///DUChain must be write-locked - ///Also removes from the environment-manager if the top-context is not on disk + /// DUChain must be write-locked + /// Also removes from the environment-manager if the top-context is not on disk void removeDocumentChainFromMemory(TopDUContext* context) { QMutexLocker l(&m_chainsMutex); @@ -433,9 +402,9 @@ auto countIt = m_referenceCounts.constFind(context); if (countIt != m_referenceCounts.constEnd()) { - //This happens during shutdown, since everything is unloaded - qCDebug(LANGUAGE) << "removed a top-context that was reference-counted:" << context->url().str() << - context->ownIndex(); + // This happens during shutdown, since everything is unloaded + qCDebug(LANGUAGE) << "removed a top-context that was reference-counted:" << context->url().str() + << context->ownIndex(); m_referenceCounts.erase(countIt); } } @@ -452,7 +421,7 @@ instance->removeFromEnvironmentManager(context); l.unlock(); - //DUChain is write-locked, so we can do whatever we want on the top-context, including deleting it + // DUChain is write-locked, so we can do whatever we want on the top-context, including deleting it context->deleteSelf(); l.relock(); @@ -462,8 +431,8 @@ DUChain::chainsByIndex[index] = nullptr; } - ///Must be locked before accessing content of this class. - ///Should be released during expensive disk-operations and such. + /// Must be locked before accessing content of this class. + /// Should be released during expensive disk-operations and such. QMutex m_chainsMutex; QMutex m_cleanupMutex; @@ -474,25 +443,25 @@ DUChainLock lock; QMultiMap m_chainsByUrl; - //Must be locked before accessing m_referenceCounts + // Must be locked before accessing m_referenceCounts QMutex m_referenceCountsMutex; QHash m_referenceCounts; Definitions m_definitions; Uses m_uses; QSet m_loading; bool m_cleanupDisabled; - //List of available top-context indices, protected by m_chainsMutex + // List of available top-context indices, protected by m_chainsMutex QVector m_availableTopContextIndices; - ///Used to keep alive the top-context that belong to documents loaded in the editor + /// Used to keep alive the top-context that belong to documents loaded in the editor QSet m_openDocumentContexts; bool m_destroyed; - ///The item must not be stored yet - ///m_chainsMutex should not be locked, since this can trigger I/O + /// The item must not be stored yet + /// m_chainsMutex should not be locked, since this can trigger I/O void addEnvironmentInformation(ParsingEnvironmentFilePointer info) { Q_ASSERT(!findInformation(info->indexedTopContext().index())); @@ -506,11 +475,11 @@ Q_ASSERT(info->d_func()->classId); } - ///The item must be managed currently - ///m_chainsMutex does not need to be locked + /// The item must be managed currently + /// m_chainsMutex does not need to be locked void removeEnvironmentInformation(ParsingEnvironmentFilePointer info) { - info->makeDynamic(); //By doing this, we make sure the data is actually being destroyed in the destructor + info->makeDynamic(); // By doing this, we make sure the data is actually being destroyed in the destructor bool removed = false; bool removed2 = false; @@ -521,7 +490,7 @@ } { - //Remove it from the environment information lists if it was there + // Remove it from the environment information lists if it was there QMutexLocker lock(m_environmentListInfo.mutex()); uint index = m_environmentListInfo.findIndex(info->url()); @@ -547,7 +516,7 @@ Q_ASSERT(!findInformation(info->indexedTopContext().index())); } - ///m_chainsMutex should _not_ be locked, because this may trigger I/O + /// m_chainsMutex should _not_ be locked, because this may trigger I/O QList getEnvironmentInformation(const IndexedString& url) { QList ret; @@ -557,31 +526,35 @@ KDevVarLengthArray topContextIndices; { - //First store all the possible indices into the KDevVarLengthArray, so we can unlock the mutex before processing them. + // First store all the possible indices into the KDevVarLengthArray, so we can unlock the mutex before + // processing them. - QMutexLocker lock(m_environmentListInfo.mutex()); //Lock the mutex to make sure the item isn't changed while it's being iterated + QMutexLocker lock( + m_environmentListInfo + .mutex()); // Lock the mutex to make sure the item isn't changed while it's being iterated const EnvironmentInformationListItem* item = m_environmentListInfo.itemFromIndex(listIndex); FOREACH_FUNCTION(uint topContextIndex, item->items) topContextIndices << topContextIndex; } - //Process the indices in a separate step after copying them from the array, so we don't need m_environmentListInfo.mutex locked, - //and can call loadInformation(..) safely, which else might lead to a deadlock. + // Process the indices in a separate step after copying them from the array, so we don't need + // m_environmentListInfo.mutex locked, and can call loadInformation(..) safely, which else might lead to a + // deadlock. for (uint topContextIndex : qAsConst(topContextIndices)) { - QExplicitlySharedDataPointer p = - ParsingEnvironmentFilePointer(loadInformation(topContextIndex)); + QExplicitlySharedDataPointer p + = ParsingEnvironmentFilePointer(loadInformation(topContextIndex)); if (p) { ret << p; } else { - qCDebug(LANGUAGE) << "Failed to load environment-information for" << - TopDUContextDynamicData::loadUrl(topContextIndex).str(); + qCDebug(LANGUAGE) << "Failed to load environment-information for" + << TopDUContextDynamicData::loadUrl(topContextIndex).str(); } } } QMutexLocker l(&m_chainsMutex); - //Add those information that have not been added to the stored lists yet + // Add those information that have not been added to the stored lists yet const auto files = m_fileEnvironmentInformations.values(url); for (const ParsingEnvironmentFilePointer& file : files) { if (!ret.contains(file)) @@ -591,14 +564,14 @@ return ret; } - ///Must be called _without_ the chainsByIndex spin-lock locked + /// Must be called _without_ the chainsByIndex spin-lock locked static inline bool hasChainForIndex(uint index) { QMutexLocker lock(&DUChain::chainsByIndexLock); return (DUChain::chainsByIndex.size() > index) && DUChain::chainsByIndex[index]; } - ///Must be called _without_ the chainsByIndex spin-lock locked. Returns the top-context if it is loaded. + /// Must be called _without_ the chainsByIndex spin-lock locked. Returns the top-context if it is loaded. static inline TopDUContext* readChainForIndex(uint index) { QMutexLocker lock(&DUChain::chainsByIndexLock); @@ -608,15 +581,15 @@ return nullptr; } - ///Makes sure that the chain with the given index is loaded + /// Makes sure that the chain with the given index is loaded ///@warning m_chainsMutex must NOT be locked when this is called void loadChain(uint index, QSet& loaded) { QMutexLocker l(&m_chainsMutex); if (!hasChainForIndex(index)) { if (m_loading.contains(index)) { - //It's probably being loaded by another thread. So wait until the load is ready + // It's probably being loaded by another thread. So wait until the load is ready while (m_loading.contains(index)) { l.unlock(); qCDebug(LANGUAGE) << "waiting for another thread to load index" << index; @@ -636,7 +609,7 @@ chain->setParsingEnvironmentFile(loadInformation(chain->ownIndex())); if (!chain->usingImportsCache()) { - //Eventually also load all the imported chains, so the import-structure is built + // Eventually also load all the imported chains, so the import-structure is built const auto importedParentContexts = chain->DUContext::importedParentContexts(); for (const DUContext::Import& import : importedParentContexts) { if (!loaded.contains(import.topContextIndex())) { @@ -655,8 +628,8 @@ } } - ///Stores all environment-information - ///Also makes sure that all information that stays is referenced, so it stays alive. + /// Stores all environment-information + /// Also makes sure that all information that stays is referenced, so it stays alive. ///@param atomic If this is false, the write-lock will be released time by time void storeAllInformation(bool atomic, DUChainWriteLocker& locker) { @@ -681,21 +654,19 @@ uint index = m_environmentInfo.findIndex(req); if (file->d_func()->isDynamic()) { - //This item has been changed, or isn't in the repository yet + // This item has been changed, or isn't in the repository yet - //Eventually remove an old entry + // Eventually remove an old entry if (index) m_environmentInfo.deleteItem(index); - //Add the new entry to the item repository + // Add the new entry to the item repository index = m_environmentInfo.index(req); Q_ASSERT(index); - auto* item = - const_cast(m_environmentInfo.itemFromIndex(index)); - auto* theData = - reinterpret_cast(reinterpret_cast(item) + - sizeof(EnvironmentInformationItem)); + auto* item = const_cast(m_environmentInfo.itemFromIndex(index)); + auto* theData = reinterpret_cast(reinterpret_cast(item) + + sizeof(EnvironmentInformationItem)); Q_ASSERT(theData->m_range == file->d_func()->m_range); Q_ASSERT(theData->m_dynamic == false); @@ -705,40 +676,37 @@ ++cnt; } else { - m_environmentInfo.itemFromIndex(index); //Prevent unloading of the data, by accessing the item + m_environmentInfo.itemFromIndex(index); // Prevent unloading of the data, by accessing the item } } - ///We must not release the lock while holding a reference to a ParsingEnvironmentFilePointer, else we may miss the deletion of an - ///information, and will get crashes. + /// We must not release the lock while holding a reference to a ParsingEnvironmentFilePointer, else we may + /// miss the deletion of an information, and will get crashes. if (!atomic && (cnt % 100 == 0)) { - //Release the lock on a regular basis + // Release the lock on a regular basis locker.unlock(); locker.lock(); } storeInformationList(url); - //Access the data in the repository, so the bucket isn't unloaded + // Access the data in the repository, so the bucket isn't unloaded uint index = m_environmentListInfo.findIndex(EnvironmentInformationListRequest(url)); if (index) { m_environmentListInfo.itemFromIndex(index); } else { QMutexLocker lock(&m_chainsMutex); - qCDebug(LANGUAGE) << "Did not find stored item for" << url.str() << "count:" << - m_fileEnvironmentInformations.values(url); + qCDebug(LANGUAGE) << "Did not find stored item for" << url.str() + << "count:" << m_fileEnvironmentInformations.values(url); } if (!atomic) { locker.unlock(); locker.lock(); } } } - QMutex& cleanupMutex() - { - return m_cleanupMutex; - } + QMutex& cleanupMutex() { return m_cleanupMutex; } /// defines how we interact with the ongoing language parse jobs enum LockFlag { @@ -750,25 +718,25 @@ TryLock = 2, }; ///@param retries When this is nonzero, then doMoreCleanup will do the specified amount of cycles - ///doing the cleanup without permanently locking the du-chain. During these steps the consistency - ///of the disk-storage is not guaranteed, but only few changes will be done during these steps, - ///so the final step where the duchain is permanently locked is much faster. + /// doing the cleanup without permanently locking the du-chain. During these steps the consistency + /// of the disk-storage is not guaranteed, but only few changes will be done during these steps, + /// so the final step where the duchain is permanently locked is much faster. void doMoreCleanup(int retries = 0, LockFlag lockFlag = BlockingLock) { if (m_cleanupDisabled) return; - //This mutex makes sure that there's never 2 threads at he same time trying to clean up + // This mutex makes sure that there's never 2 threads at he same time trying to clean up QMutexLocker lockCleanupMutex(&cleanupMutex()); if (m_destroyed || m_cleanupDisabled) return; Q_ASSERT(!instance->lock()->currentThreadHasReadLock() && !instance->lock()->currentThreadHasWriteLock()); DUChainWriteLocker writeLock(instance->lock()); - //This is used to stop all parsing before starting to do the cleanup. This way less happens during the - //soft cleanups, and we have a good chance that during the "hard" cleanup only few data has to be written. + // This is used to stop all parsing before starting to do the cleanup. This way less happens during the + // soft cleanups, and we have a good chance that during the "hard" cleanup only few data has to be written. QList locked; if (lockFlag != NoLock) { @@ -779,12 +747,12 @@ writeLock.unlock(); - //Here we wait for all parsing-threads to stop their processing + // Here we wait for all parsing-threads to stop their processing for (const auto language : qAsConst(languages)) { if (lockFlag == TryLock) { if (!language->parseLock()->tryLockForWrite()) { - qCDebug(LANGUAGE) << "Aborting cleanup because language plugin is still parsing:" << - language->name(); + qCDebug(LANGUAGE) + << "Aborting cleanup because language plugin is still parsing:" << language->name(); // some language is still parsing, don't interfere with the cleanup for (auto* lock : qAsConst(locked)) { lock->unlock(); @@ -807,9 +775,9 @@ QTime startTime = QTime::currentTime(); PersistentSymbolTable::self().clearCache(); - storeAllInformation(!retries, writeLock); //Puts environment-information into a repository + storeAllInformation(!retries, writeLock); // Puts environment-information into a repository - //We don't need to increase the reference-count, since the cleanup-mutex is locked + // We don't need to increase the reference-count, since the cleanup-mutex is locked QSet workOnContexts; { @@ -826,38 +794,38 @@ context->m_dynamicData->store(); if (retries) { - //Eventually give other threads a chance to access the duchain + // Eventually give other threads a chance to access the duchain writeLock.unlock(); - //Sleep to give the other threads a realistic chance to get a read-lock in between + // Sleep to give the other threads a realistic chance to get a read-lock in between QThread::usleep(500); writeLock.lock(); } } - //Unload all top-contexts that don't have a reference-count and that are not imported by a referenced one + // Unload all top-contexts that don't have a reference-count and that are not imported by a referenced one QSet unloadedNames; bool unloadedOne = true; bool unloadAllUnreferenced = !retries; - //Now unload contexts, but only ones that are not imported by any other currently loaded context - //The complication: Since during the lock-break new references may be added, we must never keep - //the du-chain in an invalid state. Thus we can only unload contexts that are not imported by any - //currently loaded contexts. In case of loops, we have to unload everything at once. + // Now unload contexts, but only ones that are not imported by any other currently loaded context + // The complication: Since during the lock-break new references may be added, we must never keep + // the du-chain in an invalid state. Thus we can only unload contexts that are not imported by any + // currently loaded contexts. In case of loops, we have to unload everything at once. while (unloadedOne) { unloadedOne = false; int hadUnloadable = 0; -unloadContexts: + unloadContexts: const auto currentWorkOnContexts = workOnContexts; - for (TopDUContext * unload : currentWorkOnContexts) { + for (TopDUContext* unload : currentWorkOnContexts) { bool hasReference = false; { QMutexLocker l(&m_referenceCountsMutex); - //Test if the context is imported by a referenced one + // Test if the context is imported by a referenced one for (auto it = m_referenceCounts.constBegin(), end = m_referenceCounts.constEnd(); it != end; ++it) { auto* context = it.key(); @@ -869,57 +837,61 @@ } if (!hasReference) - ++hadUnloadable; //We have found a context that is not referenced + ++hadUnloadable; // We have found a context that is not referenced else - continue; //This context is referenced + continue; // This context is referenced bool isImportedByLoaded = !unload->loadedImporters().isEmpty(); - //If we unload a context that is imported by other contexts, we create a bad loaded state + // If we unload a context that is imported by other contexts, we create a bad loaded state if (isImportedByLoaded && !unloadAllUnreferenced) continue; unloadedNames.insert(unload->url()); - //Since we've released the write-lock in between, we've got to call store() again to be sure that none of the data is dynamic - //If nothing has changed, it is only a low-cost call. + // Since we've released the write-lock in between, we've got to call store() again to be sure that none + // of the data is dynamic If nothing has changed, it is only a low-cost call. unload->m_dynamicData->store(); Q_ASSERT(!unload->d_func()->m_dynamic); removeDocumentChainFromMemory(unload); workOnContexts.remove(unload); unloadedOne = true; if (!unloadAllUnreferenced) { - //Eventually give other threads a chance to access the duchain + // Eventually give other threads a chance to access the duchain writeLock.unlock(); - //Sleep to give the other threads a realistic chance to get a read-lock in between + // Sleep to give the other threads a realistic chance to get a read-lock in between QThread::usleep(500); writeLock.lock(); } } if (hadUnloadable && !unloadedOne) { Q_ASSERT(!unloadAllUnreferenced); - //This can happen in case of loops. We have o unload everything at one time. - qCDebug(LANGUAGE) << "found" << hadUnloadable << - "unloadable contexts, but could not unload separately. Unloading atomically."; + // This can happen in case of loops. We have o unload everything at one time. + qCDebug(LANGUAGE) << "found" << hadUnloadable + << "unloadable contexts, but could not unload separately. Unloading atomically."; unloadAllUnreferenced = true; - hadUnloadable = 0; //Reset to 0, so we cannot loop forever + hadUnloadable = 0; // Reset to 0, so we cannot loop forever goto unloadContexts; } } if (retries == 0) { QMutexLocker lock(&m_chainsMutex); - //Do this atomically, since we must be sure that _everything_ is already saved - for (QMultiMap::iterator it = - m_fileEnvironmentInformations.begin(); + // Do this atomically, since we must be sure that _everything_ is already saved + for (QMultiMap::iterator it + = m_fileEnvironmentInformations.begin(); it != m_fileEnvironmentInformations.end();) { ParsingEnvironmentFile* f = it->data(); Q_ASSERT(f->d_func()->classId); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + if (f->ref.loadRelaxed() == 1) { +#else if (f->ref.load() == 1) { - Q_ASSERT(!f->d_func()->isDynamic()); //It cannot be dynamic, since we have stored before - //The ParsingEnvironmentFilePointer is only referenced once. This means that it does not belong to any - //loaded top-context, so just remove it to save some memory and processing time. +#endif + Q_ASSERT(!f->d_func()->isDynamic()); // It cannot be dynamic, since we have stored before + // The ParsingEnvironmentFilePointer is only referenced once. This means that it does not belong to + // any loaded top-context, so just remove it to save some memory and processing time. ///@todo use some kind of timeout before removing it = m_fileEnvironmentInformations.erase(it); } else { @@ -931,30 +903,32 @@ if (retries) writeLock.unlock(); - //This must be the last step, due to the on-disk reference counting - globalItemRepositoryRegistry().store(); //Stores all repositories + // This must be the last step, due to the on-disk reference counting + globalItemRepositoryRegistry().store(); // Stores all repositories { - //Store the static parsing-environment file data + // Store the static parsing-environment file data ///@todo Solve this more elegantly, using a general mechanism to store static duchain-like data Q_ASSERT(ParsingEnvironmentFile::m_staticData); QFile f(globalItemRepositoryRegistry().path() + QLatin1String("/parsing_environment_data")); bool opened = f.open(QIODevice::WriteOnly); Q_ASSERT(opened); Q_UNUSED(opened); - f.write(reinterpret_cast(ParsingEnvironmentFile::m_staticData), sizeof(StaticParsingEnvironmentData)); + f.write(reinterpret_cast(ParsingEnvironmentFile::m_staticData), + sizeof(StaticParsingEnvironmentData)); } - ///Write out the list of available top-context indices + /// Write out the list of available top-context indices { QMutexLocker lock(&m_chainsMutex); QFile f(globalItemRepositoryRegistry().path() + QLatin1String("/available_top_context_indices")); bool opened = f.open(QIODevice::WriteOnly); Q_ASSERT(opened); Q_UNUSED(opened); - f.write(reinterpret_cast(m_availableTopContextIndices.data()), m_availableTopContextIndices.size() * sizeof(uint)); + f.write(reinterpret_cast(m_availableTopContextIndices.data()), + m_availableTopContextIndices.size() * sizeof(uint)); } if (retries) { @@ -966,8 +940,8 @@ globalItemRepositoryRegistry().unlockForWriting(); const auto elapsedMS = startTime.msecsTo(QTime::currentTime()); - qCDebug(LANGUAGE) << "time spent doing cleanup:" << elapsedMS << "ms - top-contexts still open:" << - m_chainsByUrl.size() << "- retries" << retries; + qCDebug(LANGUAGE) << "time spent doing cleanup:" << elapsedMS + << "ms - top-contexts still open:" << m_chainsByUrl.size() << "- retries" << retries; } for (QReadWriteLock* lock : qAsConst(locked)) { @@ -982,7 +956,7 @@ #endif } - ///Checks whether the information is already loaded. + /// Checks whether the information is already loaded. ParsingEnvironmentFile* findInformation(uint topContextIndex) { QMutexLocker lock(&m_chainsMutex); @@ -992,42 +966,36 @@ return nullptr; } - ///Loads/gets the environment-information for the given top-context index, or returns zero if none exists + /// Loads/gets the environment-information for the given top-context index, or returns zero if none exists ///@warning m_chainsMutex should NOT be locked when this is called, because it triggers I/O ///@warning no other mutexes should be locked, as that may lead to a dedalock ParsingEnvironmentFile* loadInformation(uint topContextIndex) { ParsingEnvironmentFile* alreadyLoaded = findInformation(topContextIndex); if (alreadyLoaded) return alreadyLoaded; - //Step two: Check if it is on disk, and if is, load it + // Step two: Check if it is on disk, and if is, load it uint dataIndex = m_environmentInfo.findIndex(EnvironmentInformationRequest(topContextIndex)); if (!dataIndex) { - //No environment-information stored for this top-context + // No environment-information stored for this top-context return nullptr; } const EnvironmentInformationItem& item(*m_environmentInfo.itemFromIndex(dataIndex)); QMutexLocker lock(&m_chainsMutex); - //Due to multi-threading, we must do this check after locking the mutex, so we can be sure we don't create the same item twice at the same time + // Due to multi-threading, we must do this check after locking the mutex, so we can be sure we don't create the + // same item twice at the same time alreadyLoaded = findInformation(topContextIndex); if (alreadyLoaded) return alreadyLoaded; - ///FIXME: ugly, and remove const_cast - auto* ret = dynamic_cast(DUChainItemSystem::self().create( - const_cast( - reinterpret_cast( - reinterpret_cast(& - item) - + - sizeof( - EnvironmentInformationItem))) - )); + /// FIXME: ugly, and remove const_cast + auto* ret = dynamic_cast( + DUChainItemSystem::self().create(const_cast(reinterpret_cast( + reinterpret_cast(&item) + sizeof(EnvironmentInformationItem))))); if (ret) { Q_ASSERT(ret->d_func()->classId); Q_ASSERT(ret->indexedTopContext().index() == topContextIndex); @@ -1041,17 +1009,16 @@ return ret; } - struct CleanupListVisitor - { + struct CleanupListVisitor { QList checkContexts; bool operator()(const EnvironmentInformationItem* item) { checkContexts << item->m_topContext; return true; } }; - ///Will check a selection of all top-contexts for up-to-date ness, and remove them if out of date + /// Will check a selection of all top-contexts for up-to-date ness, and remove them if out of date void cleanupTopContexts() { DUChainWriteLocker lock(DUChain::lock()); @@ -1066,7 +1033,7 @@ if (checkContextsCount < percentageOfContexts) checkContextsCount = percentageOfContexts; - if (visitor.checkContexts.size() > ( int )checkContextsCount) + if (visitor.checkContexts.size() > (int)checkContextsCount) #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) startPos = QRandomGenerator::global()->bounded(visitor.checkContexts.size() - checkContextsCount); #else @@ -1084,44 +1051,43 @@ for (uint topIndex : qAsConst(check)) { IndexedTopDUContext top(topIndex); if (top.data()) { - qCDebug(LANGUAGE) << "removing top-context for" << top.data()->url().str() << - "because it is out of date"; + qCDebug(LANGUAGE) << "removing top-context for" << top.data()->url().str() + << "because it is out of date"; instance->removeDocumentChain(top.data()); } } qCDebug(LANGUAGE) << "check ready"; } private: - void addContextsForRemoval(QSet& topContexts, IndexedTopDUContext top) { if (topContexts.contains(top.index())) return; QExplicitlySharedDataPointer info(instance->environmentFileForDocument(top)); ///@todo Also check if the context is "useful"(Not a duplicate context, imported by a useful one, ...) if (info && info->needsUpdate()) { - //This context will be removed + // This context will be removed } else { return; } topContexts.insert(top.index()); if (info) { - //Check whether importers need to be removed as well + // Check whether importers need to be removed as well const QList> importers = info->importers(); QSet> checkNext; - //Do breadth first search, so less imports/importers have to be loaded, and a lower depth is reached + // Do breadth first search, so less imports/importers have to be loaded, and a lower depth is reached for (auto& importer : importers) { IndexedTopDUContext c = importer->indexedTopContext(); if (!topContexts.contains(c.index())) { - topContexts.insert(c.index()); //Prevent useless recursion + topContexts.insert(c.index()); // Prevent useless recursion checkNext.insert(importer); } } @@ -1133,7 +1099,7 @@ } } - ///Stores the environment-information for the given url + /// Stores the environment-information for the given url void storeInformationList(const IndexedString& url) { QMutexLocker lock(m_environmentListInfo.mutex()); @@ -1145,10 +1111,10 @@ { QMutexLocker lock(&m_chainsMutex); - QMultiMap::iterator start = m_fileEnvironmentInformations.lowerBound(url); - QMultiMap::iterator end = m_fileEnvironmentInformations.upperBound(url); + QMultiMap::iterator start + = m_fileEnvironmentInformations.lowerBound(url); + QMultiMap::iterator end + = m_fileEnvironmentInformations.upperBound(url); for (QMultiMap::iterator it = start; it != end; ++it) { uint topContextIndex = (*it)->indexedTopContext().index(); @@ -1160,12 +1126,13 @@ uint index = m_environmentListInfo.findIndex(url); if (index) { - //We only handle adding items here, since we can never be sure whether everything is loaded - //Removal is handled directly in removeEnvironmentInformation + // We only handle adding items here, since we can never be sure whether everything is loaded + // Removal is handled directly in removeEnvironmentInformation const EnvironmentInformationListItem* item = m_environmentListInfo.itemFromIndex(index); QSet oldItems; - FOREACH_FUNCTION(uint topContextIndex, item->items) { + FOREACH_FUNCTION(uint topContextIndex, item->items) + { oldItems.insert(topContextIndex); if (!newItems.contains(topContextIndex)) { newItems.insert(topContextIndex); @@ -1176,27 +1143,27 @@ if (oldItems == newItems) return; - ///Update/insert a new list - m_environmentListInfo.deleteItem(index); //Remove the previous item + /// Update/insert a new list + m_environmentListInfo.deleteItem(index); // Remove the previous item } Q_ASSERT(m_environmentListInfo.findIndex(EnvironmentInformationListRequest(url)) == 0); - //Insert the new item + // Insert the new item m_environmentListInfo.index(EnvironmentInformationListRequest(url, newItem)); Q_ASSERT(m_environmentListInfo.findIndex(EnvironmentInformationListRequest(url))); } - //Loaded environment information. Protected by m_chainsMutex + // Loaded environment information. Protected by m_chainsMutex QMultiMap m_fileEnvironmentInformations; QHash m_indexEnvironmentInformations; - ///The following repositories are thread-safe, and m_chainsMutex should not be locked when using them, because - ///they may trigger I/O. Still it may be required to lock their local mutexes. - ///Maps filenames to a list of top-contexts/environment-information. + /// The following repositories are thread-safe, and m_chainsMutex should not be locked when using them, because + /// they may trigger I/O. Still it may be required to lock their local mutexes. + /// Maps filenames to a list of top-contexts/environment-information. ItemRepository m_environmentListInfo; - ///Maps top-context-indices to environment-information item. + /// Maps top-context-indices to environment-information item. ItemRepository m_environmentInfo; }; @@ -1206,15 +1173,12 @@ { Q_ASSERT(ICore::self()); - connect( - ICore::self()->documentController(), &IDocumentController::documentLoadedPrepare, this, - &DUChain::documentLoadedPrepare); - connect( - ICore::self()->documentController(), &IDocumentController::documentUrlChanged, this, - &DUChain::documentRenamed); - connect( - ICore::self()->documentController(), &IDocumentController::documentActivated, this, - &DUChain::documentActivated); + connect(ICore::self()->documentController(), &IDocumentController::documentLoadedPrepare, this, + &DUChain::documentLoadedPrepare); + connect(ICore::self()->documentController(), &IDocumentController::documentUrlChanged, this, + &DUChain::documentRenamed); + connect(ICore::self()->documentController(), &IDocumentController::documentActivated, this, + &DUChain::documentActivated); connect(ICore::self()->documentController(), &IDocumentController::documentClosed, this, &DUChain::documentClosed); } @@ -1302,7 +1266,8 @@ { ENSURE_CHAIN_WRITE_LOCKED; IndexedTopDUContext indexed(context->indexed()); - Q_ASSERT(indexed.data() == context); ///This assertion fails if you call removeDocumentChain(..) on a document that has not been added to the du-chain + Q_ASSERT(indexed.data() == context); /// This assertion fails if you call removeDocumentChain(..) on a document that + /// has not been added to the du-chain context->m_dynamicData->deleteOnDisk(); Q_ASSERT(indexed.data() == context); sdDUChainPrivate->removeDocumentChainFromMemory(context); @@ -1317,7 +1282,7 @@ { QMutexLocker l(&sdDUChainPrivate->m_chainsMutex); -// qCDebug(LANGUAGE) << "duchain: adding document" << chain->url().str() << " " << chain; + // qCDebug(LANGUAGE) << "duchain: adding document" << chain->url().str() << " " << chain; Q_ASSERT(chain); Q_ASSERT(!sdDUChainPrivate->hasChainForIndex(chain->ownIndex())); @@ -1346,9 +1311,9 @@ // This function might be called during shutdown by stale parse jobs // Make sure we don't access null-pointers here - if (ICore::self() && ICore::self()->languageController() && - ICore::self()->languageController()->backgroundParser()->trackerForUrl(chain->url())) { - //Make sure the context stays alive at least as long as the context is open + if (ICore::self() && ICore::self()->languageController() + && ICore::self()->languageController()->backgroundParser()->trackerForUrl(chain->url())) { + // Make sure the context stays alive at least as long as the context is open ReferencedTopDUContext ctx(chain); sdDUChainPrivate->m_openDocumentContexts.insert(ctx); } @@ -1358,13 +1323,13 @@ { ParsingEnvironmentFilePointer file = chain->parsingEnvironmentFile(); if (!file) - return; //We don't need to manage + return; // We don't need to manage Q_ASSERT(file->indexedTopContext().index() == chain->ownIndex()); if (ParsingEnvironmentFile* alreadyHave = sdDUChainPrivate->findInformation(file->indexedTopContext().index())) { - ///If this triggers, there has already been another environment-information registered for this top-context. - ///removeFromEnvironmentManager should have been called before to remove the old environment-information. + /// If this triggers, there has already been another environment-information registered for this top-context. + /// removeFromEnvironmentManager should have been called before to remove the old environment-information. Q_ASSERT(alreadyHave == file.data()); Q_UNUSED(alreadyHave); return; @@ -1377,7 +1342,7 @@ { ParsingEnvironmentFilePointer file = chain->parsingEnvironmentFile(); if (!file) - return; //We don't need to manage + return; // We don't need to manage sdDUChainPrivate->removeEnvironmentInformation(file); } @@ -1442,7 +1407,7 @@ } } - //Allow selecting a top-context even if there is no ParsingEnvironmentFile + // Allow selecting a top-context even if there is no ParsingEnvironmentFile const QList ret = chainsForDocument(document); for (TopDUContext* ctx : ret) { if (!ctx->parsingEnvironmentFile() || (ctx->parsingEnvironmentFile()->isProxyContext() == proxyContext)) @@ -1494,14 +1459,15 @@ return ParsingEnvironmentFilePointer(); const QList list = sdDUChainPrivate->getEnvironmentInformation(document); -// qCDebug(LANGUAGE) << document.str() << ": matching" << list.size() << (onlyProxyContexts ? "proxy-contexts" : (noProxyContexts ? "content-contexts" : "contexts")); + // qCDebug(LANGUAGE) << document.str() << ": matching" << list.size() << (onlyProxyContexts ? "proxy-contexts" : + // (noProxyContexts ? "content-contexts" : "contexts")); for (auto& envFilePtr : list) { if (envFilePtr && (envFilePtr->isProxyContext() == proxyContext) && envFilePtr->matchEnvironment(environment) && // Verify that the environment-file and its top-context are "good": The top-context must exist, // and there must be a content-context associated to the proxy-context. - envFilePtr->topContext() && - (!proxyContext || DUChainUtils::contentContextFromProxyContext(envFilePtr->topContext()))) { + envFilePtr->topContext() + && (!proxyContext || DUChainUtils::contentContextFromProxyContext(envFilePtr->topContext()))) { return envFilePtr; } } @@ -1570,14 +1536,13 @@ auto backgroundParser = ICore::self()->languageController()->backgroundParser(); auto addWithHighPriority = [backgroundParser, doc]() { - backgroundParser->addDocument(IndexedString(doc->url()), - TopDUContext::VisibleDeclarationsAndContexts, - BackgroundParser::BestPriority); - }; + backgroundParser->addDocument(IndexedString(doc->url()), TopDUContext::VisibleDeclarationsAndContexts, + BackgroundParser::BestPriority); + }; TopDUContext* ctx = DUChainUtils::standardContextForUrl(doc->url(), true); - //Check whether the document has an attached environment-manager, and whether that one thinks the document needs to be updated. - //If yes, update it. + // Check whether the document has an attached environment-manager, and whether that one thinks the document needs to + // be updated. If yes, update it. if (ctx && ctx->parsingEnvironmentFile() && ctx->parsingEnvironmentFile()->needsUpdate()) { qCDebug(LANGUAGE) << "Document needs update, using best priority since it just got activated:" << doc->url(); addWithHighPriority(); @@ -1617,19 +1582,19 @@ const auto languages = ICore::self()->languageController()->languagesForUrl(doc->url()); if (standardContext) { - Q_ASSERT(chains.contains(standardContext)); //We have just loaded it + Q_ASSERT(chains.contains(standardContext)); // We have just loaded it Q_ASSERT((standardContext->url() == url)); sdDUChainPrivate->m_openDocumentContexts.insert(standardContext); - bool needsUpdate = standardContext->parsingEnvironmentFile() && - standardContext->parsingEnvironmentFile()->needsUpdate(); + bool needsUpdate + = standardContext->parsingEnvironmentFile() && standardContext->parsingEnvironmentFile()->needsUpdate(); if (!needsUpdate) { - //Only apply the highlighting if we don't need to update, else we might highlight total crap - //Do instant highlighting only if all imports are loaded, to make sure that we don't block the user-interface too long - //Else the highlighting will be done in the background-thread - //This is not exactly right, as the direct imports don't necessarily equal the real imports used by uses - //but it approximates the correct behavior. + // Only apply the highlighting if we don't need to update, else we might highlight total crap + // Do instant highlighting only if all imports are loaded, to make sure that we don't block the + // user-interface too long Else the highlighting will be done in the background-thread This is not exactly + // right, as the direct imports don't necessarily equal the real imports used by uses but it approximates + // the correct behavior. bool allImportsLoaded = true; const auto importedParentContexts = standardContext->importedParentContexts(); for (const DUContext::Import& import : importedParentContexts) { @@ -1654,21 +1619,15 @@ } if (needsUpdate || !(standardContext->features() & TopDUContext::AllDeclarationsContextsAndUses)) { - ICore::self()->languageController()->backgroundParser()->addDocument(IndexedString(doc->url()), - ( TopDUContext::Features )(TopDUContext - :: - AllDeclarationsContextsAndUses - | - TopDUContext - :: - ForceUpdate)); + ICore::self()->languageController()->backgroundParser()->addDocument( + IndexedString(doc->url()), + (TopDUContext::Features)(TopDUContext ::AllDeclarationsContextsAndUses | TopDUContext ::ForceUpdate)); return; } } - //Add for highlighting etc. - ICore::self()->languageController()->backgroundParser()->addDocument(IndexedString( - doc->url()), + // Add for highlighting etc. + ICore::self()->languageController()->backgroundParser()->addDocument(IndexedString(doc->url()), TopDUContext::AllDeclarationsContextsAndUses); } @@ -1678,14 +1637,12 @@ return; if (!doc->url().isValid()) { - ///Maybe this happens when a file was deleted? + /// Maybe this happens when a file was deleted? qCWarning(LANGUAGE) << "Strange, url of renamed document is invalid!"; } else { - ICore::self()->languageController()->backgroundParser()->addDocument(IndexedString(doc->url()), - ( TopDUContext::Features )(TopDUContext:: - AllDeclarationsContextsAndUses - | TopDUContext:: - ForceUpdate)); + ICore::self()->languageController()->backgroundParser()->addDocument( + IndexedString(doc->url()), + (TopDUContext::Features)(TopDUContext::AllDeclarationsContextsAndUses | TopDUContext::ForceUpdate)); } } @@ -1726,22 +1683,24 @@ QMutexLocker lock(&sdDUChainPrivate->cleanupMutex()); { - //Acquire write-lock of the repository, so when kdevelop crashes in that process, the repository is discarded - //Crashes here may happen in an inconsistent state, thus this makes sense, to protect the user from more crashes + // Acquire write-lock of the repository, so when kdevelop crashes in that process, the repository is discarded + // Crashes here may happen in an inconsistent state, thus this makes sense, to protect the user from more + // crashes globalItemRepositoryRegistry().lockForWriting(); sdDUChainPrivate->cleanupTopContexts(); globalItemRepositoryRegistry().unlockForWriting(); } - sdDUChainPrivate->doMoreCleanup(); //Must be done _before_ finalCleanup, else we may be deleting yet needed data + sdDUChainPrivate->doMoreCleanup(); // Must be done _before_ finalCleanup, else we may be deleting yet needed data sdDUChainPrivate->m_openDocumentContexts.clear(); sdDUChainPrivate->m_destroyed = true; sdDUChainPrivate->clear(); { - //Acquire write-lock of the repository, so when kdevelop crashes in that process, the repository is discarded - //Crashes here may happen in an inconsistent state, thus this makes sense, to protect the user from more crashes + // Acquire write-lock of the repository, so when kdevelop crashes in that process, the repository is discarded + // Crashes here may happen in an inconsistent state, thus this makes sense, to protect the user from more + // crashes globalItemRepositoryRegistry().lockForWriting(); finalCleanup(); globalItemRepositoryRegistry().unlockForWriting(); @@ -1764,8 +1723,8 @@ return ret; } } - static QAtomicInt& currentId(globalItemRepositoryRegistry().customCounter(QStringLiteral("Top-Context Counter"), - 1)); + static QAtomicInt& currentId( + globalItemRepositoryRegistry().customCounter(QStringLiteral("Top-Context Counter"), 1)); return currentId.fetchAndAddRelaxed(1); } @@ -1786,7 +1745,8 @@ QMutexLocker l(&sdDUChainPrivate->m_referenceCountsMutex); auto it = sdDUChainPrivate->m_referenceCounts.find(top); if (it == sdDUChainPrivate->m_referenceCounts.end()) { - //qCWarning(LANGUAGE) << "tried to decrease reference-count for" << top->url().str() << "but this top-context is not referenced"; + // qCWarning(LANGUAGE) << "tried to decrease reference-count for" << top->url().str() << "but this top-context + // is not referenced"; return; } auto& refCount = *it; @@ -1844,16 +1804,16 @@ { DUChainReadLocker lock(DUChain::lock()); TopDUContext* standardContext = DUChainUtils::standardContextForUrl(document.toUrl()); - if (standardContext && standardContext->parsingEnvironmentFile() && - !standardContext->parsingEnvironmentFile()->needsUpdate() && - standardContext->parsingEnvironmentFile()->featuresSatisfied(minFeatures)) { + if (standardContext && standardContext->parsingEnvironmentFile() + && !standardContext->parsingEnvironmentFile()->needsUpdate() + && standardContext->parsingEnvironmentFile()->featuresSatisfied(minFeatures)) { lock.unlock(); if (notifyReady) QMetaObject::invokeMethod(notifyReady, "updateReady", Qt::DirectConnection, Q_ARG(KDevelop::IndexedString, document), Q_ARG(KDevelop::ReferencedTopDUContext, ReferencedTopDUContext(standardContext))); } else { - ///Start a parse-job for the given document + /// Start a parse-job for the given document ICore::self()->languageController()->backgroundParser()->addDocument(document, minFeatures, priority, notifyReady); } @@ -1878,7 +1838,7 @@ { DUChainWriteLocker writeLock(DUChain::lock()); - ///Step 1: Compare the repositories + /// Step 1: Compare the repositories return true; } } diff --git a/kdevplatform/language/duchain/duchainlock.cpp b/kdevplatform/language/duchain/duchainlock.cpp --- a/kdevplatform/language/duchain/duchainlock.cpp +++ b/kdevplatform/language/duchain/duchainlock.cpp @@ -22,45 +22,44 @@ #include "duchainlock.h" #include "duchain.h" +#include #include #include -#include ///@todo Always prefer exactly that lock that is requested by the thread that has the foreground mutex, /// to reduce the amount of UI blocking. -//Microseconds to sleep when waiting for a lock +// Microseconds to sleep when waiting for a lock const uint uSleepTime = 500; -namespace KDevelop { +namespace KDevelop +{ class DUChainLockPrivate { public: DUChainLockPrivate() : m_writer(nullptr) , m_writerRecursion(0) , m_totalReaderRecursion(0) - { } - - int ownReaderRecursion() const { - return m_readerRecursion.localData(); } + int ownReaderRecursion() const { return m_readerRecursion.localData(); } + void changeOwnReaderRecursion(int difference) { m_readerRecursion.localData() += difference; Q_ASSERT(m_readerRecursion.localData() >= 0); m_totalReaderRecursion.fetchAndAddOrdered(difference); } - ///Holds the writer that currently has the write-lock, or zero. Is protected by m_writerRecursion. + /// Holds the writer that currently has the write-lock, or zero. Is protected by m_writerRecursion. QAtomicPointer m_writer; - ///How often is the chain write-locked by the writer? This value protects m_writer, - ///m_writer may only be changed by the thread that successfully increases this value from 0 to 1 + /// How often is the chain write-locked by the writer? This value protects m_writer, + /// m_writer may only be changed by the thread that successfully increases this value from 0 to 1 QAtomicInt m_writerRecursion; - ///How often is the chain read-locked recursively by all readers? Should be sum of all m_readerRecursion values + /// How often is the chain read-locked recursively by all readers? Should be sum of all m_readerRecursion values QAtomicInt m_totalReaderRecursion; QThreadStorage m_readerRecursion; @@ -77,14 +76,14 @@ { Q_D(DUChainLock); - ///Step 1: Increase the own reader-recursion. This will make sure no further write-locks will succeed + /// Step 1: Increase the own reader-recursion. This will make sure no further write-locks will succeed d->changeOwnReaderRecursion(1); QThread* w = d->m_writer.loadAcquire(); if (w == nullptr || w == QThread::currentThread()) { - //Successful lock: Either there is no writer, or we hold the write-lock by ourselves + // Successful lock: Either there is no writer, or we hold the write-lock by ourselves } else { - ///Step 2: Start spinning until there is no writer any more + /// Step 2: Start spinning until there is no writer any more QElapsedTimer t; if (timeout) { @@ -95,7 +94,7 @@ if (!timeout || t.elapsed() < timeout) { QThread::usleep(uSleepTime); } else { - //Fail! + // Fail! d->changeOwnReaderRecursion(-1); return false; } @@ -116,19 +115,22 @@ { Q_D(DUChainLock); - return ( bool )d->ownReaderRecursion(); + return (bool)d->ownReaderRecursion(); } bool DUChainLock::lockForWrite(uint timeout) { Q_D(DUChainLock); - //It is not allowed to acquire a write-lock while holding read-lock + // It is not allowed to acquire a write-lock while holding read-lock Q_ASSERT(d->ownReaderRecursion() == 0); - +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + if (d->m_writer.loadRelaxed() == QThread::currentThread()) { +#else if (d->m_writer.load() == QThread::currentThread()) { - //We already hold the write lock, just increase the recursion count and return +#endif + // We already hold the write lock, just increase the recursion count and return d->m_writerRecursion.fetchAndAddRelaxed(1); return true; } @@ -139,24 +141,32 @@ } while (1) { - //Try acquiring the write-lcok + // Try acquiring the write-lcok +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + if (d->m_totalReaderRecursion.loadRelaxed() == 0 && d->m_writerRecursion.testAndSetOrdered(0, 1)) { +#else if (d->m_totalReaderRecursion.load() == 0 && d->m_writerRecursion.testAndSetOrdered(0, 1)) { - //Now we can be sure that there is no other writer, as we have increased m_writerRecursion from 0 to 1 +#endif + // Now we can be sure that there is no other writer, as we have increased m_writerRecursion from 0 to 1 d->m_writer = QThread::currentThread(); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + if (d->m_totalReaderRecursion.loadRelaxed() == 0) { +#else if (d->m_totalReaderRecursion.load() == 0) { - //There is still no readers, we have successfully acquired a write-lock +#endif + // There is still no readers, we have successfully acquired a write-lock return true; } else { - //There may be readers.. we have to continue spinning + // There may be readers.. we have to continue spinning d->m_writer = nullptr; d->m_writerRecursion = 0; } } if (!timeout || t.elapsed() < timeout) { QThread::usleep(uSleepTime); } else { - //Fail! + // Fail! return false; } } @@ -170,10 +180,14 @@ Q_ASSERT(currentThreadHasWriteLock()); - //The order is important here, m_writerRecursion protects m_writer + // The order is important here, m_writerRecursion protects m_writer - //TODO: could testAndSet here + // TODO: could testAndSet here +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + if (d->m_writerRecursion.loadRelaxed() == 1) { +#else if (d->m_writerRecursion.load() == 1) { +#endif d->m_writer = nullptr; d->m_writerRecursion = 0; } else { @@ -216,8 +230,7 @@ if (m_lock) { l = m_lock->lockForRead(m_timeout); Q_ASSERT(m_timeout || l); - } - ; + }; m_locked = l; @@ -255,8 +268,7 @@ if (m_lock) { l = m_lock->lockForWrite(m_timeout); Q_ASSERT(m_timeout || l); - } - ; + }; m_locked = l; diff --git a/kdevplatform/shell/statusbar.h b/kdevplatform/shell/statusbar.h --- a/kdevplatform/shell/statusbar.h +++ b/kdevplatform/shell/statusbar.h @@ -20,13 +20,17 @@ #ifndef KDEVPLATFORM_STATUSBAR_H #define KDEVPLATFORM_STATUSBAR_H -#include #include #include +#include +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) +#include +#endif class QTimer; -namespace Sublime { +namespace Sublime +{ class View; } @@ -61,12 +65,12 @@ public Q_SLOTS: void showErrorMessage(const QString& message, int timeout); - + private Q_SLOTS: - void clearMessage( KDevelop::IStatus* ); - void showMessage( KDevelop::IStatus*, const QString & message, int timeout); - void hideProgress( KDevelop::IStatus* ); - void showProgress( KDevelop::IStatus*, int minimum, int maximum, int value); + void clearMessage(KDevelop::IStatus*); + void showMessage(KDevelop::IStatus*, const QString& message, int timeout); + void hideProgress(KDevelop::IStatus*); + void showProgress(KDevelop::IStatus*, int minimum, int maximum, int value); void slotTimeout(); void viewStatusChanged(Sublime::View* view); @@ -84,11 +88,17 @@ QHash m_messages; QTimer* const m_timer; +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + QElapsedTimer m_time; +#else QTime m_time; +#endif Sublime::View* m_currentView; - QHash m_progressItems; - StatusbarProgressWidget* m_progressWidget; // embedded in the statusbar, shows a single progressbar & button to expand the overlay widget - ProgressDialog* m_progressDialog; // the actual overlay widget that contains multiple progressbars and status messages + QHash m_progressItems; + StatusbarProgressWidget* + m_progressWidget; // embedded in the statusbar, shows a single progressbar & button to expand the overlay widget + ProgressDialog* + m_progressDialog; // the actual overlay widget that contains multiple progressbars and status messages ProgressManager* m_progressController; // progress item model }; diff --git a/kdevplatform/tests/testfile.cpp b/kdevplatform/tests/testfile.cpp --- a/kdevplatform/tests/testfile.cpp +++ b/kdevplatform/tests/testfile.cpp @@ -23,25 +23,26 @@ #include "testproject.h" #include -#include #include +#include +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) +#include +#endif -#include -#include -#include #include #include #include +#include +#include +#include #include using namespace KDevelop; class KDevelop::TestFilePrivate { public: - TestFilePrivate() - { - } + TestFilePrivate() {} void updateReady(const IndexedString& _url, const ReferencedTopDUContext& _topContext) { @@ -88,8 +89,7 @@ bool keepDUChainData = false; }; -TestFile::TestFile(const QString& contents, const QString& fileExtension, - TestProject* project, const QString& dir) +TestFile::TestFile(const QString& contents, const QString& fileExtension, TestProject* project, const QString& dir) : d_ptr(new TestFilePrivate()) { Q_D(TestFile); @@ -122,12 +122,10 @@ Q_D(TestFile); d->suffix = QLatin1Char('.') + fileExtension; - const QString file = (!dir.isEmpty() ? dir : QDir::tempPath()) - + QLatin1Char('/') + fileName + d->suffix; + const QString file = (!dir.isEmpty() ? dir : QDir::tempPath()) + QLatin1Char('/') + fileName + d->suffix; d->init(file, contents, project); } - TestFile::~TestFile() { Q_D(TestFile); @@ -176,7 +174,11 @@ // optimize: we don't want to wait the usual timeout before parsing documents here ICore::self()->languageController()->backgroundParser()->parseDocuments(); } +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + QElapsedTimer t; +#else QTime t; +#endif t.start(); while (!d->ready && t.elapsed() < timeout) { QTest::qWait(10); diff --git a/kdevplatform/util/ksharedobject.h b/kdevplatform/util/ksharedobject.h --- a/kdevplatform/util/ksharedobject.h +++ b/kdevplatform/util/ksharedobject.h @@ -19,42 +19,44 @@ #ifndef KDEVPLATFORM_KSHAREDOBJECT_H #define KDEVPLATFORM_KSHAREDOBJECT_H -#include #include +#include -namespace KDevelop { - -struct FakeAtomic +namespace KDevelop { - inline FakeAtomic(QObject& object, QSharedData& real) : m_object(object) + +struct FakeAtomic { + inline FakeAtomic(QObject& object, QSharedData& real) + : m_object(object) , m_real(real) { } inline operator int() const { const int value = m_real.ref.loadAcquire(); if (value == 0) - return 1; //Always return true, because we handle the deleting by ourself using deleteLater + return 1; // Always return true, because we handle the deleting by ourself using deleteLater return value; } - inline bool ref() - { - return m_real.ref.ref(); - } + inline bool ref() { return m_real.ref.ref(); } inline bool deref() { bool ret = m_real.ref.deref(); if (!ret) m_object.deleteLater(); - return true; //Always return true, because we handle the deleting by ourself + return true; // Always return true, because we handle the deleting by ourself } inline int load() const { +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + return m_real.ref.loadRelaxed(); +#else return m_real.ref.load(); +#endif } QObject& m_object; @@ -69,9 +71,9 @@ * * Notice however that the object will not be deleted immediately, which may lead to unintended behavior. */ -struct KSharedObject : public QSharedData -{ - inline explicit KSharedObject(QObject& object) : ref(object, *this) +struct KSharedObject : public QSharedData { + inline explicit KSharedObject(QObject& object) + : ref(object, *this) { }