forked from qt-creator/qt-creator
CppTools: Avoid unnecessary blocking of main thread
Among others, BaseEditorDocumentParser::projectPart() was a blocking operation in case the parser was running. This led to noticeable GUI freezes for the ClangCodeModel since the function was called from the main thread. Rework *EditorDocumentParser to clearly separate the configuration data (input) from the actual object state. Querying/setting configuration or (last) state does not block anymore. update() is supposed to get the necessary configuration and the last state at the beginning and to set the new state at end. Change-Id: Ib4b534fa6ff373c3059826726b3f10ece95acc21 Reviewed-by: Erik Verbruggen <erik.verbruggen@theqtcompany.com>
This commit is contained in:
@@ -91,21 +91,25 @@ ClangEditorDocumentParser::ClangEditorDocumentParser(const QString &filePath)
|
|||||||
void ClangEditorDocumentParser::update(CppTools::WorkingCopy workingCopy)
|
void ClangEditorDocumentParser::update(CppTools::WorkingCopy workingCopy)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_marker, return);
|
QTC_ASSERT(m_marker, return);
|
||||||
QMutexLocker lock(m_marker->mutex());
|
QMutexLocker locker(&m_updateIsRunning);
|
||||||
QMutexLocker lock2(&m_mutex);
|
|
||||||
|
|
||||||
m_projectPart = determineProjectPart();
|
// Determine project part
|
||||||
const QStringList options = createOptions(filePath(), projectPart(), true);
|
State state_ = state();
|
||||||
|
state_.projectPart = determineProjectPart(filePath(), configuration(), state_);
|
||||||
|
setState(state_);
|
||||||
|
|
||||||
|
// Determine command line arguments
|
||||||
|
const QStringList options = createOptions(filePath(), state_.projectPart, true);
|
||||||
qCDebug(log, "Reparse options (cmd line equivalent): %s",
|
qCDebug(log, "Reparse options (cmd line equivalent): %s",
|
||||||
commandLine(options, filePath()).toUtf8().constData());
|
commandLine(options, filePath()).toUtf8().constData());
|
||||||
QTime t; t.start();
|
|
||||||
|
|
||||||
|
// Run
|
||||||
|
QTime t; t.start();
|
||||||
|
QMutexLocker lock(m_marker->mutex());
|
||||||
m_marker->setFileName(filePath());
|
m_marker->setFileName(filePath());
|
||||||
m_marker->setCompilationOptions(options);
|
m_marker->setCompilationOptions(options);
|
||||||
const Internal::UnsavedFiles unsavedFiles = Utils::createUnsavedFiles(workingCopy);
|
const Internal::UnsavedFiles unsavedFiles = Utils::createUnsavedFiles(workingCopy);
|
||||||
m_marker->reparse(unsavedFiles);
|
m_marker->reparse(unsavedFiles);
|
||||||
|
|
||||||
qCDebug(log) << "Reparse took" << t.elapsed() << "ms.";
|
qCDebug(log) << "Reparse took" << t.elapsed() << "ms.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -268,9 +268,11 @@ void CppEditorDocument::setPreprocessorSettings(const CppTools::ProjectPart::Ptr
|
|||||||
{
|
{
|
||||||
CppTools::BaseEditorDocumentParser *parser = processor()->parser();
|
CppTools::BaseEditorDocumentParser *parser = processor()->parser();
|
||||||
QTC_ASSERT(parser, return);
|
QTC_ASSERT(parser, return);
|
||||||
if (parser->projectPart() != projectPart || parser->editorDefines() != defines) {
|
if (parser->projectPart() != projectPart || parser->configuration().editorDefines != defines) {
|
||||||
parser->setProjectPart(projectPart);
|
CppTools::BaseEditorDocumentParser::Configuration config = parser->configuration();
|
||||||
parser->setEditorDefines(defines);
|
config.manuallySetProjectPart = projectPart;
|
||||||
|
config.editorDefines = defines;
|
||||||
|
parser->setConfiguration(config);
|
||||||
|
|
||||||
emit preprocessorSettingsChanged(!defines.trimmed().isEmpty());
|
emit preprocessorSettingsChanged(!defines.trimmed().isEmpty());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,15 +44,19 @@ namespace CppTools {
|
|||||||
It's meant to be used in the C++ editor to get precise results by using
|
It's meant to be used in the C++ editor to get precise results by using
|
||||||
the "best" project part for a file.
|
the "best" project part for a file.
|
||||||
|
|
||||||
Derived classes are expected to implement update() by using the protected
|
Derived classes are expected to implement update() this way:
|
||||||
mutex, determineProjectPart() and by respecting the options set by the client.
|
|
||||||
|
\list
|
||||||
|
\li Get a copy of the configuration and the last state.
|
||||||
|
\li Acquire the protected m_updateIsRunning for the duration of update().
|
||||||
|
\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 update() returns.
|
||||||
|
\endlist
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BaseEditorDocumentParser::BaseEditorDocumentParser(const QString &filePath)
|
BaseEditorDocumentParser::BaseEditorDocumentParser(const QString &filePath)
|
||||||
: m_mutex(QMutex::Recursive)
|
: m_filePath(filePath)
|
||||||
, m_filePath(filePath)
|
|
||||||
, m_usePrecompiledHeaders(false)
|
|
||||||
, m_editorDefinesChangedSinceLastUpdate(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,44 +69,33 @@ QString BaseEditorDocumentParser::filePath() const
|
|||||||
return m_filePath;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
ProjectPart::Ptr BaseEditorDocumentParser::projectPart() const
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_mutex);
|
return state().projectPart;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseEditorDocumentParser *BaseEditorDocumentParser::get(const QString &filePath)
|
BaseEditorDocumentParser *BaseEditorDocumentParser::get(const QString &filePath)
|
||||||
@@ -115,15 +108,17 @@ BaseEditorDocumentParser *BaseEditorDocumentParser::get(const QString &filePath)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectPart::Ptr BaseEditorDocumentParser::determineProjectPart() const
|
ProjectPart::Ptr BaseEditorDocumentParser::determineProjectPart(const QString &filePath,
|
||||||
|
const Configuration &config,
|
||||||
|
const State &state)
|
||||||
{
|
{
|
||||||
if (m_manuallySetProjectPart)
|
if (config.manuallySetProjectPart)
|
||||||
return m_manuallySetProjectPart;
|
return config.manuallySetProjectPart;
|
||||||
|
|
||||||
ProjectPart::Ptr projectPart = m_projectPart;
|
ProjectPart::Ptr projectPart = state.projectPart;
|
||||||
|
|
||||||
CppModelManager *cmm = CppModelManager::instance();
|
CppModelManager *cmm = CppModelManager::instance();
|
||||||
QList<ProjectPart::Ptr> projectParts = cmm->projectPart(m_filePath);
|
QList<ProjectPart::Ptr> projectParts = cmm->projectPart(filePath);
|
||||||
if (projectParts.isEmpty()) {
|
if (projectParts.isEmpty()) {
|
||||||
if (projectPart)
|
if (projectPart)
|
||||||
// File is not directly part of any project, but we got one before. We will re-use it,
|
// File is not directly part of any project, but we got one before. We will re-use it,
|
||||||
@@ -131,7 +126,7 @@ ProjectPart::Ptr BaseEditorDocumentParser::determineProjectPart() const
|
|||||||
return projectPart;
|
return projectPart;
|
||||||
|
|
||||||
// Fall-back step 1: Get some parts through the dependency table:
|
// 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())
|
if (projectParts.isEmpty())
|
||||||
// Fall-back step 2: Use fall-back part from the model manager:
|
// Fall-back step 2: Use fall-back part from the model manager:
|
||||||
projectPart = cmm->fallbackProjectPart();
|
projectPart = cmm->fallbackProjectPart();
|
||||||
@@ -146,14 +141,4 @@ ProjectPart::Ptr BaseEditorDocumentParser::determineProjectPart() const
|
|||||||
return projectPart;
|
return projectPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseEditorDocumentParser::editorDefinesChanged() const
|
|
||||||
{
|
|
||||||
return m_editorDefinesChangedSinceLastUpdate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseEditorDocumentParser::resetEditorDefinesChanged()
|
|
||||||
{
|
|
||||||
m_editorDefinesChangedSinceLastUpdate = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace CppTools
|
} // namespace CppTools
|
||||||
|
|||||||
@@ -42,45 +42,49 @@ class CPPTOOLS_EXPORT BaseEditorDocumentParser : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
static BaseEditorDocumentParser *get(const QString &filePath);
|
||||||
|
|
||||||
|
struct Configuration {
|
||||||
|
bool usePrecompiledHeaders = false;
|
||||||
|
QByteArray editorDefines;
|
||||||
|
ProjectPart::Ptr manuallySetProjectPart;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BaseEditorDocumentParser(const QString &filePath);
|
BaseEditorDocumentParser(const QString &filePath);
|
||||||
virtual ~BaseEditorDocumentParser();
|
virtual ~BaseEditorDocumentParser();
|
||||||
|
|
||||||
QString filePath() const;
|
QString filePath() const;
|
||||||
|
|
||||||
|
Configuration configuration() const;
|
||||||
|
void setConfiguration(const Configuration &configuration);
|
||||||
|
|
||||||
virtual void update(WorkingCopy workingCopy) = 0;
|
virtual void update(WorkingCopy workingCopy) = 0;
|
||||||
|
|
||||||
ProjectPart::Ptr projectPart() const;
|
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:
|
protected:
|
||||||
ProjectPart::Ptr determineProjectPart() const;
|
struct State {
|
||||||
|
QByteArray editorDefines;
|
||||||
|
ProjectPart::Ptr projectPart;
|
||||||
|
};
|
||||||
|
|
||||||
bool editorDefinesChanged() const;
|
State state() const;
|
||||||
void resetEditorDefinesChanged();
|
void setState(const State &state);
|
||||||
|
|
||||||
protected:
|
static ProjectPart::Ptr determineProjectPart(const QString &filePath,
|
||||||
mutable QMutex m_mutex;
|
const Configuration &config,
|
||||||
ProjectPart::Ptr m_projectPart;
|
const State &state);
|
||||||
|
|
||||||
|
mutable QMutex m_updateIsRunning;
|
||||||
|
mutable QMutex m_stateAndConfigurationMutex;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const QString m_filePath;
|
const QString m_filePath;
|
||||||
|
|
||||||
ProjectPart::Ptr m_manuallySetProjectPart;
|
Configuration m_configuration;
|
||||||
|
State m_state;
|
||||||
bool m_usePrecompiledHeaders;
|
|
||||||
|
|
||||||
QByteArray m_editorDefines;
|
|
||||||
bool m_editorDefinesChangedSinceLastUpdate;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CppTools
|
} // namespace CppTools
|
||||||
|
|||||||
@@ -40,15 +40,19 @@ using namespace CppTools::Internal;
|
|||||||
|
|
||||||
BuiltinEditorDocumentParser::BuiltinEditorDocumentParser(const QString &filePath)
|
BuiltinEditorDocumentParser::BuiltinEditorDocumentParser(const QString &filePath)
|
||||||
: BaseEditorDocumentParser(filePath)
|
: BaseEditorDocumentParser(filePath)
|
||||||
, m_forceSnapshotInvalidation(false)
|
|
||||||
, m_releaseSourceAndAST(true)
|
|
||||||
{
|
{
|
||||||
qRegisterMetaType<CPlusPlus::Snapshot>("CPlusPlus::Snapshot");
|
qRegisterMetaType<CPlusPlus::Snapshot>("CPlusPlus::Snapshot");
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
|
void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_updateIsRunning);
|
||||||
|
|
||||||
|
const Configuration baseConfig = configuration();
|
||||||
|
const bool releaseSourceAndAST_ = releaseSourceAndAST();
|
||||||
|
|
||||||
|
State baseState = state();
|
||||||
|
ExtraState state = extraState();
|
||||||
|
|
||||||
if (filePath().isEmpty())
|
if (filePath().isEmpty())
|
||||||
return;
|
return;
|
||||||
@@ -62,52 +66,52 @@ void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
|
|||||||
QString projectConfigFile;
|
QString projectConfigFile;
|
||||||
LanguageFeatures features = LanguageFeatures::defaultFeatures();
|
LanguageFeatures features = LanguageFeatures::defaultFeatures();
|
||||||
|
|
||||||
m_projectPart = determineProjectPart();
|
baseState.projectPart = determineProjectPart(filePath(), baseConfig, baseState);
|
||||||
|
|
||||||
if (m_forceSnapshotInvalidation) {
|
if (state.forceSnapshotInvalidation) {
|
||||||
invalidateSnapshot = true;
|
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->toolchainDefines;
|
||||||
configFile += part->projectDefines;
|
configFile += part->projectDefines;
|
||||||
headerPaths = part->headerPaths;
|
headerPaths = part->headerPaths;
|
||||||
projectConfigFile = part->projectConfigFile;
|
projectConfigFile = part->projectConfigFile;
|
||||||
if (usePrecompiledHeaders())
|
if (baseConfig.usePrecompiledHeaders)
|
||||||
precompiledHeaders = part->precompiledHeaders;
|
precompiledHeaders = part->precompiledHeaders;
|
||||||
features = part->languageFeatures;
|
features = part->languageFeatures;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (configFile != m_configFile) {
|
if (configFile != state.configFile) {
|
||||||
m_configFile = configFile;
|
state.configFile = configFile;
|
||||||
invalidateSnapshot = true;
|
invalidateSnapshot = true;
|
||||||
invalidateConfig = true;
|
invalidateConfig = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (editorDefinesChanged()) {
|
if (baseConfig.editorDefines != baseState.editorDefines) {
|
||||||
|
baseState.editorDefines = baseConfig.editorDefines;
|
||||||
invalidateSnapshot = true;
|
invalidateSnapshot = true;
|
||||||
editorDefinesChanged_ = true;
|
editorDefinesChanged_ = true;
|
||||||
resetEditorDefinesChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (headerPaths != m_headerPaths) {
|
if (headerPaths != state.headerPaths) {
|
||||||
m_headerPaths = headerPaths;
|
state.headerPaths = headerPaths;
|
||||||
invalidateSnapshot = true;
|
invalidateSnapshot = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (projectConfigFile != m_projectConfigFile) {
|
if (projectConfigFile != state.projectConfigFile) {
|
||||||
m_projectConfigFile = projectConfigFile;
|
state.projectConfigFile = projectConfigFile;
|
||||||
invalidateSnapshot = true;
|
invalidateSnapshot = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (precompiledHeaders != m_precompiledHeaders) {
|
if (precompiledHeaders != state.precompiledHeaders) {
|
||||||
m_precompiledHeaders = precompiledHeaders;
|
state.precompiledHeaders = precompiledHeaders;
|
||||||
invalidateSnapshot = true;
|
invalidateSnapshot = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned rev = 0;
|
unsigned rev = 0;
|
||||||
if (Document::Ptr doc = document())
|
if (Document::Ptr doc = state.snapshot.document(filePath()))
|
||||||
rev = doc->revision();
|
rev = doc->revision();
|
||||||
else
|
else
|
||||||
invalidateSnapshot = true;
|
invalidateSnapshot = true;
|
||||||
@@ -115,26 +119,26 @@ void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
|
|||||||
Snapshot globalSnapshot = modelManager->snapshot();
|
Snapshot globalSnapshot = modelManager->snapshot();
|
||||||
|
|
||||||
if (invalidateSnapshot) {
|
if (invalidateSnapshot) {
|
||||||
m_snapshot = Snapshot();
|
state.snapshot = Snapshot();
|
||||||
} else {
|
} else {
|
||||||
// Remove changed files from the snapshot
|
// Remove changed files from the snapshot
|
||||||
QSet<Utils::FileName> toRemove;
|
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());
|
const Utils::FileName fileName = Utils::FileName::fromString(doc->fileName());
|
||||||
if (workingCopy.contains(fileName)) {
|
if (workingCopy.contains(fileName)) {
|
||||||
if (workingCopy.get(fileName).second != doc->editorRevision())
|
if (workingCopy.get(fileName).second != doc->editorRevision())
|
||||||
addFileAndDependencies(&toRemove, fileName);
|
addFileAndDependencies(&state.snapshot, &toRemove, fileName);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Document::Ptr otherDoc = globalSnapshot.document(fileName);
|
Document::Ptr otherDoc = globalSnapshot.document(fileName);
|
||||||
if (!otherDoc.isNull() && otherDoc->revision() != doc->revision())
|
if (!otherDoc.isNull() && otherDoc->revision() != doc->revision())
|
||||||
addFileAndDependencies(&toRemove, fileName);
|
addFileAndDependencies(&state.snapshot, &toRemove, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!toRemove.isEmpty()) {
|
if (!toRemove.isEmpty()) {
|
||||||
invalidateSnapshot = true;
|
invalidateSnapshot = true;
|
||||||
foreach (const Utils::FileName &fileName, toRemove)
|
foreach (const Utils::FileName &fileName, toRemove)
|
||||||
m_snapshot.remove(fileName);
|
state.snapshot.remove(fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,19 +146,19 @@ void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
|
|||||||
if (invalidateSnapshot) {
|
if (invalidateSnapshot) {
|
||||||
const QString configurationFileName = modelManager->configurationFileName();
|
const QString configurationFileName = modelManager->configurationFileName();
|
||||||
if (invalidateConfig)
|
if (invalidateConfig)
|
||||||
m_snapshot.remove(configurationFileName);
|
state.snapshot.remove(configurationFileName);
|
||||||
if (!m_snapshot.contains(configurationFileName))
|
if (!state.snapshot.contains(configurationFileName))
|
||||||
workingCopy.insert(configurationFileName, m_configFile);
|
workingCopy.insert(configurationFileName, state.configFile);
|
||||||
m_snapshot.remove(filePath());
|
state.snapshot.remove(filePath());
|
||||||
|
|
||||||
static const QString editorDefinesFileName
|
static const QString editorDefinesFileName
|
||||||
= CppModelManager::editorConfigurationFileName();
|
= CppModelManager::editorConfigurationFileName();
|
||||||
if (editorDefinesChanged_) {
|
if (editorDefinesChanged_) {
|
||||||
m_snapshot.remove(editorDefinesFileName);
|
state.snapshot.remove(editorDefinesFileName);
|
||||||
workingCopy.insert(editorDefinesFileName, editorDefines());
|
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 QString fileName = doc->fileName();
|
||||||
const bool isInEditor = fileName == filePath();
|
const bool isInEditor = fileName == filePath();
|
||||||
Document::Ptr otherDoc = modelManager->document(fileName);
|
Document::Ptr otherDoc = modelManager->document(fileName);
|
||||||
@@ -163,68 +167,64 @@ void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
|
|||||||
newRev = qMax(rev + 1, newRev);
|
newRev = qMax(rev + 1, newRev);
|
||||||
doc->setRevision(newRev);
|
doc->setRevision(newRev);
|
||||||
modelManager->emitDocumentUpdated(doc);
|
modelManager->emitDocumentUpdated(doc);
|
||||||
if (m_releaseSourceAndAST)
|
if (releaseSourceAndAST_)
|
||||||
doc->releaseSourceAndAST();
|
doc->releaseSourceAndAST();
|
||||||
});
|
});
|
||||||
Snapshot globalSnapshot = modelManager->snapshot();
|
Snapshot globalSnapshot = modelManager->snapshot();
|
||||||
globalSnapshot.remove(filePath());
|
globalSnapshot.remove(filePath());
|
||||||
sourceProcessor.setGlobalSnapshot(globalSnapshot);
|
sourceProcessor.setGlobalSnapshot(globalSnapshot);
|
||||||
sourceProcessor.setWorkingCopy(workingCopy);
|
sourceProcessor.setWorkingCopy(workingCopy);
|
||||||
sourceProcessor.setHeaderPaths(m_headerPaths);
|
sourceProcessor.setHeaderPaths(state.headerPaths);
|
||||||
sourceProcessor.setLanguageFeatures(features);
|
sourceProcessor.setLanguageFeatures(features);
|
||||||
sourceProcessor.run(configurationFileName);
|
sourceProcessor.run(configurationFileName);
|
||||||
if (!m_projectConfigFile.isEmpty())
|
if (!state.projectConfigFile.isEmpty())
|
||||||
sourceProcessor.run(m_projectConfigFile);
|
sourceProcessor.run(state.projectConfigFile);
|
||||||
if (usePrecompiledHeaders()) {
|
if (baseConfig.usePrecompiledHeaders) {
|
||||||
foreach (const QString &precompiledHeader, m_precompiledHeaders)
|
foreach (const QString &precompiledHeader, state.precompiledHeaders)
|
||||||
sourceProcessor.run(precompiledHeader);
|
sourceProcessor.run(precompiledHeader);
|
||||||
}
|
}
|
||||||
if (!editorDefines().isEmpty())
|
if (!baseState.editorDefines.isEmpty())
|
||||||
sourceProcessor.run(editorDefinesFileName);
|
sourceProcessor.run(editorDefinesFileName);
|
||||||
sourceProcessor.run(filePath(), usePrecompiledHeaders() ? m_precompiledHeaders
|
sourceProcessor.run(filePath(), baseConfig.usePrecompiledHeaders ? state.precompiledHeaders
|
||||||
: QStringList());
|
: QStringList());
|
||||||
m_snapshot = sourceProcessor.snapshot();
|
state.snapshot = sourceProcessor.snapshot();
|
||||||
Snapshot newSnapshot = m_snapshot.simplified(document());
|
Snapshot newSnapshot = state.snapshot.simplified(state.snapshot.document(filePath()));
|
||||||
for (Snapshot::const_iterator i = m_snapshot.begin(), ei = m_snapshot.end(); i != ei; ++i) {
|
for (Snapshot::const_iterator i = state.snapshot.begin(), ei = state.snapshot.end(); i != ei; ++i) {
|
||||||
if (Client::isInjectedFile(i.key().toString()))
|
if (Client::isInjectedFile(i.key().toString()))
|
||||||
newSnapshot.insert(i.value());
|
newSnapshot.insert(i.value());
|
||||||
}
|
}
|
||||||
m_snapshot = newSnapshot;
|
state.snapshot = newSnapshot;
|
||||||
m_snapshot.updateDependencyTable();
|
state.snapshot.updateDependencyTable();
|
||||||
|
|
||||||
emit finished(document(), m_snapshot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setState(baseState);
|
||||||
|
setExtraState(state);
|
||||||
|
|
||||||
|
if (invalidateSnapshot)
|
||||||
|
emit finished(state.snapshot.document(filePath()), state.snapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuiltinEditorDocumentParser::releaseResources()
|
void BuiltinEditorDocumentParser::releaseResources()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_mutex);
|
ExtraState s = extraState();
|
||||||
m_snapshot = Snapshot();
|
s.snapshot = Snapshot();
|
||||||
m_forceSnapshotInvalidation = true;
|
s.forceSnapshotInvalidation = true;
|
||||||
|
setExtraState(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
Document::Ptr BuiltinEditorDocumentParser::document() const
|
Document::Ptr BuiltinEditorDocumentParser::document() const
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_mutex);
|
return extraState().snapshot.document(filePath());
|
||||||
return m_snapshot.document(filePath());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Snapshot BuiltinEditorDocumentParser::snapshot() const
|
Snapshot BuiltinEditorDocumentParser::snapshot() const
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_mutex);
|
return extraState().snapshot;
|
||||||
return m_snapshot;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectPart::HeaderPaths BuiltinEditorDocumentParser::headerPaths() const
|
ProjectPart::HeaderPaths BuiltinEditorDocumentParser::headerPaths() const
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_mutex);
|
return extraState().headerPaths;
|
||||||
return m_headerPaths;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BuiltinEditorDocumentParser::setReleaseSourceAndAST(bool onoff)
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&m_mutex);
|
|
||||||
m_releaseSourceAndAST = onoff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BuiltinEditorDocumentParser *BuiltinEditorDocumentParser::get(const QString &filePath)
|
BuiltinEditorDocumentParser *BuiltinEditorDocumentParser::get(const QString &filePath)
|
||||||
@@ -234,12 +234,39 @@ BuiltinEditorDocumentParser *BuiltinEditorDocumentParser::get(const QString &fil
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuiltinEditorDocumentParser::addFileAndDependencies(QSet<Utils::FileName> *toRemove,
|
void BuiltinEditorDocumentParser::addFileAndDependencies(Snapshot *snapshot,
|
||||||
|
QSet<Utils::FileName> *toRemove,
|
||||||
const Utils::FileName &fileName) const
|
const Utils::FileName &fileName) const
|
||||||
{
|
{
|
||||||
|
QTC_ASSERT(snapshot, return);
|
||||||
|
|
||||||
toRemove->insert(fileName);
|
toRemove->insert(fileName);
|
||||||
if (fileName != Utils::FileName::fromString(filePath())) {
|
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));
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,7 +37,6 @@
|
|||||||
|
|
||||||
#include <cplusplus/CppDocument.h>
|
#include <cplusplus/CppDocument.h>
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
namespace CppTools {
|
namespace CppTools {
|
||||||
@@ -49,14 +48,16 @@ class CPPTOOLS_EXPORT BuiltinEditorDocumentParser : public BaseEditorDocumentPar
|
|||||||
public:
|
public:
|
||||||
BuiltinEditorDocumentParser(const QString &filePath);
|
BuiltinEditorDocumentParser(const QString &filePath);
|
||||||
|
|
||||||
|
bool releaseSourceAndAST() const;
|
||||||
|
void setReleaseSourceAndAST(bool release);
|
||||||
|
|
||||||
void update(WorkingCopy workingCopy) override;
|
void update(WorkingCopy workingCopy) override;
|
||||||
void releaseResources();
|
|
||||||
|
|
||||||
CPlusPlus::Document::Ptr document() const;
|
CPlusPlus::Document::Ptr document() const;
|
||||||
CPlusPlus::Snapshot snapshot() const;
|
CPlusPlus::Snapshot snapshot() const;
|
||||||
ProjectPart::HeaderPaths headerPaths() const;
|
ProjectPart::HeaderPaths headerPaths() const;
|
||||||
|
|
||||||
void setReleaseSourceAndAST(bool onoff);
|
void releaseResources();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void finished(CPlusPlus::Document::Ptr document, CPlusPlus::Snapshot snapshot);
|
void finished(CPlusPlus::Document::Ptr document, CPlusPlus::Snapshot snapshot);
|
||||||
@@ -65,18 +66,26 @@ public:
|
|||||||
static BuiltinEditorDocumentParser *get(const QString &filePath);
|
static BuiltinEditorDocumentParser *get(const QString &filePath);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addFileAndDependencies(QSet<Utils::FileName> *toRemove, const Utils::FileName &fileName) const;
|
void addFileAndDependencies(CPlusPlus::Snapshot *snapshot,
|
||||||
|
QSet<Utils::FileName> *toRemove,
|
||||||
|
const Utils::FileName &fileName) const;
|
||||||
|
|
||||||
private:
|
struct ExtraState {
|
||||||
QByteArray m_configFile;
|
QByteArray configFile;
|
||||||
|
|
||||||
ProjectPart::HeaderPaths m_headerPaths;
|
ProjectPart::HeaderPaths headerPaths;
|
||||||
QString m_projectConfigFile;
|
QString projectConfigFile;
|
||||||
QStringList m_precompiledHeaders;
|
QStringList precompiledHeaders;
|
||||||
|
|
||||||
CPlusPlus::Snapshot m_snapshot;
|
CPlusPlus::Snapshot snapshot;
|
||||||
bool m_forceSnapshotInvalidation;
|
bool forceSnapshotInvalidation = false;
|
||||||
bool m_releaseSourceAndAST;
|
};
|
||||||
|
|
||||||
|
ExtraState extraState() const;
|
||||||
|
void setExtraState(const ExtraState &extraState);
|
||||||
|
|
||||||
|
bool m_releaseSourceAndAST = true;
|
||||||
|
ExtraState m_extraState;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CppTools
|
} // namespace CppTools
|
||||||
|
|||||||
@@ -134,7 +134,10 @@ BuiltinEditorDocumentProcessor::BuiltinEditorDocumentProcessor(
|
|||||||
using namespace Internal;
|
using namespace Internal;
|
||||||
|
|
||||||
QSharedPointer<CppCodeModelSettings> cms = CppToolsPlugin::instance()->codeModelSettings();
|
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) {
|
if (m_semanticHighlighter) {
|
||||||
m_semanticHighlighter->setHighlightingRunner(
|
m_semanticHighlighter->setHighlightingRunner(
|
||||||
|
|||||||
@@ -167,13 +167,11 @@ private:
|
|||||||
const QString &m_filePath;
|
const QString &m_filePath;
|
||||||
};
|
};
|
||||||
|
|
||||||
void waitForProcessedEditorDocument(const QString &filePath)
|
ProjectPart::Ptr projectPartOfEditorDocument(const QString &filePath)
|
||||||
{
|
{
|
||||||
CppEditorDocumentHandle *editorDocument
|
auto *editorDocument = CppModelManager::instance()->cppEditorDocument(filePath);
|
||||||
= CppModelManager::instance()->cppEditorDocument(filePath);
|
QTC_ASSERT(editorDocument, return ProjectPart::Ptr());
|
||||||
QVERIFY(editorDocument);
|
return editorDocument->processor()->parser()->projectPart();
|
||||||
while (editorDocument->processor()->isParserRunning())
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
@@ -914,7 +912,9 @@ void CppToolsPlugin::test_modelmanager_precompiled_headers()
|
|||||||
|
|
||||||
auto *parser = BuiltinEditorDocumentParser::get(fileName);
|
auto *parser = BuiltinEditorDocumentParser::get(fileName);
|
||||||
QVERIFY(parser);
|
QVERIFY(parser);
|
||||||
parser->setUsePrecompiledHeaders(true);
|
BaseEditorDocumentParser::Configuration config = parser->configuration();
|
||||||
|
config.usePrecompiledHeaders = true;
|
||||||
|
parser->setConfiguration(config);
|
||||||
parser->update(mm->workingCopy());
|
parser->update(mm->workingCopy());
|
||||||
|
|
||||||
// Check if defines from pch are considered
|
// Check if defines from pch are considered
|
||||||
@@ -995,7 +995,10 @@ void CppToolsPlugin::test_modelmanager_defines_per_editor()
|
|||||||
|
|
||||||
const QString filePath = editor->document()->filePath().toString();
|
const QString filePath = editor->document()->filePath().toString();
|
||||||
BaseEditorDocumentParser *parser = BaseEditorDocumentParser::get(filePath);
|
BaseEditorDocumentParser *parser = BaseEditorDocumentParser::get(filePath);
|
||||||
parser->setEditorDefines(editorDefines.toUtf8());
|
BaseEditorDocumentParser::Configuration config = parser->configuration();
|
||||||
|
config.editorDefines = editorDefines.toUtf8();
|
||||||
|
parser->setConfiguration(config);
|
||||||
|
|
||||||
parser->update(mm->workingCopy());
|
parser->update(mm->workingCopy());
|
||||||
|
|
||||||
Document::Ptr doc = mm->document(main1File);
|
Document::Ptr doc = mm->document(main1File);
|
||||||
@@ -1006,7 +1009,6 @@ void CppToolsPlugin::test_modelmanager_defines_per_editor()
|
|||||||
void CppToolsPlugin::test_modelmanager_updateEditorsAfterProjectUpdate()
|
void CppToolsPlugin::test_modelmanager_updateEditorsAfterProjectUpdate()
|
||||||
{
|
{
|
||||||
ModelManagerTestHelper helper;
|
ModelManagerTestHelper helper;
|
||||||
CppModelManager *mm = CppModelManager::instance();
|
|
||||||
|
|
||||||
MyTestDataDir testDataDirectory(_("testdata_defines"));
|
MyTestDataDir testDataDirectory(_("testdata_defines"));
|
||||||
const QString fileA = testDataDirectory.file(_("main1.cpp")); // content not relevant
|
const QString fileA = testDataDirectory.file(_("main1.cpp")); // content not relevant
|
||||||
@@ -1017,10 +1019,8 @@ void CppToolsPlugin::test_modelmanager_updateEditorsAfterProjectUpdate()
|
|||||||
QVERIFY(editorA);
|
QVERIFY(editorA);
|
||||||
EditorCloser closerA(editorA);
|
EditorCloser closerA(editorA);
|
||||||
QCOMPARE(Core::DocumentModel::openedDocuments().size(), 1);
|
QCOMPARE(Core::DocumentModel::openedDocuments().size(), 1);
|
||||||
|
QVERIFY(TestCase::waitForProcessedEditorDocument(fileA));
|
||||||
CppEditorDocumentHandle *editorDocumentA = mm->cppEditorDocument(fileA);
|
ProjectPart::Ptr documentAProjectPart = projectPartOfEditorDocument(fileA);
|
||||||
QVERIFY(editorDocumentA);
|
|
||||||
ProjectPart::Ptr documentAProjectPart = editorDocumentA->processor()->parser()->projectPart();
|
|
||||||
QVERIFY(!documentAProjectPart->project);
|
QVERIFY(!documentAProjectPart->project);
|
||||||
|
|
||||||
// Open file B in editor
|
// Open file B in editor
|
||||||
@@ -1028,10 +1028,8 @@ void CppToolsPlugin::test_modelmanager_updateEditorsAfterProjectUpdate()
|
|||||||
QVERIFY(editorB);
|
QVERIFY(editorB);
|
||||||
EditorCloser closerB(editorB);
|
EditorCloser closerB(editorB);
|
||||||
QCOMPARE(Core::DocumentModel::openedDocuments().size(), 2);
|
QCOMPARE(Core::DocumentModel::openedDocuments().size(), 2);
|
||||||
|
QVERIFY(TestCase::waitForProcessedEditorDocument(fileB));
|
||||||
CppEditorDocumentHandle *editorDocumentB = mm->cppEditorDocument(fileB);
|
ProjectPart::Ptr documentBProjectPart = projectPartOfEditorDocument(fileB);
|
||||||
QVERIFY(editorDocumentB);
|
|
||||||
ProjectPart::Ptr documentBProjectPart = editorDocumentB->processor()->parser()->projectPart();
|
|
||||||
QVERIFY(!documentBProjectPart->project);
|
QVERIFY(!documentBProjectPart->project);
|
||||||
|
|
||||||
// Switch back to document A
|
// Switch back to document A
|
||||||
@@ -1053,16 +1051,14 @@ void CppToolsPlugin::test_modelmanager_updateEditorsAfterProjectUpdate()
|
|||||||
helper.updateProjectInfo(pi);
|
helper.updateProjectInfo(pi);
|
||||||
|
|
||||||
// ... and check for updated editor document A
|
// ... and check for updated editor document A
|
||||||
while (editorDocumentA->processor()->isParserRunning())
|
QVERIFY(TestCase::waitForProcessedEditorDocument(fileA));
|
||||||
QCoreApplication::processEvents();
|
documentAProjectPart = projectPartOfEditorDocument(fileA);
|
||||||
documentAProjectPart = editorDocumentA->processor()->parser()->projectPart();
|
|
||||||
QCOMPARE(documentAProjectPart->project, project);
|
QCOMPARE(documentAProjectPart->project, project);
|
||||||
|
|
||||||
// Switch back to document B and check if that's updated, too
|
// Switch back to document B and check if that's updated, too
|
||||||
Core::EditorManager::activateEditor(editorB);
|
Core::EditorManager::activateEditor(editorB);
|
||||||
while (editorDocumentB->processor()->isParserRunning())
|
QVERIFY(TestCase::waitForProcessedEditorDocument(fileB));
|
||||||
QCoreApplication::processEvents();
|
documentBProjectPart = projectPartOfEditorDocument(fileB);
|
||||||
documentBProjectPart = editorDocumentB->processor()->parser()->projectPart();
|
|
||||||
QCOMPARE(documentBProjectPart->project, project);
|
QCOMPARE(documentBProjectPart->project, project);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1131,7 +1127,7 @@ void CppToolsPlugin::test_modelmanager_documentsAndRevisions()
|
|||||||
TextEditor::BaseTextEditor *editor1;
|
TextEditor::BaseTextEditor *editor1;
|
||||||
QVERIFY(helper.openBaseTextEditor(filePath1, &editor1));
|
QVERIFY(helper.openBaseTextEditor(filePath1, &editor1));
|
||||||
helper.closeEditorAtEndOfTestCase(editor1);
|
helper.closeEditorAtEndOfTestCase(editor1);
|
||||||
waitForProcessedEditorDocument(filePath1);
|
QVERIFY(TestCase::waitForProcessedEditorDocument(filePath1));
|
||||||
VERIFY_DOCUMENT_REVISION(modelManager->document(filePath1), 2U);
|
VERIFY_DOCUMENT_REVISION(modelManager->document(filePath1), 2U);
|
||||||
VERIFY_DOCUMENT_REVISION(modelManager->document(filePath2), 1U);
|
VERIFY_DOCUMENT_REVISION(modelManager->document(filePath2), 1U);
|
||||||
|
|
||||||
@@ -1144,7 +1140,7 @@ void CppToolsPlugin::test_modelmanager_documentsAndRevisions()
|
|||||||
TextEditor::BaseTextEditor *editor2;
|
TextEditor::BaseTextEditor *editor2;
|
||||||
QVERIFY(helper.openBaseTextEditor(filePath2, &editor2));
|
QVERIFY(helper.openBaseTextEditor(filePath2, &editor2));
|
||||||
helper.closeEditorAtEndOfTestCase(editor2);
|
helper.closeEditorAtEndOfTestCase(editor2);
|
||||||
waitForProcessedEditorDocument(filePath2);
|
QVERIFY(TestCase::waitForProcessedEditorDocument(filePath2));
|
||||||
VERIFY_DOCUMENT_REVISION(modelManager->document(filePath1), 3U);
|
VERIFY_DOCUMENT_REVISION(modelManager->document(filePath1), 3U);
|
||||||
VERIFY_DOCUMENT_REVISION(modelManager->document(filePath2), 3U);
|
VERIFY_DOCUMENT_REVISION(modelManager->document(filePath2), 3U);
|
||||||
|
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ void CppToolsPlugin::test_cppsourceprocessor_includes_cyclic()
|
|||||||
const QString filePath = editor->document()->filePath().toString();
|
const QString filePath = editor->document()->filePath().toString();
|
||||||
auto *processor = BaseEditorDocumentProcessor::get(filePath);
|
auto *processor = BaseEditorDocumentProcessor::get(filePath);
|
||||||
QVERIFY(processor);
|
QVERIFY(processor);
|
||||||
|
QVERIFY(TestCase::waitForProcessedEditorDocument(filePath));
|
||||||
Snapshot snapshot = processor->snapshot();
|
Snapshot snapshot = processor->snapshot();
|
||||||
QCOMPARE(snapshot.size(), 3); // Configuration file included
|
QCOMPARE(snapshot.size(), 3); // Configuration file included
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,10 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "cpptoolstestcase.h"
|
#include "cpptoolstestcase.h"
|
||||||
|
|
||||||
|
#include "baseeditordocumentparser.h"
|
||||||
|
#include "baseeditordocumentprocessor.h"
|
||||||
|
#include "editordocumenthandle.h"
|
||||||
#include "cppmodelmanager.h"
|
#include "cppmodelmanager.h"
|
||||||
#include "cppworkingcopy.h"
|
#include "cppworkingcopy.h"
|
||||||
|
|
||||||
@@ -140,6 +144,31 @@ bool TestCase::garbageCollectGlobalSnapshot()
|
|||||||
return globalSnapshot().isEmpty();
|
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)
|
bool TestCase::parseFiles(const QSet<QString> &filePaths)
|
||||||
{
|
{
|
||||||
CppModelManager::instance()->updateSourceFiles(filePaths).waitForFinished();
|
CppModelManager::instance()->updateSourceFiles(filePaths).waitForFinished();
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ public:
|
|||||||
static CPlusPlus::Snapshot globalSnapshot();
|
static CPlusPlus::Snapshot globalSnapshot();
|
||||||
static bool garbageCollectGlobalSnapshot();
|
static bool garbageCollectGlobalSnapshot();
|
||||||
|
|
||||||
|
static bool waitForProcessedEditorDocument(const QString &filePath, int timeOutInMs = 5000);
|
||||||
|
|
||||||
enum { defaultTimeOutInMs = 30 * 1000 /*= 30 secs*/ };
|
enum { defaultTimeOutInMs = 30 * 1000 /*= 30 secs*/ };
|
||||||
static bool waitUntilCppModelManagerIsAwareOf(
|
static bool waitUntilCppModelManagerIsAwareOf(
|
||||||
ProjectExplorer::Project *project,
|
ProjectExplorer::Project *project,
|
||||||
|
|||||||
Reference in New Issue
Block a user