Merge remote-tracking branch 'origin/3.5'

Conflicts:
	scripts/deployqtHelper_mac.sh

Change-Id: Ia0d5fef8c28e0bfb3b0c703ad3652e2d70d9e7d1
This commit is contained in:
Oswald Buddenhagen
2015-07-17 17:25:26 +02:00
133 changed files with 1755 additions and 1198 deletions

View File

@@ -31,6 +31,7 @@
#include "baseeditordocumentparser.h"
#include "baseeditordocumentprocessor.h"
#include "cpptoolsreuse.h"
#include "editordocumenthandle.h"
namespace CppTools {
@@ -44,15 +45,18 @@ namespace CppTools {
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.
Derived classes are expected to implement updateHelper() this way:
\list
\li Get a copy of the configuration and the last state.
\li Work on the data and do whatever is necessary. At least, update
the project part with the help of determineProjectPart().
\li Ensure the new state is set before updateHelper() returns.
\endlist
*/
BaseEditorDocumentParser::BaseEditorDocumentParser(const QString &filePath)
: m_mutex(QMutex::Recursive)
, m_filePath(filePath)
, m_usePrecompiledHeaders(false)
, m_editorDefinesChangedSinceLastUpdate(false)
: m_filePath(filePath)
{
}
@@ -65,44 +69,39 @@ QString BaseEditorDocumentParser::filePath() const
return m_filePath;
}
BaseEditorDocumentParser::Configuration BaseEditorDocumentParser::configuration() const
{
QMutexLocker locker(&m_stateAndConfigurationMutex);
return m_configuration;
}
void BaseEditorDocumentParser::setConfiguration(const Configuration &configuration)
{
QMutexLocker locker(&m_stateAndConfigurationMutex);
m_configuration = configuration;
}
void BaseEditorDocumentParser::update(const InMemoryInfo &info)
{
QMutexLocker locker(&m_updateIsRunning);
updateHelper(info);
}
BaseEditorDocumentParser::State BaseEditorDocumentParser::state() const
{
QMutexLocker locker(&m_stateAndConfigurationMutex);
return m_state;
}
void BaseEditorDocumentParser::setState(const State &state)
{
QMutexLocker locker(&m_stateAndConfigurationMutex);
m_state = state;
}
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;
}
return state().projectPart;
}
BaseEditorDocumentParser *BaseEditorDocumentParser::get(const QString &filePath)
@@ -115,43 +114,44 @@ BaseEditorDocumentParser *BaseEditorDocumentParser::get(const QString &filePath)
return 0;
}
void BaseEditorDocumentParser::updateProjectPart()
ProjectPart::Ptr BaseEditorDocumentParser::determineProjectPart(const QString &filePath,
const Configuration &config,
const State &state)
{
if (m_manuallySetProjectPart) {
m_projectPart = m_manuallySetProjectPart;
return;
}
if (config.manuallySetProjectPart)
return config.manuallySetProjectPart;
ProjectPart::Ptr projectPart = state.projectPart;
CppModelManager *cmm = CppModelManager::instance();
QList<ProjectPart::Ptr> projectParts = cmm->projectPart(m_filePath);
QList<ProjectPart::Ptr> projectParts = cmm->projectPart(filePath);
if (projectParts.isEmpty()) {
if (m_projectPart)
if (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;
return projectPart;
// Fall-back step 1: Get some parts through the dependency table:
projectParts = cmm->projectPartFromDependencies(Utils::FileName::fromString(m_filePath));
projectParts = cmm->projectPartFromDependencies(Utils::FileName::fromString(filePath));
if (projectParts.isEmpty())
// Fall-back step 2: Use fall-back part from the model manager:
m_projectPart = cmm->fallbackProjectPart();
projectPart = cmm->fallbackProjectPart();
else
m_projectPart = projectParts.first();
projectPart = projectParts.first();
} else {
if (!projectParts.contains(m_projectPart))
if (!projectParts.contains(projectPart))
// Apparently the project file changed, so update our project part.
m_projectPart = projectParts.first();
projectPart = projectParts.first();
}
return projectPart;
}
bool BaseEditorDocumentParser::editorDefinesChanged() const
BaseEditorDocumentParser::InMemoryInfo::InMemoryInfo(bool withModifiedFiles)
: workingCopy(CppTools::CppModelManager::instance()->workingCopy())
{
return m_editorDefinesChangedSinceLastUpdate;
}
void BaseEditorDocumentParser::resetEditorDefinesChanged()
{
m_editorDefinesChangedSinceLastUpdate = false;
if (withModifiedFiles)
modifiedFiles = CppTools::modifiedFiles();
}
} // namespace CppTools

View File

@@ -33,6 +33,7 @@
#include "cppmodelmanager.h"
#include "cpptools_global.h"
#include "cppworkingcopy.h"
#include <QObject>
@@ -42,45 +43,54 @@ class CPPTOOLS_EXPORT BaseEditorDocumentParser : public QObject
{
Q_OBJECT
public:
static BaseEditorDocumentParser *get(const QString &filePath);
struct Configuration {
bool usePrecompiledHeaders = false;
QByteArray editorDefines;
ProjectPart::Ptr manuallySetProjectPart;
};
public:
BaseEditorDocumentParser(const QString &filePath);
virtual ~BaseEditorDocumentParser();
QString filePath() const;
Configuration configuration() const;
void setConfiguration(const Configuration &configuration);
virtual void update(WorkingCopy workingCopy) = 0;
struct CPPTOOLS_EXPORT InMemoryInfo {
InMemoryInfo(bool withModifiedFiles);
WorkingCopy workingCopy;
Utils::FileNameList modifiedFiles;
};
void update(const InMemoryInfo &info);
ProjectPart::Ptr projectPart() const;
void setProjectPart(ProjectPart::Ptr projectPart);
bool usePrecompiledHeaders() const;
void setUsePrecompiledHeaders(bool usePrecompiledHeaders);
QByteArray editorDefines() const;
void setEditorDefines(const QByteArray &editorDefines);
public:
static BaseEditorDocumentParser *get(const QString &filePath);
protected:
void updateProjectPart();
struct State {
QByteArray editorDefines;
ProjectPart::Ptr projectPart;
};
State state() const;
void setState(const State &state);
bool editorDefinesChanged() const;
void resetEditorDefinesChanged();
static ProjectPart::Ptr determineProjectPart(const QString &filePath,
const Configuration &config,
const State &state);
protected:
mutable QMutex m_mutex;
mutable QMutex m_stateAndConfigurationMutex;
private:
virtual void updateHelper(const InMemoryInfo &inMemoryInfo) = 0;
const QString m_filePath;
ProjectPart::Ptr m_projectPart;
ProjectPart::Ptr m_manuallySetProjectPart;
bool m_usePrecompiledHeaders;
QByteArray m_editorDefines;
bool m_editorDefinesChangedSinceLastUpdate;
Configuration m_configuration;
State m_state;
mutable QMutex m_updateIsRunning;
};
} // namespace CppTools

View File

@@ -31,6 +31,7 @@
#include "baseeditordocumentprocessor.h"
#include "cppworkingcopy.h"
#include "cpptoolsreuse.h"
#include "editordocumenthandle.h"
#include <utils/qtcassert.h>
@@ -118,7 +119,7 @@ QList<QTextEdit::ExtraSelection> BaseEditorDocumentProcessor::toTextEditorSelect
void BaseEditorDocumentProcessor::runParser(QFutureInterface<void> &future,
BaseEditorDocumentParser *parser,
WorkingCopy workingCopy)
BaseEditorDocumentParser::InMemoryInfo info)
{
future.setProgressRange(0, 1);
if (future.isCanceled()) {
@@ -126,7 +127,7 @@ void BaseEditorDocumentProcessor::runParser(QFutureInterface<void> &future,
return;
}
parser->update(workingCopy);
parser->update(info);
CppModelManager::instance()
->finishedRefreshingSourceFiles(QSet<QString>() << parser->filePath());

View File

@@ -86,7 +86,7 @@ protected:
static void runParser(QFutureInterface<void> &future,
CppTools::BaseEditorDocumentParser *parser,
CppTools::WorkingCopy workingCopy);
BaseEditorDocumentParser::InMemoryInfo info);
// Convenience
QString filePath() const { return m_baseTextDocument->filePath().toString(); }

View File

@@ -40,19 +40,22 @@ using namespace CppTools::Internal;
BuiltinEditorDocumentParser::BuiltinEditorDocumentParser(const QString &filePath)
: BaseEditorDocumentParser(filePath)
, m_forceSnapshotInvalidation(false)
, m_releaseSourceAndAST(true)
{
qRegisterMetaType<CPlusPlus::Snapshot>("CPlusPlus::Snapshot");
}
void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
void BuiltinEditorDocumentParser::updateHelper(const InMemoryInfo &info)
{
QMutexLocker locker(&m_mutex);
if (filePath().isEmpty())
return;
const Configuration baseConfig = configuration();
const bool releaseSourceAndAST_ = releaseSourceAndAST();
State baseState = state();
ExtraState state = extraState();
WorkingCopy workingCopy = info.workingCopy;
bool invalidateSnapshot = false, invalidateConfig = false, editorDefinesChanged_ = false;
CppModelManager *modelManager = CppModelManager::instance();
@@ -62,52 +65,52 @@ void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
QString projectConfigFile;
LanguageFeatures features = LanguageFeatures::defaultFeatures();
updateProjectPart();
baseState.projectPart = determineProjectPart(filePath(), baseConfig, baseState);
if (m_forceSnapshotInvalidation) {
if (state.forceSnapshotInvalidation) {
invalidateSnapshot = true;
m_forceSnapshotInvalidation = false;
state.forceSnapshotInvalidation = false;
}
if (const ProjectPart::Ptr part = projectPart()) {
if (const ProjectPart::Ptr part = baseState.projectPart) {
configFile += part->toolchainDefines;
configFile += part->projectDefines;
headerPaths = part->headerPaths;
projectConfigFile = part->projectConfigFile;
if (usePrecompiledHeaders())
if (baseConfig.usePrecompiledHeaders)
precompiledHeaders = part->precompiledHeaders;
features = part->languageFeatures;
}
if (configFile != m_configFile) {
m_configFile = configFile;
if (configFile != state.configFile) {
state.configFile = configFile;
invalidateSnapshot = true;
invalidateConfig = true;
}
if (editorDefinesChanged()) {
if (baseConfig.editorDefines != baseState.editorDefines) {
baseState.editorDefines = baseConfig.editorDefines;
invalidateSnapshot = true;
editorDefinesChanged_ = true;
resetEditorDefinesChanged();
}
if (headerPaths != m_headerPaths) {
m_headerPaths = headerPaths;
if (headerPaths != state.headerPaths) {
state.headerPaths = headerPaths;
invalidateSnapshot = true;
}
if (projectConfigFile != m_projectConfigFile) {
m_projectConfigFile = projectConfigFile;
if (projectConfigFile != state.projectConfigFile) {
state.projectConfigFile = projectConfigFile;
invalidateSnapshot = true;
}
if (precompiledHeaders != m_precompiledHeaders) {
m_precompiledHeaders = precompiledHeaders;
if (precompiledHeaders != state.precompiledHeaders) {
state.precompiledHeaders = precompiledHeaders;
invalidateSnapshot = true;
}
unsigned rev = 0;
if (Document::Ptr doc = document())
if (Document::Ptr doc = state.snapshot.document(filePath()))
rev = doc->revision();
else
invalidateSnapshot = true;
@@ -115,26 +118,26 @@ void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
Snapshot globalSnapshot = modelManager->snapshot();
if (invalidateSnapshot) {
m_snapshot = Snapshot();
state.snapshot = Snapshot();
} else {
// Remove changed files from the snapshot
QSet<Utils::FileName> toRemove;
foreach (const Document::Ptr &doc, m_snapshot) {
foreach (const Document::Ptr &doc, state.snapshot) {
const Utils::FileName fileName = Utils::FileName::fromString(doc->fileName());
if (workingCopy.contains(fileName)) {
if (workingCopy.get(fileName).second != doc->editorRevision())
addFileAndDependencies(&toRemove, fileName);
addFileAndDependencies(&state.snapshot, &toRemove, fileName);
continue;
}
Document::Ptr otherDoc = globalSnapshot.document(fileName);
if (!otherDoc.isNull() && otherDoc->revision() != doc->revision())
addFileAndDependencies(&toRemove, fileName);
addFileAndDependencies(&state.snapshot, &toRemove, fileName);
}
if (!toRemove.isEmpty()) {
invalidateSnapshot = true;
foreach (const Utils::FileName &fileName, toRemove)
m_snapshot.remove(fileName);
state.snapshot.remove(fileName);
}
}
@@ -142,19 +145,19 @@ void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
if (invalidateSnapshot) {
const QString configurationFileName = modelManager->configurationFileName();
if (invalidateConfig)
m_snapshot.remove(configurationFileName);
if (!m_snapshot.contains(configurationFileName))
workingCopy.insert(configurationFileName, m_configFile);
m_snapshot.remove(filePath());
state.snapshot.remove(configurationFileName);
if (!state.snapshot.contains(configurationFileName))
workingCopy.insert(configurationFileName, state.configFile);
state.snapshot.remove(filePath());
static const QString editorDefinesFileName
= CppModelManager::editorConfigurationFileName();
if (editorDefinesChanged_) {
m_snapshot.remove(editorDefinesFileName);
workingCopy.insert(editorDefinesFileName, editorDefines());
state.snapshot.remove(editorDefinesFileName);
workingCopy.insert(editorDefinesFileName, baseState.editorDefines);
}
CppSourceProcessor sourceProcessor(m_snapshot, [&](const Document::Ptr &doc) {
CppSourceProcessor sourceProcessor(state.snapshot, [&](const Document::Ptr &doc) {
const QString fileName = doc->fileName();
const bool isInEditor = fileName == filePath();
Document::Ptr otherDoc = modelManager->document(fileName);
@@ -163,68 +166,64 @@ void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
newRev = qMax(rev + 1, newRev);
doc->setRevision(newRev);
modelManager->emitDocumentUpdated(doc);
if (m_releaseSourceAndAST)
if (releaseSourceAndAST_)
doc->releaseSourceAndAST();
});
Snapshot globalSnapshot = modelManager->snapshot();
globalSnapshot.remove(filePath());
sourceProcessor.setGlobalSnapshot(globalSnapshot);
sourceProcessor.setWorkingCopy(workingCopy);
sourceProcessor.setHeaderPaths(m_headerPaths);
sourceProcessor.setHeaderPaths(state.headerPaths);
sourceProcessor.setLanguageFeatures(features);
sourceProcessor.run(configurationFileName);
if (!m_projectConfigFile.isEmpty())
sourceProcessor.run(m_projectConfigFile);
if (usePrecompiledHeaders()) {
foreach (const QString &precompiledHeader, m_precompiledHeaders)
if (!state.projectConfigFile.isEmpty())
sourceProcessor.run(state.projectConfigFile);
if (baseConfig.usePrecompiledHeaders) {
foreach (const QString &precompiledHeader, state.precompiledHeaders)
sourceProcessor.run(precompiledHeader);
}
if (!editorDefines().isEmpty())
if (!baseState.editorDefines.isEmpty())
sourceProcessor.run(editorDefinesFileName);
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) {
sourceProcessor.run(filePath(), baseConfig.usePrecompiledHeaders ? state.precompiledHeaders
: QStringList());
state.snapshot = sourceProcessor.snapshot();
Snapshot newSnapshot = state.snapshot.simplified(state.snapshot.document(filePath()));
for (Snapshot::const_iterator i = state.snapshot.begin(), ei = state.snapshot.end(); i != ei; ++i) {
if (Client::isInjectedFile(i.key().toString()))
newSnapshot.insert(i.value());
}
m_snapshot = newSnapshot;
m_snapshot.updateDependencyTable();
emit finished(document(), m_snapshot);
state.snapshot = newSnapshot;
state.snapshot.updateDependencyTable();
}
setState(baseState);
setExtraState(state);
if (invalidateSnapshot)
emit finished(state.snapshot.document(filePath()), state.snapshot);
}
void BuiltinEditorDocumentParser::releaseResources()
{
QMutexLocker locker(&m_mutex);
m_snapshot = Snapshot();
m_forceSnapshotInvalidation = true;
ExtraState s = extraState();
s.snapshot = Snapshot();
s.forceSnapshotInvalidation = true;
setExtraState(s);
}
Document::Ptr BuiltinEditorDocumentParser::document() const
{
QMutexLocker locker(&m_mutex);
return m_snapshot.document(filePath());
return extraState().snapshot.document(filePath());
}
Snapshot BuiltinEditorDocumentParser::snapshot() const
{
QMutexLocker locker(&m_mutex);
return m_snapshot;
return extraState().snapshot;
}
ProjectPart::HeaderPaths BuiltinEditorDocumentParser::headerPaths() const
{
QMutexLocker locker(&m_mutex);
return m_headerPaths;
}
void BuiltinEditorDocumentParser::setReleaseSourceAndAST(bool onoff)
{
QMutexLocker locker(&m_mutex);
m_releaseSourceAndAST = onoff;
return extraState().headerPaths;
}
BuiltinEditorDocumentParser *BuiltinEditorDocumentParser::get(const QString &filePath)
@@ -234,12 +233,39 @@ BuiltinEditorDocumentParser *BuiltinEditorDocumentParser::get(const QString &fil
return 0;
}
void BuiltinEditorDocumentParser::addFileAndDependencies(QSet<Utils::FileName> *toRemove,
void BuiltinEditorDocumentParser::addFileAndDependencies(Snapshot *snapshot,
QSet<Utils::FileName> *toRemove,
const Utils::FileName &fileName) const
{
QTC_ASSERT(snapshot, return);
toRemove->insert(fileName);
if (fileName != Utils::FileName::fromString(filePath())) {
Utils::FileNameList deps = m_snapshot.filesDependingOn(fileName);
Utils::FileNameList deps = snapshot->filesDependingOn(fileName);
toRemove->unite(QSet<Utils::FileName>::fromList(deps));
}
}
BuiltinEditorDocumentParser::ExtraState BuiltinEditorDocumentParser::extraState() const
{
QMutexLocker locker(&m_stateAndConfigurationMutex);
return m_extraState;
}
void BuiltinEditorDocumentParser::setExtraState(const ExtraState &extraState)
{
QMutexLocker locker(&m_stateAndConfigurationMutex);
m_extraState = extraState;
}
bool BuiltinEditorDocumentParser::releaseSourceAndAST() const
{
QMutexLocker locker(&m_stateAndConfigurationMutex);
return m_releaseSourceAndAST;
}
void BuiltinEditorDocumentParser::setReleaseSourceAndAST(bool release)
{
QMutexLocker locker(&m_stateAndConfigurationMutex);
m_releaseSourceAndAST = release;
}

View File

@@ -37,7 +37,6 @@
#include <cplusplus/CppDocument.h>
#include <QMutex>
#include <QString>
namespace CppTools {
@@ -49,14 +48,14 @@ class CPPTOOLS_EXPORT BuiltinEditorDocumentParser : public BaseEditorDocumentPar
public:
BuiltinEditorDocumentParser(const QString &filePath);
void update(WorkingCopy workingCopy) override;
void releaseResources();
bool releaseSourceAndAST() const;
void setReleaseSourceAndAST(bool release);
CPlusPlus::Document::Ptr document() const;
CPlusPlus::Snapshot snapshot() const;
ProjectPart::HeaderPaths headerPaths() const;
void setReleaseSourceAndAST(bool onoff);
void releaseResources();
signals:
void finished(CPlusPlus::Document::Ptr document, CPlusPlus::Snapshot snapshot);
@@ -65,18 +64,26 @@ public:
static BuiltinEditorDocumentParser *get(const QString &filePath);
private:
void addFileAndDependencies(QSet<Utils::FileName> *toRemove, const Utils::FileName &fileName) const;
void updateHelper(const InMemoryInfo &info) override;
void addFileAndDependencies(CPlusPlus::Snapshot *snapshot,
QSet<Utils::FileName> *toRemove,
const Utils::FileName &fileName) const;
private:
QByteArray m_configFile;
struct ExtraState {
QByteArray configFile;
ProjectPart::HeaderPaths m_headerPaths;
QString m_projectConfigFile;
QStringList m_precompiledHeaders;
ProjectPart::HeaderPaths headerPaths;
QString projectConfigFile;
QStringList precompiledHeaders;
CPlusPlus::Snapshot m_snapshot;
bool m_forceSnapshotInvalidation;
bool m_releaseSourceAndAST;
CPlusPlus::Snapshot snapshot;
bool forceSnapshotInvalidation = false;
};
ExtraState extraState() const;
void setExtraState(const ExtraState &extraState);
bool m_releaseSourceAndAST = true;
ExtraState m_extraState;
};
} // namespace CppTools

View File

@@ -43,8 +43,8 @@
#include <cplusplus/CppDocument.h>
#include <cplusplus/SimpleLexer.h>
#include <utils/QtConcurrentTools>
#include <utils/qtcassert.h>
#include <utils/runextensions.h>
#include <QLoggingCategory>
@@ -134,7 +134,10 @@ BuiltinEditorDocumentProcessor::BuiltinEditorDocumentProcessor(
using namespace Internal;
QSharedPointer<CppCodeModelSettings> cms = CppToolsPlugin::instance()->codeModelSettings();
m_parser.setUsePrecompiledHeaders(cms->pchUsage() != CppCodeModelSettings::PchUse_None);
BaseEditorDocumentParser::Configuration config = m_parser.configuration();
config.usePrecompiledHeaders = cms->pchUsage() != CppCodeModelSettings::PchUse_None;
m_parser.setConfiguration(config);
if (m_semanticHighlighter) {
m_semanticHighlighter->setHighlightingRunner(
@@ -163,7 +166,9 @@ BuiltinEditorDocumentProcessor::~BuiltinEditorDocumentProcessor()
void BuiltinEditorDocumentProcessor::run()
{
m_parserFuture = QtConcurrent::run(&runParser, parser(), CppTools::CppModelManager::instance()->workingCopy());
m_parserFuture = QtConcurrent::run(&runParser,
parser(),
BuiltinEditorDocumentParser::InMemoryInfo(false));
}
BaseEditorDocumentParser *BuiltinEditorDocumentProcessor::parser()

View File

@@ -162,7 +162,7 @@ void indexFindErrors(QFutureInterface<void> &future, const ParseParams params)
// Parse the file as precisely as possible
BuiltinEditorDocumentParser parser(file);
parser.setReleaseSourceAndAST(false);
parser.update(params.workingCopy);
parser.update(BuiltinEditorDocumentParser::InMemoryInfo(false));
CPlusPlus::Document::Ptr document = parser.document();
QTC_ASSERT(document, return);

View File

@@ -2188,7 +2188,7 @@ void CppCompletionAssistInterface::getCppSpecifics() const
m_gotCppSpecifics = true;
if (BuiltinEditorDocumentParser *parser = BuiltinEditorDocumentParser::get(fileName())) {
parser->update(m_workingCopy);
parser->update(BuiltinEditorDocumentParser::InMemoryInfo(false));
m_snapshot = parser->snapshot();
m_headerPaths = parser->headerPaths();
if (Document::Ptr document = parser->document())

View File

@@ -167,13 +167,11 @@ private:
const QString &m_filePath;
};
void waitForProcessedEditorDocument(const QString &filePath)
ProjectPart::Ptr projectPartOfEditorDocument(const QString &filePath)
{
CppEditorDocumentHandle *editorDocument
= CppModelManager::instance()->cppEditorDocument(filePath);
QVERIFY(editorDocument);
while (editorDocument->processor()->isParserRunning())
QCoreApplication::processEvents();
auto *editorDocument = CppModelManager::instance()->cppEditorDocument(filePath);
QTC_ASSERT(editorDocument, return ProjectPart::Ptr());
return editorDocument->processor()->parser()->projectPart();
}
} // anonymous namespace
@@ -914,8 +912,10 @@ void CppToolsPlugin::test_modelmanager_precompiled_headers()
auto *parser = BuiltinEditorDocumentParser::get(fileName);
QVERIFY(parser);
parser->setUsePrecompiledHeaders(true);
parser->update(mm->workingCopy());
BaseEditorDocumentParser::Configuration config = parser->configuration();
config.usePrecompiledHeaders = true;
parser->setConfiguration(config);
parser->update(BuiltinEditorDocumentParser::InMemoryInfo(false));
// Check if defines from pch are considered
Document::Ptr document = mm->document(fileName);
@@ -995,8 +995,10 @@ void CppToolsPlugin::test_modelmanager_defines_per_editor()
const QString filePath = editor->document()->filePath().toString();
BaseEditorDocumentParser *parser = BaseEditorDocumentParser::get(filePath);
parser->setEditorDefines(editorDefines.toUtf8());
parser->update(mm->workingCopy());
BaseEditorDocumentParser::Configuration config = parser->configuration();
config.editorDefines = editorDefines.toUtf8();
parser->setConfiguration(config);
parser->update(BuiltinEditorDocumentParser::InMemoryInfo(false));
Document::Ptr doc = mm->document(main1File);
QCOMPARE(nameOfFirstDeclaration(doc), firstDeclarationName);
@@ -1006,7 +1008,6 @@ void CppToolsPlugin::test_modelmanager_defines_per_editor()
void CppToolsPlugin::test_modelmanager_updateEditorsAfterProjectUpdate()
{
ModelManagerTestHelper helper;
CppModelManager *mm = CppModelManager::instance();
MyTestDataDir testDataDirectory(_("testdata_defines"));
const QString fileA = testDataDirectory.file(_("main1.cpp")); // content not relevant
@@ -1017,10 +1018,8 @@ void CppToolsPlugin::test_modelmanager_updateEditorsAfterProjectUpdate()
QVERIFY(editorA);
EditorCloser closerA(editorA);
QCOMPARE(Core::DocumentModel::openedDocuments().size(), 1);
CppEditorDocumentHandle *editorDocumentA = mm->cppEditorDocument(fileA);
QVERIFY(editorDocumentA);
ProjectPart::Ptr documentAProjectPart = editorDocumentA->processor()->parser()->projectPart();
QVERIFY(TestCase::waitForProcessedEditorDocument(fileA));
ProjectPart::Ptr documentAProjectPart = projectPartOfEditorDocument(fileA);
QVERIFY(!documentAProjectPart->project);
// Open file B in editor
@@ -1028,10 +1027,8 @@ void CppToolsPlugin::test_modelmanager_updateEditorsAfterProjectUpdate()
QVERIFY(editorB);
EditorCloser closerB(editorB);
QCOMPARE(Core::DocumentModel::openedDocuments().size(), 2);
CppEditorDocumentHandle *editorDocumentB = mm->cppEditorDocument(fileB);
QVERIFY(editorDocumentB);
ProjectPart::Ptr documentBProjectPart = editorDocumentB->processor()->parser()->projectPart();
QVERIFY(TestCase::waitForProcessedEditorDocument(fileB));
ProjectPart::Ptr documentBProjectPart = projectPartOfEditorDocument(fileB);
QVERIFY(!documentBProjectPart->project);
// Switch back to document A
@@ -1053,16 +1050,14 @@ void CppToolsPlugin::test_modelmanager_updateEditorsAfterProjectUpdate()
helper.updateProjectInfo(pi);
// ... and check for updated editor document A
while (editorDocumentA->processor()->isParserRunning())
QCoreApplication::processEvents();
documentAProjectPart = editorDocumentA->processor()->parser()->projectPart();
QVERIFY(TestCase::waitForProcessedEditorDocument(fileA));
documentAProjectPart = projectPartOfEditorDocument(fileA);
QCOMPARE(documentAProjectPart->project, project);
// Switch back to document B and check if that's updated, too
Core::EditorManager::activateEditor(editorB);
while (editorDocumentB->processor()->isParserRunning())
QCoreApplication::processEvents();
documentBProjectPart = editorDocumentB->processor()->parser()->projectPart();
QVERIFY(TestCase::waitForProcessedEditorDocument(fileB));
documentBProjectPart = projectPartOfEditorDocument(fileB);
QCOMPARE(documentBProjectPart->project, project);
}
@@ -1131,7 +1126,7 @@ void CppToolsPlugin::test_modelmanager_documentsAndRevisions()
TextEditor::BaseTextEditor *editor1;
QVERIFY(helper.openBaseTextEditor(filePath1, &editor1));
helper.closeEditorAtEndOfTestCase(editor1);
waitForProcessedEditorDocument(filePath1);
QVERIFY(TestCase::waitForProcessedEditorDocument(filePath1));
VERIFY_DOCUMENT_REVISION(modelManager->document(filePath1), 2U);
VERIFY_DOCUMENT_REVISION(modelManager->document(filePath2), 1U);
@@ -1144,7 +1139,7 @@ void CppToolsPlugin::test_modelmanager_documentsAndRevisions()
TextEditor::BaseTextEditor *editor2;
QVERIFY(helper.openBaseTextEditor(filePath2, &editor2));
helper.closeEditorAtEndOfTestCase(editor2);
waitForProcessedEditorDocument(filePath2);
QVERIFY(TestCase::waitForProcessedEditorDocument(filePath2));
VERIFY_DOCUMENT_REVISION(modelManager->document(filePath1), 3U);
VERIFY_DOCUMENT_REVISION(modelManager->document(filePath2), 3U);

View File

@@ -137,6 +137,7 @@ void CppToolsPlugin::test_cppsourceprocessor_includes_cyclic()
const QString filePath = editor->document()->filePath().toString();
auto *processor = BaseEditorDocumentProcessor::get(filePath);
QVERIFY(processor);
QVERIFY(TestCase::waitForProcessedEditorDocument(filePath));
Snapshot snapshot = processor->snapshot();
QCOMPARE(snapshot.size(), 3); // Configuration file included

View File

@@ -32,6 +32,7 @@
#include "cpptoolsplugin.h"
#include <coreplugin/documentmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/idocument.h>
#include <texteditor/convenience.h>
@@ -287,4 +288,13 @@ bool skipFileDueToSizeLimit(const QFileInfo &fileInfo, int limitInMB)
return false;
}
Utils::FileNameList modifiedFiles()
{
Utils::FileNameList files;
foreach (Core::IDocument *doc, Core::DocumentManager::modifiedDocuments())
files.append(doc->filePath());
files.removeDuplicates();
return files;
}
} // CppTools

View File

@@ -44,6 +44,10 @@ class QStringRef;
class QTextCursor;
QT_END_NAMESPACE
namespace Utils {
class FileNameList;
} // namespace Utils
namespace CPlusPlus {
class Macro;
class Symbol;
@@ -52,6 +56,8 @@ class LookupContext;
namespace CppTools {
Utils::FileNameList CPPTOOLS_EXPORT modifiedFiles();
void CPPTOOLS_EXPORT moveCursorToEndOfIdentifier(QTextCursor *tc);
void CPPTOOLS_EXPORT moveCursorToStartOfIdentifier(QTextCursor *tc);

View File

@@ -29,6 +29,10 @@
****************************************************************************/
#include "cpptoolstestcase.h"
#include "baseeditordocumentparser.h"
#include "baseeditordocumentprocessor.h"
#include "editordocumenthandle.h"
#include "cppmodelmanager.h"
#include "cppworkingcopy.h"
@@ -140,6 +144,31 @@ bool TestCase::garbageCollectGlobalSnapshot()
return globalSnapshot().isEmpty();
}
static bool waitForProcessedEditorDocument_internal(CppEditorDocumentHandle *editorDocument,
int timeOutInMs)
{
QTC_ASSERT(editorDocument, return false);
QTime timer;
timer.start();
forever {
if (!editorDocument->processor()->isParserRunning())
return true;
if (timer.elapsed() > timeOutInMs)
return false;
QCoreApplication::processEvents();
QThread::msleep(20);
}
}
bool TestCase::waitForProcessedEditorDocument(const QString &filePath, int timeOutInMs)
{
auto *editorDocument = CppModelManager::instance()->cppEditorDocument(filePath);
return waitForProcessedEditorDocument_internal(editorDocument, timeOutInMs);
}
bool TestCase::parseFiles(const QSet<QString> &filePaths)
{
CppModelManager::instance()->updateSourceFiles(filePaths).waitForFinished();

View File

@@ -95,6 +95,8 @@ public:
static CPlusPlus::Snapshot globalSnapshot();
static bool garbageCollectGlobalSnapshot();
static bool waitForProcessedEditorDocument(const QString &filePath, int timeOutInMs = 5000);
enum { defaultTimeOutInMs = 30 * 1000 /*= 30 secs*/ };
static bool waitUntilCppModelManagerIsAwareOf(
ProjectExplorer::Project *project,