Commit 27e343b9 authored by Nikolai Kosjar's avatar Nikolai Kosjar Committed by Erik Verbruggen

CppTools: Extract BaseEditorDocumentParser out of SnapshotUpdater

Change-Id: If89e81eec6d600d3d39cc09203cf434d0768c1b4
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@digia.com>
parent 6b5298fa
......@@ -1413,7 +1413,7 @@ void CppCodeModelInspectorDialog::refresh()
// Project Parts
const ProjectPart::Ptr editorsProjectPart = editorSupport
? editorSupport->snapshotUpdater()->currentProjectPart()
? editorSupport->snapshotUpdater()->projectPart()
: ProjectPart::Ptr();
const QList<ProjectInfo> projectInfos = cmmi->projectInfos();
......
/****************************************************************************
**
** 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<ProjectPart::Ptr> 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
/****************************************************************************
**
** 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
......@@ -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<CppModelManager *>(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<CppModelManager *>(CppModelManagerInterface::instance());
QList<ProjectPart::Ptr> 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<QString> *toRemove, const QString &fileName) const
{
toRemove->insert(fileName);
if (fileName != m_fileInEditor) {
if (fileName != filePath()) {
QStringList deps = m_deps.filesDependingOn(fileName);
toRemove->unite(QSet<QString>::fromList(deps));
}
......
......@@ -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 <cplusplus/CppDocument.h>
#include <cplusplus/DependencyTable.h>
#include <utils/qtcoverride.h>
#include <QMutex>
#include <QString>
namespace CppTools {
class CPPTOOLS_EXPORT SnapshotUpdater
class CPPTOOLS_EXPORT SnapshotUpdater : public BaseEditorDocumentParser
{
Q_DISABLE_COPY(SnapshotUpdater)
public:
SnapshotUpdater(const QString &fileInEditor = QString());
QString fileInEditor() const
{ return m_fileInEditor; }
SnapshotUpdater(const QString &filePath);
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<QString> *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;
};
......
......@@ -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 \
......
......@@ -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",
......
......@@ -262,7 +262,7 @@ CppCompletionAssistProvider *CppEditorSupport::completionAssistProvider() const
QSharedPointer<SnapshotUpdater> CppEditorSupport::snapshotUpdater()
{
QSharedPointer<SnapshotUpdater> updater = snapshotUpdater_internal();
if (!updater || updater->fileInEditor() != fileName()) {
if (!updater || updater->filePath() != fileName()) {
updater = QSharedPointer<SnapshotUpdater>(new SnapshotUpdater(fileName()));
setSnapshotUpdater_internal(updater);
......@@ -293,7 +293,7 @@ static void parse(QFutureInterface<void> &future, QSharedPointer<SnapshotUpdater
CppModelManager *cmm = qobject_cast<CppModelManager *>(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<TextEditor::HighlightingResult>();
snapshotUpdater()->releaseSnapshot();
snapshotUpdater()->releaseResources();
setSemanticInfo(SemanticInfo(), /*emitSignal=*/ false);
m_lastHighlightOnCompleteSemanticInfo = true;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment