diff options
author | David Schulz <david.schulz@qt.io> | 2018-09-28 13:37:11 +0200 |
---|---|---|
committer | David Schulz <david.schulz@qt.io> | 2018-10-10 09:05:04 +0000 |
commit | 2730fd4c489f81762eac9088552c8e2f06b9eb77 (patch) | |
tree | 6e1d403ea8ad0b82822c4f9178d37183bfc78af3 | |
parent | fd186bed20ba6e475bade1fac8f909ce86aa18a4 (diff) |
Editor: Do not access a text document from another thread
Task-number: QTCREATORBUG-21192
Change-Id: I5c327f268da2364f1fc4f671993e8498cd0b7421
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
-rw-r--r-- | src/plugins/texteditor/codeassist/documentcontentcompletion.cpp | 76 |
1 files changed, 38 insertions, 38 deletions
diff --git a/src/plugins/texteditor/codeassist/documentcontentcompletion.cpp b/src/plugins/texteditor/codeassist/documentcontentcompletion.cpp index cdb69be9b9..44572146f1 100644 --- a/src/plugins/texteditor/codeassist/documentcontentcompletion.cpp +++ b/src/plugins/texteditor/codeassist/documentcontentcompletion.cpp @@ -46,14 +46,14 @@ class DocumentContentCompletionProcessor : public IAssistProcessor { public: DocumentContentCompletionProcessor(const QString &snippetGroupId); + ~DocumentContentCompletionProcessor() override; IAssistProposal *perform(const AssistInterface *interface) override; - bool running() final { return m_running; } + bool running() final { return m_watcher.isRunning(); } private: - TextEditor::SnippetAssistCollector m_snippetCollector; - IAssistProposal *createProposal(const AssistInterface *interface); - bool m_running = false; + QString m_snippetGroup; + QFutureWatcher<QStringList> m_watcher; }; DocumentContentCompletionProvider::DocumentContentCompletionProvider(const QString &snippetGroup) @@ -71,45 +71,39 @@ IAssistProcessor *DocumentContentCompletionProvider::createProcessor() const } DocumentContentCompletionProcessor::DocumentContentCompletionProcessor(const QString &snippetGroupId) - : m_snippetCollector(snippetGroupId, QIcon(":/texteditor/images/snippet.png")) + : m_snippetGroup(snippetGroupId) { } -IAssistProposal *DocumentContentCompletionProcessor::perform(const AssistInterface *interface) +DocumentContentCompletionProcessor::~DocumentContentCompletionProcessor() { - Utils::onResultReady(Utils::runAsync( - &DocumentContentCompletionProcessor::createProposal, this, interface), - [this](IAssistProposal *proposal){ - m_running = false; - setAsyncProposalAvailable(proposal); - }); - m_running = true; - return nullptr; + if (m_watcher.isRunning()) + m_watcher.cancel(); } -static void generateProposalItems(const QString &text, QSet<QString> &words, - QList<AssistProposalItemInterface *> &items) +static void createProposal(QFutureInterface<QStringList> &future, const QString text) { - static const QRegularExpression wordRE("([a-zA-Z_][a-zA-Z0-9_]{2,})"); + const QRegularExpression wordRE("([a-zA-Z_][a-zA-Z0-9_]{2,})"); - QRegularExpressionMatch match; - int index = text.indexOf(wordRE, 0, &match); - while (index >= 0) { + QSet<QString> words; + QRegularExpressionMatchIterator it = wordRE.globalMatch(text); + while (it.hasNext()) { + if (future.isCanceled()) + return; + QRegularExpressionMatch match = it.next(); const QString &word = match.captured(); - if (!words.contains(word)) { - auto item = new AssistProposalItem(); - item->setText(word); - items.append(item); + if (!words.contains(word)) words.insert(word); - } - index += word.size(); - index = text.indexOf(wordRE, index, &match); } + + future.reportResult(words.toList()); } -IAssistProposal *DocumentContentCompletionProcessor::createProposal( - const AssistInterface *interface) +IAssistProposal *DocumentContentCompletionProcessor::perform(const AssistInterface *interface) { QScopedPointer<const AssistInterface> assistInterface(interface); + if (running()) + return nullptr; + int pos = interface->position(); QChar chr; @@ -126,14 +120,20 @@ IAssistProposal *DocumentContentCompletionProcessor::createProposal( return nullptr; } - QSet<QString> words; - QList<AssistProposalItemInterface *> items = m_snippetCollector.collect(); - QTextBlock block = interface->textDocument()->firstBlock(); + const QString text = interface->textDocument()->toPlainText(); - while (block.isValid()) { - generateProposalItems(block.text(), words, items); - block = block.next(); - } - - return new GenericProposal(pos, items); + m_watcher.setFuture(Utils::runAsync(&createProposal, text)); + QObject::connect(&m_watcher, &QFutureWatcher<QStringList>::resultReadyAt, + &m_watcher, [this, pos](int index){ + const TextEditor::SnippetAssistCollector snippetCollector( + m_snippetGroup, QIcon(":/texteditor/images/snippet.png")); + QList<AssistProposalItemInterface *> items = snippetCollector.collect(); + for (const QString &word : m_watcher.resultAt(index)) { + auto item = new AssistProposalItem(); + item->setText(word); + items.append(item); + } + setAsyncProposalAvailable(new GenericProposal(pos, items)); + }); + return nullptr; } |