From 27e343b970a7cf6ea64bcb189a7e3e8ea817913b Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 30 Jul 2014 17:37:17 +0200 Subject: [PATCH] CppTools: Extract BaseEditorDocumentParser out of SnapshotUpdater Change-Id: If89e81eec6d600d3d39cc09203cf434d0768c1b4 Reviewed-by: Erik Verbruggen --- .../cppeditor/cppcodemodelinspectordialog.cpp | 2 +- .../cpptools/baseeditordocumentparser.cpp | 143 ++++++++++++++++++ .../cpptools/baseeditordocumentparser.h | 83 ++++++++++ src/plugins/cpptools/cppsnapshotupdater.cpp | 111 +++----------- src/plugins/cpptools/cppsnapshotupdater.h | 30 +--- src/plugins/cpptools/cpptools.pro | 2 + src/plugins/cpptools/cpptools.qbs | 1 + .../cpptools/cpptoolseditorsupport.cpp | 6 +- 8 files changed, 266 insertions(+), 112 deletions(-) create mode 100644 src/plugins/cpptools/baseeditordocumentparser.cpp create mode 100644 src/plugins/cpptools/baseeditordocumentparser.h diff --git a/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp b/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp index c60e8839328..3e6b6b3418a 100644 --- a/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp +++ b/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp @@ -1413,7 +1413,7 @@ void CppCodeModelInspectorDialog::refresh() // Project Parts const ProjectPart::Ptr editorsProjectPart = editorSupport - ? editorSupport->snapshotUpdater()->currentProjectPart() + ? editorSupport->snapshotUpdater()->projectPart() : ProjectPart::Ptr(); const QList projectInfos = cmmi->projectInfos(); diff --git a/src/plugins/cpptools/baseeditordocumentparser.cpp b/src/plugins/cpptools/baseeditordocumentparser.cpp new file mode 100644 index 00000000000..058fae5b993 --- /dev/null +++ b/src/plugins/cpptools/baseeditordocumentparser.cpp @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "baseeditordocumentparser.h" + +namespace CppTools { + +/*! + \class CppTools::BaseEditorDocumentParser + + \brief The BaseEditorDocumentParser class parses a source text as + precisely as possible. + + It's meant to be used in the C++ editor to get precise results by using + the "best" project part for a file. + + Derived classes are expected to implement update() by using the protected + mutex, updateProjectPart() and by respecting the options set by the client. +*/ + +BaseEditorDocumentParser::BaseEditorDocumentParser(const QString &filePath) + : m_mutex(QMutex::Recursive) + , m_filePath(filePath) + , m_usePrecompiledHeaders(false) + , m_editorDefinesChangedSinceLastUpdate(false) +{ +} + +BaseEditorDocumentParser::~BaseEditorDocumentParser() +{ +} + +QString BaseEditorDocumentParser::filePath() const +{ + return m_filePath; +} + +ProjectPart::Ptr BaseEditorDocumentParser::projectPart() const +{ + QMutexLocker locker(&m_mutex); + return m_projectPart; +} + +void BaseEditorDocumentParser::setProjectPart(ProjectPart::Ptr projectPart) +{ + QMutexLocker locker(&m_mutex); + m_manuallySetProjectPart = projectPart; +} + +bool BaseEditorDocumentParser::usePrecompiledHeaders() const +{ + QMutexLocker locker(&m_mutex); + return m_usePrecompiledHeaders; +} + +void BaseEditorDocumentParser::setUsePrecompiledHeaders(bool usePrecompiledHeaders) +{ + QMutexLocker locker(&m_mutex); + m_usePrecompiledHeaders = usePrecompiledHeaders; +} + +QByteArray BaseEditorDocumentParser::editorDefines() const +{ + QMutexLocker locker(&m_mutex); + return m_editorDefines; +} + +void BaseEditorDocumentParser::setEditorDefines(const QByteArray &editorDefines) +{ + QMutexLocker locker(&m_mutex); + + if (editorDefines != m_editorDefines) { + m_editorDefines = editorDefines; + m_editorDefinesChangedSinceLastUpdate = true; + } +} + +void BaseEditorDocumentParser::updateProjectPart() +{ + if (m_manuallySetProjectPart) { + m_projectPart = m_manuallySetProjectPart; + return; + } + + CppModelManagerInterface *cmm = CppModelManagerInterface::instance(); + QList projectParts = cmm->projectPart(m_filePath); + if (projectParts.isEmpty()) { + if (m_projectPart) + // File is not directly part of any project, but we got one before. We will re-use it, + // because re-calculating this can be expensive when the dependency table is big. + return; + + // Fall-back step 1: Get some parts through the dependency table: + projectParts = cmm->projectPartFromDependencies(m_filePath); + if (projectParts.isEmpty()) + // Fall-back step 2: Use fall-back part from the model manager: + m_projectPart = cmm->fallbackProjectPart(); + else + m_projectPart = projectParts.first(); + } else { + if (!projectParts.contains(m_projectPart)) + // Apparently the project file changed, so update our project part. + m_projectPart = projectParts.first(); + } +} + +bool BaseEditorDocumentParser::editorDefinesChanged() const +{ + return m_editorDefinesChangedSinceLastUpdate; +} + +void BaseEditorDocumentParser::resetEditorDefinesChanged() +{ + m_editorDefinesChangedSinceLastUpdate = false; +} + +} // namespace CppTools diff --git a/src/plugins/cpptools/baseeditordocumentparser.h b/src/plugins/cpptools/baseeditordocumentparser.h new file mode 100644 index 00000000000..e62bbae4c6b --- /dev/null +++ b/src/plugins/cpptools/baseeditordocumentparser.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef BASEEDITORDOCUMENTPARSER_H +#define BASEEDITORDOCUMENTPARSER_H + +#include "cppmodelmanagerinterface.h" +#include "cpptools_global.h" + +namespace CppTools { + +class CPPTOOLS_EXPORT BaseEditorDocumentParser +{ + Q_DISABLE_COPY(BaseEditorDocumentParser) + BaseEditorDocumentParser(); + +public: + BaseEditorDocumentParser(const QString &filePath); + virtual ~BaseEditorDocumentParser(); + + QString filePath() const; + + virtual void update(WorkingCopy workingCopy) = 0; + + ProjectPart::Ptr projectPart() const; + void setProjectPart(ProjectPart::Ptr projectPart); + + bool usePrecompiledHeaders() const; + void setUsePrecompiledHeaders(bool usePrecompiledHeaders); + + QByteArray editorDefines() const; + void setEditorDefines(const QByteArray &editorDefines); + +protected: + void updateProjectPart(); + + bool editorDefinesChanged() const; + void resetEditorDefinesChanged(); + +protected: + mutable QMutex m_mutex; + +private: + const QString m_filePath; + + ProjectPart::Ptr m_projectPart; + ProjectPart::Ptr m_manuallySetProjectPart; + + bool m_usePrecompiledHeaders; + + QByteArray m_editorDefines; + bool m_editorDefinesChangedSinceLastUpdate; +}; + +} // namespace CppTools + +#endif // BASEEDITORDOCUMENTPARSER_H diff --git a/src/plugins/cpptools/cppsnapshotupdater.cpp b/src/plugins/cpptools/cppsnapshotupdater.cpp index c6ef0cde258..8883a567f93 100644 --- a/src/plugins/cpptools/cppsnapshotupdater.cpp +++ b/src/plugins/cpptools/cppsnapshotupdater.cpp @@ -36,11 +36,8 @@ using namespace CPlusPlus; using namespace CppTools; using namespace CppTools::Internal; -SnapshotUpdater::SnapshotUpdater(const QString &fileInEditor) - : m_mutex(QMutex::Recursive) - , m_fileInEditor(fileInEditor) - , m_editorDefinesChangedSinceLastUpdate(false) - , m_usePrecompiledHeaders(false) +SnapshotUpdater::SnapshotUpdater(const QString &filePath) + : BaseEditorDocumentParser(filePath) , m_forceSnapshotInvalidation(false) , m_releaseSourceAndAST(true) { @@ -50,10 +47,10 @@ void SnapshotUpdater::update(WorkingCopy workingCopy) { QMutexLocker locker(&m_mutex); - if (m_fileInEditor.isEmpty()) + if (filePath().isEmpty()) return; - bool invalidateSnapshot = false, invalidateConfig = false, editorDefinesChanged = false; + bool invalidateSnapshot = false, invalidateConfig = false, editorDefinesChanged_ = false; CppModelManager *modelManager = dynamic_cast(CppModelManagerInterface::instance()); @@ -69,13 +66,13 @@ void SnapshotUpdater::update(WorkingCopy workingCopy) m_forceSnapshotInvalidation = false; } - if (m_projectPart) { - configFile += m_projectPart->toolchainDefines; - configFile += m_projectPart->projectDefines; - headerPaths = m_projectPart->headerPaths; - projectConfigFile = m_projectPart->projectConfigFile; - if (m_usePrecompiledHeaders) - precompiledHeaders = m_projectPart->precompiledHeaders; + if (const ProjectPart::Ptr part = projectPart()) { + configFile += part->toolchainDefines; + configFile += part->projectDefines; + headerPaths = part->headerPaths; + projectConfigFile = part->projectConfigFile; + if (usePrecompiledHeaders()) + precompiledHeaders = part->precompiledHeaders; } if (configFile != m_configFile) { @@ -84,10 +81,10 @@ void SnapshotUpdater::update(WorkingCopy workingCopy) invalidateConfig = true; } - if (m_editorDefinesChangedSinceLastUpdate) { + if (editorDefinesChanged()) { invalidateSnapshot = true; - editorDefinesChanged = true; - m_editorDefinesChangedSinceLastUpdate = false; + editorDefinesChanged_ = true; + resetEditorDefinesChanged(); } if (headerPaths != m_headerPaths) { @@ -144,18 +141,18 @@ void SnapshotUpdater::update(WorkingCopy workingCopy) m_snapshot.remove(configurationFileName); if (!m_snapshot.contains(configurationFileName)) workingCopy.insert(configurationFileName, m_configFile); - m_snapshot.remove(m_fileInEditor); + m_snapshot.remove(filePath()); static const QString editorDefinesFileName = CppModelManagerInterface::editorConfigurationFileName(); - if (editorDefinesChanged) { + if (editorDefinesChanged_) { m_snapshot.remove(editorDefinesFileName); - workingCopy.insert(editorDefinesFileName, m_editorDefines); + workingCopy.insert(editorDefinesFileName, editorDefines()); } CppSourceProcessor sourceProcessor(m_snapshot, [&](const Document::Ptr &doc) { const QString fileName = doc->fileName(); - const bool isInEditor = fileName == fileInEditor(); + const bool isInEditor = fileName == filePath(); Document::Ptr otherDoc = modelManager->document(fileName); unsigned newRev = otherDoc.isNull() ? 1U : otherDoc->revision() + 1; if (isInEditor) @@ -166,22 +163,21 @@ void SnapshotUpdater::update(WorkingCopy workingCopy) doc->releaseSourceAndAST(); }); Snapshot globalSnapshot = modelManager->snapshot(); - globalSnapshot.remove(fileInEditor()); + globalSnapshot.remove(filePath()); sourceProcessor.setGlobalSnapshot(globalSnapshot); sourceProcessor.setWorkingCopy(workingCopy); sourceProcessor.setHeaderPaths(m_headerPaths); sourceProcessor.run(configurationFileName); if (!m_projectConfigFile.isEmpty()) sourceProcessor.run(m_projectConfigFile); - if (m_usePrecompiledHeaders) { + if (usePrecompiledHeaders()) { foreach (const QString &precompiledHeader, m_precompiledHeaders) sourceProcessor.run(precompiledHeader); } - if (!m_editorDefines.isEmpty()) + if (!editorDefines().isEmpty()) sourceProcessor.run(editorDefinesFileName); - sourceProcessor.run(m_fileInEditor, m_usePrecompiledHeaders ? m_precompiledHeaders + sourceProcessor.run(filePath(), usePrecompiledHeaders() ? m_precompiledHeaders : QStringList()); - m_snapshot = sourceProcessor.snapshot(); Snapshot newSnapshot = m_snapshot.simplified(document()); for (Snapshot::const_iterator i = m_snapshot.begin(), ei = m_snapshot.end(); i != ei; ++i) { @@ -193,7 +189,7 @@ void SnapshotUpdater::update(WorkingCopy workingCopy) } } -void SnapshotUpdater::releaseSnapshot() +void SnapshotUpdater::releaseResources() { QMutexLocker locker(&m_mutex); m_snapshot = Snapshot(); @@ -204,7 +200,7 @@ void SnapshotUpdater::releaseSnapshot() Document::Ptr SnapshotUpdater::document() const { QMutexLocker locker(&m_mutex); - return m_snapshot.document(m_fileInEditor); + return m_snapshot.document(filePath()); } Snapshot SnapshotUpdater::snapshot() const @@ -219,73 +215,16 @@ ProjectPart::HeaderPaths SnapshotUpdater::headerPaths() const return m_headerPaths; } -ProjectPart::Ptr SnapshotUpdater::currentProjectPart() const -{ - QMutexLocker locker(&m_mutex); - return m_projectPart; -} - -void SnapshotUpdater::setProjectPart(ProjectPart::Ptr projectPart) -{ - QMutexLocker locker(&m_mutex); - m_manuallySetProjectPart = projectPart; -} - -void SnapshotUpdater::setUsePrecompiledHeaders(bool usePrecompiledHeaders) -{ - QMutexLocker locker(&m_mutex); - m_usePrecompiledHeaders = usePrecompiledHeaders; -} - -void SnapshotUpdater::setEditorDefines(const QByteArray &editorDefines) -{ - QMutexLocker locker(&m_mutex); - - if (editorDefines != m_editorDefines) { - m_editorDefines = editorDefines; - m_editorDefinesChangedSinceLastUpdate = true; - } -} - void SnapshotUpdater::setReleaseSourceAndAST(bool onoff) { QMutexLocker locker(&m_mutex); m_releaseSourceAndAST = onoff; } -void SnapshotUpdater::updateProjectPart() -{ - if (m_manuallySetProjectPart) { - m_projectPart = m_manuallySetProjectPart; - return; - } - - CppModelManager *cmm = dynamic_cast(CppModelManagerInterface::instance()); - QList pParts = cmm->projectPart(m_fileInEditor); - if (pParts.isEmpty()) { - if (m_projectPart) - // File is not directly part of any project, but we got one before. We will re-use it, - // because re-calculating this can be expensive when the dependency table is big. - return; - - // Fall-back step 1: Get some parts through the dependency table: - pParts = cmm->projectPartFromDependencies(m_fileInEditor); - if (pParts.isEmpty()) - // Fall-back step 2: Use fall-back part from the model manager: - m_projectPart = cmm->fallbackProjectPart(); - else - m_projectPart = pParts.first(); - } else { - if (!pParts.contains(m_projectPart)) - // Apparently the project file changed, so update our project part. - m_projectPart = pParts.first(); - } -} - void SnapshotUpdater::addFileAndDependencies(QSet *toRemove, const QString &fileName) const { toRemove->insert(fileName); - if (fileName != m_fileInEditor) { + if (fileName != filePath()) { QStringList deps = m_deps.filesDependingOn(fileName); toRemove->unite(QSet::fromList(deps)); } diff --git a/src/plugins/cpptools/cppsnapshotupdater.h b/src/plugins/cpptools/cppsnapshotupdater.h index b4009de0ab5..1b360c34708 100644 --- a/src/plugins/cpptools/cppsnapshotupdater.h +++ b/src/plugins/cpptools/cppsnapshotupdater.h @@ -30,59 +30,45 @@ #ifndef CPPTOOLS_INTERNAL_SNAPSHOTUPDATER_H #define CPPTOOLS_INTERNAL_SNAPSHOTUPDATER_H +#include "baseeditordocumentparser.h" #include "cpptools_global.h" #include "cppmodelmanager.h" #include #include +#include #include #include namespace CppTools { -class CPPTOOLS_EXPORT SnapshotUpdater +class CPPTOOLS_EXPORT SnapshotUpdater : public BaseEditorDocumentParser { - Q_DISABLE_COPY(SnapshotUpdater) - public: - SnapshotUpdater(const QString &fileInEditor = QString()); + SnapshotUpdater(const QString &filePath); - QString fileInEditor() const - { return m_fileInEditor; } - - void update(WorkingCopy workingCopy); - void releaseSnapshot(); + void update(WorkingCopy workingCopy) QTC_OVERRIDE; + void releaseResources(); CPlusPlus::Document::Ptr document() const; CPlusPlus::Snapshot snapshot() const; ProjectPart::HeaderPaths headerPaths() const; - ProjectPart::Ptr currentProjectPart() const; - void setProjectPart(ProjectPart::Ptr projectPart); - - void setUsePrecompiledHeaders(bool usePrecompiledHeaders); - void setEditorDefines(const QByteArray &editorDefines); - void setReleaseSourceAndAST(bool onoff); private: - void updateProjectPart(); void addFileAndDependencies(QSet *toRemove, const QString &fileName) const; private: - mutable QMutex m_mutex; - const QString m_fileInEditor; - ProjectPart::Ptr m_projectPart, m_manuallySetProjectPart; QByteArray m_configFile; - bool m_editorDefinesChangedSinceLastUpdate; - QByteArray m_editorDefines; + ProjectPart::HeaderPaths m_headerPaths; QString m_projectConfigFile; QStringList m_precompiledHeaders; + CPlusPlus::Snapshot m_snapshot; CPlusPlus::DependencyTable m_deps; - bool m_usePrecompiledHeaders; bool m_forceSnapshotInvalidation; bool m_releaseSourceAndAST; }; diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro index cb34c770838..b5be6344851 100644 --- a/src/plugins/cpptools/cpptools.pro +++ b/src/plugins/cpptools/cpptools.pro @@ -4,6 +4,7 @@ include(../../qtcreatorplugin.pri) HEADERS += \ abstracteditorsupport.h \ + baseeditordocumentparser.h \ builtinindexingsupport.h \ commentssettings.h \ completionsettingspage.h \ @@ -62,6 +63,7 @@ HEADERS += \ SOURCES += \ abstracteditorsupport.cpp \ + baseeditordocumentparser.cpp \ builtinindexingsupport.cpp \ commentssettings.cpp \ completionsettingspage.cpp \ diff --git a/src/plugins/cpptools/cpptools.qbs b/src/plugins/cpptools/cpptools.qbs index 5635be318ad..081160dd7a2 100644 --- a/src/plugins/cpptools/cpptools.qbs +++ b/src/plugins/cpptools/cpptools.qbs @@ -24,6 +24,7 @@ QtcPlugin { files: [ "abstracteditorsupport.cpp", "abstracteditorsupport.h", + "baseeditordocumentparser.cpp", "baseeditordocumentparser.h", "builtinindexingsupport.cpp", "builtinindexingsupport.h", "commentssettings.cpp", "commentssettings.h", "completionsettingspage.cpp", "completionsettingspage.h", "completionsettingspage.ui", diff --git a/src/plugins/cpptools/cpptoolseditorsupport.cpp b/src/plugins/cpptools/cpptoolseditorsupport.cpp index 123f93da1b3..9ebc61e955e 100644 --- a/src/plugins/cpptools/cpptoolseditorsupport.cpp +++ b/src/plugins/cpptools/cpptoolseditorsupport.cpp @@ -262,7 +262,7 @@ CppCompletionAssistProvider *CppEditorSupport::completionAssistProvider() const QSharedPointer CppEditorSupport::snapshotUpdater() { QSharedPointer updater = snapshotUpdater_internal(); - if (!updater || updater->fileInEditor() != fileName()) { + if (!updater || updater->filePath() != fileName()) { updater = QSharedPointer(new SnapshotUpdater(fileName())); setSnapshotUpdater_internal(updater); @@ -293,7 +293,7 @@ static void parse(QFutureInterface &future, QSharedPointer(CppModelManager::instance()); updater->update(workingCopy); - cmm->finishedRefreshingSourceFiles(QStringList(updater->fileInEditor())); + cmm->finishedRefreshingSourceFiles(QStringList(updater->filePath())); future.setProgressValue(1); } @@ -488,7 +488,7 @@ void CppEditorSupport::releaseResources() { m_highlighter.cancel(); m_highlighter = QFuture(); - snapshotUpdater()->releaseSnapshot(); + snapshotUpdater()->releaseResources(); setSemanticInfo(SemanticInfo(), /*emitSignal=*/ false); m_lastHighlightOnCompleteSemanticInfo = true; }