diff --git a/src/plugins/cpptools/builtineditordocumentprocessor.cpp b/src/plugins/cpptools/builtineditordocumentprocessor.cpp index 4d8968e3049..0474ed45e69 100644 --- a/src/plugins/cpptools/builtineditordocumentprocessor.cpp +++ b/src/plugins/cpptools/builtineditordocumentprocessor.cpp @@ -50,15 +50,14 @@ enum { debug = 0 }; namespace { -QFuture runHighlighter(const CPlusPlus::Document::Ptr &doc, - const CPlusPlus::Snapshot &snapshot, - QTextDocument *textDocument) +CppTools::CheckSymbols * createHighlighter(const CPlusPlus::Document::Ptr &doc, + const CPlusPlus::Snapshot &snapshot, + QTextDocument *textDocument) { - QFuture failed; - QTC_ASSERT(doc, return failed); - QTC_ASSERT(doc->translationUnit(), return failed); - QTC_ASSERT(doc->translationUnit()->ast(), return failed); - QTC_ASSERT(textDocument, return failed); + QTC_ASSERT(doc, return 0); + QTC_ASSERT(doc->translationUnit(), return 0); + QTC_ASSERT(doc->translationUnit()->ast(), return 0); + QTC_ASSERT(textDocument, return 0); using namespace CPlusPlus; using namespace CppTools; @@ -106,7 +105,7 @@ QFuture runHighlighter(const CPlusPlus::Document } LookupContext context(doc, snapshot); - return CheckSymbols::go(doc, context, macroUses); + return CheckSymbols::create(doc, context, macroUses); } QList toTextEditorBlocks( @@ -128,6 +127,7 @@ BuiltinEditorDocumentProcessor::BuiltinEditorDocumentProcessor( bool enableSemanticHighlighter) : BaseEditorDocumentProcessor(document) , m_parser(document->filePath()) + , m_codeWarningsUpdated(false) , m_semanticHighlighter(enableSemanticHighlighter ? new CppTools::SemanticHighlighter(document) : 0) @@ -141,8 +141,12 @@ BuiltinEditorDocumentProcessor::BuiltinEditorDocumentProcessor( m_semanticHighlighter->setHighlightingRunner( [this]() -> QFuture { const SemanticInfo semanticInfo = m_semanticInfoUpdater.semanticInfo(); - return runHighlighter(semanticInfo.doc, semanticInfo.snapshot, - baseTextDocument()->document()); + CheckSymbols *checkSymbols = createHighlighter(semanticInfo.doc, semanticInfo.snapshot, + baseTextDocument()->document()); + QTC_ASSERT(checkSymbols, return QFuture()); + connect(checkSymbols, &CheckSymbols::codeWarningsUpdated, + this, &BuiltinEditorDocumentProcessor::onCodeWarningsUpdated); + return checkSymbols->start(); }); } @@ -206,9 +210,9 @@ void BuiltinEditorDocumentProcessor::onParserFinished(CPlusPlus::Document::Ptr d const auto ifdefoutBlocks = toTextEditorBlocks(document->skippedBlocks()); emit ifdefedOutBlocksUpdated(revision(), ifdefoutBlocks); - // Emit code warnings - auto codeWarnings = toTextEditorSelections(document->diagnosticMessages(), textDocument()); - emit codeWarningsUpdated(revision(), codeWarnings); + // Store parser warnings + m_codeWarnings = toTextEditorSelections(document->diagnosticMessages(), textDocument()); + m_codeWarningsUpdated = false; emit cppDocumentUpdated(document); @@ -231,6 +235,27 @@ void BuiltinEditorDocumentProcessor::onSemanticInfoUpdated(const SemanticInfo se m_semanticHighlighter->run(); } +void BuiltinEditorDocumentProcessor::onCodeWarningsUpdated( + CPlusPlus::Document::Ptr document, + const QList &codeWarnings) +{ + if (document.isNull()) + return; + + if (document->fileName() != filePath()) + return; // some other document got updated + + if (document->editorRevision() != revision()) + return; // outdated content, wait for a new document to be parsed + + if (m_codeWarningsUpdated) + return; // code warnings already updated + + m_codeWarnings += toTextEditorSelections(codeWarnings, textDocument()); + m_codeWarningsUpdated = true; + emit codeWarningsUpdated(revision(), m_codeWarnings); +} + SemanticInfo::Source BuiltinEditorDocumentProcessor::createSemanticInfoSource(bool force) const { const WorkingCopy workingCopy = CppTools::CppModelManager::instance()->workingCopy(); diff --git a/src/plugins/cpptools/builtineditordocumentprocessor.h b/src/plugins/cpptools/builtineditordocumentprocessor.h index 2ff6c228417..a0901181200 100644 --- a/src/plugins/cpptools/builtineditordocumentprocessor.h +++ b/src/plugins/cpptools/builtineditordocumentprocessor.h @@ -60,6 +60,8 @@ public: private: void onParserFinished(CPlusPlus::Document::Ptr document, CPlusPlus::Snapshot snapshot); void onSemanticInfoUpdated(const CppTools::SemanticInfo semanticInfo); + void onCodeWarningsUpdated(CPlusPlus::Document::Ptr document, + const QList &codeWarnings); SemanticInfo::Source createSemanticInfoSource(bool force) const; @@ -68,6 +70,8 @@ private: QFuture m_parserFuture; CPlusPlus::Snapshot m_documentSnapshot; + QList m_codeWarnings; + bool m_codeWarningsUpdated; SemanticInfoUpdater m_semanticInfoUpdater; QScopedPointer m_semanticHighlighter; diff --git a/src/plugins/cpptools/cppchecksymbols.cpp b/src/plugins/cpptools/cppchecksymbols.cpp index 45a4f3d8a15..90ad1c1565c 100644 --- a/src/plugins/cpptools/cppchecksymbols.cpp +++ b/src/plugins/cpptools/cppchecksymbols.cpp @@ -305,6 +305,16 @@ CheckSymbols::Future CheckSymbols::go(Document::Ptr doc, const LookupContext &co return (new CheckSymbols(doc, context, macroUses))->start(); } +CheckSymbols * CheckSymbols::create(Document::Ptr doc, const LookupContext &context, + const QList ¯oUses) +{ + QTC_ASSERT(doc, return NULL); + QTC_ASSERT(doc->translationUnit(), return NULL); + QTC_ASSERT(doc->translationUnit()->ast(), return NULL); + + return new CheckSymbols(doc, context, macroUses); +} + CheckSymbols::CheckSymbols(Document::Ptr doc, const LookupContext &context, const QList ¯oUses) : ASTVisitor(doc->translationUnit()), _doc(doc), _context(context) , _lineOfLastUsage(0), _macroUses(macroUses) @@ -335,10 +345,6 @@ void CheckSymbols::run() _potentialStatics = collectTypes.statics(); Utils::sort(_macroUses, sortByLinePredicate); - // TODO: Handle concurrent (write) access of diagnostic messages and ensure - // propagation to the editor widget -// _doc->clearDiagnosticMessages(); - if (!isCanceled()) { if (_doc->translationUnit()) { accept(_doc->translationUnit()->ast()); @@ -347,15 +353,15 @@ void CheckSymbols::run() } } + emit codeWarningsUpdated(_doc, _diagMsgs); + reportFinished(); } bool CheckSymbols::warning(unsigned line, unsigned column, const QString &text, unsigned length) { Document::DiagnosticMessage m(Document::DiagnosticMessage::Warning, _fileName, line, column, text, length); - // TODO: Handle concurrent (write) access of diagnostic messages and ensure - // propagation to the editor widget -// _doc->addDiagnosticMessage(m); + _diagMsgs.append(m); return false; } diff --git a/src/plugins/cpptools/cppchecksymbols.h b/src/plugins/cpptools/cppchecksymbols.h index 0700e94bfde..92566b36150 100644 --- a/src/plugins/cpptools/cppchecksymbols.h +++ b/src/plugins/cpptools/cppchecksymbols.h @@ -44,10 +44,12 @@ namespace CppTools { class CPPTOOLS_EXPORT CheckSymbols: + public QObject, protected CPlusPlus::ASTVisitor, public QRunnable, public QFutureInterface { + Q_OBJECT public: virtual ~CheckSymbols(); @@ -70,6 +72,9 @@ public: static Future go(CPlusPlus::Document::Ptr doc, const CPlusPlus::LookupContext &context, const QList ¯oUses); + static CheckSymbols * create(CPlusPlus::Document::Ptr doc, + const CPlusPlus::LookupContext &context, + const QList ¯oUses); static QMap > chunks(const QFuture &future, int from, int to) { @@ -87,6 +92,10 @@ public: return chunks; } +signals: + void codeWarningsUpdated(CPlusPlus::Document::Ptr document, + const QList selections); + protected: using ASTVisitor::visit; using ASTVisitor::endVisit; @@ -182,6 +191,7 @@ private: QSet _potentialStatics; QList _astStack; QVector _usages; + QList _diagMsgs; int _chunkSize; unsigned _lineOfLastUsage; QList _macroUses; diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 1980bf82584..a07bf91238a 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -307,6 +307,8 @@ CppModelManager::CppModelManager(QObject *parent) this, SLOT(onCoreAboutToClose())); qRegisterMetaType("CPlusPlus::Document::Ptr"); + qRegisterMetaType>( + "QList"); d->m_modelManagerSupportFallback.reset(new ModelManagerSupportInternal); CppToolsPlugin::instance()->codeModelSettings()->setDefaultId(