From 7ce9ef9db4ae499f4c7ac67e3640785634d5e369 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Wed, 18 Nov 2015 17:07:44 +0100 Subject: [PATCH] Clang: Integrate highlighting results from backend Change-Id: I2c3fb69aabfe075bde76d63eafc2ca370f17493c Reviewed-by: Marco Bubke --- .../clangbackendipc/clangbackendipc-lib.pri | 10 +- src/libs/clangbackendipc/cmbmessages.cpp | 7 + .../highlightingchangedmessage.cpp | 119 +++++++++++ .../highlightingchangedmessage.h | 80 ++++++++ .../highlightingmarkcontainer.cpp | 173 ++++++++++++++++ .../highlightingmarkcontainer.h | 79 ++++++++ .../clangbackendipc/ipcclientdispatcher.cpp | 6 + .../clangbackendipc/ipcclientdispatcher.h | 1 + .../clangbackendipc/ipcclientinterface.cpp | 4 + src/libs/clangbackendipc/ipcclientinterface.h | 3 + src/libs/clangbackendipc/ipcclientproxy.cpp | 6 + src/libs/clangbackendipc/ipcclientproxy.h | 1 + .../clangbackendipc/ipcserverinterface.cpp | 5 +- src/libs/clangbackendipc/ipcserverinterface.h | 1 + src/libs/clangbackendipc/ipcserverproxy.cpp | 6 + src/libs/clangbackendipc/ipcserverproxy.h | 2 + .../requesthighlightingmessage.cpp | 89 ++++++++ .../requesthighlightingmessage.h | 69 +++++++ .../clangbackendipcintegration.cpp | 72 +++++-- .../clangbackendipcintegration.h | 12 +- src/plugins/clangcodemodel/clangcodemodel.pro | 2 + src/plugins/clangcodemodel/clangcodemodel.qbs | 2 + .../clangcodemodel/clangcodemodelplugin.cpp | 5 - .../clangcodemodel/clangcodemodelplugin.h | 2 - .../clangcodemodelunittestfiles.pri | 6 +- .../clangeditordocumentparser.cpp | 91 +-------- .../clangeditordocumentparser.h | 15 +- .../clangeditordocumentprocessor.cpp | 116 +++++------ .../clangeditordocumentprocessor.h | 12 +- .../clangmodelmanagersupport.cpp | 2 +- .../highlightingmarksreporter.cpp | 155 ++++++++++++++ .../highlightingmarksreporter.h | 80 ++++++++ .../test/clangcodecompletion_test.cpp | 7 + src/plugins/cpptools/cppprojects.h | 2 - .../clangbackend/ipcsource/clangipcserver.cpp | 83 +++++--- .../clangbackend/ipcsource/clangipcserver.h | 5 +- .../ipcsource/clangtranslationunit.cpp | 14 ++ .../ipcsource/clangtranslationunit.h | 2 + .../ipcsource/highlightinginformation.cpp | 35 +--- .../ipcsource/highlightinginformation.h | 4 +- .../ipcsource/highlightinginformations.cpp | 18 ++ .../ipcsource/highlightinginformations.h | 3 + .../ipcsource/translationunits.cpp | 79 +++++--- .../clangbackend/ipcsource/translationunits.h | 28 ++- tests/unit/echoserver/echoipcserver.cpp | 6 + tests/unit/echoserver/echoipcserver.h | 1 + .../mockup/texteditor/semantichighlighter.h | 68 +++++++ tests/unit/unittest/chunksreportedmonitor.cpp | 64 ++++++ tests/unit/unittest/chunksreportedmonitor.h | 63 ++++++ tests/unit/unittest/clangipcservertest.cpp | 20 ++ .../unittest/clientserverinprocesstest.cpp | 28 +++ .../unittest/clientserveroutsideprocess.cpp | 1 + .../unittest/highlightinginformationstest.cpp | 8 + .../highlightingmarksreportertest.cpp | 190 ++++++++++++++++++ tests/unit/unittest/mockipclient.h | 2 + tests/unit/unittest/mockipcserver.h | 2 + ...back.h => mocksendeditorupdatescallback.h} | 16 +- .../unittest/readandwritemessageblocktest.cpp | 17 ++ tests/unit/unittest/translationunitstest.cpp | 134 +++++++----- tests/unit/unittest/translationunittest.cpp | 86 +++++--- tests/unit/unittest/unittest.pro | 7 +- 61 files changed, 1844 insertions(+), 382 deletions(-) create mode 100644 src/libs/clangbackendipc/highlightingchangedmessage.cpp create mode 100644 src/libs/clangbackendipc/highlightingchangedmessage.h create mode 100644 src/libs/clangbackendipc/highlightingmarkcontainer.cpp create mode 100644 src/libs/clangbackendipc/highlightingmarkcontainer.h create mode 100644 src/libs/clangbackendipc/requesthighlightingmessage.cpp create mode 100644 src/libs/clangbackendipc/requesthighlightingmessage.h create mode 100644 src/plugins/clangcodemodel/highlightingmarksreporter.cpp create mode 100644 src/plugins/clangcodemodel/highlightingmarksreporter.h create mode 100644 tests/unit/mockup/texteditor/semantichighlighter.h create mode 100644 tests/unit/unittest/chunksreportedmonitor.cpp create mode 100644 tests/unit/unittest/chunksreportedmonitor.h create mode 100644 tests/unit/unittest/highlightingmarksreportertest.cpp rename tests/unit/unittest/{mocksenddiagnosticscallback.h => mocksendeditorupdatescallback.h} (82%) diff --git a/src/libs/clangbackendipc/clangbackendipc-lib.pri b/src/libs/clangbackendipc/clangbackendipc-lib.pri index 6ac4144d5c..cbe5ad01fe 100644 --- a/src/libs/clangbackendipc/clangbackendipc-lib.pri +++ b/src/libs/clangbackendipc/clangbackendipc-lib.pri @@ -42,10 +42,13 @@ SOURCES += $$PWD/ipcserverinterface.cpp \ $$PWD/sourcelocationcontainer.cpp \ $$PWD/fixitcontainer.cpp \ $$PWD/requestdiagnosticsmessage.cpp \ + $$PWD/requesthighlightingmessage.cpp \ $$PWD/registerunsavedfilesforeditormessage.cpp \ $$PWD/unregisterunsavedfilesforeditormessage.cpp \ $$PWD/updatetranslationunitsforeditormessage.cpp \ - $$PWD/updatevisibletranslationunitsmessage.cpp + $$PWD/updatevisibletranslationunitsmessage.cpp \ + $$PWD/highlightingchangedmessage.cpp \ + $$PWD/highlightingmarkcontainer.cpp HEADERS += \ $$PWD/ipcserverinterface.h \ @@ -84,9 +87,12 @@ HEADERS += \ $$PWD/sourcelocationcontainer.h \ $$PWD/fixitcontainer.h \ $$PWD/requestdiagnosticsmessage.h \ + $$PWD/requesthighlightingmessage.h \ $$PWD/registerunsavedfilesforeditormessage.h \ $$PWD/unregisterunsavedfilesforeditormessage.h \ $$PWD/updatetranslationunitsforeditormessage.h \ - $$PWD/updatevisibletranslationunitsmessage.h + $$PWD/updatevisibletranslationunitsmessage.h \ + $$PWD/highlightingchangedmessage.h \ + $$PWD/highlightingmarkcontainer.h contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols diff --git a/src/libs/clangbackendipc/cmbmessages.cpp b/src/libs/clangbackendipc/cmbmessages.cpp index d275de5353..c3ce8d0e17 100644 --- a/src/libs/clangbackendipc/cmbmessages.cpp +++ b/src/libs/clangbackendipc/cmbmessages.cpp @@ -43,6 +43,9 @@ #include "diagnosticschangedmessage.h" #include "registerunsavedfilesforeditormessage.h" #include "requestdiagnosticsmessage.h" +#include "requesthighlightingmessage.h" +#include "highlightingchangedmessage.h" +#include "highlightingmarkcontainer.h" #include "projectpartsdonotexistmessage.h" #include "sourcelocationcontainer.h" #include "sourcerangecontainer.h" @@ -83,6 +86,9 @@ void Messages::registerMessages() registerMetaType(); registerMetaType(); + registerMetaType(); + registerMetaType(); + registerMetaType(); registerMetaType(); @@ -94,6 +100,7 @@ void Messages::registerMessages() // Containers registerMetaType(); + registerMetaType(); registerMetaType(); registerMetaType(); registerMetaType(); diff --git a/src/libs/clangbackendipc/highlightingchangedmessage.cpp b/src/libs/clangbackendipc/highlightingchangedmessage.cpp new file mode 100644 index 0000000000..b049ebef52 --- /dev/null +++ b/src/libs/clangbackendipc/highlightingchangedmessage.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "highlightingchangedmessage.h" + +#include "container_common.h" + +#include +#include + +#include + +namespace ClangBackEnd { + +HighlightingChangedMessage::HighlightingChangedMessage(const FileContainer &file, + const QVector &highlightingMarks, + const QVector &skippedPreprocessorRanges) + : file_(file), + highlightingMarks_(highlightingMarks), + skippedPreprocessorRanges_(skippedPreprocessorRanges) +{ +} + +const FileContainer &HighlightingChangedMessage::file() const +{ + return file_; +} + +const QVector &HighlightingChangedMessage::highlightingMarks() const +{ + return highlightingMarks_; +} + +const QVector &HighlightingChangedMessage::skippedPreprocessorRanges() const +{ + return skippedPreprocessorRanges_; +} + +QDataStream &operator<<(QDataStream &out, const HighlightingChangedMessage &message) +{ + out << message.file_; + out << message.highlightingMarks_; + out << message.skippedPreprocessorRanges_; + + return out; +} + +QDataStream &operator>>(QDataStream &in, HighlightingChangedMessage &message) +{ + in >> message.file_; + in >> message.highlightingMarks_; + in >> message.skippedPreprocessorRanges_; + + return in; +} + +bool operator==(const HighlightingChangedMessage &first, const HighlightingChangedMessage &second) +{ + return first.file_ == second.file_ + && first.highlightingMarks_ == second.highlightingMarks_ + && first.skippedPreprocessorRanges_ == second.skippedPreprocessorRanges_; +} + +bool operator<(const HighlightingChangedMessage &first, const HighlightingChangedMessage &second) +{ + return first.file_ < second.file_ + && compareContainer(first.highlightingMarks_, second.highlightingMarks_) + && compareContainer(first.skippedPreprocessorRanges_, second.skippedPreprocessorRanges_); +} + +QDebug operator<<(QDebug debug, const HighlightingChangedMessage &message) +{ + debug.nospace() << "HighlightingChangedMessage(" + << message.file_ + << ", " << message.highlightingMarks_.size() + << ", " << message.skippedPreprocessorRanges_.size() + << ")"; + + return debug; +} + +void PrintTo(const HighlightingChangedMessage &message, ::std::ostream* os) +{ + *os << "HighlightingChangedMessage("; + PrintTo(message.file(), os); + *os << "," << message.highlightingMarks().size(); + *os << "," << message.skippedPreprocessorRanges().size(); + *os << ")"; +} + +} // namespace ClangBackEnd + diff --git a/src/libs/clangbackendipc/highlightingchangedmessage.h b/src/libs/clangbackendipc/highlightingchangedmessage.h new file mode 100644 index 0000000000..6efabe19ee --- /dev/null +++ b/src/libs/clangbackendipc/highlightingchangedmessage.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CLANGBACKEND_HIGHLIGHTINGCHANGEDMESSAGE_H +#define CLANGBACKEND_HIGHLIGHTINGCHANGEDMESSAGE_H + +#include "clangbackendipc_global.h" +#include "filecontainer.h" +#include "highlightingmarkcontainer.h" +#include "sourcerangecontainer.h" + +#include + +namespace ClangBackEnd { + +class CMBIPC_EXPORT HighlightingChangedMessage +{ + friend CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const HighlightingChangedMessage &message); + friend CMBIPC_EXPORT QDataStream &operator>>(QDataStream &in, HighlightingChangedMessage &message); + friend CMBIPC_EXPORT bool operator==(const HighlightingChangedMessage &first, const HighlightingChangedMessage &second); + friend CMBIPC_EXPORT bool operator<(const HighlightingChangedMessage &first, const HighlightingChangedMessage &second); + friend CMBIPC_EXPORT QDebug operator<<(QDebug debug, const HighlightingChangedMessage &message); + friend void PrintTo(const HighlightingChangedMessage &message, ::std::ostream* os); + +public: + HighlightingChangedMessage() = default; + HighlightingChangedMessage(const FileContainer &file, + const QVector &highlightingMarks, + const QVector &skippedPreprocessorRanges); + + const FileContainer &file() const; + const QVector &highlightingMarks() const; + const QVector &skippedPreprocessorRanges() const; + +private: + FileContainer file_; + QVector highlightingMarks_; + QVector skippedPreprocessorRanges_; +}; + +CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const HighlightingChangedMessage &message); +CMBIPC_EXPORT QDataStream &operator>>(QDataStream &in, HighlightingChangedMessage &message); +CMBIPC_EXPORT bool operator==(const HighlightingChangedMessage &first, const HighlightingChangedMessage &second); +CMBIPC_EXPORT bool operator<(const HighlightingChangedMessage &first, const HighlightingChangedMessage &second); + +CMBIPC_EXPORT QDebug operator<<(QDebug debug, const HighlightingChangedMessage &message); +void PrintTo(const HighlightingChangedMessage &message, ::std::ostream* os); + +} // namespace ClangBackEnd + +Q_DECLARE_METATYPE(ClangBackEnd::HighlightingChangedMessage) + +#endif // CLANGBACKEND_HIGHLIGHTINGCHANGEDMESSAGE_H diff --git a/src/libs/clangbackendipc/highlightingmarkcontainer.cpp b/src/libs/clangbackendipc/highlightingmarkcontainer.cpp new file mode 100644 index 0000000000..efa5b04af2 --- /dev/null +++ b/src/libs/clangbackendipc/highlightingmarkcontainer.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "highlightingmarkcontainer.h" + +#include +#include + +#include + +namespace ClangBackEnd { + +HighlightingMarkContainer::HighlightingMarkContainer(uint line, + uint column, + uint length, + HighlightingType type) + : line_(line), + column_(column), + length_(length), + type_(type) +{ +} + +uint HighlightingMarkContainer::line() const +{ + return line_; +} + +uint HighlightingMarkContainer::column() const +{ + return column_; +} + +uint HighlightingMarkContainer::length() const +{ + return length_; +} + +HighlightingType HighlightingMarkContainer::type() const +{ + return type_; +} + +quint32 &HighlightingMarkContainer::typeAsInt() +{ + return reinterpret_cast(type_); +} + +QDataStream &operator<<(QDataStream &out, const HighlightingMarkContainer &container) +{ + out << container.line_; + out << container.column_; + out << container.length_; + out << quint32(container.type_); + + return out; +} + +QDataStream &operator>>(QDataStream &in, HighlightingMarkContainer &container) +{ + in >> container.line_; + in >> container.column_; + in >> container.length_; + in >> container.typeAsInt(); + + return in; +} + +bool operator==(const HighlightingMarkContainer &first, const HighlightingMarkContainer &second) +{ + return first.line_ == second.line_ + && first.column_ == second.column_ + && first.length_ == second.length_ + && first.type_ == second.type_; +} + +bool operator<(const HighlightingMarkContainer &first, const HighlightingMarkContainer &second) +{ + if (first.line() == second.line()) { + if (first.column() == second.column()) { + if (first.length() == second.length()) + return first.type() < second.type(); + return first.length() < second.length(); + } + + return first.column() < second.column(); + } + + return first.line() < second.line(); +} + +#define RETURN_TEXT_FOR_CASE(enumValue) case HighlightingType::enumValue: return #enumValue +static const char *highlightingTypeToCStringLiteral(HighlightingType type) +{ + switch (type) { + RETURN_TEXT_FOR_CASE(Invalid); + RETURN_TEXT_FOR_CASE(Comment); + RETURN_TEXT_FOR_CASE(Keyword); + RETURN_TEXT_FOR_CASE(StringLiteral); + RETURN_TEXT_FOR_CASE(NumberLiteral); + RETURN_TEXT_FOR_CASE(Function); + RETURN_TEXT_FOR_CASE(VirtualFunction); + RETURN_TEXT_FOR_CASE(Type); + RETURN_TEXT_FOR_CASE(LocalVariable); + RETURN_TEXT_FOR_CASE(GlobalVariable); + RETURN_TEXT_FOR_CASE(Field); + RETURN_TEXT_FOR_CASE(Enumeration); + RETURN_TEXT_FOR_CASE(Operator); + RETURN_TEXT_FOR_CASE(Preprocessor); + RETURN_TEXT_FOR_CASE(Label); + RETURN_TEXT_FOR_CASE(OutputArgument); + RETURN_TEXT_FOR_CASE(PreprocessorDefinition); + RETURN_TEXT_FOR_CASE(PreprocessorExpansion); + default: return "UnhandledHighlightingType"; + } +} +#undef RETURN_TEXT_FOR_CASE + +QDebug operator<<(QDebug debug, const HighlightingMarkContainer &container) +{ + debug.nospace() << "HighlightingMarkContainer(" + << container.line() << ", " + << container.column() << ", " + << container.length() << ", " + << highlightingTypeToCStringLiteral(container.type()) << ", " + << ")"; + + return debug; +} + +void PrintTo(HighlightingType highlightingType, std::ostream *os) +{ + *os << highlightingTypeToCStringLiteral(highlightingType); +} + +void PrintTo(const HighlightingMarkContainer& container, ::std::ostream *os) +{ + *os << "HighlightingMarkContainer(" + << container.line() << ", " + << container.column() << ", " + << container.length() << ", "; + PrintTo(container.type(), os); + *os << ")"; +} + +} // namespace ClangBackEnd diff --git a/src/libs/clangbackendipc/highlightingmarkcontainer.h b/src/libs/clangbackendipc/highlightingmarkcontainer.h new file mode 100644 index 0000000000..e466cb868e --- /dev/null +++ b/src/libs/clangbackendipc/highlightingmarkcontainer.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CLANGBACKEND_HIGHLIGHTINGMARKCONTAINER_H +#define CLANGBACKEND_HIGHLIGHTINGMARKCONTAINER_H + +#include "clangbackendipc_global.h" + +#include + +namespace ClangBackEnd { + +class CMBIPC_EXPORT HighlightingMarkContainer +{ + friend CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const HighlightingMarkContainer &container); + friend CMBIPC_EXPORT QDataStream &operator>>(QDataStream &in, HighlightingMarkContainer &container); + friend CMBIPC_EXPORT bool operator==(const HighlightingMarkContainer &first, const HighlightingMarkContainer &second); + friend CMBIPC_EXPORT bool operator<(const HighlightingMarkContainer &first, const HighlightingMarkContainer &second); + +public: + HighlightingMarkContainer() = default; + HighlightingMarkContainer(uint line, uint column, uint length, HighlightingType type); + + uint line() const; + uint column() const; + uint length() const; + HighlightingType type() const; + +private: + quint32 &typeAsInt(); + +private: + uint line_; + uint column_; + uint length_; + HighlightingType type_; +}; + +CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const HighlightingMarkContainer &container); +CMBIPC_EXPORT QDataStream &operator>>(QDataStream &in, HighlightingMarkContainer &container); +CMBIPC_EXPORT bool operator==(const HighlightingMarkContainer &first, const HighlightingMarkContainer &second); +CMBIPC_EXPORT bool operator<(const HighlightingMarkContainer &first, const HighlightingMarkContainer &second); + +CMBIPC_EXPORT QDebug operator<<(QDebug debug, const HighlightingMarkContainer &container); +CMBIPC_EXPORT void PrintTo(HighlightingType highlightingType, ::std::ostream *os); +void PrintTo(const HighlightingMarkContainer &container, ::std::ostream *os); + +} // namespace ClangBackEnd + +Q_DECLARE_METATYPE(ClangBackEnd::HighlightingMarkContainer) + +#endif // CLANGBACKEND_HIGHLIGHTINGMARKCONTAINER_H diff --git a/src/libs/clangbackendipc/ipcclientdispatcher.cpp b/src/libs/clangbackendipc/ipcclientdispatcher.cpp index bd9c7eb7f2..6b22a29f4a 100644 --- a/src/libs/clangbackendipc/ipcclientdispatcher.cpp +++ b/src/libs/clangbackendipc/ipcclientdispatcher.cpp @@ -80,5 +80,11 @@ void IpcClientDispatcher::diagnosticsChanged(const DiagnosticsChangedMessage &me client->diagnosticsChanged(message); } +void IpcClientDispatcher::highlightingChanged(const HighlightingChangedMessage &message) +{ + for (auto *client : clients) + client->highlightingChanged(message); +} + } // namespace ClangBackEnd diff --git a/src/libs/clangbackendipc/ipcclientdispatcher.h b/src/libs/clangbackendipc/ipcclientdispatcher.h index 7d8329e416..e8445df1f0 100644 --- a/src/libs/clangbackendipc/ipcclientdispatcher.h +++ b/src/libs/clangbackendipc/ipcclientdispatcher.h @@ -49,6 +49,7 @@ public: void translationUnitDoesNotExist(const TranslationUnitDoesNotExistMessage &message) override; void projectPartsDoNotExist(const ProjectPartsDoNotExistMessage &message) override; void diagnosticsChanged(const DiagnosticsChangedMessage &message) override; + void highlightingChanged(const HighlightingChangedMessage &message) override; private: QVector clients; diff --git a/src/libs/clangbackendipc/ipcclientinterface.cpp b/src/libs/clangbackendipc/ipcclientinterface.cpp index 28d2410662..b6447949e6 100644 --- a/src/libs/clangbackendipc/ipcclientinterface.cpp +++ b/src/libs/clangbackendipc/ipcclientinterface.cpp @@ -35,6 +35,7 @@ #include "projectpartsdonotexistmessage.h" #include "translationunitdoesnotexistmessage.h" #include "diagnosticschangedmessage.h" +#include "highlightingchangedmessage.h" #include #include @@ -50,6 +51,7 @@ void IpcClientInterface::dispatch(const QVariant &message) static const int translationUnitDoesNotExistMessage = QMetaType::type("ClangBackEnd::TranslationUnitDoesNotExistMessage"); static const int projectPartsDoNotExistMessage = QMetaType::type("ClangBackEnd::ProjectPartsDoNotExistMessage"); static const int diagnosticsChangedMessage = QMetaType::type("ClangBackEnd::DiagnosticsChangedMessage"); + static const int highlightingChangedMessage = QMetaType::type("ClangBackEnd::HighlightingChangedMessage"); int type = message.userType(); @@ -65,6 +67,8 @@ void IpcClientInterface::dispatch(const QVariant &message) projectPartsDoNotExist(message.value()); else if (type == diagnosticsChangedMessage) diagnosticsChanged(message.value()); + else if (type == highlightingChangedMessage) + highlightingChanged(message.value()); else qWarning() << "Unknown IpcClientMessage"; } diff --git a/src/libs/clangbackendipc/ipcclientinterface.h b/src/libs/clangbackendipc/ipcclientinterface.h index 5600e13076..539371e12d 100644 --- a/src/libs/clangbackendipc/ipcclientinterface.h +++ b/src/libs/clangbackendipc/ipcclientinterface.h @@ -51,6 +51,8 @@ class RequestDiagnosticsMessage; class RegisterUnsavedFilesForEditorMessage; class UnregisterUnsavedFilesForEditorMessage; class UpdateVisibleTranslationUnitsMessage; +class RequestHighlightingMessage; +class HighlightingChangedMessage; class CMBIPC_EXPORT IpcClientInterface : public IpcInterface { @@ -63,6 +65,7 @@ public: virtual void translationUnitDoesNotExist(const TranslationUnitDoesNotExistMessage &message) = 0; virtual void projectPartsDoNotExist(const ProjectPartsDoNotExistMessage &message) = 0; virtual void diagnosticsChanged(const DiagnosticsChangedMessage &message) = 0; + virtual void highlightingChanged(const HighlightingChangedMessage &message) = 0; }; } // namespace ClangBackEnd diff --git a/src/libs/clangbackendipc/ipcclientproxy.cpp b/src/libs/clangbackendipc/ipcclientproxy.cpp index cb058b7bb4..cbfddf8522 100644 --- a/src/libs/clangbackendipc/ipcclientproxy.cpp +++ b/src/libs/clangbackendipc/ipcclientproxy.cpp @@ -35,6 +35,7 @@ #include "cmbechomessage.h" #include "cmbregistertranslationunitsforeditormessage.h" #include "diagnosticschangedmessage.h" +#include "highlightingchangedmessage.h" #include "ipcserverinterface.h" #include "projectpartsdonotexistmessage.h" #include "translationunitdoesnotexistmessage.h" @@ -104,6 +105,11 @@ void IpcClientProxy::diagnosticsChanged(const DiagnosticsChangedMessage &message writeMessageBlock.write(QVariant::fromValue(message)); } +void IpcClientProxy::highlightingChanged(const HighlightingChangedMessage &message) +{ + writeMessageBlock.write(QVariant::fromValue(message)); +} + void IpcClientProxy::readMessages() { for (const QVariant &message : readMessageBlock.readAll()) diff --git a/src/libs/clangbackendipc/ipcclientproxy.h b/src/libs/clangbackendipc/ipcclientproxy.h index 77b53c7cd2..d239631b9a 100644 --- a/src/libs/clangbackendipc/ipcclientproxy.h +++ b/src/libs/clangbackendipc/ipcclientproxy.h @@ -63,6 +63,7 @@ public: void translationUnitDoesNotExist(const TranslationUnitDoesNotExistMessage &message) override; void projectPartsDoNotExist(const ProjectPartsDoNotExistMessage &message) override; void diagnosticsChanged(const DiagnosticsChangedMessage &message) override; + void highlightingChanged(const HighlightingChangedMessage &message) override; void readMessages(); diff --git a/src/libs/clangbackendipc/ipcserverinterface.cpp b/src/libs/clangbackendipc/ipcserverinterface.cpp index 93717dfa33..d25fee4525 100644 --- a/src/libs/clangbackendipc/ipcserverinterface.cpp +++ b/src/libs/clangbackendipc/ipcserverinterface.cpp @@ -37,6 +37,7 @@ #include "cmbunregistertranslationunitsforeditormessage.h" #include "registerunsavedfilesforeditormessage.h" #include "requestdiagnosticsmessage.h" +#include "requesthighlightingmessage.h" #include "unregisterunsavedfilesforeditormessage.h" #include "updatetranslationunitsforeditormessage.h" #include "updatevisibletranslationunitsmessage.h" @@ -58,9 +59,9 @@ void IpcServerInterface::dispatch(const QVariant &message) static const int unregisterUnsavedFilesForEditorMessageType = QMetaType::type("ClangBackEnd::UnregisterUnsavedFilesForEditorMessage"); static const int completeCodeMessageType = QMetaType::type("ClangBackEnd::CompleteCodeMessage"); static const int requestDiagnosticsMessageType = QMetaType::type("ClangBackEnd::RequestDiagnosticsMessage"); + static const int requestHighlightingTypeMessage = QMetaType::type("ClangBackEnd::RequestHighlightingMessage"); static const int updateVisibleTranslationUnitsMessageType = QMetaType::type("ClangBackEnd::UpdateVisibleTranslationUnitsMessage"); - int type = message.userType(); if (type == endMessageType) @@ -83,6 +84,8 @@ void IpcServerInterface::dispatch(const QVariant &message) completeCode(message.value()); else if (type == requestDiagnosticsMessageType) requestDiagnostics(message.value()); + else if (type == requestHighlightingTypeMessage) + requestHighlighting(message.value()); else if (type == updateVisibleTranslationUnitsMessageType) updateVisibleTranslationUnits(message.value()); else diff --git a/src/libs/clangbackendipc/ipcserverinterface.h b/src/libs/clangbackendipc/ipcserverinterface.h index 98d1441c0d..451bcaab75 100644 --- a/src/libs/clangbackendipc/ipcserverinterface.h +++ b/src/libs/clangbackendipc/ipcserverinterface.h @@ -54,6 +54,7 @@ public: virtual void unregisterUnsavedFilesForEditor(const UnregisterUnsavedFilesForEditorMessage &message) = 0; virtual void completeCode(const CompleteCodeMessage &message) = 0; virtual void requestDiagnostics(const RequestDiagnosticsMessage &message) = 0; + virtual void requestHighlighting(const RequestHighlightingMessage &message) = 0; virtual void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) = 0; void addClient(IpcClientInterface *client); diff --git a/src/libs/clangbackendipc/ipcserverproxy.cpp b/src/libs/clangbackendipc/ipcserverproxy.cpp index fa5777267c..90419da958 100644 --- a/src/libs/clangbackendipc/ipcserverproxy.cpp +++ b/src/libs/clangbackendipc/ipcserverproxy.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -120,6 +121,11 @@ void IpcServerProxy::requestDiagnostics(const ClangBackEnd::RequestDiagnosticsMe writeMessageBlock.write(QVariant::fromValue(message)); } +void IpcServerProxy::requestHighlighting(const RequestHighlightingMessage &message) +{ + writeMessageBlock.write(QVariant::fromValue(message)); +} + void IpcServerProxy::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) { writeMessageBlock.write(QVariant::fromValue(message)); diff --git a/src/libs/clangbackendipc/ipcserverproxy.h b/src/libs/clangbackendipc/ipcserverproxy.h index d4c42887f4..6d6db7e4f2 100644 --- a/src/libs/clangbackendipc/ipcserverproxy.h +++ b/src/libs/clangbackendipc/ipcserverproxy.h @@ -65,7 +65,9 @@ public: void unregisterUnsavedFilesForEditor(const UnregisterUnsavedFilesForEditorMessage &message) override; void completeCode(const CompleteCodeMessage &message) override; void requestDiagnostics(const RequestDiagnosticsMessage &message) override; + void requestHighlighting(const RequestHighlightingMessage &message) override; void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override; + void readMessages(); void resetCounter(); diff --git a/src/libs/clangbackendipc/requesthighlightingmessage.cpp b/src/libs/clangbackendipc/requesthighlightingmessage.cpp new file mode 100644 index 0000000000..8dcc105e1f --- /dev/null +++ b/src/libs/clangbackendipc/requesthighlightingmessage.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "requesthighlightingmessage.h" + +#include +#include + +#include + +namespace ClangBackEnd { + +RequestHighlightingMessage::RequestHighlightingMessage(const FileContainer &file) + : fileContainer_(file) +{ +} + +const FileContainer RequestHighlightingMessage::fileContainer() const +{ + return fileContainer_; +} + +QDataStream &operator<<(QDataStream &out, const RequestHighlightingMessage &message) +{ + out << message.fileContainer_; + + return out; +} + +QDataStream &operator>>(QDataStream &in, RequestHighlightingMessage &message) +{ + in >> message.fileContainer_; + + return in; +} + +bool operator==(const RequestHighlightingMessage &first, const RequestHighlightingMessage &second) +{ + return first.fileContainer_ == second.fileContainer_; +} + +bool operator<(const RequestHighlightingMessage &first, const RequestHighlightingMessage &second) +{ + return first.fileContainer_ < second.fileContainer_; +} + +QDebug operator<<(QDebug debug, const RequestHighlightingMessage &message) +{ + debug.nospace() << "RequestHighlightingMessage(" + << message.fileContainer() + << ")"; + + return debug; +} + +void PrintTo(const RequestHighlightingMessage &message, ::std::ostream* os) +{ + *os << message.fileContainer().filePath().constData() + << "(" << message.fileContainer().projectPartId().constData() << ")"; +} + +} // namespace ClangBackEnd diff --git a/src/libs/clangbackendipc/requesthighlightingmessage.h b/src/libs/clangbackendipc/requesthighlightingmessage.h new file mode 100644 index 0000000000..ff611d5216 --- /dev/null +++ b/src/libs/clangbackendipc/requesthighlightingmessage.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CLANGBACKEND_REQUESTHIGHLIGHTING_H +#define CLANGBACKEND_REQUESTHIGHLIGHTING_H + +#include "filecontainer.h" + +namespace ClangBackEnd { + +class CMBIPC_EXPORT RequestHighlightingMessage +{ + friend CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const RequestHighlightingMessage &message); + friend CMBIPC_EXPORT QDataStream &operator>>(QDataStream &in, RequestHighlightingMessage &message); + friend CMBIPC_EXPORT bool operator==(const RequestHighlightingMessage &first, const RequestHighlightingMessage &second); + friend CMBIPC_EXPORT bool operator<(const RequestHighlightingMessage &first, const RequestHighlightingMessage &second); + friend CMBIPC_EXPORT QDebug operator<<(QDebug debug, const RequestHighlightingMessage &message); + friend void PrintTo(const RequestHighlightingMessage &message, ::std::ostream* os); + +public: + RequestHighlightingMessage() = default; + RequestHighlightingMessage(const FileContainer &fileContainer); + + const FileContainer fileContainer() const; + +private: + FileContainer fileContainer_; +}; + +CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const RequestHighlightingMessage &message); +CMBIPC_EXPORT QDataStream &operator>>(QDataStream &in, RequestHighlightingMessage &message); +CMBIPC_EXPORT bool operator==(const RequestHighlightingMessage &first, const RequestHighlightingMessage &second); +CMBIPC_EXPORT bool operator<(const RequestHighlightingMessage &first, const RequestHighlightingMessage &second); + +CMBIPC_EXPORT QDebug operator<<(QDebug debug, const RequestHighlightingMessage &message); +void PrintTo(const RequestHighlightingMessage &message, ::std::ostream* os); + +} // namespace ClangBackEnd + +Q_DECLARE_METATYPE(ClangBackEnd::RequestHighlightingMessage) + +#endif // CLANGBACKEND_REQUESTHIGHLIGHTING_H diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp index 24c3415b0f..055099e7c6 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp @@ -48,6 +48,7 @@ #include #include +#include #include #include @@ -62,6 +63,7 @@ #include #include #include +#include #include #include #include @@ -174,6 +176,24 @@ void IpcReceiver::diagnosticsChanged(const DiagnosticsChangedMessage &message) } } +void IpcReceiver::highlightingChanged(const HighlightingChangedMessage &message) +{ + qCDebug(log) << "<<< HighlightingChangedMessage with" + << message.highlightingMarks().size() << "items"; + + auto processor = ClangEditorDocumentProcessor::get(message.file().filePath()); + + if (processor && processor->projectPart()) { + const QString highlightingProjectPartId = message.file().projectPartId(); + const QString documentProjectPartId = processor->projectPart()->id(); + if (highlightingProjectPartId == documentProjectPartId) { + processor->updateHighlighting(message.highlightingMarks(), + message.skippedPreprocessorRanges(), + message.file().documentRevision()); + } + } +} + void IpcReceiver::translationUnitDoesNotExist(const TranslationUnitDoesNotExistMessage &message) { QTC_CHECK(!"Got TranslationUnitDoesNotExistMessage"); @@ -203,6 +223,7 @@ public: void unregisterUnsavedFilesForEditor(const ClangBackEnd::UnregisterUnsavedFilesForEditorMessage &message) override; void completeCode(const ClangBackEnd::CompleteCodeMessage &message) override; void requestDiagnostics(const ClangBackEnd::RequestDiagnosticsMessage &message) override; + void requestHighlighting(const ClangBackEnd::RequestHighlightingMessage &message) override; private: ClangBackEnd::ConnectionClient &m_connection; @@ -268,6 +289,12 @@ void IpcSender::requestDiagnostics(const RequestDiagnosticsMessage &message) m_connection.serverProxy().requestDiagnostics(message); } +void IpcSender::requestHighlighting(const RequestHighlightingMessage &message) +{ + QTC_CHECK(m_connection.isConnected()); + m_connection.serverProxy().requestHighlighting(message); +} + IpcCommunicator::IpcCommunicator() : m_connection(&m_ipcReceiver) , m_ipcSender(new IpcSender(m_connection)) @@ -446,33 +473,50 @@ void IpcCommunicator::updateUnsavedFile(const QString &filePath, const QByteArra documentRevision}}); } -void IpcCommunicator::requestDiagnostics(const FileContainer &fileContainer) +void IpcCommunicator::requestDiagnosticsAndHighlighting(const FileContainer &fileContainer, + DocumentChangedCheck documentChangedCheck) { if (m_sendMode == IgnoreSendRequests) return; - if (documentHasChanged(fileContainer.filePath())) { - updateTranslationUnitsForEditor({fileContainer}); + if (documentChangedCheck == DocumentChangedCheck::RevisionCheck) { + if (documentHasChanged(fileContainer.filePath())) { + updateTranslationUnitsForEditor({fileContainer}); + requestDiagnostics(fileContainer); + requestHighlighting(fileContainer); + setLastSentDocumentRevision(fileContainer.filePath(), + fileContainer.documentRevision()); + } + } else { + requestDiagnostics(fileContainer); + requestHighlighting(fileContainer); + } +} - const RequestDiagnosticsMessage message(fileContainer); - qCDebug(log) << ">>>" << message; - m_ipcSender->requestDiagnostics(message); +void IpcCommunicator::requestDiagnostics(const FileContainer &fileContainer) +{ + const RequestDiagnosticsMessage message(fileContainer); + qCDebug(log) << ">>>" << message; + m_ipcSender->requestDiagnostics(message); +} - setLastSentDocumentRevision(fileContainer.filePath(), - fileContainer.documentRevision()); - } +void IpcCommunicator::requestHighlighting(const FileContainer &fileContainer) +{ + const RequestHighlightingMessage message(fileContainer); + qCDebug(log) << ">>>" << message; + m_ipcSender->requestHighlighting(message); } -void IpcCommunicator::requestDiagnostics(Core::IDocument *document) +void IpcCommunicator::requestDiagnosticsAndHighlighting(Core::IDocument *document) { const auto textDocument = qobject_cast(document); const auto filePath = textDocument->filePath().toString(); const QString projectPartId = Utils::projectPartIdForFile(filePath); - requestDiagnostics(FileContainer(filePath, - projectPartId, - Utf8StringVector(), - textDocument->document()->revision())); + requestDiagnosticsAndHighlighting(FileContainer(filePath, + projectPartId, + Utf8StringVector(), + textDocument->document()->revision())); } void IpcCommunicator::updateChangeContentStartPosition(const QString &filePath, int position) diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.h b/src/plugins/clangcodemodel/clangbackendipcintegration.h index 030976bfbe..8d105cc968 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.h +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.h @@ -81,6 +81,7 @@ private: void echo(const ClangBackEnd::EchoMessage &message) override; void codeCompleted(const ClangBackEnd::CodeCompletedMessage &message) override; void diagnosticsChanged(const ClangBackEnd::DiagnosticsChangedMessage &message) override; + void highlightingChanged(const ClangBackEnd::HighlightingChangedMessage &message) override; void translationUnitDoesNotExist(const ClangBackEnd::TranslationUnitDoesNotExistMessage &message) override; void projectPartsDoNotExist(const ClangBackEnd::ProjectPartsDoNotExistMessage &message) override; @@ -105,6 +106,7 @@ public: virtual void unregisterUnsavedFilesForEditor(const ClangBackEnd::UnregisterUnsavedFilesForEditorMessage &message) = 0; virtual void completeCode(const ClangBackEnd::CompleteCodeMessage &message) = 0; virtual void requestDiagnostics(const ClangBackEnd::RequestDiagnosticsMessage &message) = 0; + virtual void requestHighlighting(const ClangBackEnd::RequestHighlightingMessage &message) = 0; }; class IpcCommunicator : public QObject @@ -116,6 +118,8 @@ public: using FileContainers = QVector; using ProjectPartContainers = QVector; + enum class DocumentChangedCheck { NoCheck, RevisionCheck }; + public: IpcCommunicator(); @@ -140,8 +144,9 @@ public: void updateUnsavedFileFromCppEditorDocument(const QString &filePath); void updateTranslationUnit(const QString &filePath, const QByteArray &contents, uint documentRevision); void updateUnsavedFile(const QString &filePath, const QByteArray &contents, uint documentRevision); - void requestDiagnostics(const ClangBackEnd::FileContainer &fileContainer); - void requestDiagnostics(Core::IDocument *document); + void requestDiagnosticsAndHighlighting(const ClangBackEnd::FileContainer &fileContainer, + DocumentChangedCheck documentChangedCheck = DocumentChangedCheck::RevisionCheck); + void requestDiagnosticsAndHighlighting(Core::IDocument *document); void updateChangeContentStartPosition(const QString &filePath, int position); void registerFallbackProjectPart(); @@ -162,6 +167,9 @@ private: void registerCurrentCppEditorDocuments(); void registerCurrentCodeModelUiHeaders(); + void requestHighlighting(const ClangBackEnd::FileContainer &fileContainer); + void requestDiagnostics(const ClangBackEnd::FileContainer &fileContainer); + void onBackendRestarted(); void onEditorAboutToClose(Core::IEditor *editor); void onCoreAboutToClose(); diff --git a/src/plugins/clangcodemodel/clangcodemodel.pro b/src/plugins/clangcodemodel/clangcodemodel.pro index 3a73d66790..b12de496f9 100644 --- a/src/plugins/clangcodemodel/clangcodemodel.pro +++ b/src/plugins/clangcodemodel/clangcodemodel.pro @@ -41,6 +41,7 @@ SOURCES += \ cxprettyprinter.cpp \ diagnostic.cpp \ fastindexer.cpp \ + highlightingmarksreporter.cpp \ pchinfo.cpp \ pchmanager.cpp \ raii/scopedclangoptions.cpp \ @@ -86,6 +87,7 @@ HEADERS += \ cxraii.h \ diagnostic.h \ fastindexer.h \ + highlightingmarksreporter.h \ pchinfo.h \ pchmanager.h \ raii/scopedclangoptions.h \ diff --git a/src/plugins/clangcodemodel/clangcodemodel.qbs b/src/plugins/clangcodemodel/clangcodemodel.qbs index 26543eda86..d0153d3979 100644 --- a/src/plugins/clangcodemodel/clangcodemodel.qbs +++ b/src/plugins/clangcodemodel/clangcodemodel.qbs @@ -81,6 +81,8 @@ QtcPlugin { files: [ "cppcreatemarkers.cpp", "cppcreatemarkers.h", + "highlightingmarksreporter.cpp", + "highlightingmarksreporter.h", ] } diff --git a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp index 80b098c940..bbf917d45d 100644 --- a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp +++ b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp @@ -58,11 +58,6 @@ static void initializeTextMarks() Utils::Theme::ClangCodeModel_Error_TextMarkColor); } -ClangCodeModelPlugin::ClangCodeModelPlugin() -{ - qRegisterMetaType(); -} - bool ClangCodeModelPlugin::initialize(const QStringList &arguments, QString *errorMessage) { Q_UNUSED(arguments) diff --git a/src/plugins/clangcodemodel/clangcodemodelplugin.h b/src/plugins/clangcodemodel/clangcodemodelplugin.h index 39d4ba6633..6a767d5b71 100644 --- a/src/plugins/clangcodemodel/clangcodemodelplugin.h +++ b/src/plugins/clangcodemodel/clangcodemodelplugin.h @@ -50,8 +50,6 @@ class ClangCodeModelPlugin: public ExtensionSystem::IPlugin Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ClangCodeModel.json") public: - ClangCodeModelPlugin(); - bool initialize(const QStringList &arguments, QString *errorMessage); void extensionsInitialized(); diff --git a/src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri b/src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri index 35ba6f84c0..1771e0e0c6 100644 --- a/src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri +++ b/src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri @@ -5,11 +5,13 @@ SOURCES += $$PWD/completionchunkstotextconverter.cpp \ $$PWD/activationsequencecontextprocessor.cpp \ $$PWD/clangcompletioncontextanalyzer.cpp \ $$PWD/clangdiagnosticfilter.cpp \ - $$PWD/clangfixitoperation.cpp + $$PWD/clangfixitoperation.cpp \ + $$PWD/highlightingmarksreporter.cpp HEADERS += $$PWD/completionchunkstotextconverter.h \ $$PWD/activationsequenceprocessor.h \ $$PWD/activationsequencecontextprocessor.h \ $$PWD/clangcompletioncontextanalyzer.h \ $$PWD/clangdiagnosticfilter.h \ - $$PWD/clangfixitoperation.h + $$PWD/clangfixitoperation.h \ + $$PWD/highlightingmarksreporter.h diff --git a/src/plugins/clangcodemodel/clangeditordocumentparser.cpp b/src/plugins/clangcodemodel/clangeditordocumentparser.cpp index caeefd2267..4b2daaa737 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentparser.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentparser.cpp @@ -29,111 +29,22 @@ ****************************************************************************/ #include "clangeditordocumentparser.h" -#include "clangutils.h" -#include "pchinfo.h" -#include "pchmanager.h" - -#include -#include -#include - -#include -#include - -#include - -static Q_LOGGING_CATEGORY(log, "qtc.clangcodemodel.clangeditordocumentparser") - -namespace { - -QStringList createOptions(const QString &filePath, - const CppTools::ProjectPart::Ptr &part, - bool includeSpellCheck = false) -{ - using namespace ClangCodeModel; - - QStringList options; - if (part.isNull()) - return options; - - if (includeSpellCheck) - options += QLatin1String("-fspell-checking"); - - options += ClangCodeModel::Utils::createClangOptions(part, filePath); - - if (Internal::PchInfo::Ptr pchInfo = Internal::PchManager::instance()->pchInfo(part)) - options.append(ClangCodeModel::Utils::createPCHInclusionOptions(pchInfo->fileName())); - - return options; -} - -QString messageLine(const QStringList &options, const QString &fileName) -{ - const QStringList allOptions = QStringList(options) - << QLatin1String("-fsyntax-only") << fileName; - QStringList allOptionsQuoted; - foreach (const QString &option, allOptions) - allOptionsQuoted.append(QLatin1Char('\'') + option + QLatin1Char('\'')); - return ::Utils::HostOsInfo::withExecutableSuffix(QLatin1String("clang")) - + QLatin1Char(' ') + allOptionsQuoted.join(QLatin1Char(' ')); -} - -} // anonymous namespace namespace ClangCodeModel { ClangEditorDocumentParser::ClangEditorDocumentParser(const QString &filePath) : BaseEditorDocumentParser(filePath) - , m_marker(new ClangCodeModel::SemanticMarker) { BaseEditorDocumentParser::Configuration config = configuration(); config.stickToPreviousProjectPart = false; setConfiguration(config); } -void ClangEditorDocumentParser::updateHelper(const BaseEditorDocumentParser::InMemoryInfo &info) +void ClangEditorDocumentParser::updateHelper(const BaseEditorDocumentParser::InMemoryInfo &) { - QTC_ASSERT(m_marker, return); - - // Determine project part State state_ = state(); state_.projectPart = determineProjectPart(filePath(), configuration(), state_); setState(state_); - emit projectPartDetermined(state_.projectPart); - - // Determine message line arguments - const QStringList options = createOptions(filePath(), state_.projectPart, true); - qCDebug(log, "Reparse options (cmd line equivalent): %s", - messageLine(options, filePath()).toUtf8().constData()); - - // Run - QTime t; t.start(); - QMutexLocker lock(m_marker->mutex()); - m_marker->setFileName(filePath()); - m_marker->setCompilationOptions(options); - const Internal::UnsavedFiles unsavedFiles = Utils::createUnsavedFiles(info.workingCopy, - info.modifiedFiles); - m_marker->reparse(unsavedFiles); - qCDebug(log) << "Reparse took" << t.elapsed() << "ms."; -} - -QList ClangEditorDocumentParser::diagnostics() const -{ - QTC_ASSERT(m_marker, return QList()); - QMutexLocker(m_marker->mutex()); - return m_marker->diagnostics(); -} - -QList ClangEditorDocumentParser::ifdefedOutBlocks() const -{ - QTC_ASSERT(m_marker, return QList()); - QMutexLocker(m_marker->mutex()); - return m_marker->ifdefedOutBlocks(); -} - -SemanticMarker::Ptr ClangEditorDocumentParser::semanticMarker() const -{ - return m_marker; } } // namespace ClangCodeModel diff --git a/src/plugins/clangcodemodel/clangeditordocumentparser.h b/src/plugins/clangcodemodel/clangeditordocumentparser.h index ef207749c2..7dc54732f3 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentparser.h +++ b/src/plugins/clangcodemodel/clangeditordocumentparser.h @@ -31,12 +31,8 @@ #ifndef CLANGEDITORDOCUMENTPARSER_H #define CLANGEDITORDOCUMENTPARSER_H -#include "semanticmarker.h" - #include -namespace CppTools { class WorkingCopy; } - namespace ClangCodeModel { class ClangEditorDocumentParser : public CppTools::BaseEditorDocumentParser @@ -46,17 +42,8 @@ class ClangEditorDocumentParser : public CppTools::BaseEditorDocumentParser public: ClangEditorDocumentParser(const QString &filePath); - QList diagnostics() const; - QList ifdefedOutBlocks() const; - SemanticMarker::Ptr semanticMarker() const; - -signals: - void projectPartDetermined(CppTools::ProjectPart::Ptr projectPart); - private: - void updateHelper(const BaseEditorDocumentParser::InMemoryInfo &info) override; - - SemanticMarker::Ptr m_marker; + void updateHelper(const BaseEditorDocumentParser::InMemoryInfo &) override; }; } // namespace ClangCodeModel diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index 5739960751..e4f4b7e5bc 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -36,6 +36,7 @@ #include "clangutils.h" #include "cppcreatemarkers.h" #include "diagnostic.h" +#include "highlightingmarksreporter.h" #include "pchinfo.h" #include @@ -59,22 +60,6 @@ #include -namespace { - -typedef CPlusPlus::Document::DiagnosticMessage CppToolsDiagnostic; - -QList toTextEditorBlocks( - const QList &ranges) -{ - QList result; - result.reserve(ranges.size()); - foreach (const ClangCodeModel::SemanticMarker::Range &range, ranges) - result.append(TextEditor::BlockRange(range.first, range.last)); - return result; -} - -} // anonymous namespace - namespace ClangCodeModel { namespace Internal { @@ -89,26 +74,12 @@ ClangEditorDocumentProcessor::ClangEditorDocumentProcessor( , m_semanticHighlighter(document) , m_builtinProcessor(document, /*enableSemanticHighlighter=*/ false) { - connect(m_parser.data(), &ClangEditorDocumentParser::projectPartDetermined, - this, &ClangEditorDocumentProcessor::onParserDeterminedProjectPart); - // Forwarding the semantic info from the builtin processor enables us to provide all // editor (widget) related features that are not yet implemented by the clang plugin. connect(&m_builtinProcessor, &CppTools::BuiltinEditorDocumentProcessor::cppDocumentUpdated, this, &ClangEditorDocumentProcessor::cppDocumentUpdated); connect(&m_builtinProcessor, &CppTools::BuiltinEditorDocumentProcessor::semanticInfoUpdated, this, &ClangEditorDocumentProcessor::semanticInfoUpdated); - - m_semanticHighlighter.setHighlightingRunner( - [this]() -> QFuture { - const int firstLine = 1; - const int lastLine = baseTextDocument()->document()->blockCount(); - - CreateMarkers *createMarkers = CreateMarkers::create(m_parser->semanticMarker(), - baseTextDocument()->filePath().toString(), - firstLine, lastLine); - return createMarkers->start(); - }); } ClangEditorDocumentProcessor::~ClangEditorDocumentProcessor() @@ -125,7 +96,7 @@ ClangEditorDocumentProcessor::~ClangEditorDocumentProcessor() void ClangEditorDocumentProcessor::run() { - requestDiagnostics(); + requestDiagnosticsAndHighlighting(); // Run clang parser disconnect(&m_parserWatcher, &QFutureWatcher::finished, @@ -153,7 +124,7 @@ void ClangEditorDocumentProcessor::recalculateSemanticInfoDetached(bool force) void ClangEditorDocumentProcessor::semanticRehighlight() { m_semanticHighlighter.updateFormatMapFromFontSettings(); - m_semanticHighlighter.run(); + requestDiagnosticsAndHighlighting(DocumentChangedCheck::NoCheck); } CppTools::SemanticInfo ClangEditorDocumentProcessor::recalculateSemanticInfo() @@ -201,6 +172,36 @@ void ClangEditorDocumentProcessor::updateCodeWarnings(const QVector +toTextEditorBlocks(const QVector &ifdefedOutRanges) +{ + QList blockRanges; + blockRanges.reserve(ifdefedOutRanges.size()); + + for (const auto &range : ifdefedOutRanges) + blockRanges.append(TextEditor::BlockRange(range.start().offset(),range.end().offset())); + + return blockRanges; +} + +void ClangEditorDocumentProcessor::updateHighlighting( + const QVector &highlightingMarks, + const QVector &skippedPreprocessorRanges, + uint documentRevision) +{ + if (documentRevision == revision()) { + const auto skippedPreprocessorBlocks = toTextEditorBlocks(skippedPreprocessorRanges); + emit ifdefedOutBlocksUpdated(documentRevision, skippedPreprocessorBlocks); + + m_semanticHighlighter.setHighlightingRunner( + [highlightingMarks]() { + auto *reporter = new HighlightingMarksReporter(highlightingMarks); + return reporter->start(); + }); + m_semanticHighlighter.run(); + } +} + static int currentLine(const TextEditor::AssistInterface &assistInterface) { int line, column; @@ -240,36 +241,24 @@ static bool isProjectPartLoadedOrIsFallback(CppTools::ProjectPart::Ptr projectPa && (projectPart->id().isEmpty() || ClangCodeModel::Utils::isProjectPartLoaded(projectPart)); } -void ClangEditorDocumentProcessor::updateProjectPartAndTranslationUnitForEditor( - CppTools::ProjectPart::Ptr projectPart) +void ClangEditorDocumentProcessor::updateProjectPartAndTranslationUnitForEditor() { - QTC_ASSERT(projectPart, return); + const CppTools::ProjectPart::Ptr projectPart = m_parser->projectPart(); if (isProjectPartLoadedOrIsFallback(projectPart)) { updateTranslationUnitForEditor(projectPart.data()); - requestDiagnostics(projectPart.data()); + requestDiagnosticsAndHighlighting(projectPart.data()); m_projectPart = projectPart; } } -void ClangEditorDocumentProcessor::onParserDeterminedProjectPart( - CppTools::ProjectPart::Ptr projectPart) -{ - updateProjectPartAndTranslationUnitForEditor(projectPart); -} - void ClangEditorDocumentProcessor::onParserFinished() { if (revision() != m_parserRevision) return; - // Emit ifdefed out blocks - const auto ifdefoutBlocks = toTextEditorBlocks(m_parser->ifdefedOutBlocks()); - emit ifdefedOutBlocksUpdated(revision(), ifdefoutBlocks); - - // Run semantic highlighter - m_semanticHighlighter.run(); + updateProjectPartAndTranslationUnitForEditor(); } void ClangEditorDocumentProcessor::updateTranslationUnitForEditor(CppTools::ProjectPart *projectPart) @@ -287,25 +276,38 @@ void ClangEditorDocumentProcessor::updateTranslationUnitForEditor(CppTools::Proj } } -void ClangEditorDocumentProcessor::requestDiagnostics(CppTools::ProjectPart *projectPart) +void ClangEditorDocumentProcessor::requestDiagnosticsAndHighlighting(CppTools::ProjectPart *projectPart) { if (!m_projectPart || projectPart->id() != m_projectPart->id()) { IpcCommunicator &ipcCommunicator = m_modelManagerSupport->ipcCommunicator(); - ipcCommunicator.requestDiagnostics({fileContainer(projectPart)}); + const ClangBackEnd::FileContainer fileContainer_ = fileContainer(projectPart); + ipcCommunicator.requestDiagnosticsAndHighlighting(fileContainer_); } } -void ClangEditorDocumentProcessor::requestDiagnostics() +IpcCommunicator::DocumentChangedCheck +toIpcCommunicatorDocumentChangedCheck(ClangEditorDocumentProcessor::DocumentChangedCheck condition) +{ + return condition == ClangEditorDocumentProcessor::DocumentChangedCheck::RevisionCheck + ? IpcCommunicator::DocumentChangedCheck::RevisionCheck + : IpcCommunicator::DocumentChangedCheck::NoCheck; +} + +void ClangEditorDocumentProcessor::requestDiagnosticsAndHighlighting(DocumentChangedCheck documentChangedCheck) { - // Get diagnostics if (m_projectPart) { auto &ipcCommunicator = m_modelManagerSupport->ipcCommunicator(); - ipcCommunicator.requestDiagnostics({filePath(), - m_projectPart->id(), - baseTextDocument()->plainText(), - true, - revision()}); + + const ClangBackEnd::FileContainer fileContainer(filePath(), + m_projectPart->id(), + baseTextDocument()->plainText(), + true, + revision()); + + const auto documentCheck = toIpcCommunicatorDocumentChangedCheck(documentChangedCheck); + + ipcCommunicator.requestDiagnosticsAndHighlighting(fileContainer, documentCheck); } } diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h index ded0258210..cc696cc8e9 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h @@ -43,6 +43,7 @@ namespace ClangBackEnd { class DiagnosticContainer; +class HighlightingMarkContainer; class FileContainer; } @@ -75,6 +76,9 @@ public: void updateCodeWarnings(const QVector &diagnostics, uint documentRevision); + void updateHighlighting(const QVector &highlightingMarks, + const QVector &skippedPreprocessorRanges, + uint documentRevision); TextEditor::QuickFixOperations extraRefactoringOperations(const TextEditor::AssistInterface &assistInterface) override; @@ -84,17 +88,17 @@ public: void clearDiagnosticsWithFixIts(); public: + enum class DocumentChangedCheck { NoCheck, RevisionCheck }; static ClangEditorDocumentProcessor *get(const QString &filePath); private slots: - void onParserDeterminedProjectPart(CppTools::ProjectPart::Ptr projectPart); void onParserFinished(); private: - void updateProjectPartAndTranslationUnitForEditor(CppTools::ProjectPart::Ptr projectPart); + void updateProjectPartAndTranslationUnitForEditor(); void updateTranslationUnitForEditor(CppTools::ProjectPart *projectPart); - void requestDiagnostics(CppTools::ProjectPart *projectPart); - void requestDiagnostics(); + void requestDiagnosticsAndHighlighting(CppTools::ProjectPart *projectPart); + void requestDiagnosticsAndHighlighting(DocumentChangedCheck documentChangedCheck = DocumentChangedCheck::RevisionCheck); ClangBackEnd::FileContainer fileContainer(CppTools::ProjectPart *projectPart) const; private: diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index 2678064830..1b66c067e9 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -193,7 +193,7 @@ void ModelManagerSupportClang::onCppDocumentReloadFinishedOnTranslationUnit(bool if (success) { TextEditor::TextDocument *textDocument = qobject_cast(sender()); connectToTextDocumentContentsChangedForTranslationUnit(textDocument); - m_ipcCommunicator.requestDiagnostics(textDocument); + m_ipcCommunicator.requestDiagnosticsAndHighlighting(textDocument); } } diff --git a/src/plugins/clangcodemodel/highlightingmarksreporter.cpp b/src/plugins/clangcodemodel/highlightingmarksreporter.cpp new file mode 100644 index 0000000000..6b3fc07996 --- /dev/null +++ b/src/plugins/clangcodemodel/highlightingmarksreporter.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "highlightingmarksreporter.h" + +#include + +#include + +namespace { + +CppTools::SemanticHighlighter::Kind toCppToolsSemanticHighlighterKind( + ClangBackEnd::HighlightingType type) +{ + using ClangBackEnd::HighlightingType; + using CppTools::SemanticHighlighter; + + switch (type) { + case HighlightingType::Keyword: + return SemanticHighlighter::PseudoKeywordUse; + case HighlightingType::Function: + return SemanticHighlighter::FunctionUse; + case HighlightingType::VirtualFunction: + return SemanticHighlighter::VirtualMethodUse; + case HighlightingType::Type: + return SemanticHighlighter::TypeUse; + case HighlightingType::LocalVariable: + return SemanticHighlighter::LocalUse; + case HighlightingType::Field: + return SemanticHighlighter::FieldUse; + case HighlightingType::GlobalVariable: + return SemanticHighlighter::Unknown; + case HighlightingType::Enumeration: + return SemanticHighlighter::EnumerationUse; + case HighlightingType::Label: + return SemanticHighlighter::LabelUse; + case HighlightingType::Preprocessor: + return SemanticHighlighter::MacroUse; + default: + return SemanticHighlighter::Unknown; + } + + Q_UNREACHABLE(); +} + +TextEditor::HighlightingResult toHighlightingResult( + const ClangBackEnd::HighlightingMarkContainer &highlightingMark) +{ + const auto highlighterKind = toCppToolsSemanticHighlighterKind(highlightingMark.type()); + + return TextEditor::HighlightingResult(highlightingMark.line(), + highlightingMark.column(), + highlightingMark.length(), + highlighterKind); +} + +} // anonymous + +namespace ClangCodeModel { + +HighlightingMarksReporter::HighlightingMarksReporter( + const QVector &highlightingMarks) + : m_highlightingMarks(highlightingMarks) +{ + m_chunksToReport.reserve(m_chunkSize + 1); +} + +void HighlightingMarksReporter::reportChunkWise( + const TextEditor::HighlightingResult &highlightingResult) +{ + if (m_chunksToReport.size() >= m_chunkSize) { + if (m_flushRequested && highlightingResult.line != m_flushLine) { + reportAndClearCurrentChunks(); + } else if (!m_flushRequested) { + m_flushRequested = true; + m_flushLine = highlightingResult.line; + } + } + + m_chunksToReport.append(highlightingResult); +} + +void HighlightingMarksReporter::reportAndClearCurrentChunks() +{ + m_flushRequested = false; + m_flushLine = 0; + + if (!m_chunksToReport.isEmpty()) { + reportResults(m_chunksToReport); + m_chunksToReport.erase(m_chunksToReport.begin(), m_chunksToReport.end()); + } +} + +void HighlightingMarksReporter::setChunkSize(int chunkSize) +{ + m_chunkSize = chunkSize; +} + +void HighlightingMarksReporter::run() +{ + run_internal(); + reportFinished(); +} + +void HighlightingMarksReporter::run_internal() +{ + if (isCanceled()) + return; + + for (const auto &highlightingMark : m_highlightingMarks) + reportChunkWise(toHighlightingResult(highlightingMark)); + + if (isCanceled()) + return; + + reportAndClearCurrentChunks(); +} + +QFuture HighlightingMarksReporter::start() +{ + this->setRunnable(this); + this->reportStarted(); + QFuture future = this->future(); + QThreadPool::globalInstance()->start(this, QThread::LowestPriority); + return future; +} + +} // namespace ClangCodeModel diff --git a/src/plugins/clangcodemodel/highlightingmarksreporter.h b/src/plugins/clangcodemodel/highlightingmarksreporter.h new file mode 100644 index 0000000000..5726ce0b58 --- /dev/null +++ b/src/plugins/clangcodemodel/highlightingmarksreporter.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CLANGCODEMODEL_HIGHLIGHTINGMARKSREPORTER_H +#define CLANGCODEMODEL_HIGHLIGHTINGMARKSREPORTER_H + +#include "clang_global.h" + +#include +#include +#include +#include + +#include + +#include + +namespace ClangCodeModel { + +class HighlightingMarksReporter: + public QObject, + public QRunnable, + public QFutureInterface +{ + Q_OBJECT + +public: + HighlightingMarksReporter(const QVector &highlightingMarks); + + void setChunkSize(int chunkSize); + + QFuture start(); + +private: + void run() override; + void run_internal(); + + void reportChunkWise(const TextEditor::HighlightingResult &highlightingResult); + void reportAndClearCurrentChunks(); + +private: + QVector m_highlightingMarks; + QVector m_chunksToReport; + + int m_chunkSize = 100; + + bool m_flushRequested = false; + unsigned m_flushLine = 0; +}; + +} // namespace ClangCodeModel + +#endif // CLANGCODEMODEL_HIGHLIGHTINGMARKSREPORTER_H diff --git a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp index 857bf3b407..01d5cdbbef 100644 --- a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp +++ b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp @@ -380,6 +380,11 @@ QString toString(const RequestDiagnosticsMessage &) return QStringLiteral("RequestDiagnosticsMessage\n"); } +QString toString(const RequestHighlightingMessage &) +{ + return QStringLiteral("RequestHighlightingMessage\n"); +} + class IpcSenderSpy : public IpcSenderInterface { public: @@ -413,6 +418,8 @@ public: void requestDiagnostics(const RequestDiagnosticsMessage &message) override { senderLog.append(toString(message)); } + void requestHighlighting(const RequestHighlightingMessage &message) override + { senderLog.append(toString(message)); } public: QString senderLog; diff --git a/src/plugins/cpptools/cppprojects.h b/src/plugins/cpptools/cppprojects.h index a63f557587..3d8ddba0be 100644 --- a/src/plugins/cpptools/cppprojects.h +++ b/src/plugins/cpptools/cppprojects.h @@ -247,6 +247,4 @@ private: } // namespace CppTools -Q_DECLARE_METATYPE(CppTools::ProjectPart::Ptr) - #endif // CPPPROJECTPART_H diff --git a/src/tools/clangbackend/ipcsource/clangipcserver.cpp b/src/tools/clangbackend/ipcsource/clangipcserver.cpp index 31c3ae481f..a7652caf28 100644 --- a/src/tools/clangbackend/ipcsource/clangipcserver.cpp +++ b/src/tools/clangbackend/ipcsource/clangipcserver.cpp @@ -33,7 +33,9 @@ #include "clangfilesystemwatcher.h" #include "codecompleter.h" #include "diagnosticset.h" +#include "highlightinginformations.h" #include "projectpartsdonotexistexception.h" +#include "skippedsourceranges.h" #include "translationunitdoesnotexistexception.h" #include "translationunitfilenotexitexception.h" #include "translationunitisnullexception.h" @@ -48,8 +50,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -62,37 +66,44 @@ namespace ClangBackEnd { namespace { -const int sendDiagnosticsTimerInterval = 300; +const int delayedEditorUpdatesTimerInterval = 300; } ClangIpcServer::ClangIpcServer() : translationUnits(projects, unsavedFiles) { - translationUnits.setSendChangeDiagnosticsCallback([this] (const DiagnosticsChangedMessage &message) - { - client()->diagnosticsChanged(message); - }); + const auto sendEditorUpdates + = [this] (const DiagnosticsChangedMessage &diagnosticsMessage, + const HighlightingChangedMessage &highlightingsMessage) { + client()->diagnosticsChanged(diagnosticsMessage); + client()->highlightingChanged(highlightingsMessage); + }; + + const auto sendDelayedEditorUpdates = [this] () { + try { + auto editorUpdatesSendState = translationUnits.sendDelayedEditorUpdates(); + if (editorUpdatesSendState == EditorUpdatesSendState::MaybeThereAreMoreEditorUpdates) + sendDelayedEditorUpdatesTimer.setInterval(0); + else + sendDelayedEditorUpdatesTimer.stop(); + } catch (const std::exception &exception) { + qWarning() << "Error in ClangIpcServer::sendDelayedEditorUpdatesTimer:" << exception.what(); + } + }; + + const auto onFileChanged = [this] (const Utf8String &filePath) { + startSendDelayedEditorUpdatesTimerIfFileIsNotATranslationUnit(filePath); + }; - QObject::connect(&sendDiagnosticsTimer, + translationUnits.setSendDelayedEditorUpdatesCallback(sendEditorUpdates); + + QObject::connect(&sendDelayedEditorUpdatesTimer, &QTimer::timeout, - [this] () { - try { - auto diagnostSendState = translationUnits.sendChangedDiagnostics(); - if (diagnostSendState == DiagnosticSendState::MaybeThereAreMoreDiagnostics) - sendDiagnosticsTimer.setInterval(0); - else - sendDiagnosticsTimer.stop(); - } catch (const std::exception &exception) { - qWarning() << "Error in ClangIpcServer::sendDiagnosticsTimer:" << exception.what(); - } - }); + sendDelayedEditorUpdates); QObject::connect(translationUnits.clangFileSystemWatcher(), &ClangFileSystemWatcher::fileChanged, - [this] (const Utf8String &filePath) - { - startSendDiagnosticTimerIfFileIsNotATranslationUnit(filePath); - }); + onFileChanged); } void ClangIpcServer::end() @@ -107,7 +118,7 @@ void ClangIpcServer::registerTranslationUnitsForEditor(const ClangBackEnd::Regis try { translationUnits.create(message.fileContainers()); unsavedFiles.createOrUpdate(message.fileContainers()); - sendDiagnosticsTimer.start(0); + sendDelayedEditorUpdatesTimer.start(0); } catch (const ProjectPartDoNotExistException &exception) { client()->projectPartsDoNotExist(ProjectPartsDoNotExistMessage(exception.projectPartIds())); } catch (const std::exception &exception) { @@ -124,7 +135,7 @@ void ClangIpcServer::updateTranslationUnitsForEditor(const UpdateTranslationUnit if (newerFileContainers.size() > 0) { translationUnits.update(newerFileContainers); unsavedFiles.createOrUpdate(newerFileContainers); - sendDiagnosticsTimer.start(sendDiagnosticsTimerInterval); + sendDelayedEditorUpdatesTimer.start(delayedEditorUpdatesTimerInterval); } } catch (const ProjectPartDoNotExistException &exception) { client()->projectPartsDoNotExist(ProjectPartsDoNotExistMessage(exception.projectPartIds())); @@ -182,7 +193,7 @@ void ClangIpcServer::registerUnsavedFilesForEditor(const RegisterUnsavedFilesFor try { unsavedFiles.createOrUpdate(message.fileContainers()); translationUnits.updateTranslationUnitsWithChangedDependencies(message.fileContainers()); - sendDiagnosticsTimer.start(sendDiagnosticsTimerInterval); + sendDelayedEditorUpdatesTimer.start(delayedEditorUpdatesTimerInterval); } catch (const ProjectPartDoNotExistException &exception) { client()->projectPartsDoNotExist(ProjectPartsDoNotExistMessage(exception.projectPartIds())); } catch (const std::exception &exception) { @@ -244,6 +255,26 @@ void ClangIpcServer::requestDiagnostics(const RequestDiagnosticsMessage &message } } +void ClangIpcServer::requestHighlighting(const RequestHighlightingMessage &message) +{ + TIME_SCOPE_DURATION("ClangIpcServer::requestHighlighting"); + + try { + auto translationUnit = translationUnits.translationUnit(message.fileContainer().filePath(), + message.fileContainer().projectPartId()); + + client()->highlightingChanged(HighlightingChangedMessage(translationUnit.fileContainer(), + translationUnit.highlightingInformations().toHighlightingMarksContainers(), + translationUnit.skippedSourceRanges().toSourceRangeContainers())); + } catch (const TranslationUnitDoesNotExistException &exception) { + client()->translationUnitDoesNotExist(TranslationUnitDoesNotExistMessage(exception.fileContainer())); + } catch (const ProjectPartDoNotExistException &exception) { + client()->projectPartsDoNotExist(ProjectPartsDoNotExistMessage(exception.projectPartIds())); + } catch (const std::exception &exception) { + qWarning() << "Error in ClangIpcServer::requestHighlighting:" << exception.what(); + } +} + void ClangIpcServer::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) { TIME_SCOPE_DURATION("ClangIpcServer::updateVisibleTranslationUnits"); @@ -261,10 +292,10 @@ const TranslationUnits &ClangIpcServer::translationUnitsForTestOnly() const return translationUnits; } -void ClangIpcServer::startSendDiagnosticTimerIfFileIsNotATranslationUnit(const Utf8String &filePath) +void ClangIpcServer::startSendDelayedEditorUpdatesTimerIfFileIsNotATranslationUnit(const Utf8String &filePath) { if (!translationUnits.hasTranslationUnit(filePath)) - sendDiagnosticsTimer.start(0); + sendDelayedEditorUpdatesTimer.start(0); } } diff --git a/src/tools/clangbackend/ipcsource/clangipcserver.h b/src/tools/clangbackend/ipcsource/clangipcserver.h index 88daf5b410..5ca9553c85 100644 --- a/src/tools/clangbackend/ipcsource/clangipcserver.h +++ b/src/tools/clangbackend/ipcsource/clangipcserver.h @@ -61,18 +61,19 @@ public: void unregisterUnsavedFilesForEditor(const UnregisterUnsavedFilesForEditorMessage &message) override; void completeCode(const CompleteCodeMessage &message) override; void requestDiagnostics(const RequestDiagnosticsMessage &message) override; + void requestHighlighting(const RequestHighlightingMessage &message) override; void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override; const TranslationUnits &translationUnitsForTestOnly() const; private: - void startSendDiagnosticTimerIfFileIsNotATranslationUnit(const Utf8String &filePath); + void startSendDelayedEditorUpdatesTimerIfFileIsNotATranslationUnit(const Utf8String &filePath); private: ProjectParts projects; UnsavedFiles unsavedFiles; TranslationUnits translationUnits; - QTimer sendDiagnosticsTimer; + QTimer sendDelayedEditorUpdatesTimer; }; } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp b/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp index ed9799652a..a7dd59f27e 100644 --- a/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp +++ b/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp @@ -85,6 +85,7 @@ public: uint documentRevision = 0; bool needsToBeReparsed = false; bool hasNewDiagnostics = true; + bool hasNewHighlightingInformations = true; bool isUsedByCurrentEditor = false; bool isVisibleInEditor = false; }; @@ -239,6 +240,11 @@ bool TranslationUnit::hasNewDiagnostics() const return d->hasNewDiagnostics; } +bool TranslationUnit::hasNewHighlightingInformations() const +{ + return d->hasNewHighlightingInformations; +} + DiagnosticSet TranslationUnit::diagnostics() const { d->hasNewDiagnostics = false; @@ -268,6 +274,7 @@ void TranslationUnit::setDirtyIfDependencyIsMet(const Utf8String &filePath) if (d->dependedFilePaths.contains(filePath) && isMainFileAndExistsOrIsOtherFile(filePath)) { d->needsToBeReparsed = true; d->hasNewDiagnostics = true; + d->hasNewHighlightingInformations = true; } } @@ -302,6 +309,13 @@ Cursor TranslationUnit::cursor() const return clang_getTranslationUnitCursor(cxTranslationUnit()); } +HighlightingInformations TranslationUnit::highlightingInformations() const +{ + d->hasNewHighlightingInformations = false; + + return highlightingInformationsInRange(cursor().sourceRange()); +} + HighlightingInformations TranslationUnit::highlightingInformationsInRange(const SourceRange &range) const { CXToken *cxTokens = 0; diff --git a/src/tools/clangbackend/ipcsource/clangtranslationunit.h b/src/tools/clangbackend/ipcsource/clangtranslationunit.h index 37c4741361..2e325ceaf6 100644 --- a/src/tools/clangbackend/ipcsource/clangtranslationunit.h +++ b/src/tools/clangbackend/ipcsource/clangtranslationunit.h @@ -112,6 +112,7 @@ public: bool isNeedingReparse() const; bool hasNewDiagnostics() const; + bool hasNewHighlightingInformations() const; DiagnosticSet diagnostics() const; QVector mainFileDiagnostics() const; @@ -131,6 +132,7 @@ public: Cursor cursorAt(const Utf8String &filePath, uint line, uint column) const; Cursor cursor() const; + HighlightingInformations highlightingInformations() const; HighlightingInformations highlightingInformationsInRange(const SourceRange &range) const; SkippedSourceRanges skippedSourceRanges() const; diff --git a/src/tools/clangbackend/ipcsource/highlightinginformation.cpp b/src/tools/clangbackend/ipcsource/highlightinginformation.cpp index d91ddf26b9..a570f3cf5c 100644 --- a/src/tools/clangbackend/ipcsource/highlightinginformation.cpp +++ b/src/tools/clangbackend/ipcsource/highlightinginformation.cpp @@ -28,6 +28,8 @@ ** ****************************************************************************/ +#include + #include "clangstring.h" #include "cursor.h" #include "highlightinginformation.h" @@ -81,6 +83,11 @@ QVector HighlightingInformation::outputFunctionArgument return outputFunctionArguments; } +HighlightingInformation::operator HighlightingMarkContainer() const +{ + return HighlightingMarkContainer(line, column, length, type); +} + namespace { bool isFinalFunction(const Cursor &cursor) @@ -278,7 +285,7 @@ HighlightingType HighlightingInformation::kind(CXToken *cxToken, const Cursor &c Q_UNREACHABLE(); } -void PrintTo(const HighlightingInformation& information, ::std::ostream *os) +void PrintTo(const HighlightingInformation &information, ::std::ostream *os) { *os << "type: "; PrintTo(information.type, os); @@ -287,30 +294,4 @@ void PrintTo(const HighlightingInformation& information, ::std::ostream *os) << " length: " << information.length; } -void PrintTo(HighlightingType highlightingType, std::ostream *os) -{ - switch (highlightingType) { - case HighlightingType::Invalid: *os << "Invalid"; break; - case HighlightingType::Comment: *os << "Comment"; break; - case HighlightingType::Keyword: *os << "Keyword"; break; - case HighlightingType::StringLiteral: *os << "StringLiteral"; break; - case HighlightingType::NumberLiteral: *os << "NumberLiteral"; break; - case HighlightingType::Function: *os << "Function"; break; - case HighlightingType::VirtualFunction: *os << "VirtualFunction"; break; - case HighlightingType::Type: *os << "Type"; break; - case HighlightingType::LocalVariable: *os << "LocalVariable"; break; - case HighlightingType::GlobalVariable: *os << "GlobalVariable"; break; - case HighlightingType::Field: *os << "Field"; break; - case HighlightingType::Enumeration: *os << "Enumeration"; break; - case HighlightingType::Operator: *os << "Operator"; break; - case HighlightingType::Preprocessor: *os << "Preprocessor"; break; - case HighlightingType::Label: *os << "Label"; break; - case HighlightingType::OutputArgument: *os << "OutputArgument"; break; - case HighlightingType::PreprocessorDefinition: *os << "PreprocessorDefinition"; break; - case HighlightingType::PreprocessorExpansion: *os << "PreprocessorExpansion"; break; - } -} - - - } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/highlightinginformation.h b/src/tools/clangbackend/ipcsource/highlightinginformation.h index ee327b6213..418efdda8f 100644 --- a/src/tools/clangbackend/ipcsource/highlightinginformation.h +++ b/src/tools/clangbackend/ipcsource/highlightinginformation.h @@ -32,6 +32,7 @@ #define CLANGBACKEND_HIGHLIGHTINGINFORMATION_H #include +#include #include "cursor.h" @@ -52,6 +53,8 @@ public: bool hasFunctionArguments() const; QVector outputFunctionArguments() const; + operator HighlightingMarkContainer() const; + private: HighlightingType identifierKind(const Cursor &cursor) const; HighlightingType referencedTypeKind(const Cursor &cursor) const; @@ -71,7 +74,6 @@ private: }; void PrintTo(const HighlightingInformation& highlightingInformation, ::std::ostream *os); -void PrintTo(HighlightingType highlightingType, ::std::ostream *os); inline bool operator==(const HighlightingInformation &first, const HighlightingInformation &second) { diff --git a/src/tools/clangbackend/ipcsource/highlightinginformations.cpp b/src/tools/clangbackend/ipcsource/highlightinginformations.cpp index f7157768fd..c90ea4a590 100644 --- a/src/tools/clangbackend/ipcsource/highlightinginformations.cpp +++ b/src/tools/clangbackend/ipcsource/highlightinginformations.cpp @@ -30,6 +30,10 @@ #include "highlightinginformations.h" +#include "highlightingmarkcontainer.h" + +#include + namespace ClangBackEnd { HighlightingInformations::HighlightingInformations(CXTranslationUnit cxTranslationUnit, CXToken *tokens, uint tokensCount) @@ -56,6 +60,20 @@ HighlightingInformations::const_iterator HighlightingInformations::end() const return const_iterator(cxCursor.cend(), cxToken + cxTokenCount, cxTranslationUnit); } +QVector HighlightingInformations::toHighlightingMarksContainers() const +{ + QVector containers; + containers.reserve(size()); + + const auto isValidHighlightMark = [] (const HighlightingInformation &highlightMark) { + return !highlightMark.hasType(HighlightingType::Invalid); + }; + + std::copy_if(begin(), end(), std::back_inserter(containers), isValidHighlightMark); + + return containers; +} + bool HighlightingInformations::isEmpty() const { return cxTokenCount == 0; diff --git a/src/tools/clangbackend/ipcsource/highlightinginformations.h b/src/tools/clangbackend/ipcsource/highlightinginformations.h index 2c7b8ce9bb..7b3365780e 100644 --- a/src/tools/clangbackend/ipcsource/highlightinginformations.h +++ b/src/tools/clangbackend/ipcsource/highlightinginformations.h @@ -40,6 +40,7 @@ namespace ClangBackEnd { using uint = unsigned int; +class HighlightingMarkContainer; class HighlightingInformations { @@ -61,6 +62,8 @@ public: const_iterator begin() const; const_iterator end() const; + QVector toHighlightingMarksContainers() const; + private: CXTranslationUnit cxTranslationUnit = nullptr; CXToken *const cxToken = nullptr; diff --git a/src/tools/clangbackend/ipcsource/translationunits.cpp b/src/tools/clangbackend/ipcsource/translationunits.cpp index 07975bf693..c1daa3bf50 100644 --- a/src/tools/clangbackend/ipcsource/translationunits.cpp +++ b/src/tools/clangbackend/ipcsource/translationunits.cpp @@ -32,8 +32,11 @@ #include #include +#include +#include #include #include +#include #include #include @@ -163,62 +166,73 @@ void TranslationUnits::updateTranslationUnitsWithChangedDependencies(const QVect updateTranslationUnitsWithChangedDependency(fileContainer.filePath()); } -DiagnosticSendState TranslationUnits::sendChangedDiagnostics() +EditorUpdatesSendState TranslationUnits::sendDelayedEditorUpdates() { - auto diagnosticSendState = sendChangedDiagnosticsForCurrentEditor(); - if (diagnosticSendState == DiagnosticSendState::NoDiagnosticSend) - diagnosticSendState = sendChangedDiagnosticsForVisibleEditors(); - if (diagnosticSendState == DiagnosticSendState::NoDiagnosticSend) - diagnosticSendState = sendChangedDiagnosticsForAll(); + auto editorUpdatesSendState = sendDelayedEditorUpdatesForCurrentEditor(); + if (editorUpdatesSendState == EditorUpdatesSendState::NoEditorUpdatesSend) + editorUpdatesSendState = sendDelayedEditorUpdatesForVisibleEditors(); + if (editorUpdatesSendState == EditorUpdatesSendState::NoEditorUpdatesSend) + editorUpdatesSendState = sendDelayedEditorUpdatesForAll(); - return diagnosticSendState; + return editorUpdatesSendState; } template -DiagnosticSendState TranslationUnits::sendChangedDiagnostics(Predicate predicate) +EditorUpdatesSendState TranslationUnits::sendDelayedEditorUpdates(Predicate predicate) { auto foundTranslationUnit = std::find_if(translationUnits_.begin(), translationUnits_.end(), predicate); if (foundTranslationUnit != translationUnits().end()) { - sendDiagnosticChangedMessage(*foundTranslationUnit); - return DiagnosticSendState::MaybeThereAreMoreDiagnostics; + sendDelayedEditorUpdates(*foundTranslationUnit); + return EditorUpdatesSendState::MaybeThereAreMoreEditorUpdates; } - return DiagnosticSendState::NoDiagnosticSend; + return EditorUpdatesSendState::NoEditorUpdatesSend; } -DiagnosticSendState TranslationUnits::sendChangedDiagnosticsForCurrentEditor() +namespace { + +bool translationUnitHasEditorDocumentUpdates(const TranslationUnit &translationUnit) +{ + return translationUnit.hasNewDiagnostics() || translationUnit.hasNewHighlightingInformations(); +} + +} + +EditorUpdatesSendState TranslationUnits::sendDelayedEditorUpdatesForCurrentEditor() { - auto hasDiagnosticsForCurrentEditor = [] (const TranslationUnit &translationUnit) { - return translationUnit.isUsedByCurrentEditor() && translationUnit.hasNewDiagnostics(); + auto hasEditorUpdatesForCurrentEditor = [] (const TranslationUnit &translationUnit) { + return translationUnit.isUsedByCurrentEditor() + && translationUnitHasEditorDocumentUpdates(translationUnit); }; - return sendChangedDiagnostics(hasDiagnosticsForCurrentEditor); + return sendDelayedEditorUpdates(hasEditorUpdatesForCurrentEditor); } -DiagnosticSendState TranslationUnits::sendChangedDiagnosticsForVisibleEditors() +EditorUpdatesSendState TranslationUnits::sendDelayedEditorUpdatesForVisibleEditors() { - auto hasDiagnosticsForVisibleEditor = [] (const TranslationUnit &translationUnit) { - return translationUnit.isVisibleInEditor() && translationUnit.hasNewDiagnostics(); + auto hasEditorUpdatesForVisibleEditor = [] (const TranslationUnit &translationUnit) { + return translationUnit.isVisibleInEditor() + && translationUnitHasEditorDocumentUpdates(translationUnit); }; - return sendChangedDiagnostics(hasDiagnosticsForVisibleEditor); + return sendDelayedEditorUpdates(hasEditorUpdatesForVisibleEditor); } -DiagnosticSendState TranslationUnits::sendChangedDiagnosticsForAll() +EditorUpdatesSendState TranslationUnits::sendDelayedEditorUpdatesForAll() { - auto hasDiagnostics = [] (const TranslationUnit &translationUnit) { - return translationUnit.hasNewDiagnostics(); + auto hasEditorUpdates = [] (const TranslationUnit &translationUnit) { + return translationUnitHasEditorDocumentUpdates(translationUnit); }; - return sendChangedDiagnostics(hasDiagnostics); + return sendDelayedEditorUpdates(hasEditorUpdates); } -void TranslationUnits::setSendChangeDiagnosticsCallback(std::function &&callback) +void TranslationUnits::setSendDelayedEditorUpdatesCallback(DelayedEditorUpdatesCallback &&callback) { - sendDiagnosticsChangedCallback = std::move(callback); + sendDelayedEditorUpdatesCallback = std::move(callback); } QVector TranslationUnits::newerFileContainers(const QVector &fileContainers) const @@ -340,13 +354,18 @@ void TranslationUnits::checkIfTranslationUnitsForFilePathsDoesExists(const QVect } } -void TranslationUnits::sendDiagnosticChangedMessage(const TranslationUnit &translationUnit) +void TranslationUnits::sendDelayedEditorUpdates(const TranslationUnit &translationUnit) { - if (sendDiagnosticsChangedCallback) { - DiagnosticsChangedMessage message(translationUnit.fileContainer(), - translationUnit.mainFileDiagnostics()); + if (sendDelayedEditorUpdatesCallback) { + const auto fileContainer = translationUnit.fileContainer(); + DiagnosticsChangedMessage diagnosticsMessage(fileContainer, + translationUnit.mainFileDiagnostics()); + HighlightingChangedMessage highlightingsMessage(fileContainer, + translationUnit.highlightingInformations().toHighlightingMarksContainers(), + translationUnit.skippedSourceRanges().toSourceRangeContainers()); - sendDiagnosticsChangedCallback(std::move(message)); + sendDelayedEditorUpdatesCallback(std::move(diagnosticsMessage), + std::move(highlightingsMessage)); } } diff --git a/src/tools/clangbackend/ipcsource/translationunits.h b/src/tools/clangbackend/ipcsource/translationunits.h index abc0c4670f..9493103a9c 100644 --- a/src/tools/clangbackend/ipcsource/translationunits.h +++ b/src/tools/clangbackend/ipcsource/translationunits.h @@ -46,15 +46,20 @@ namespace ClangBackEnd { class ProjectParts; class UnsavedFiles; class DiagnosticsChangedMessage; +class HighlightingChangedMessage; -enum class DiagnosticSendState +enum class EditorUpdatesSendState { - NoDiagnosticSend, - MaybeThereAreMoreDiagnostics, + NoEditorUpdatesSend, + MaybeThereAreMoreEditorUpdates, }; class TranslationUnits { +public: + using DelayedEditorUpdatesCallback = std::function; + public: TranslationUnits(ProjectParts &projectParts, UnsavedFiles &unsavedFiles); @@ -78,12 +83,13 @@ public: void updateTranslationUnitsWithChangedDependency(const Utf8String &filePath); void updateTranslationUnitsWithChangedDependencies(const QVector &fileContainers); - DiagnosticSendState sendChangedDiagnostics(); - DiagnosticSendState sendChangedDiagnosticsForCurrentEditor(); - DiagnosticSendState sendChangedDiagnosticsForVisibleEditors(); - DiagnosticSendState sendChangedDiagnosticsForAll(); + EditorUpdatesSendState sendDelayedEditorUpdatesForCurrentEditor(); + EditorUpdatesSendState sendDelayedEditorUpdatesForVisibleEditors(); + EditorUpdatesSendState sendDelayedEditorUpdatesForAll(); + + EditorUpdatesSendState sendDelayedEditorUpdates(); - void setSendChangeDiagnosticsCallback(std::function &&callback); + void setSendDelayedEditorUpdatesCallback(DelayedEditorUpdatesCallback &&callback); QVector newerFileContainers(const QVector &fileContainers) const; @@ -102,15 +108,15 @@ private: void checkIfTranslationUnitsDoesNotExists(const QVector &fileContainers) const; void checkIfTranslationUnitsForFilePathsDoesExists(const QVector &fileContainers) const; - void sendDiagnosticChangedMessage(const TranslationUnit &translationUnit); + void sendDelayedEditorUpdates(const TranslationUnit &translationUnit); void removeTranslationUnits(const QVector &fileContainers); template - DiagnosticSendState sendChangedDiagnostics(Predicate predicate); + EditorUpdatesSendState sendDelayedEditorUpdates(Predicate predicate); private: ClangFileSystemWatcher fileSystemWatcher; - std::function sendDiagnosticsChangedCallback; + DelayedEditorUpdatesCallback sendDelayedEditorUpdatesCallback; std::vector translationUnits_; ProjectParts &projectParts; UnsavedFiles &unsavedFiles_; diff --git a/tests/unit/echoserver/echoipcserver.cpp b/tests/unit/echoserver/echoipcserver.cpp index fe1e79180f..2f8f790383 100644 --- a/tests/unit/echoserver/echoipcserver.cpp +++ b/tests/unit/echoserver/echoipcserver.cpp @@ -41,6 +41,7 @@ #include "connectionserver.h" #include "registerunsavedfilesforeditormessage.h" #include "requestdiagnosticsmessage.h" +#include "requesthighlightingmessage.h" #include "unregisterunsavedfilesforeditormessage.h" #include "updatetranslationunitsforeditormessage.h" #include "updatevisibletranslationunitsmessage.h" @@ -107,6 +108,11 @@ void EchoIpcServer::requestDiagnostics(const RequestDiagnosticsMessage &message) echoMessage(QVariant::fromValue(message)); } +void EchoIpcServer::requestHighlighting(const RequestHighlightingMessage &message) +{ + echoMessage(QVariant::fromValue(message)); +} + void EchoIpcServer::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) { echoMessage(QVariant::fromValue(message)); diff --git a/tests/unit/echoserver/echoipcserver.h b/tests/unit/echoserver/echoipcserver.h index f7710f6f3d..05b0da68bd 100644 --- a/tests/unit/echoserver/echoipcserver.h +++ b/tests/unit/echoserver/echoipcserver.h @@ -49,6 +49,7 @@ public: void unregisterUnsavedFilesForEditor(const UnregisterUnsavedFilesForEditorMessage &message) override; void completeCode(const CompleteCodeMessage &message) override; void requestDiagnostics(const RequestDiagnosticsMessage &message) override; + void requestHighlighting(const RequestHighlightingMessage &message) override; void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override; private: diff --git a/tests/unit/mockup/texteditor/semantichighlighter.h b/tests/unit/mockup/texteditor/semantichighlighter.h new file mode 100644 index 0000000000..fa9b5d0a66 --- /dev/null +++ b/tests/unit/mockup/texteditor/semantichighlighter.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef TEXTEDITOR_SEMANTICHIGHLIGHTER_H +#define TEXTEDITOR_SEMANTICHIGHLIGHTER_H + +namespace TextEditor { + +class HighlightingResult { +public: + unsigned line; + unsigned column; + unsigned length; + int kind; + + bool isValid() const + { return line != 0; } + + bool isInvalid() const + { return line == 0; } + + HighlightingResult() + : line(0), column(0), length(0), kind(0) + {} + + HighlightingResult(unsigned line, unsigned column, unsigned length, int kind) + : line(line), column(column), length(length), kind(kind) + {} + + bool operator==(const HighlightingResult& other) const + { + return line == other.line + && column == other.column + && length == other.length + && kind == other.kind; + } +}; + +} // namespace TextEditor + +#endif // TEXTEDITOR_SEMANTICHIGHLIGHTER_H diff --git a/tests/unit/unittest/chunksreportedmonitor.cpp b/tests/unit/unittest/chunksreportedmonitor.cpp new file mode 100644 index 0000000000..f304b42b82 --- /dev/null +++ b/tests/unit/unittest/chunksreportedmonitor.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "chunksreportedmonitor.h" + +#include + +namespace ClangBackEnd { + +ChunksReportedMonitor::ChunksReportedMonitor(const QFuture &future) + : m_future(future) +{ + m_futureWatcher.setFuture(future); + connect(&m_futureWatcher, &QFutureWatcher::resultsReadyAt, + this, &ChunksReportedMonitor::onResultsReadyAt); +} + +bool ChunksReportedMonitor::waitUntilFinished(int timeoutInMs) +{ + QSignalSpy spy(&m_futureWatcher, SIGNAL(finished())); + return spy.wait(timeoutInMs); +} + +void ChunksReportedMonitor::onResultsReadyAt(int beginIndex, int endIndex) +{ + Q_UNUSED(beginIndex) + Q_UNUSED(endIndex) + ++m_resultsReadyCounter; +} + +uint ChunksReportedMonitor::resultsReadyCounter() +{ + waitUntilFinished(); + return m_resultsReadyCounter; +} + +} // namespace ClangBackEnd diff --git a/tests/unit/unittest/chunksreportedmonitor.h b/tests/unit/unittest/chunksreportedmonitor.h new file mode 100644 index 0000000000..6725d46ea9 --- /dev/null +++ b/tests/unit/unittest/chunksreportedmonitor.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CLANGBACKEND_CHUNKSREPORTEDMONITOR_H +#define CLANGBACKEND_CHUNKSREPORTEDMONITOR_H + +#include +#include +#include + +#include + +namespace ClangBackEnd { + +class ChunksReportedMonitor : public QObject +{ + Q_OBJECT + +public: + ChunksReportedMonitor(const QFuture &future); + + uint resultsReadyCounter(); + +private: + bool waitUntilFinished(int timeoutInMs = 5000); + void onResultsReadyAt(int beginIndex, int endIndex); + +private: + QFuture m_future; + QFutureWatcher m_futureWatcher; + uint m_resultsReadyCounter = 0; +}; + +} // namespace ClangBackEnd + +#endif // CLANGBACKEND_CHUNKSREPORTEDMONITOR_H diff --git a/tests/unit/unittest/clangipcservertest.cpp b/tests/unit/unittest/clangipcservertest.cpp index 2f0711832b..a95e42d53d 100644 --- a/tests/unit/unittest/clangipcservertest.cpp +++ b/tests/unit/unittest/clangipcservertest.cpp @@ -31,8 +31,11 @@ #include "mockipclient.h" #include +#include +#include #include #include +#include #include #include @@ -43,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +66,7 @@ using testing::Contains; using testing::Not; using testing::Eq; using testing::PrintToString; +using testing::_; namespace { @@ -78,6 +83,9 @@ using ClangBackEnd::TranslationUnitDoesNotExistMessage; using ClangBackEnd::ProjectPartsDoNotExistMessage; using ClangBackEnd::UpdateTranslationUnitsForEditorMessage; using ClangBackEnd::UpdateVisibleTranslationUnitsMessage; +using ClangBackEnd::RequestHighlightingMessage; +using ClangBackEnd::HighlightingChangedMessage; +using ClangBackEnd::HighlightingMarkContainer; MATCHER_P5(HasDirtyTranslationUnit, filePath, @@ -168,6 +176,18 @@ TEST_F(ClangIpcServer, GetCodeCompletion) clangServer.completeCode(completeCodeMessage); } +TEST_F(ClangIpcServer, RequestHighlighting) +{ + RequestHighlightingMessage requestHighlightingMessage({variableTestFilePath, projectPartId}); + + HighlightingMarkContainer highlightingMarkContainer(1, 6, 8, ClangBackEnd::HighlightingType::Function); + + EXPECT_CALL(mockIpcClient, highlightingChanged(Property(&HighlightingChangedMessage::highlightingMarks, Contains(highlightingMarkContainer)))) + .Times(1); + + clangServer.requestHighlighting(requestHighlightingMessage); +} + TEST_F(ClangIpcServer, GetCodeCompletionDependingOnArgumets) { CompleteCodeMessage completeCodeMessage(variableTestFilePath, diff --git a/tests/unit/unittest/clientserverinprocesstest.cpp b/tests/unit/unittest/clientserverinprocesstest.cpp index 0b5bb27d11..b483fe1099 100644 --- a/tests/unit/unittest/clientserverinprocesstest.cpp +++ b/tests/unit/unittest/clientserverinprocesstest.cpp @@ -47,9 +47,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -197,6 +199,17 @@ TEST_F(ClientServerInProcess, SendRequestDiagnosticsMessage) scheduleServerMessages(); } +TEST_F(ClientServerInProcess, SendRequestHighlightingMessage) +{ + ClangBackEnd::RequestHighlightingMessage message({Utf8StringLiteral("foo.cpp"), + Utf8StringLiteral("projectId")}); + + EXPECT_CALL(mockIpcServer, requestHighlighting(message)) + .Times(1); + + serverProxy.requestHighlighting(message); + scheduleServerMessages(); +} TEST_F(ClientServerInProcess, SendCodeCompletedMessage) { @@ -289,6 +302,21 @@ TEST_F(ClientServerInProcess, SendDiagnosticsChangedMessage) scheduleClientMessages(); } +TEST_F(ClientServerInProcess, SendHighlightingChangedMessage) +{ + ClangBackEnd::HighlightingMarkContainer container(1, 1, 1, ClangBackEnd::HighlightingType::Keyword); + + ClangBackEnd::HighlightingChangedMessage message(fileContainer, + {container}, + QVector()); + + EXPECT_CALL(mockIpcClient, highlightingChanged(message)) + .Times(1); + + clientProxy.highlightingChanged(message); + scheduleClientMessages(); +} + ClientServerInProcess::ClientServerInProcess() : serverProxy(&mockIpcClient, &buffer), clientProxy(&mockIpcServer, &buffer) diff --git a/tests/unit/unittest/clientserveroutsideprocess.cpp b/tests/unit/unittest/clientserveroutsideprocess.cpp index 8db8a12d8e..0e04376585 100644 --- a/tests/unit/unittest/clientserveroutsideprocess.cpp +++ b/tests/unit/unittest/clientserveroutsideprocess.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include diff --git a/tests/unit/unittest/highlightinginformationstest.cpp b/tests/unit/unittest/highlightinginformationstest.cpp index 39238d8f7a..0af449e4d4 100644 --- a/tests/unit/unittest/highlightinginformationstest.cpp +++ b/tests/unit/unittest/highlightinginformationstest.cpp @@ -144,6 +144,14 @@ TEST_F(HighlightingInformations, IteratorBeginEnd) ASSERT_THAT(infos.end(), endIterator); } +TEST_F(HighlightingInformations, ForFullTranslationUnitRange) +{ + const auto infos = translationUnit.highlightingInformations(); + + ASSERT_THAT(infos, AllOf(Contains(IsHighlightingInformation(1u, 1u, 4u, HighlightingType::Keyword)), + Contains(IsHighlightingInformation(277u, 5u, 15u, HighlightingType::Function)))); +} + TEST_F(HighlightingInformations, Size) { const auto range = translationUnit.sourceRange(5, 5, 5, 10); diff --git a/tests/unit/unittest/highlightingmarksreportertest.cpp b/tests/unit/unittest/highlightingmarksreportertest.cpp new file mode 100644 index 0000000000..bc23150d47 --- /dev/null +++ b/tests/unit/unittest/highlightingmarksreportertest.cpp @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "gtest-qt-printing.h" + +using ClangBackEnd::Cursor; +using ClangBackEnd::HighlightingInformations; +using ClangBackEnd::HighlightingMarkContainer; +using ClangBackEnd::HighlightingType; +using ClangBackEnd::TranslationUnit; +using ClangBackEnd::UnsavedFiles; +using ClangBackEnd::ProjectPart; +using ClangBackEnd::ProjectParts; +using ClangBackEnd::TranslationUnits; +using ClangBackEnd::ChunksReportedMonitor; + +namespace { + +struct Data { + ProjectParts projects; + UnsavedFiles unsavedFiles; + TranslationUnits translationUnits{projects, unsavedFiles}; + TranslationUnit translationUnit{Utf8StringLiteral(TESTDATA_DIR"/highlightinginformations.cpp"), + ProjectPart(Utf8StringLiteral("projectPartId"), + {Utf8StringLiteral("-std=c++14")}), + {}, + translationUnits}; +}; + +class HighlightingMarksReporter : public ::testing::Test +{ +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + +protected: + static Data *d; +}; + +QVector noHighlightingMarks() +{ + return QVector(); +} + +QVector generateHighlightingMarks(uint count) +{ + auto container = QVector(); + + for (uint i = 0; i < count; ++i) { + const uint line = i + 1; + container.append(HighlightingMarkContainer(line, 1, 1, HighlightingType::Type)); + } + + return container; +} + +TEST_F(HighlightingMarksReporter, StartAndFinish) +{ + auto reporter = new ClangCodeModel::HighlightingMarksReporter(noHighlightingMarks()); + + auto future = reporter->start(); + + future.waitForFinished(); + ASSERT_THAT(future.isFinished(), true); +} + +TEST_F(HighlightingMarksReporter, ReportNothingIfNothingToReport) +{ + auto reporter = new ClangCodeModel::HighlightingMarksReporter(generateHighlightingMarks(0)); + + auto future = reporter->start(); + + ChunksReportedMonitor monitor(future); + ASSERT_THAT(monitor.resultsReadyCounter(), 0L); +} + +TEST_F(HighlightingMarksReporter, ReportSingleResultAsOneChunk) +{ + auto reporter = new ClangCodeModel::HighlightingMarksReporter(generateHighlightingMarks(1)); + reporter->setChunkSize(1); + + auto future = reporter->start(); + + ChunksReportedMonitor monitor(future); + ASSERT_THAT(monitor.resultsReadyCounter(), 1L); +} + +TEST_F(HighlightingMarksReporter, ReportRestIfChunkSizeNotReached) +{ + auto reporter = new ClangCodeModel::HighlightingMarksReporter(generateHighlightingMarks(1)); + const int notReachedChunkSize = 100; + reporter->setChunkSize(notReachedChunkSize); + + auto future = reporter->start(); + + ChunksReportedMonitor monitor(future); + ASSERT_THAT(monitor.resultsReadyCounter(), 1L); +} + +TEST_F(HighlightingMarksReporter, ReportChunksWithoutRest) +{ + auto reporter = new ClangCodeModel::HighlightingMarksReporter(generateHighlightingMarks(4)); + reporter->setChunkSize(1); + + auto future = reporter->start(); + + ChunksReportedMonitor monitor(future); + ASSERT_THAT(monitor.resultsReadyCounter(), 2L); +} + +TEST_F(HighlightingMarksReporter, ReportSingleChunkAndRest) +{ + auto reporter = new ClangCodeModel::HighlightingMarksReporter(generateHighlightingMarks(5)); + reporter->setChunkSize(2); + + auto future = reporter->start(); + + ChunksReportedMonitor monitor(future); + ASSERT_THAT(monitor.resultsReadyCounter(), 2L); +} + +TEST_F(HighlightingMarksReporter, ReportCompleteLines) +{ + QVector highlightingMarks { + HighlightingMarkContainer(1, 1, 1, HighlightingType::Type), + HighlightingMarkContainer(1, 2, 1, HighlightingType::Type), + HighlightingMarkContainer(2, 1, 1, HighlightingType::Type), + }; + auto reporter = new ClangCodeModel::HighlightingMarksReporter(highlightingMarks); + reporter->setChunkSize(1); + + auto future = reporter->start(); + + ChunksReportedMonitor monitor(future); + ASSERT_THAT(monitor.resultsReadyCounter(), 2L); +} + +Data *HighlightingMarksReporter::d; + +void HighlightingMarksReporter::SetUpTestCase() +{ + d = new Data; +} + +void HighlightingMarksReporter::TearDownTestCase() +{ + delete d; + d = nullptr; +} + +} // anonymous diff --git a/tests/unit/unittest/mockipclient.h b/tests/unit/unittest/mockipclient.h index 75c24dc9e3..b05d9e16d1 100644 --- a/tests/unit/unittest/mockipclient.h +++ b/tests/unit/unittest/mockipclient.h @@ -52,6 +52,8 @@ public: void(const ClangBackEnd::ProjectPartsDoNotExistMessage &message)); MOCK_METHOD1(diagnosticsChanged, void(const ClangBackEnd::DiagnosticsChangedMessage &message)); + MOCK_METHOD1(highlightingChanged, + void(const ClangBackEnd::HighlightingChangedMessage &message)); }; #endif // MOCKIPCLIENT_H diff --git a/tests/unit/unittest/mockipcserver.h b/tests/unit/unittest/mockipcserver.h index 83f9870b4d..90b6f34270 100644 --- a/tests/unit/unittest/mockipcserver.h +++ b/tests/unit/unittest/mockipcserver.h @@ -60,6 +60,8 @@ public: void(const ClangBackEnd::CompleteCodeMessage &message)); MOCK_METHOD1(requestDiagnostics, void(const ClangBackEnd::RequestDiagnosticsMessage &message)); + MOCK_METHOD1(requestHighlighting, + void(const ClangBackEnd::RequestHighlightingMessage &message)); MOCK_METHOD1(updateVisibleTranslationUnits, void(const ClangBackEnd::UpdateVisibleTranslationUnitsMessage &message)); }; diff --git a/tests/unit/unittest/mocksenddiagnosticscallback.h b/tests/unit/unittest/mocksendeditorupdatescallback.h similarity index 82% rename from tests/unit/unittest/mocksenddiagnosticscallback.h rename to tests/unit/unittest/mocksendeditorupdatescallback.h index ecb24fcbc9..7e13281a54 100644 --- a/tests/unit/unittest/mocksenddiagnosticscallback.h +++ b/tests/unit/unittest/mocksendeditorupdatescallback.h @@ -27,27 +27,27 @@ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ -#ifndef MOCKSENDDIAGNOSTICSCALLBACK_H -#define MOCKSENDDIAGNOSTICSCALLBACK_H +#ifndef MOCKSENDEDITORUPDATESCALLBACK_H +#define MOCKSENDEDITORUPDATESCALLBACK_H #include #include #include #include "gtest-qt-printing.h" -class SendDiagnosticCallback +class SendEditorUpdatesCallback { public: - virtual ~SendDiagnosticCallback() = default; + virtual ~SendEditorUpdatesCallback() = default; - virtual void sendDiagnostic() = 0; + virtual void sendEditorUpdates() = 0; }; -class MockSendDiagnosticCallback : public SendDiagnosticCallback +class MockSendEditorUpdatesCallback : public SendEditorUpdatesCallback { public: - MOCK_METHOD0(sendDiagnostic, + MOCK_METHOD0(sendEditorUpdates, void()); }; -#endif // MOCKSENDDIAGNOSTICSCALLBACK_H +#endif // MOCKSENDEDITORUPDATESCALLBACK_H diff --git a/tests/unit/unittest/readandwritemessageblocktest.cpp b/tests/unit/unittest/readandwritemessageblocktest.cpp index 78f1f8d486..f319d1cabb 100644 --- a/tests/unit/unittest/readandwritemessageblocktest.cpp +++ b/tests/unit/unittest/readandwritemessageblocktest.cpp @@ -37,7 +37,10 @@ #include #include #include +#include +#include #include +#include #include #include #include @@ -189,6 +192,15 @@ TEST_F(ReadAndWriteMessageBlock, CompareDiagnosticsChangedMessage) {container})); } +TEST_F(ReadAndWriteMessageBlock, CompareHighlightingChangedMessage) +{ + ClangBackEnd::HighlightingMarkContainer container(1, 1, 1, ClangBackEnd::HighlightingType::Keyword); + + CompareMessage(ClangBackEnd::HighlightingChangedMessage(fileContainer, + {container}, + QVector())); +} + TEST_F(ReadAndWriteMessageBlock, CompareRegisterUnsavedFilesForEditorMessage) { CompareMessage(ClangBackEnd::RegisterUnsavedFilesForEditorMessage({fileContainer})); @@ -204,6 +216,11 @@ TEST_F(ReadAndWriteMessageBlock, CompareRequestDiagnosticsMessage) CompareMessage(ClangBackEnd::RequestDiagnosticsMessage(fileContainer)); } +TEST_F(ReadAndWriteMessageBlock, CompareRequestHighlightingMessage) +{ + CompareMessage(ClangBackEnd::RequestHighlightingMessage(fileContainer)); +} + TEST_F(ReadAndWriteMessageBlock, GetInvalidMessageForAPartialBuffer) { writeCodeCompletedMessage(); diff --git a/tests/unit/unittest/translationunitstest.cpp b/tests/unit/unittest/translationunitstest.cpp index 9c84b4973e..87dfc886ea 100644 --- a/tests/unit/unittest/translationunitstest.cpp +++ b/tests/unit/unittest/translationunitstest.cpp @@ -30,6 +30,8 @@ #include #include +#include +#include #include #include #include @@ -45,7 +47,7 @@ #include -#include "mocksenddiagnosticscallback.h" +#include "mocksendeditorupdatescallback.h" #include #include @@ -56,7 +58,8 @@ using ClangBackEnd::TranslationUnit; using ClangBackEnd::UnsavedFiles; using ClangBackEnd::ProjectPart; using ClangBackEnd::DiagnosticsChangedMessage; -using ClangBackEnd::DiagnosticSendState; +using ClangBackEnd::HighlightingChangedMessage; +using ClangBackEnd::EditorUpdatesSendState; using testing::IsNull; using testing::NotNull; @@ -84,15 +87,15 @@ class TranslationUnits : public ::testing::Test { protected: void SetUp() override; - void sendAllDiagnostics(); - void sendAllCurrentEditorDiagnostics(); - void sendAllVisibleEditorsDiagnostics(); + void sendAllEditorUpdates(); + void sendAllEditorUpdatesForCurrentEditor(); + void sendAllEditorUpdatesForVisibleEditors(); protected: ClangBackEnd::ProjectParts projects; ClangBackEnd::UnsavedFiles unsavedFiles; ClangBackEnd::TranslationUnits translationUnits{projects, unsavedFiles}; - MockSendDiagnosticCallback mockSendDiagnosticCallback; + MockSendEditorUpdatesCallback mockSendEditorUpdatesCallback; const Utf8String filePath = Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp"); const Utf8String headerPath = Utf8StringLiteral(TESTDATA_DIR"/translationunits.h"); const Utf8String nonExistingFilePath = Utf8StringLiteral("foo.cpp"); @@ -208,6 +211,32 @@ TEST_F(TranslationUnits, RemoveFileAndCheckForDiagnostics) ASSERT_TRUE(translationUnits.translationUnit(filePath, projectPartId).hasNewDiagnostics()); } +TEST_F(TranslationUnits, UpdateUnsavedFileAndCheckForHighlightingInformations) +{ + ClangBackEnd::FileContainer fileContainer(filePath, projectPartId, Utf8StringVector(), 74u); + ClangBackEnd::FileContainer headerContainer(headerPath, projectPartId, Utf8StringVector(), 74u); + ClangBackEnd::FileContainer headerContainerWithUnsavedContent(headerPath, projectPartId, Utf8String(), true, 75u); + translationUnits.create({fileContainer, headerContainer}); + translationUnits.translationUnit(filePath, projectPartId).highlightingInformations(); + + translationUnits.update({headerContainerWithUnsavedContent}); + + ASSERT_TRUE(translationUnits.translationUnit(filePath, projectPartId).hasNewHighlightingInformations()); +} + +TEST_F(TranslationUnits, RemoveFileAndCheckForHighlightingInformations) +{ + ClangBackEnd::FileContainer fileContainer(filePath, projectPartId, Utf8StringVector(), 74u); + ClangBackEnd::FileContainer headerContainer(headerPath, projectPartId, Utf8StringVector(), 74u); + ClangBackEnd::FileContainer headerContainerWithUnsavedContent(headerPath, projectPartId, Utf8String(), true, 75u); + translationUnits.create({fileContainer, headerContainer}); + translationUnits.translationUnit(filePath, projectPartId).highlightingInformations(); + + translationUnits.remove({headerContainerWithUnsavedContent}); + + ASSERT_TRUE(translationUnits.translationUnit(filePath, projectPartId).hasNewHighlightingInformations()); +} + TEST_F(TranslationUnits, DontGetNewerFileContainerIfRevisionIsTheSame) { ClangBackEnd::FileContainer fileContainer(filePath, projectPartId, Utf8StringVector(), 74u); @@ -345,75 +374,77 @@ TEST_F(TranslationUnits, IsNotVisibleEditorAfterBeingVisible) ASSERT_FALSE(translationUnit.isVisibleInEditor()); } -TEST_F(TranslationUnits, DoNotSendDiagnosticsIfThereIsNothingToSend) +TEST_F(TranslationUnits, DoNotSendEditorUpdatesIfThereIsNothingToSend) { - EXPECT_CALL(mockSendDiagnosticCallback, sendDiagnostic()).Times(0); + EXPECT_CALL(mockSendEditorUpdatesCallback, sendEditorUpdates()).Times(0); - sendAllDiagnostics(); + sendAllEditorUpdates(); } -TEST_F(TranslationUnits, SendDiagnosticsAfterTranslationUnitCreation) +TEST_F(TranslationUnits, SendEditorUpdatessAfterTranslationUnitCreation) { translationUnits.create({fileContainer, headerContainer}); - EXPECT_CALL(mockSendDiagnosticCallback, sendDiagnostic()).Times(2); + EXPECT_CALL(mockSendEditorUpdatesCallback, sendEditorUpdates()).Times(2); - sendAllDiagnostics(); + sendAllEditorUpdates(); } -TEST_F(TranslationUnits, DoNotSendDiagnosticsAfterGettingDiagnostics) +TEST_F(TranslationUnits, DoNotSendEditorUpdatesAfterGettingEditorUpdates) { translationUnits.create({fileContainer, headerContainer}); auto translationUnit = translationUnits.translationUnit(fileContainer); - translationUnit.diagnostics(); + translationUnit.diagnostics(); // Reset + translationUnit.highlightingInformations(); // Reset - EXPECT_CALL(mockSendDiagnosticCallback, sendDiagnostic()).Times(1); + EXPECT_CALL(mockSendEditorUpdatesCallback, sendEditorUpdates()).Times(1); - sendAllDiagnostics(); + sendAllEditorUpdates(); } -TEST_F(TranslationUnits, SendDiagnosticsForCurrentEditor) +TEST_F(TranslationUnits, SendEditorUpdatesForCurrentEditor) { translationUnits.create({fileContainer, headerContainer}); auto translationUnit = translationUnits.translationUnit(fileContainer); translationUnit.setIsUsedByCurrentEditor(true); - EXPECT_CALL(mockSendDiagnosticCallback, sendDiagnostic()).Times(1); + EXPECT_CALL(mockSendEditorUpdatesCallback, sendEditorUpdates()).Times(1); - sendAllCurrentEditorDiagnostics(); + sendAllEditorUpdatesForCurrentEditor(); } -TEST_F(TranslationUnits, DoNotSendDiagnosticsForCurrentEditorIfThereIsNoCurrentEditor) +TEST_F(TranslationUnits, DoNotSendEditorUpdatesForCurrentEditorIfThereIsNoCurrentEditor) { translationUnits.create({fileContainer, headerContainer}); - EXPECT_CALL(mockSendDiagnosticCallback, sendDiagnostic()).Times(0); + EXPECT_CALL(mockSendEditorUpdatesCallback, sendEditorUpdates()).Times(0); - sendAllCurrentEditorDiagnostics(); + sendAllEditorUpdatesForCurrentEditor(); } -TEST_F(TranslationUnits, DoNotSendDiagnosticsForCurrentEditorAfterGettingDiagnostics) +TEST_F(TranslationUnits, DoNotSendEditorUpdatesForCurrentEditorAfterGettingEditorUpdates) { translationUnits.create({fileContainer, headerContainer}); auto translationUnit = translationUnits.translationUnit(fileContainer); translationUnit.setIsUsedByCurrentEditor(true); - translationUnit.diagnostics(); + translationUnit.diagnostics(); // Reset + translationUnit.highlightingInformations(); // Reset - EXPECT_CALL(mockSendDiagnosticCallback, sendDiagnostic()).Times(0); + EXPECT_CALL(mockSendEditorUpdatesCallback, sendEditorUpdates()).Times(0); - sendAllCurrentEditorDiagnostics(); + sendAllEditorUpdatesForCurrentEditor(); } -TEST_F(TranslationUnits, DoNotSendDiagnosticsForVisibleEditorIfThereAreNoVisibleEditors) +TEST_F(TranslationUnits, DoNotSendEditorUpdatesForVisibleEditorIfThereAreNoVisibleEditors) { translationUnits.create({fileContainer, headerContainer}); - EXPECT_CALL(mockSendDiagnosticCallback, sendDiagnostic()).Times(0); + EXPECT_CALL(mockSendEditorUpdatesCallback, sendEditorUpdates()).Times(0); - translationUnits.sendChangedDiagnosticsForVisibleEditors(); + translationUnits.sendDelayedEditorUpdatesForVisibleEditors(); } -TEST_F(TranslationUnits, SendDiagnosticsForVisibleEditors) +TEST_F(TranslationUnits, SendEditorUpdatesForVisibleEditors) { translationUnits.create({fileContainer, headerContainer}); auto fileTranslationUnit = translationUnits.translationUnit(fileContainer); @@ -421,55 +452,58 @@ TEST_F(TranslationUnits, SendDiagnosticsForVisibleEditors) auto headerTranslationUnit = translationUnits.translationUnit(headerContainer); headerTranslationUnit.setIsVisibleInEditor(true); - EXPECT_CALL(mockSendDiagnosticCallback, sendDiagnostic()).Times(2); + EXPECT_CALL(mockSendEditorUpdatesCallback, sendEditorUpdates()).Times(2); - sendAllVisibleEditorsDiagnostics(); + sendAllEditorUpdatesForVisibleEditors(); } -TEST_F(TranslationUnits, SendOnlyOneDiagnosticsForVisibleEditor) +TEST_F(TranslationUnits, SendOnlyOneEditorUpdateForVisibleEditor) { translationUnits.create({fileContainer, headerContainer}); auto fileTranslationUnit = translationUnits.translationUnit(fileContainer); fileTranslationUnit.setIsVisibleInEditor(true); auto headerTranslationUnit = translationUnits.translationUnit(headerContainer); headerTranslationUnit.setIsVisibleInEditor(true); - headerTranslationUnit.diagnostics(); + headerTranslationUnit.diagnostics(); // Reset + headerTranslationUnit.highlightingInformations(); // Reset - EXPECT_CALL(mockSendDiagnosticCallback, sendDiagnostic()).Times(1); + EXPECT_CALL(mockSendEditorUpdatesCallback, sendEditorUpdates()).Times(1); - sendAllVisibleEditorsDiagnostics(); + sendAllEditorUpdatesForVisibleEditors(); } void TranslationUnits::SetUp() { projects.createOrUpdate({ClangBackEnd::ProjectPartContainer(projectPartId)}); - auto callback = [&] (const DiagnosticsChangedMessage &) { mockSendDiagnosticCallback.sendDiagnostic(); }; - translationUnits.setSendChangeDiagnosticsCallback(callback); + auto callback = [&] (const DiagnosticsChangedMessage &, const HighlightingChangedMessage &) { + mockSendEditorUpdatesCallback.sendEditorUpdates(); + }; + translationUnits.setSendDelayedEditorUpdatesCallback(callback); } -void TranslationUnits::sendAllDiagnostics() +void TranslationUnits::sendAllEditorUpdates() { - auto diagnosticSendState = DiagnosticSendState::MaybeThereAreMoreDiagnostics; + auto editorUpdatesSendState = EditorUpdatesSendState::MaybeThereAreMoreEditorUpdates; - while (diagnosticSendState == DiagnosticSendState::MaybeThereAreMoreDiagnostics) - diagnosticSendState = translationUnits.sendChangedDiagnostics(); + while (editorUpdatesSendState == EditorUpdatesSendState::MaybeThereAreMoreEditorUpdates) + editorUpdatesSendState = translationUnits.sendDelayedEditorUpdates(); } -void TranslationUnits::sendAllCurrentEditorDiagnostics() +void TranslationUnits::sendAllEditorUpdatesForCurrentEditor() { - auto diagnosticSendState = DiagnosticSendState::MaybeThereAreMoreDiagnostics; + auto editorUpdatesSendState = EditorUpdatesSendState::MaybeThereAreMoreEditorUpdates; - while (diagnosticSendState == DiagnosticSendState::MaybeThereAreMoreDiagnostics) - diagnosticSendState = translationUnits.sendChangedDiagnosticsForCurrentEditor(); + while (editorUpdatesSendState == EditorUpdatesSendState::MaybeThereAreMoreEditorUpdates) + editorUpdatesSendState = translationUnits.sendDelayedEditorUpdatesForCurrentEditor(); } -void TranslationUnits::sendAllVisibleEditorsDiagnostics() +void TranslationUnits::sendAllEditorUpdatesForVisibleEditors() { - auto diagnosticSendState = DiagnosticSendState::MaybeThereAreMoreDiagnostics; + auto editorUpdatesSendState = EditorUpdatesSendState::MaybeThereAreMoreEditorUpdates; - while (diagnosticSendState == DiagnosticSendState::MaybeThereAreMoreDiagnostics) - diagnosticSendState = translationUnits.sendChangedDiagnosticsForVisibleEditors(); + while (editorUpdatesSendState == EditorUpdatesSendState::MaybeThereAreMoreEditorUpdates) + editorUpdatesSendState = translationUnits.sendDelayedEditorUpdatesForVisibleEditors(); } } diff --git a/tests/unit/unittest/translationunittest.cpp b/tests/unit/unittest/translationunittest.cpp index 12b0137a6e..24bdcdac10 100644 --- a/tests/unit/unittest/translationunittest.cpp +++ b/tests/unit/unittest/translationunittest.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -194,18 +195,20 @@ TEST_F(TranslationUnit, DependedFilePaths) Contains(Utf8StringLiteral(TESTDATA_DIR"/translationunits.h")))); } -TEST_F(TranslationUnit, NeedsNoReparseAfterCreation) +TEST_F(TranslationUnit, DeletedFileShouldNotNeedReparsing) { - translationUnit.cxTranslationUnit(); + auto translationUnit = createTemporaryTranslationUnit(); + + translationUnit.setDirtyIfDependencyIsMet(translationUnit.filePath()); ASSERT_FALSE(translationUnit.isNeedingReparse()); } -TEST_F(TranslationUnit, HasNewDiagnosticsAfterCreation) +TEST_F(TranslationUnit, NeedsNoReparseAfterCreation) { translationUnit.cxTranslationUnit(); - ASSERT_TRUE(translationUnit.hasNewDiagnostics()); + ASSERT_FALSE(translationUnit.isNeedingReparse()); } TEST_F(TranslationUnit, NeedsReparseAfterChangeOfMainFile) @@ -217,15 +220,6 @@ TEST_F(TranslationUnit, NeedsReparseAfterChangeOfMainFile) ASSERT_TRUE(translationUnit.isNeedingReparse()); } -TEST_F(TranslationUnit, HasNewDiagnosticsAfterChangeOfMainFile) -{ - translationUnit.cxTranslationUnit(); - - translationUnit.setDirtyIfDependencyIsMet(translationUnitFilePath); - - ASSERT_TRUE(translationUnit.hasNewDiagnostics()); -} - TEST_F(TranslationUnit, NoNeedForReparsingForIndependendFile) { translationUnit.cxTranslationUnit(); @@ -244,23 +238,30 @@ TEST_F(TranslationUnit, NeedsReparsingForDependendFile) ASSERT_TRUE(translationUnit.isNeedingReparse()); } -TEST_F(TranslationUnit, NeedsReparsingForMainFile) +TEST_F(TranslationUnit, NeedsNoReparsingAfterReparsing) { translationUnit.cxTranslationUnit(); + translationUnit.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/translationunits.h")); - translationUnit.setDirtyIfDependencyIsMet(translationUnitFilePath); + translationUnit.cxTranslationUnit(); - ASSERT_TRUE(translationUnit.isNeedingReparse()); + ASSERT_FALSE(translationUnit.isNeedingReparse()); } -TEST_F(TranslationUnit, NeedsNoReparsingAfterReparsing) +TEST_F(TranslationUnit, HasNewDiagnosticsAfterCreation) { translationUnit.cxTranslationUnit(); - translationUnit.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/translationunits.h")); + ASSERT_TRUE(translationUnit.hasNewDiagnostics()); +} + +TEST_F(TranslationUnit, HasNewDiagnosticsAfterChangeOfMainFile) +{ translationUnit.cxTranslationUnit(); - ASSERT_FALSE(translationUnit.isNeedingReparse()); + translationUnit.setDirtyIfDependencyIsMet(translationUnitFilePath); + + ASSERT_TRUE(translationUnit.hasNewDiagnostics()); } TEST_F(TranslationUnit, HasNoNewDiagnosticsForIndependendFile) @@ -282,32 +283,59 @@ TEST_F(TranslationUnit, HasNewDiagnosticsForDependendFile) ASSERT_TRUE(translationUnit.hasNewDiagnostics()); } -TEST_F(TranslationUnit, HasNewDiagnosticsForMainFile) +TEST_F(TranslationUnit, HasNoNewDiagnosticsAfterGettingDiagnostics) { translationUnit.cxTranslationUnit(); - translationUnit.setDirtyIfDependencyIsMet(translationUnitFilePath); - ASSERT_TRUE(translationUnit.hasNewDiagnostics()); + translationUnit.diagnostics(); // Reset hasNewDiagnostics + + ASSERT_FALSE(translationUnit.hasNewDiagnostics()); } -TEST_F(TranslationUnit, HasNoNewDiagnosticsAfterGettingDiagnostics) +TEST_F(TranslationUnit, HasNewHighlightingInformationsAfterCreation) { translationUnit.cxTranslationUnit(); + + ASSERT_TRUE(translationUnit.hasNewHighlightingInformations()); +} + +TEST_F(TranslationUnit, HasNewHighlightingInformationsForMainFile) +{ + translationUnit.cxTranslationUnit(); + translationUnit.setDirtyIfDependencyIsMet(translationUnitFilePath); - translationUnit.diagnostics(); + ASSERT_TRUE(translationUnit.hasNewHighlightingInformations()); +} - ASSERT_FALSE(translationUnit.hasNewDiagnostics()); +TEST_F(TranslationUnit, HasNoNewHighlightingInformationsForIndependendFile) +{ + translationUnit.cxTranslationUnit(); + translationUnit.highlightingInformations(); + + translationUnit.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/otherfiles.h")); + + ASSERT_FALSE(translationUnit.hasNewHighlightingInformations()); } -TEST_F(TranslationUnit, DeletedFileShouldBeNotSetDirty) +TEST_F(TranslationUnit, HasNewHighlightingInformationsForDependendFile) { - auto translationUnit = createTemporaryTranslationUnit(); + translationUnit.cxTranslationUnit(); - translationUnit.setDirtyIfDependencyIsMet(translationUnit.filePath()); + translationUnit.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/translationunits.h")); - ASSERT_FALSE(translationUnit.isNeedingReparse()); + ASSERT_TRUE(translationUnit.hasNewHighlightingInformations()); +} + +TEST_F(TranslationUnit, HasNoNewHighlightingInformationsAfterGettingHighlightingInformations) +{ + translationUnit.cxTranslationUnit(); + translationUnit.setDirtyIfDependencyIsMet(translationUnitFilePath); + + translationUnit.highlightingInformations(); + + ASSERT_FALSE(translationUnit.hasNewHighlightingInformations()); } ::TranslationUnit TranslationUnit::createTemporaryTranslationUnit() diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index b2d209d4dc..4c18b07caf 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -56,7 +56,9 @@ SOURCES += \ senddocumenttrackertest.cpp \ cursortest.cpp \ highlightinginformationstest.cpp \ - skippedsourcerangestest.cpp + skippedsourcerangestest.cpp \ + highlightingmarksreportertest.cpp \ + chunksreportedmonitor.cpp HEADERS += \ gtest-qt-printing.h \ @@ -64,6 +66,7 @@ HEADERS += \ mockipcserver.h \ spydummy.h \ matcher-diagnosticcontainer.h \ - mocksenddiagnosticscallback.h + chunksreportedmonitor.h \ + mocksendeditorupdatescallback.h OTHER_FILES += $$files(data/*) -- GitLab