CppTools: Cancel parsing if editor is closed

The m_parserFuture.cancel() in ~BuiltinEditorDocumentProcessor() did not
cancel anything. Thus, closing a document while the parser was running
led to a blocking UI thread.

Now it cancels at the next include directive it encounters.

Change-Id: I092fddbbd747e0bc95265b6e9b4fcc26b3f76cb3
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Nikolai Kosjar
2016-07-27 14:48:42 +02:00
committed by Tim Jenssen
parent c8020af997
commit ad49e64ff0
11 changed files with 48 additions and 8 deletions

View File

@@ -762,6 +762,11 @@ QByteArray Preprocessor::run(const QString &fileName,
return preprocessed; return preprocessed;
} }
void Preprocessor::setCancelChecker(const Preprocessor::CancelChecker &cancelChecker)
{
m_cancelChecker = cancelChecker;
}
bool Preprocessor::expandFunctionlikeMacros() const bool Preprocessor::expandFunctionlikeMacros() const
{ {
return m_expandFunctionlikeMacros; return m_expandFunctionlikeMacros;
@@ -1636,6 +1641,9 @@ void Preprocessor::handlePreprocessorDirective(PPToken *tk)
void Preprocessor::handleIncludeDirective(PPToken *tk, bool includeNext) void Preprocessor::handleIncludeDirective(PPToken *tk, bool includeNext)
{ {
if (m_cancelChecker && m_cancelChecker())
return;
m_state.m_lexer->setScanAngleStringLiteralTokens(true); m_state.m_lexer->setScanAngleStringLiteralTokens(true);
lex(tk); // consume "include" token lex(tk); // consume "include" token
m_state.m_lexer->setScanAngleStringLiteralTokens(false); m_state.m_lexer->setScanAngleStringLiteralTokens(false);

View File

@@ -56,6 +56,8 @@
#include <QByteArray> #include <QByteArray>
#include <QPair> #include <QPair>
#include <functional>
namespace CPlusPlus { namespace CPlusPlus {
class Environment; class Environment;
@@ -81,6 +83,9 @@ public:
QByteArray run(const QString &filename, const QByteArray &source, QByteArray run(const QString &filename, const QByteArray &source,
bool noLines = false, bool markGeneratedTokens = true); bool noLines = false, bool markGeneratedTokens = true);
using CancelChecker = std::function<bool()>;
void setCancelChecker(const CancelChecker &cancelChecker);
bool expandFunctionlikeMacros() const; bool expandFunctionlikeMacros() const;
void setExpandFunctionlikeMacros(bool expandFunctionlikeMacros); void setExpandFunctionlikeMacros(bool expandFunctionlikeMacros);
@@ -253,6 +258,7 @@ private:
Client *m_client; Client *m_client;
Environment *m_env; Environment *m_env;
QByteArray m_scratchBuffer; QByteArray m_scratchBuffer;
CancelChecker m_cancelChecker;
bool m_expandFunctionlikeMacros; bool m_expandFunctionlikeMacros;
bool m_keepComments; bool m_keepComments;

View File

@@ -35,7 +35,8 @@ ClangEditorDocumentParser::ClangEditorDocumentParser(const QString &filePath)
setConfiguration(config); setConfiguration(config);
} }
void ClangEditorDocumentParser::updateHelper(const CppTools::WorkingCopy &) void ClangEditorDocumentParser::updateHelper(const QFutureInterface<void> &,
const CppTools::WorkingCopy &)
{ {
State state_ = state(); State state_ = state();
state_.projectPart = determineProjectPart(filePath(), configuration(), state_); state_.projectPart = determineProjectPart(filePath(), configuration(), state_);

View File

@@ -37,7 +37,8 @@ public:
ClangEditorDocumentParser(const QString &filePath); ClangEditorDocumentParser(const QString &filePath);
private: private:
void updateHelper(const CppTools::WorkingCopy &) override; void updateHelper(const QFutureInterface<void> &future,
const CppTools::WorkingCopy &) override;
}; };
} // namespace ClangCodeModel } // namespace ClangCodeModel

View File

@@ -77,9 +77,16 @@ void BaseEditorDocumentParser::setConfiguration(const Configuration &configurati
} }
void BaseEditorDocumentParser::update(const WorkingCopy &workingCopy) void BaseEditorDocumentParser::update(const WorkingCopy &workingCopy)
{
QFutureInterface<void> dummy;
update(dummy, workingCopy);
}
void BaseEditorDocumentParser::update(const QFutureInterface<void> &future,
const WorkingCopy &workingCopy)
{ {
QMutexLocker locker(&m_updateIsRunning); QMutexLocker locker(&m_updateIsRunning);
updateHelper(workingCopy); updateHelper(future, workingCopy);
} }
BaseEditorDocumentParser::State BaseEditorDocumentParser::state() const BaseEditorDocumentParser::State BaseEditorDocumentParser::state() const

View File

@@ -29,6 +29,7 @@
#include "cppworkingcopy.h" #include "cppworkingcopy.h"
#include "projectpart.h" #include "projectpart.h"
#include <QFutureInterface>
#include <QObject> #include <QObject>
#include <QMutex> #include <QMutex>
@@ -39,7 +40,7 @@ class CPPTOOLS_EXPORT BaseEditorDocumentParser : public QObject
Q_OBJECT Q_OBJECT
public: public:
using Ptr = QSharedPointer<BaseEditorDocumentParser>;; using Ptr = QSharedPointer<BaseEditorDocumentParser>;
static Ptr get(const QString &filePath); static Ptr get(const QString &filePath);
struct Configuration { struct Configuration {
@@ -58,6 +59,7 @@ public:
void setConfiguration(const Configuration &configuration); void setConfiguration(const Configuration &configuration);
void update(const WorkingCopy &workingCopy); void update(const WorkingCopy &workingCopy);
void update(const QFutureInterface<void> &future, const WorkingCopy &workingCopy);
ProjectPart::Ptr projectPart() const; ProjectPart::Ptr projectPart() const;
@@ -76,7 +78,8 @@ protected:
mutable QMutex m_stateAndConfigurationMutex; mutable QMutex m_stateAndConfigurationMutex;
private: private:
virtual void updateHelper(const WorkingCopy &workingCopy) = 0; virtual void updateHelper(const QFutureInterface<void> &future,
const WorkingCopy &workingCopy) = 0;
const QString m_filePath; const QString m_filePath;
Configuration m_configuration; Configuration m_configuration;

View File

@@ -77,7 +77,7 @@ void BaseEditorDocumentProcessor::runParser(QFutureInterface<void> &future,
return; return;
} }
parser->update(workingCopy); parser->update(future, workingCopy);
CppToolsBridge::finishedRefreshingSourceFiles({parser->filePath()}); CppToolsBridge::finishedRefreshingSourceFiles({parser->filePath()});
future.setProgressValue(1); future.setProgressValue(1);

View File

@@ -55,7 +55,8 @@ BuiltinEditorDocumentParser::BuiltinEditorDocumentParser(const QString &filePath
qRegisterMetaType<CPlusPlus::Snapshot>("CPlusPlus::Snapshot"); qRegisterMetaType<CPlusPlus::Snapshot>("CPlusPlus::Snapshot");
} }
void BuiltinEditorDocumentParser::updateHelper(const WorkingCopy &theWorkingCopy) void BuiltinEditorDocumentParser::updateHelper(const QFutureInterface<void> &future,
const WorkingCopy &theWorkingCopy)
{ {
if (filePath().isEmpty()) if (filePath().isEmpty())
return; return;
@@ -181,6 +182,10 @@ void BuiltinEditorDocumentParser::updateHelper(const WorkingCopy &theWorkingCopy
if (releaseSourceAndAST_) if (releaseSourceAndAST_)
doc->releaseSourceAndAST(); doc->releaseSourceAndAST();
}); });
sourceProcessor.setCancelChecker([future]() {
return future.isCanceled();
});
Snapshot globalSnapshot = modelManager->snapshot(); Snapshot globalSnapshot = modelManager->snapshot();
globalSnapshot.remove(filePath()); globalSnapshot.remove(filePath());
sourceProcessor.setGlobalSnapshot(globalSnapshot); sourceProcessor.setGlobalSnapshot(globalSnapshot);

View File

@@ -58,7 +58,8 @@ public:
static Ptr get(const QString &filePath); static Ptr get(const QString &filePath);
private: private:
void updateHelper(const WorkingCopy &workingCopy) override; void updateHelper(const QFutureInterface<void> &future,
const WorkingCopy &workingCopy) override;
void addFileAndDependencies(CPlusPlus::Snapshot *snapshot, void addFileAndDependencies(CPlusPlus::Snapshot *snapshot,
QSet<Utils::FileName> *toRemove, QSet<Utils::FileName> *toRemove,
const Utils::FileName &fileName) const; const Utils::FileName &fileName) const;

View File

@@ -121,6 +121,11 @@ CppSourceProcessor::CppSourceProcessor(const Snapshot &snapshot, DocumentCallbac
CppSourceProcessor::~CppSourceProcessor() CppSourceProcessor::~CppSourceProcessor()
{ } { }
void CppSourceProcessor::setCancelChecker(const CppSourceProcessor::CancelChecker &cancelChecker)
{
m_preprocess.setCancelChecker(cancelChecker);
}
void CppSourceProcessor::setWorkingCopy(const WorkingCopy &workingCopy) void CppSourceProcessor::setWorkingCopy(const WorkingCopy &workingCopy)
{ m_workingCopy = workingCopy; } { m_workingCopy = workingCopy; }

View File

@@ -59,6 +59,9 @@ public:
CppSourceProcessor(const CPlusPlus::Snapshot &snapshot, DocumentCallback documentFinished); CppSourceProcessor(const CPlusPlus::Snapshot &snapshot, DocumentCallback documentFinished);
~CppSourceProcessor(); ~CppSourceProcessor();
using CancelChecker = std::function<bool()>;
void setCancelChecker(const CancelChecker &cancelChecker);
void setWorkingCopy(const CppTools::WorkingCopy &workingCopy); void setWorkingCopy(const CppTools::WorkingCopy &workingCopy);
void setHeaderPaths(const ProjectPartHeaderPaths &headerPaths); void setHeaderPaths(const ProjectPartHeaderPaths &headerPaths);
void setLanguageFeatures(CPlusPlus::LanguageFeatures languageFeatures); void setLanguageFeatures(CPlusPlus::LanguageFeatures languageFeatures);