diff --git a/dist/changes-3.6.0.md b/dist/changes-3.6.0.md index 98dfebadf27..5644a917117 100644 --- a/dist/changes-3.6.0.md +++ b/dist/changes-3.6.0.md @@ -21,6 +21,10 @@ Editing * Fixed that Qt Creator tried to write auto-save files in read-only directories * Fixed possible crash with code completion (QTCREATORBUG-14875) +* Fixed that closing session was leaving invalid editor windows open + (QTCREATORBUG-15193) +* Fixed that editors were closing even when closing Qt Creator was cancelled + (QTCREATORBUG-14401) Project Management @@ -29,6 +33,10 @@ Project Management (QTCREATORBUG-14606) * Added option to synchronize kits between all projects in a session (QTCREATORBUG-5823) +* Fixed that `%{CurrentBuild:Type}` was not expanded correctly + (QTCREATORBUG-15178) +* Fixed that `Stop applications before building` also stopped applications + when deploying (QTCREATORBUG-15281) QMake Projects @@ -39,6 +47,8 @@ QMake Projects * Fixed that `QMAKE_EXT_H` was ignored for UI code model (QTCREATORBUG-14910) * Fixed that `make` build step was not updated on environment changes (QTCREATORBUG-14831) +* Fixed adding files to `.qrc` files through the project tree + (QTCREATORBUG-15277) CMake Projects @@ -50,9 +60,13 @@ CMake Projects C++ Support * Added support for `noexcept` +* Fixed crash with function arguments hint (QTCREATORBUG-15275) +* Fixed that object instantiation was sometimes highlighted as function call + (QTCREATORBUG-15212) * Clang code model * Added more diagnostic messages to editors * Added Clang's Fix-its to refactoring actions (QTCREATORBUG-14868) + * Added option for additional command line arguments Debugging @@ -73,6 +87,7 @@ Analyzer QML Profiler * Improved performance of timeline view (QTCREATORBUG-14983) +* Fixed offset when dragging timeline categories (QTCREATORBUG-15333) Qt Quick Designer @@ -114,6 +129,7 @@ Android (QTCREATORBUG-14832) * Fixed deployment on devices without `readlink` (QTCREATORBUG-15006) * Fixed debugging of signed applications (requires Qt 5.6) (QTCREATORBUG-13035) +* Fixed that building failed if Java is not in `PATH` (QTCREATORBUG-15382) iOS @@ -124,6 +140,7 @@ Remote Linux * Added support for ECDSA public keys with 384 and 521 bits, ECDSA user keys, and ECDSA key creation * Fixed environment and working directory for Valgrind analyzer +* Fixed attaching to remote debugging server (QTCREATORBUG-15210) Credits for these changes go to: Aleix Pol diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/GridLayoutSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/GridLayoutSpecifics.qml new file mode 100644 index 00000000000..f16981eb125 --- /dev/null +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/GridLayoutSpecifics.qml @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +****************************************************************************/ + +import QtQuick 2.1 +import HelperWidgets 2.0 +import QtQuick.Layouts 1.0 + +Column { + anchors.left: parent.left + anchors.right: parent.right + + Section { + anchors.left: parent.left + anchors.right: parent.right + caption: qsTr("GridLayout") + + + SectionLayout { + + Label { + text: qsTr("Columns") + } + + SecondColumnLayout { + SpinBox { + backendValue: backendValues.columns + minimumValue: 0 + maximumValue: 2000 + decimals: 0 + } + + ExpandingSpacer { + } + } + + Label { + text: qsTr("Rows") + } + + SecondColumnLayout { + SpinBox { + backendValue: backendValues.rows + minimumValue: 0 + maximumValue: 2000 + decimals: 0 + } + + ExpandingSpacer { + } + } + + Label { + text: qsTr("Flow") + } + + SecondColumnLayout { + ComboBox { + model: ["LeftToRight", "TopToBottom"] + backendValue: backendValues.flow + Layout.fillWidth: true + scope: "GridLayout" + } + } + + Label { + text: qsTr("Layout Direction") + } + + SecondColumnLayout { + ComboBox { + model: ["LeftToRight", "RightToLeft"] + backendValue: backendValues.layoutDirection + Layout.fillWidth: true + scope: "Qt" + } + + } + + + Label { + text: qsTr("Row Spacing") + } + + SecondColumnLayout { + SpinBox { + backendValue: backendValues.rowSpacing + minimumValue: -4000 + maximumValue: 4000 + decimals: 0 + } + + ExpandingSpacer { + } + } + + Label { + text: qsTr("Column Spacing") + } + + SecondColumnLayout { + SpinBox { + backendValue: backendValues.columnSpacing + minimumValue: -4000 + maximumValue: 4000 + decimals: 0 + } + + ExpandingSpacer { + } + } + } + } +} diff --git a/src/libs/clangbackendipc/clangbackendipc-lib.pri b/src/libs/clangbackendipc/clangbackendipc-lib.pri index cc11840a043..3084a13761b 100644 --- a/src/libs/clangbackendipc/clangbackendipc-lib.pri +++ b/src/libs/clangbackendipc/clangbackendipc-lib.pri @@ -46,7 +46,8 @@ SOURCES += $$PWD/ipcserverinterface.cpp \ $$PWD/requestdiagnosticsmessage.cpp \ $$PWD/registerunsavedfilesforeditormessage.cpp \ $$PWD/unregisterunsavedfilesforeditormessage.cpp \ - $$PWD/updatetranslationunitsforeditormessage.cpp + $$PWD/updatetranslationunitsforeditormessage.cpp \ + $$PWD/updatevisibletranslationunitsmessage.cpp HEADERS += \ $$PWD/ipcserverinterface.h \ @@ -87,6 +88,7 @@ HEADERS += \ $$PWD/requestdiagnosticsmessage.h \ $$PWD/registerunsavedfilesforeditormessage.h \ $$PWD/unregisterunsavedfilesforeditormessage.h \ - $$PWD/updatetranslationunitsforeditormessage.h + $$PWD/updatetranslationunitsforeditormessage.h \ + $$PWD/updatevisibletranslationunitsmessage.h contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols diff --git a/src/libs/clangbackendipc/cmbmessages.cpp b/src/libs/clangbackendipc/cmbmessages.cpp index 04af03c5e7d..d275de5353d 100644 --- a/src/libs/clangbackendipc/cmbmessages.cpp +++ b/src/libs/clangbackendipc/cmbmessages.cpp @@ -49,6 +49,7 @@ #include "translationunitdoesnotexistmessage.h" #include "unregisterunsavedfilesforeditormessage.h" #include "updatetranslationunitsforeditormessage.h" +#include "updatevisibletranslationunitsmessage.h" #include @@ -82,6 +83,8 @@ void Messages::registerMessages() registerMetaType(); registerMetaType(); + registerMetaType(); + registerMetaType(); registerMetaType(); registerMetaType(); diff --git a/src/libs/clangbackendipc/ipcclientinterface.h b/src/libs/clangbackendipc/ipcclientinterface.h index 32d17e4c60d..5600e130763 100644 --- a/src/libs/clangbackendipc/ipcclientinterface.h +++ b/src/libs/clangbackendipc/ipcclientinterface.h @@ -50,6 +50,7 @@ class DiagnosticsChangedMessage; class RequestDiagnosticsMessage; class RegisterUnsavedFilesForEditorMessage; class UnregisterUnsavedFilesForEditorMessage; +class UpdateVisibleTranslationUnitsMessage; class CMBIPC_EXPORT IpcClientInterface : public IpcInterface { diff --git a/src/libs/clangbackendipc/ipcserverinterface.cpp b/src/libs/clangbackendipc/ipcserverinterface.cpp index 92ba85a6de7..93717dfa33a 100644 --- a/src/libs/clangbackendipc/ipcserverinterface.cpp +++ b/src/libs/clangbackendipc/ipcserverinterface.cpp @@ -39,6 +39,7 @@ #include "requestdiagnosticsmessage.h" #include "unregisterunsavedfilesforeditormessage.h" #include "updatetranslationunitsforeditormessage.h" +#include "updatevisibletranslationunitsmessage.h" #include #include @@ -57,6 +58,8 @@ 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 updateVisibleTranslationUnitsMessageType = QMetaType::type("ClangBackEnd::UpdateVisibleTranslationUnitsMessage"); + int type = message.userType(); @@ -80,6 +83,8 @@ void IpcServerInterface::dispatch(const QVariant &message) completeCode(message.value()); else if (type == requestDiagnosticsMessageType) requestDiagnostics(message.value()); + else if (type == updateVisibleTranslationUnitsMessageType) + updateVisibleTranslationUnits(message.value()); else qWarning() << "Unknown IpcServerMessage"; } diff --git a/src/libs/clangbackendipc/ipcserverinterface.h b/src/libs/clangbackendipc/ipcserverinterface.h index 0682970412c..98d1441c0d5 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 updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) = 0; void addClient(IpcClientInterface *client); void removeClient(IpcClientInterface *client); diff --git a/src/libs/clangbackendipc/ipcserverproxy.cpp b/src/libs/clangbackendipc/ipcserverproxy.cpp index a1d9d978be5..fa5777267c8 100644 --- a/src/libs/clangbackendipc/ipcserverproxy.cpp +++ b/src/libs/clangbackendipc/ipcserverproxy.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -119,5 +120,10 @@ void IpcServerProxy::requestDiagnostics(const ClangBackEnd::RequestDiagnosticsMe writeMessageBlock.write(QVariant::fromValue(message)); } +void IpcServerProxy::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) +{ + writeMessageBlock.write(QVariant::fromValue(message)); +} + } // namespace ClangBackEnd diff --git a/src/libs/clangbackendipc/ipcserverproxy.h b/src/libs/clangbackendipc/ipcserverproxy.h index a3f52ff128c..d4c42887f4f 100644 --- a/src/libs/clangbackendipc/ipcserverproxy.h +++ b/src/libs/clangbackendipc/ipcserverproxy.h @@ -65,7 +65,7 @@ public: void unregisterUnsavedFilesForEditor(const UnregisterUnsavedFilesForEditorMessage &message) override; void completeCode(const CompleteCodeMessage &message) override; void requestDiagnostics(const RequestDiagnosticsMessage &message) override; - + void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override; void readMessages(); void resetCounter(); diff --git a/src/libs/clangbackendipc/updatevisibletranslationunitsmessage.cpp b/src/libs/clangbackendipc/updatevisibletranslationunitsmessage.cpp new file mode 100644 index 00000000000..8e383fa86c1 --- /dev/null +++ b/src/libs/clangbackendipc/updatevisibletranslationunitsmessage.cpp @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** 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 "updatevisibletranslationunitsmessage.h" + +#include "container_common.h" + +#include +#include + +#include +#include +#include + +namespace ClangBackEnd { + +UpdateVisibleTranslationUnitsMessage::UpdateVisibleTranslationUnitsMessage( + const Utf8String ¤tEditorFilePath, + const Utf8StringVector &visibleEditorFilePaths) + : currentEditorFilePath_(currentEditorFilePath), + visibleEditorFilePaths_(visibleEditorFilePaths) +{ +} + +const Utf8String &UpdateVisibleTranslationUnitsMessage::currentEditorFilePath() const +{ + return currentEditorFilePath_; +} + +const Utf8StringVector &UpdateVisibleTranslationUnitsMessage::visibleEditorFilePaths() const +{ + return visibleEditorFilePaths_; +} + +QDataStream &operator<<(QDataStream &out, const UpdateVisibleTranslationUnitsMessage &message) +{ + out << message.currentEditorFilePath_; + out << message.visibleEditorFilePaths_; + + return out; +} + +QDataStream &operator>>(QDataStream &in, UpdateVisibleTranslationUnitsMessage &message) +{ + in >> message.currentEditorFilePath_; + in >> message.visibleEditorFilePaths_; + + return in; +} + +bool operator==(const UpdateVisibleTranslationUnitsMessage &first, const UpdateVisibleTranslationUnitsMessage &second) +{ + return first.currentEditorFilePath_ == second.currentEditorFilePath_ + && first.visibleEditorFilePaths_ == second.visibleEditorFilePaths_; +} + +bool operator<(const UpdateVisibleTranslationUnitsMessage &first, const UpdateVisibleTranslationUnitsMessage &second) +{ + return first.currentEditorFilePath_ < second.currentEditorFilePath_ + && compareContainer(first.visibleEditorFilePaths_, second.visibleEditorFilePaths_); +} + +QDebug operator<<(QDebug debug, const UpdateVisibleTranslationUnitsMessage &message) +{ + debug.nospace() << "UpdateVisibleTranslationUnitsMessage("; + + debug.nospace() << message.currentEditorFilePath() << ", "; + + for (const Utf8String &visibleEditorFilePath : message.visibleEditorFilePaths()) + debug.nospace() << visibleEditorFilePath << ", "; + + debug.nospace() << ")"; + + return debug; +} + +void PrintTo(const UpdateVisibleTranslationUnitsMessage &message, ::std::ostream* os) +{ + *os << "UpdateVisibleTranslationUnitsMessage("; + + *os << message.currentEditorFilePath().constData() << ", "; + + auto visiblePaths = message.visibleEditorFilePaths(); + + std::copy(visiblePaths.cbegin(), visiblePaths.cend(), std::ostream_iterator(*os, ", ")); + + *os << ")"; +} + +} // namespace ClangBackEnd diff --git a/src/libs/clangbackendipc/updatevisibletranslationunitsmessage.h b/src/libs/clangbackendipc/updatevisibletranslationunitsmessage.h new file mode 100644 index 00000000000..3383ccc616f --- /dev/null +++ b/src/libs/clangbackendipc/updatevisibletranslationunitsmessage.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** 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_UPDATEVISIBLETRANSLATIONUNITSMESSAGE_H +#define CLANGBACKEND_UPDATEVISIBLETRANSLATIONUNITSMESSAGE_H + +#include + +#include + +#include + +namespace ClangBackEnd { + +class CMBIPC_EXPORT UpdateVisibleTranslationUnitsMessage +{ + friend CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const UpdateVisibleTranslationUnitsMessage &message); + friend CMBIPC_EXPORT QDataStream &operator>>(QDataStream &in, UpdateVisibleTranslationUnitsMessage &message); + friend CMBIPC_EXPORT bool operator==(const UpdateVisibleTranslationUnitsMessage &first, const UpdateVisibleTranslationUnitsMessage &second); + friend CMBIPC_EXPORT bool operator<(const UpdateVisibleTranslationUnitsMessage &first, const UpdateVisibleTranslationUnitsMessage &second); + +public: + UpdateVisibleTranslationUnitsMessage() = default; + UpdateVisibleTranslationUnitsMessage(const Utf8String ¤tEditorFilePath, + const Utf8StringVector &visibleEditorFilePaths); + + const Utf8String ¤tEditorFilePath() const; + const Utf8StringVector &visibleEditorFilePaths() const; + +private: + Utf8String currentEditorFilePath_; + Utf8StringVector visibleEditorFilePaths_; +}; + +CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const UpdateVisibleTranslationUnitsMessage &message); +CMBIPC_EXPORT QDataStream &operator>>(QDataStream &in, UpdateVisibleTranslationUnitsMessage &message); +CMBIPC_EXPORT bool operator==(const UpdateVisibleTranslationUnitsMessage &first, const UpdateVisibleTranslationUnitsMessage &second); +CMBIPC_EXPORT bool operator<(const UpdateVisibleTranslationUnitsMessage &first, const UpdateVisibleTranslationUnitsMessage &second); + +CMBIPC_EXPORT QDebug operator<<(QDebug debug, const UpdateVisibleTranslationUnitsMessage &message); +void PrintTo(const UpdateVisibleTranslationUnitsMessage &message, ::std::ostream* os); +} // namespace ClangBackEnd + +Q_DECLARE_METATYPE(ClangBackEnd::UpdateVisibleTranslationUnitsMessage) + +#endif // CLANGBACKEND_UPDATEVISIBLETRANSLATIONUNITSMESSAGE_H diff --git a/src/libs/qmldebug/qmldebugclient.cpp b/src/libs/qmldebug/qmldebugclient.cpp index fb21d84341f..591d8b74577 100644 --- a/src/libs/qmldebug/qmldebugclient.cpp +++ b/src/libs/qmldebug/qmldebugclient.cpp @@ -426,6 +426,18 @@ void QmlDebugConnection::setMaximumDataStreamVersion(int maximumVersion) d->maximumDataStreamVersion = maximumVersion; } +QAbstractSocket::SocketState QmlDebugConnection::socketState() const +{ + Q_D(const QmlDebugConnection); + // TODO: when merging into master, add clause for local socket + if (QAbstractSocket *socket = qobject_cast(d->device)) + return socket->state(); + else + return QAbstractSocket::UnconnectedState; +} + +// + QmlDebugClientPrivate::QmlDebugClientPrivate() : connection(0) { diff --git a/src/libs/qmldebug/qmldebugclient.h b/src/libs/qmldebug/qmldebugclient.h index 862f058c17f..2bd4fc96cdb 100644 --- a/src/libs/qmldebug/qmldebugclient.h +++ b/src/libs/qmldebug/qmldebugclient.h @@ -51,6 +51,7 @@ public: void connectToHost(const QString &hostName, quint16 port); void startLocalServer(const QString &fileName); + QAbstractSocket::SocketState socketState() const; int currentDataStreamVersion() const; void setMaximumDataStreamVersion(int maximumVersion); diff --git a/src/libs/sqlite/utf8string.cpp b/src/libs/sqlite/utf8string.cpp index c8cbaea2230..9fb92b5d39d 100644 --- a/src/libs/sqlite/utf8string.cpp +++ b/src/libs/sqlite/utf8string.cpp @@ -269,6 +269,14 @@ void PrintTo(const Utf8String &text, ::std::ostream* os) *os << "\"" << text.toByteArray().data() << "\""; } +std::ostream& operator<<(std::ostream &os, const Utf8String &utf8String) +{ + using std::ostream; + os << utf8String.constData(); + + return os; +} + uint qHash(const Utf8String &utf8String) { return qHash(utf8String.byteArray); diff --git a/src/libs/sqlite/utf8string.h b/src/libs/sqlite/utf8string.h index c6adfc93716..6158f8b690d 100644 --- a/src/libs/sqlite/utf8string.h +++ b/src/libs/sqlite/utf8string.h @@ -36,6 +36,8 @@ #include #include +#include + class Utf8StringVector; class Utf8String; @@ -120,6 +122,7 @@ SQLITE_EXPORT QDataStream &operator<<(QDataStream &datastream, const Utf8String SQLITE_EXPORT QDataStream &operator>>(QDataStream &datastream, Utf8String &text); SQLITE_EXPORT QDebug operator<<(QDebug debug, const Utf8String &text); SQLITE_EXPORT void PrintTo(const Utf8String &text, ::std::ostream* os); +SQLITE_EXPORT std::ostream& operator<<(std::ostream &os, const Utf8String &utf8String); SQLITE_EXPORT uint qHash(const Utf8String &utf8String); diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri index c305e5b3854..14699830765 100644 --- a/src/libs/utils/utils-lib.pri +++ b/src/libs/utils/utils-lib.pri @@ -8,6 +8,10 @@ QT += gui network qml CONFIG += exceptions # used by portlist.cpp, textfileformat.cpp, and ssh/* +win32: LIBS += -luser32 -lshell32 +# PortsGatherer +win32: LIBS += -liphlpapi -lws2_32 + SOURCES += $$PWD/environment.cpp \ $$PWD/environmentmodel.cpp \ $$PWD/qtcprocess.cpp \ diff --git a/src/libs/utils/utils.pro b/src/libs/utils/utils.pro index 83d61eac6df..b3f2f208928 100644 --- a/src/libs/utils/utils.pro +++ b/src/libs/utils/utils.pro @@ -1,8 +1,4 @@ include(../../qtcreatorlibrary.pri) include(utils-lib.pri) -win32: LIBS += -luser32 -lshell32 -# PortsGatherer -win32: LIBS += -liphlpapi -lws2_32 - DEFINES += QTC_REL_TOOLS_PATH=$$shell_quote(\"$$relative_path($$IDE_LIBEXEC_PATH, $$IDE_BIN_PATH)\") diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp index d5e2593e04b..49cc4285390 100644 --- a/src/plugins/android/androidsettingswidget.cpp +++ b/src/plugins/android/androidsettingswidget.cpp @@ -308,7 +308,7 @@ void AndroidSettingsWidget::check(AndroidSettingsWidget::Mode mode) toolchainsForAbi.insert(ati.abi); QSet qtVersionsForAbi; - foreach (QtSupport::BaseQtVersion *qtVersion, QtSupport::QtVersionManager::versions()) { + foreach (QtSupport::BaseQtVersion *qtVersion, QtSupport::QtVersionManager::unsortedVersions()) { if (qtVersion->type() != QLatin1String(Constants::ANDROIDQT) || qtVersion->qtAbis().isEmpty()) continue; qtVersionsForAbi.insert(qtVersion->qtAbis().first()); diff --git a/src/plugins/android/androidtoolchain.cpp b/src/plugins/android/androidtoolchain.cpp index c2ccacbc8f7..6b09208c9c9 100644 --- a/src/plugins/android/androidtoolchain.cpp +++ b/src/plugins/android/androidtoolchain.cpp @@ -106,7 +106,6 @@ bool AndroidToolChain::isValid() const void AndroidToolChain::addToEnvironment(Environment &env) const { - // TODO this vars should be configurable in projects -> build tab // TODO invalidate all .pro files !!! @@ -114,9 +113,15 @@ void AndroidToolChain::addToEnvironment(Environment &env) const env.set(QLatin1String("ANDROID_NDK_TOOLCHAIN_PREFIX"), AndroidConfig::toolchainPrefix(targetAbi())); env.set(QLatin1String("ANDROID_NDK_TOOLS_PREFIX"), AndroidConfig::toolsPrefix(targetAbi())); env.set(QLatin1String("ANDROID_NDK_TOOLCHAIN_VERSION"), m_ndkToolChainVersion); - QString javaHome = AndroidConfigurations::currentConfig().openJDKLocation().toString(); - if (!javaHome.isEmpty() && QFileInfo::exists(javaHome)) - env.set(QLatin1String("JAVA_HOME"), javaHome); + const Utils::FileName javaHome = AndroidConfigurations::currentConfig().openJDKLocation(); + if (!javaHome.isEmpty() && javaHome.toFileInfo().exists()) { + env.set(QLatin1String("JAVA_HOME"), javaHome.toString()); + Utils::FileName javaBin = javaHome; + javaBin.appendPath(QLatin1String("bin")); + const QString jb = javaBin.toUserOutput(); + if (!Utils::contains(env.path(), [&jb](const QString &p) { return p == jb; })) + env.prependOrSetPath(jb); + } env.set(QLatin1String("ANDROID_HOME"), AndroidConfigurations::currentConfig().sdkLocation().toString()); env.set(QLatin1String("ANDROID_SDK_ROOT"), AndroidConfigurations::currentConfig().sdkLocation().toString()); } diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp index 6c46c05b76e..13544424bd8 100644 --- a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp +++ b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp @@ -189,6 +189,11 @@ QList ClangDiagnosticManager::takeExtraSelections() return extraSelections; } +void ClangDiagnosticManager::clearDiagnosticsWithFixIts() +{ + m_fixItdiagnostics.clear(); +} + void ClangDiagnosticManager::generateEditorSelections() { m_extraSelections.clear(); diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.h b/src/plugins/clangcodemodel/clangdiagnosticmanager.h index 85ba1dde499..8007fc47fe8 100644 --- a/src/plugins/clangcodemodel/clangdiagnosticmanager.h +++ b/src/plugins/clangcodemodel/clangdiagnosticmanager.h @@ -56,6 +56,8 @@ public: const QVector &diagnosticsWithFixIts() const; QList takeExtraSelections(); + void clearDiagnosticsWithFixIts(); + private: QString filePath() const; void filterDiagnostics(const QVector &diagnostics); diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index 341f541255c..5739960751c 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -224,6 +224,11 @@ ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainer() const return fileContainer(m_projectPart.data()); } +void ClangEditorDocumentProcessor::clearDiagnosticsWithFixIts() +{ + m_diagnosticManager.clearDiagnosticsWithFixIts(); +} + ClangEditorDocumentProcessor *ClangEditorDocumentProcessor::get(const QString &filePath) { return qobject_cast(BaseEditorDocumentProcessor::get(filePath)); diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h index 575725e8738..ded0258210f 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h @@ -81,6 +81,8 @@ public: ClangBackEnd::FileContainer fileContainer() const; + void clearDiagnosticsWithFixIts(); + public: static ClangEditorDocumentProcessor *get(const QString &filePath); diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index 06cda925ee1..26780648305 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -197,6 +197,15 @@ void ModelManagerSupportClang::onCppDocumentReloadFinishedOnTranslationUnit(bool } } +namespace { +void clearDiagnosticFixIts(const QString &filePath) +{ + auto processor = ClangEditorDocumentProcessor::get(filePath); + if (processor) + processor->clearDiagnosticsWithFixIts(); +} +} + void ModelManagerSupportClang::onCppDocumentContentsChangedOnTranslationUnit(int position, int /*charsRemoved*/, int /*charsAdded*/) @@ -206,6 +215,8 @@ void ModelManagerSupportClang::onCppDocumentContentsChangedOnTranslationUnit(int m_ipcCommunicator.updateChangeContentStartPosition(document->filePath().toString(), position); m_ipcCommunicator.updateTranslationUnitIfNotCurrentDocument(document); + + clearDiagnosticFixIts(document->filePath().toString()); } void ModelManagerSupportClang::onCppDocumentAboutToReloadOnUnsavedFile() diff --git a/src/plugins/cpptools/cppprojects.cpp b/src/plugins/cpptools/cppprojects.cpp index d1ab05fb686..ba2b14ba0f5 100644 --- a/src/plugins/cpptools/cppprojects.cpp +++ b/src/plugins/cpptools/cppprojects.cpp @@ -59,6 +59,16 @@ ProjectPart::ProjectPart() { } +static ProjectPart::HeaderPath toProjectPartHeaderPath(const ProjectExplorer::HeaderPath &headerPath) +{ + const ProjectPart::HeaderPath::Type headerPathType = + headerPath.kind() == ProjectExplorer::HeaderPath::FrameworkHeaderPath + ? ProjectPart::HeaderPath::FrameworkPath + : ProjectPart::HeaderPath::IncludePath; + + return ProjectPart::HeaderPath(headerPath.path(), headerPathType); +} + /*! \brief Retrieves info from concrete compiler using it's flags. @@ -106,10 +116,9 @@ void ProjectPart::evaluateToolchain(const ToolChain *tc, const QList headers = tc->systemHeaderPaths(commandLineFlags, sysRoot); foreach (const ProjectExplorer::HeaderPath &header, headers) { - headerPaths << ProjectPart::HeaderPath(header.path(), - header.kind() == ProjectExplorer::HeaderPath::FrameworkHeaderPath - ? ProjectPart::HeaderPath::FrameworkPath - : ProjectPart::HeaderPath::IncludePath); + const HeaderPath headerPath = toProjectPartHeaderPath(header); + if (!headerPaths.contains(headerPath)) + headerPaths << headerPath; } toolchainDefines = tc->predefinedMacros(commandLineFlags); diff --git a/src/plugins/ios/iosconfigurations.cpp b/src/plugins/ios/iosconfigurations.cpp index 9bf56c2a6ee..31da93fd426 100644 --- a/src/plugins/ios/iosconfigurations.cpp +++ b/src/plugins/ios/iosconfigurations.cpp @@ -144,7 +144,7 @@ static QHash findToolChains(const QList &p static QHash> iosQtVersions() { QHash> versions; - foreach (BaseQtVersion *qtVersion, QtVersionManager::versions()) { + foreach (BaseQtVersion *qtVersion, QtVersionManager::unsortedVersions()) { if (!qtVersion->isValid() || qtVersion->type() != QLatin1String(Constants::IOSQT)) continue; foreach (const Abi &abi, qtVersion->qtAbis()) diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp index 017c2e444d9..c4d2aaebe3f 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp @@ -108,7 +108,7 @@ QList QmakeProjectImporter::import(const FileName &importPath, bool qCDebug(logs) << " QMake:" << canonicalQmakeBinary; BaseQtVersion *version - = Utils::findOrDefault(QtVersionManager::versions(), + = Utils::findOrDefault(QtVersionManager::unsortedVersions(), [&canonicalQmakeBinary](BaseQtVersion *v) -> bool { QFileInfo vfi = v->qmakeCommand().toFileInfo(); FileName current = FileName::fromString(vfi.canonicalFilePath()); diff --git a/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp b/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp index c031a8d3176..d713684883d 100644 --- a/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp @@ -270,9 +270,22 @@ void QmlProfilerClientManager::tryToConnect() if (d->connection && d->connection->isConnected()) { d->connectionTimer.stop(); d->connectionAttempts = 0; + } else if (d->connection && + d->connection->socketState() != QAbstractSocket::ConnectedState) { + // Replace the connection after trying for some time. On some operating systems (OSX) the + // very first connection to a TCP server takes a very long time to get established. + + // delete directly here, so that any pending events aren't delivered. We don't want the + // connection first to be established and then torn down again. + delete d->connection; + d->connection = 0; + connectClient(d->tcpPort); + connectToClient(); } else if (d->connectionAttempts == 50) { d->connectionTimer.stop(); d->connectionAttempts = 0; + delete d->connection; // delete directly. + d->connection = 0; QMessageBox *infoBox = QmlProfilerTool::requestMessageBox(); infoBox->setIcon(QMessageBox::Critical); @@ -333,14 +346,11 @@ void QmlProfilerClientManager::logState(const QString &msg) void QmlProfilerClientManager::retryMessageBoxFinished(int result) { - if (d->connection) { - QTC_ASSERT(!d->connection->isConnected(), return); - if (d->connection->isConnecting()) - d->connection->disconnect(); - } + QTC_ASSERT(!d->connection, disconnectClient()); switch (result) { case QMessageBox::Retry: { + connectClient(d->tcpPort); d->connectionAttempts = 0; d->connectionTimer.start(); break; diff --git a/src/plugins/qtsupport/qtversionmanager.cpp b/src/plugins/qtsupport/qtversionmanager.cpp index 48583720d00..ca8f925f63e 100644 --- a/src/plugins/qtsupport/qtversionmanager.cpp +++ b/src/plugins/qtsupport/qtversionmanager.cpp @@ -502,7 +502,7 @@ static void updateDocumentation() void QtVersionManager::updateDumpFor(const FileName &qmakeCommand) { - foreach (BaseQtVersion *v, versions()) { + foreach (BaseQtVersion *v, unsortedVersions()) { if (v->qmakeCommand() == qmakeCommand) v->recheckDumper(); } @@ -630,7 +630,7 @@ void QtVersionManager::setNewQtVersions(QList newVersions) BaseQtVersion *QtVersionManager::qtVersionForQMakeBinary(const FileName &qmakePath) { - return Utils::findOrDefault(versions(), Utils::equal(&BaseQtVersion::qmakeCommand, qmakePath)); + return Utils::findOrDefault(unsortedVersions(), Utils::equal(&BaseQtVersion::qmakeCommand, qmakePath)); } } // namespace QtVersion diff --git a/src/tools/clangbackend/ipcsource/clangipcserver.cpp b/src/tools/clangbackend/ipcsource/clangipcserver.cpp index 320c982c88e..31c3ae481f3 100644 --- a/src/tools/clangbackend/ipcsource/clangipcserver.cpp +++ b/src/tools/clangbackend/ipcsource/clangipcserver.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -243,6 +244,18 @@ void ClangIpcServer::requestDiagnostics(const RequestDiagnosticsMessage &message } } +void ClangIpcServer::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) +{ + TIME_SCOPE_DURATION("ClangIpcServer::updateVisibleTranslationUnits"); + + try { + translationUnits.setCurrentEditor(message.currentEditorFilePath()); + translationUnits.setVisibleEditors(message.visibleEditorFilePaths()); + } catch (const std::exception &exception) { + qWarning() << "Error in ClangIpcServer::updateVisibleTranslationUnits:" << exception.what(); + } +} + const TranslationUnits &ClangIpcServer::translationUnitsForTestOnly() const { return translationUnits; diff --git a/src/tools/clangbackend/ipcsource/clangipcserver.h b/src/tools/clangbackend/ipcsource/clangipcserver.h index d4e5c6442ac..bfb1313e64f 100644 --- a/src/tools/clangbackend/ipcsource/clangipcserver.h +++ b/src/tools/clangbackend/ipcsource/clangipcserver.h @@ -61,6 +61,7 @@ public: void unregisterUnsavedFilesForEditor(const UnregisterUnsavedFilesForEditorMessage &message) override; void completeCode(const CompleteCodeMessage &message) override; void requestDiagnostics(const RequestDiagnosticsMessage &message) override; + void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override; const TranslationUnits &translationUnitsForTestOnly() const; diff --git a/src/tools/clangbackend/ipcsource/commandlinearguments.cpp b/src/tools/clangbackend/ipcsource/commandlinearguments.cpp index 41c80430be9..5a0aa0e8e92 100644 --- a/src/tools/clangbackend/ipcsource/commandlinearguments.cpp +++ b/src/tools/clangbackend/ipcsource/commandlinearguments.cpp @@ -30,6 +30,8 @@ #include "commandlinearguments.h" +#include + #include namespace ClangBackEnd { @@ -67,13 +69,23 @@ const char *CommandLineArguments::at(int position) const return m_arguments.at(uint(position)); } +static Utf8String maybeQuoted(const char *argumentAsCString) +{ + const auto quotationMark = Utf8StringLiteral("\""); + const auto argument = Utf8String::fromUtf8(argumentAsCString); + + if (argument.contains(quotationMark)) + return argument; + + return quotationMark + argument + quotationMark; +} + void CommandLineArguments::print() const { using namespace std; - cerr << "Arguments to libclang:"; for (const auto &argument : m_arguments) - cerr << ' ' << argument; + cerr << ' ' << maybeQuoted(argument).constData(); cerr << endl; } diff --git a/src/tools/clangbackend/ipcsource/highlightinginformation.cpp b/src/tools/clangbackend/ipcsource/highlightinginformation.cpp index 808a0407d14..d91ddf26b9d 100644 --- a/src/tools/clangbackend/ipcsource/highlightinginformation.cpp +++ b/src/tools/clangbackend/ipcsource/highlightinginformation.cpp @@ -241,11 +241,23 @@ HighlightingType literalKind(const Cursor &cursor) Q_UNREACHABLE(); } +bool hasOperatorName(const char *operatorString) +{ + return std::strncmp(operatorString, "operator", 8) == 0; +} + +HighlightingType operatorKind(const Cursor &cursor) +{ + if (hasOperatorName(cursor.spelling().cString())) + return HighlightingType::Operator; + else + return HighlightingType::Invalid; +} HighlightingType punctationKind(const Cursor &cursor) { switch (cursor.kind()) { - case CXCursor_DeclRefExpr: return HighlightingType::Operator; + case CXCursor_DeclRefExpr: return operatorKind(cursor); default: return HighlightingType::Invalid; } } diff --git a/src/tools/clangbackend/ipcsource/translationunit.cpp b/src/tools/clangbackend/ipcsource/translationunit.cpp index 8769f7caef3..cd880f0567d 100644 --- a/src/tools/clangbackend/ipcsource/translationunit.cpp +++ b/src/tools/clangbackend/ipcsource/translationunit.cpp @@ -83,8 +83,10 @@ public: CXTranslationUnit translationUnit = nullptr; CXIndex index = nullptr; uint documentRevision = 0; - bool needsToBeReparsed = false; - bool hasNewDiagnostics = false; + bool needsToBeReparsed = false; + bool hasNewDiagnostics = true; + bool isUsedByCurrentEditor = false; + bool isVisibleInEditor = false; }; TranslationUnitData::TranslationUnitData(const Utf8String &filePath, @@ -125,6 +127,26 @@ bool TranslationUnit::isNull() const return !d; } +void TranslationUnit::setIsUsedByCurrentEditor(bool isUsedByCurrentEditor) +{ + d->isUsedByCurrentEditor = isUsedByCurrentEditor; +} + +bool TranslationUnit::isUsedByCurrentEditor() const +{ + return d->isUsedByCurrentEditor; +} + +void TranslationUnit::setIsVisibleInEditor(bool isVisibleInEditor) +{ + d->isVisibleInEditor = isVisibleInEditor; +} + +bool TranslationUnit::isVisibleInEditor() const +{ + return d->isVisibleInEditor; +} + void TranslationUnit::reset() { d.reset(); diff --git a/src/tools/clangbackend/ipcsource/translationunit.h b/src/tools/clangbackend/ipcsource/translationunit.h index fd3831cb3e0..37c47413611 100644 --- a/src/tools/clangbackend/ipcsource/translationunit.h +++ b/src/tools/clangbackend/ipcsource/translationunit.h @@ -86,6 +86,12 @@ public: bool isNull() const; + void setIsUsedByCurrentEditor(bool isUsedByCurrentEditor); + bool isUsedByCurrentEditor() const; + + void setIsVisibleInEditor(bool isVisibleInEditor); + bool isVisibleInEditor() const; + void reset(); void reparse() const; diff --git a/src/tools/clangbackend/ipcsource/translationunits.cpp b/src/tools/clangbackend/ipcsource/translationunits.cpp index 8fd3b14b7c6..07975bf693d 100644 --- a/src/tools/clangbackend/ipcsource/translationunits.cpp +++ b/src/tools/clangbackend/ipcsource/translationunits.cpp @@ -39,6 +39,8 @@ #include +#include + namespace ClangBackEnd { bool operator==(const FileContainer &fileContainer, const TranslationUnit &translationUnit) @@ -62,10 +64,8 @@ void TranslationUnits::create(const QVector &fileContainers) { checkIfTranslationUnitsDoesNotExists(fileContainers); - for (const FileContainer &fileContainer : fileContainers) { + for (const FileContainer &fileContainer : fileContainers) createTranslationUnit(fileContainer); - updateTranslationUnitsWithChangedDependency(fileContainer.filePath()); - } } void TranslationUnits::update(const QVector &fileContainers) @@ -97,6 +97,18 @@ void TranslationUnits::remove(const QVector &fileContainers) updateTranslationUnitsWithChangedDependencies(fileContainers); } +void TranslationUnits::setCurrentEditor(const Utf8String &filePath) +{ + for (TranslationUnit &translationUnit : translationUnits_) + translationUnit.setIsUsedByCurrentEditor(translationUnit.filePath() == filePath); +} + +void TranslationUnits::setVisibleEditors(const Utf8StringVector &filePaths) +{ + for (TranslationUnit &translationUnit : translationUnits_) + translationUnit.setIsVisibleInEditor(filePaths.contains(translationUnit.filePath())); +} + const TranslationUnit &TranslationUnits::translationUnit(const Utf8String &filePath, const Utf8String &projectPartId) const { checkIfProjectPartExists(projectPartId); @@ -153,14 +165,55 @@ void TranslationUnits::updateTranslationUnitsWithChangedDependencies(const QVect DiagnosticSendState TranslationUnits::sendChangedDiagnostics() { - for (const auto &translationUnit : translationUnits_) { - if (translationUnit.hasNewDiagnostics()) { - sendDiagnosticChangedMessage(translationUnit); - return DiagnosticSendState::MaybeThereAreMoreDiagnostics; - } + auto diagnosticSendState = sendChangedDiagnosticsForCurrentEditor(); + if (diagnosticSendState == DiagnosticSendState::NoDiagnosticSend) + diagnosticSendState = sendChangedDiagnosticsForVisibleEditors(); + if (diagnosticSendState == DiagnosticSendState::NoDiagnosticSend) + diagnosticSendState = sendChangedDiagnosticsForAll(); + + return diagnosticSendState; +} + +template +DiagnosticSendState TranslationUnits::sendChangedDiagnostics(Predicate predicate) +{ + auto foundTranslationUnit = std::find_if(translationUnits_.begin(), + translationUnits_.end(), + predicate); + + if (foundTranslationUnit != translationUnits().end()) { + sendDiagnosticChangedMessage(*foundTranslationUnit); + return DiagnosticSendState::MaybeThereAreMoreDiagnostics; } - return DiagnosticSendState::AllDiagnosticSend; + return DiagnosticSendState::NoDiagnosticSend; +} + +DiagnosticSendState TranslationUnits::sendChangedDiagnosticsForCurrentEditor() +{ + auto hasDiagnosticsForCurrentEditor = [] (const TranslationUnit &translationUnit) { + return translationUnit.isUsedByCurrentEditor() && translationUnit.hasNewDiagnostics(); + }; + + return sendChangedDiagnostics(hasDiagnosticsForCurrentEditor); +} + +DiagnosticSendState TranslationUnits::sendChangedDiagnosticsForVisibleEditors() +{ + auto hasDiagnosticsForVisibleEditor = [] (const TranslationUnit &translationUnit) { + return translationUnit.isVisibleInEditor() && translationUnit.hasNewDiagnostics(); + }; + + return sendChangedDiagnostics(hasDiagnosticsForVisibleEditor); +} + +DiagnosticSendState TranslationUnits::sendChangedDiagnosticsForAll() +{ + auto hasDiagnostics = [] (const TranslationUnit &translationUnit) { + return translationUnit.hasNewDiagnostics(); + }; + + return sendChangedDiagnostics(hasDiagnostics); } void TranslationUnits::setSendChangeDiagnosticsCallback(std::function &&callback) diff --git a/src/tools/clangbackend/ipcsource/translationunits.h b/src/tools/clangbackend/ipcsource/translationunits.h index 58433b85666..a08d642d48b 100644 --- a/src/tools/clangbackend/ipcsource/translationunits.h +++ b/src/tools/clangbackend/ipcsource/translationunits.h @@ -49,8 +49,8 @@ class DiagnosticsChangedMessage; enum class DiagnosticSendState { - AllDiagnosticSend, - MaybeThereAreMoreDiagnostics + NoDiagnosticSend, + MaybeThereAreMoreDiagnostics, }; class TranslationUnits @@ -62,6 +62,9 @@ public: void update(const QVector &fileContainers); void remove(const QVector &fileContainers); + void setCurrentEditor(const Utf8String &filePath); + void setVisibleEditors(const Utf8StringVector &filePaths); + const TranslationUnit &translationUnit(const Utf8String &filePath, const Utf8String &projectPartId) const; const TranslationUnit &translationUnit(const FileContainer &fileContainer) const; bool hasTranslationUnit(const Utf8String &filePath) const; @@ -76,6 +79,9 @@ public: void updateTranslationUnitsWithChangedDependencies(const QVector &fileContainers); DiagnosticSendState sendChangedDiagnostics(); + DiagnosticSendState sendChangedDiagnosticsForCurrentEditor(); + DiagnosticSendState sendChangedDiagnosticsForVisibleEditors(); + DiagnosticSendState sendChangedDiagnosticsForAll(); void setSendChangeDiagnosticsCallback(std::function &&callback); @@ -99,6 +105,9 @@ private: void sendDiagnosticChangedMessage(const TranslationUnit &translationUnit); void removeTranslationUnits(const QVector &fileContainers); + template + DiagnosticSendState sendChangedDiagnostics(Predicate predicate); + private: ClangFileSystemWatcher fileSystemWatcher; std::function sendDiagnosticsChangedCallback; diff --git a/src/tools/iostool/main.cpp b/src/tools/iostool/main.cpp index 90eed751b33..246c55c75c4 100644 --- a/src/tools/iostool/main.cpp +++ b/src/tools/iostool/main.cpp @@ -114,6 +114,7 @@ public: IosTool *iosTool(); public slots: void handleNewRelayConnection(); + void removeRelayConnection(Relayer *relayer); protected: virtual void newRelayConnection() = 0; @@ -231,9 +232,12 @@ void Relayer::setClientSocket(QTcpSocket *clientSocket) { QTC_CHECK(!m_clientSocket); m_clientSocket = clientSocket; - if (m_clientSocket) + if (m_clientSocket) { connect(m_clientSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(handleClientHasError(QAbstractSocket::SocketError))); + connect(m_clientSocket, &QAbstractSocket::disconnected, + this, [this](){server()->removeRelayConnection(this);}); + } } bool Relayer::startRelay(int serverFileDescriptor) @@ -354,7 +358,7 @@ void Relayer::handleClientHasData() void Relayer::handleClientHasError(QAbstractSocket::SocketError error) { iosTool()->errorMsg(tr("iOS Debugging connection to creator failed with error %1").arg(error)); - iosTool()->stopRelayServers(); + server()->removeRelayConnection(this); } IosTool *Relayer::iosTool() @@ -446,6 +450,12 @@ void RelayServer::handleNewRelayConnection() newRelayConnection(); } +void RelayServer::removeRelayConnection(Relayer *relayer) +{ + m_connections.removeAll(relayer); + relayer->deleteLater(); +} + SingleRelayServer::SingleRelayServer(IosTool *parent, int serverFileDescriptor) : RelayServer(parent) @@ -458,9 +468,7 @@ SingleRelayServer::SingleRelayServer(IosTool *parent, void SingleRelayServer::newRelayConnection() { if (m_connections.size() > 0) { - m_server.close(); - QTcpSocket *s = m_server.nextPendingConnection(); - delete s; + delete m_server.nextPendingConnection(); return; } QTcpSocket *clientSocket = m_server.nextPendingConnection(); @@ -469,7 +477,6 @@ void SingleRelayServer::newRelayConnection() m_connections.append(newConnection); newConnection->startRelay(m_serverFileDescriptor); } - m_server.close(); } GenericRelayServer::GenericRelayServer(IosTool *parent, int remotePort, diff --git a/tests/unit/echoserver/echoipcserver.cpp b/tests/unit/echoserver/echoipcserver.cpp index c9dbfb42e88..fe1e79180f3 100644 --- a/tests/unit/echoserver/echoipcserver.cpp +++ b/tests/unit/echoserver/echoipcserver.cpp @@ -43,6 +43,7 @@ #include "requestdiagnosticsmessage.h" #include "unregisterunsavedfilesforeditormessage.h" #include "updatetranslationunitsforeditormessage.h" +#include "updatevisibletranslationunitsmessage.h" #include #include @@ -106,6 +107,11 @@ void EchoIpcServer::requestDiagnostics(const RequestDiagnosticsMessage &message) echoMessage(QVariant::fromValue(message)); } +void EchoIpcServer::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) +{ + echoMessage(QVariant::fromValue(message)); +} + void EchoIpcServer::echoMessage(const QVariant &message) { client()->echo(EchoMessage(message)); diff --git a/tests/unit/echoserver/echoipcserver.h b/tests/unit/echoserver/echoipcserver.h index cb3c55d2bb4..f7710f6f3dc 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 updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override; private: void echoMessage(const QVariant &message); diff --git a/tests/unit/unittest/clangipcservertest.cpp b/tests/unit/unittest/clangipcservertest.cpp index 175e19e5213..2f0711832b0 100644 --- a/tests/unit/unittest/clangipcservertest.cpp +++ b/tests/unit/unittest/clangipcservertest.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -76,12 +77,20 @@ using ClangBackEnd::ProjectPartContainer; using ClangBackEnd::TranslationUnitDoesNotExistMessage; using ClangBackEnd::ProjectPartsDoNotExistMessage; using ClangBackEnd::UpdateTranslationUnitsForEditorMessage; +using ClangBackEnd::UpdateVisibleTranslationUnitsMessage; -MATCHER_P3(HasDirtyTranslationUnit, filePath, projectPartId, documentRevision, +MATCHER_P5(HasDirtyTranslationUnit, + filePath, + projectPartId, + documentRevision, + isNeedingReparse, + hasNewDiagnostics, std::string(negation ? "isn't" : "is") + " translation unit with file path "+ PrintToString(filePath) + " and project " + PrintToString(projectPartId) + " and document revision " + PrintToString(documentRevision) + + " and isNeedingReparse = " + PrintToString(isNeedingReparse) + + " and hasNewDiagnostics = " + PrintToString(hasNewDiagnostics) ) { auto &&translationUnits = arg.translationUnitsForTestOnly(); @@ -89,16 +98,24 @@ MATCHER_P3(HasDirtyTranslationUnit, filePath, projectPartId, documentRevision, auto translationUnit = translationUnits.translationUnit(filePath, projectPartId); if (translationUnit.documentRevision() == documentRevision) { - if (translationUnit.hasNewDiagnostics()) { - if (translationUnit.isNeedingReparse()) - return true; + if (translationUnit.hasNewDiagnostics() && !hasNewDiagnostics) { + *result_listener << "hasNewDiagnostics is true"; + return false; + } else if (!translationUnit.hasNewDiagnostics() && hasNewDiagnostics) { + *result_listener << "hasNewDiagnostics is false"; + return false; + } + + if (translationUnit.isNeedingReparse() && !isNeedingReparse) { + *result_listener << "isNeedingReparse is true"; + return false; + } else if (!translationUnit.isNeedingReparse() && isNeedingReparse) { *result_listener << "isNeedingReparse is false"; return false; } - *result_listener << "hasNewDiagnostics is false"; - return false; + return true; } *result_listener << "revision number is " << PrintToString(translationUnit.documentRevision()); @@ -120,11 +137,13 @@ protected: void registerProjectPart(); void changeProjectPartArguments(); void changeProjectPartArgumentsToWrongValues(); + void updateVisibilty(const Utf8String ¤tEditor, const Utf8String &additionalVisibleEditor); static const Utf8String unsavedContent(const QString &unsavedFilePath); protected: MockIpcClient mockIpcClient; ClangBackEnd::ClangIpcServer clangServer; + const ClangBackEnd::TranslationUnits &translationUnits = clangServer.translationUnitsForTestOnly(); const Utf8String projectPartId = Utf8StringLiteral("pathToProjectPart.pro"); const Utf8String functionTestFilePath = Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_function.cpp"); const Utf8String variableTestFilePath = Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_variable.cpp"); @@ -133,53 +152,6 @@ protected: const Utf8String parseErrorTestFilePath = Utf8StringLiteral(TESTDATA_DIR"/complete_translationunit_parse_error.cpp"); }; - -void ClangIpcServer::SetUp() -{ - clangServer.addClient(&mockIpcClient); - registerProjectPart(); - registerFiles(); -} - -void ClangIpcServer::registerFiles() -{ - RegisterTranslationUnitForEditorMessage message({FileContainer(functionTestFilePath, projectPartId, unsavedContent(unsavedTestFilePath), true), - FileContainer(variableTestFilePath, projectPartId)}); - - clangServer.registerTranslationUnitsForEditor(message); -} - -void ClangIpcServer::registerProjectPart() -{ - RegisterProjectPartsForEditorMessage message({ProjectPartContainer(projectPartId)}); - - clangServer.registerProjectPartsForEditor(message); -} - -void ClangIpcServer::changeProjectPartArguments() -{ - RegisterProjectPartsForEditorMessage message({ProjectPartContainer(projectPartId, {Utf8StringLiteral("-DArgumentDefinition")})}); - - clangServer.registerProjectPartsForEditor(message); -} - -void ClangIpcServer::changeProjectPartArgumentsToWrongValues() -{ - RegisterProjectPartsForEditorMessage message({ProjectPartContainer(projectPartId, {Utf8StringLiteral("-blah")})}); - - clangServer.registerProjectPartsForEditor(message); -} - -const Utf8String ClangIpcServer::unsavedContent(const QString &unsavedFilePath) -{ - QFile unsavedFileContentFile(unsavedFilePath); - bool isOpen = unsavedFileContentFile.open(QIODevice::ReadOnly | QIODevice::Text); - if (!isOpen) - ADD_FAILURE() << "File with the unsaved content cannot be opened!"; - - return Utf8String::fromByteArray(unsavedFileContentFile.readAll()); -} - TEST_F(ClangIpcServer, GetCodeCompletion) { CompleteCodeMessage completeCodeMessage(functionTestFilePath, @@ -406,8 +378,98 @@ TEST_F(ClangIpcServer, TicketNumberIsForwarded) clangServer.completeCode(completeCodeMessage); } -TEST_F(ClangIpcServer, TranslationUnitIsDirtyAfterCreation) +TEST_F(ClangIpcServer, TranslationUnitAfterCreationNeedsNoReparseAndHasNewDiagnostics) { - ASSERT_THAT(clangServer, HasDirtyTranslationUnit(functionTestFilePath, projectPartId, 0)); + ASSERT_THAT(clangServer, HasDirtyTranslationUnit(functionTestFilePath, projectPartId, 0U, false, true)); } + +TEST_F(ClangIpcServer, SetCurrentAndVisibleEditor) +{ + auto functionTranslationUnit = translationUnits.translationUnit(functionTestFilePath, projectPartId); + auto variableTranslationUnit = translationUnits.translationUnit(variableTestFilePath, projectPartId); + + updateVisibilty(functionTestFilePath, variableTestFilePath); + + ASSERT_TRUE(functionTranslationUnit.isUsedByCurrentEditor()); + ASSERT_TRUE(functionTranslationUnit.isVisibleInEditor()); + ASSERT_TRUE(variableTranslationUnit.isVisibleInEditor()); +} + +TEST_F(ClangIpcServer, IsNotCurrentCurrentAndVisibleEditorAnymore) +{ + auto functionTranslationUnit = translationUnits.translationUnit(functionTestFilePath, projectPartId); + auto variableTranslationUnit = translationUnits.translationUnit(variableTestFilePath, projectPartId); + updateVisibilty(functionTestFilePath, variableTestFilePath); + + updateVisibilty(variableTestFilePath, Utf8String()); + + ASSERT_FALSE(functionTranslationUnit.isUsedByCurrentEditor()); + ASSERT_FALSE(functionTranslationUnit.isVisibleInEditor()); + ASSERT_TRUE(variableTranslationUnit.isUsedByCurrentEditor()); + ASSERT_TRUE(variableTranslationUnit.isVisibleInEditor()); +} + +void ClangIpcServer::SetUp() +{ + clangServer.addClient(&mockIpcClient); + registerProjectPart(); + registerFiles(); +} + +void ClangIpcServer::registerFiles() +{ + RegisterTranslationUnitForEditorMessage message({FileContainer(functionTestFilePath, projectPartId, unsavedContent(unsavedTestFilePath), true), + FileContainer(variableTestFilePath, projectPartId)}); + + clangServer.registerTranslationUnitsForEditor(message); +} + +void ClangIpcServer::registerProjectPart() +{ + RegisterProjectPartsForEditorMessage message({ProjectPartContainer(projectPartId)}); + + clangServer.registerProjectPartsForEditor(message); +} + +void ClangIpcServer::changeProjectPartArguments() +{ + RegisterProjectPartsForEditorMessage message({ProjectPartContainer(projectPartId, {Utf8StringLiteral("-DArgumentDefinition")})}); + + clangServer.registerProjectPartsForEditor(message); +} + +void ClangIpcServer::changeProjectPartArgumentsToWrongValues() +{ + RegisterProjectPartsForEditorMessage message({ProjectPartContainer(projectPartId, {Utf8StringLiteral("-blah")})}); + + clangServer.registerProjectPartsForEditor(message); +} + +void ClangIpcServer::updateVisibilty(const Utf8String ¤tEditor, const Utf8String &additionalVisibleEditor) +{ + UpdateVisibleTranslationUnitsMessage message(currentEditor, + {currentEditor, additionalVisibleEditor}); + + clangServer.updateVisibleTranslationUnits(message); +} + +const Utf8String ClangIpcServer::unsavedContent(const QString &unsavedFilePath) +{ + QFile unsavedFileContentFile(unsavedFilePath); + bool isOpen = unsavedFileContentFile.open(QIODevice::ReadOnly | QIODevice::Text); + if (!isOpen) + ADD_FAILURE() << "File with the unsaved content cannot be opened!"; + + return Utf8String::fromByteArray(unsavedFileContentFile.readAll()); +} + +TEST_F(ClangIpcServer, TranslationUnitAfterUpdateNeedsReparseAndHasNewDiagnostics) +{ + const auto fileContainer = FileContainer(functionTestFilePath, projectPartId,unsavedContent(unsavedTestFilePath), true, 1); + + clangServer.updateTranslationUnitsForEditor({{fileContainer}}); + + ASSERT_THAT(clangServer, HasDirtyTranslationUnit(functionTestFilePath, projectPartId, 1U, true, true)); +} + } diff --git a/tests/unit/unittest/clientserverinprocesstest.cpp b/tests/unit/unittest/clientserverinprocesstest.cpp index 87632e2c069..0b5bb27d114 100644 --- a/tests/unit/unittest/clientserverinprocesstest.cpp +++ b/tests/unit/unittest/clientserverinprocesstest.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -232,6 +233,19 @@ TEST_F(ClientServerInProcess, SendUnregisterProjectPartsForEditorMessage) scheduleServerMessages(); } +TEST_F(ClientServerInProcess, UpdateVisibleTranslationUnitsMessage) +{ + ClangBackEnd::UpdateVisibleTranslationUnitsMessage message(Utf8StringLiteral(TESTDATA_DIR"/fileone.cpp"), + {Utf8StringLiteral(TESTDATA_DIR"/fileone.cpp"), + Utf8StringLiteral(TESTDATA_DIR"/filetwo.cpp")}); + + EXPECT_CALL(mockIpcServer, updateVisibleTranslationUnits(message)) + .Times(1); + + serverProxy.updateVisibleTranslationUnits(message); + scheduleServerMessages(); +} + TEST_F(ClientServerInProcess, SendTranslationUnitDoesNotExistMessage) { ClangBackEnd::TranslationUnitDoesNotExistMessage message(fileContainer); diff --git a/tests/unit/unittest/data/highlightinginformations.cpp b/tests/unit/unittest/data/highlightinginformations.cpp index d651fd65e1c..db5f8afde72 100644 --- a/tests/unit/unittest/data/highlightinginformations.cpp +++ b/tests/unit/unittest/data/highlightinginformations.cpp @@ -383,3 +383,19 @@ void f17() { TemplatedType TemplatedTypeDeclaration; } + +void f18() +{ + auto value = 1 + 2; +} + +class ScopeClass +{ +public: + static void ScopeOperator(); +}; + +void f19() +{ + ScopeClass::ScopeOperator(); +} diff --git a/tests/unit/unittest/highlightinginformationstest.cpp b/tests/unit/unittest/highlightinginformationstest.cpp index c09f12cc170..8e5ee4f0ee0 100644 --- a/tests/unit/unittest/highlightinginformationstest.cpp +++ b/tests/unit/unittest/highlightinginformationstest.cpp @@ -881,6 +881,20 @@ TEST_F(HighlightingInformations, TemplatedTypeDeclaration) ASSERT_THAT(infos[0], HasType(HighlightingType::Type)); } +TEST_F(HighlightingInformations, NoOperator) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(389, 24)); + + ASSERT_THAT(infos[2], HasType(HighlightingType::Invalid)); +} + +TEST_F(HighlightingInformations, ScopeOperator) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(400, 33)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::Invalid)); +} + Data *HighlightingInformations::d; void HighlightingInformations::SetUpTestCase() diff --git a/tests/unit/unittest/mockipcserver.h b/tests/unit/unittest/mockipcserver.h index 31591c28c0d..83f9870b4d6 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(updateVisibleTranslationUnits, + void(const ClangBackEnd::UpdateVisibleTranslationUnitsMessage &message)); }; #endif // MOCKIPCSERVER_H diff --git a/tests/unit/unittest/mocksenddiagnosticscallback.h b/tests/unit/unittest/mocksenddiagnosticscallback.h new file mode 100644 index 00000000000..ecb24fcbc99 --- /dev/null +++ b/tests/unit/unittest/mocksenddiagnosticscallback.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** 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 MOCKSENDDIAGNOSTICSCALLBACK_H +#define MOCKSENDDIAGNOSTICSCALLBACK_H + +#include +#include +#include +#include "gtest-qt-printing.h" + +class SendDiagnosticCallback +{ +public: + virtual ~SendDiagnosticCallback() = default; + + virtual void sendDiagnostic() = 0; +}; + +class MockSendDiagnosticCallback : public SendDiagnosticCallback +{ +public: + MOCK_METHOD0(sendDiagnostic, + void()); +}; + +#endif // MOCKSENDDIAGNOSTICSCALLBACK_H diff --git a/tests/unit/unittest/translationunitstest.cpp b/tests/unit/unittest/translationunitstest.cpp index ec2dfb9951d..0b19ecdf62d 100644 --- a/tests/unit/unittest/translationunitstest.cpp +++ b/tests/unit/unittest/translationunitstest.cpp @@ -43,9 +43,10 @@ #include #include - #include +#include "mocksenddiagnosticscallback.h" + #include #include #include @@ -54,6 +55,8 @@ using ClangBackEnd::TranslationUnit; using ClangBackEnd::UnsavedFiles; using ClangBackEnd::ProjectPart; +using ClangBackEnd::DiagnosticsChangedMessage; +using ClangBackEnd::DiagnosticSendState; using testing::IsNull; using testing::NotNull; @@ -81,23 +84,24 @@ class TranslationUnits : public ::testing::Test { protected: void SetUp() override; + void sendAllDiagnostics(); + void sendAllCurrentEditorDiagnostics(); + void sendAllVisibleEditorsDiagnostics(); +protected: ClangBackEnd::ProjectParts projects; ClangBackEnd::UnsavedFiles unsavedFiles; ClangBackEnd::TranslationUnits translationUnits{projects, unsavedFiles}; + MockSendDiagnosticCallback mockSendDiagnosticCallback; const Utf8String filePath = Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp"); const Utf8String headerPath = Utf8StringLiteral(TESTDATA_DIR"/translationunits.h"); const Utf8String nonExistingFilePath = Utf8StringLiteral("foo.cpp"); const Utf8String projectPartId = Utf8StringLiteral("projectPartId"); const Utf8String nonExistingProjectPartId = Utf8StringLiteral("nonExistingProjectPartId"); + const ClangBackEnd::FileContainer fileContainer{filePath, projectPartId}; + const ClangBackEnd::FileContainer headerContainer{headerPath, projectPartId}; }; -void TranslationUnits::SetUp() -{ - projects.createOrUpdate({ClangBackEnd::ProjectPartContainer(projectPartId)}); -} - - TEST_F(TranslationUnits, ThrowForGettingWithWrongFilePath) { ASSERT_THROW(translationUnits.translationUnit(nonExistingFilePath, projectPartId), @@ -279,4 +283,193 @@ TEST_F(TranslationUnits, HasNotTranslationUnit) ASSERT_FALSE(translationUnits.hasTranslationUnit(filePath)); } +TEST_F(TranslationUnits, isUsedByCurrentEditor) +{ + translationUnits.create({fileContainer}); + auto translationUnit = translationUnits.translationUnit(fileContainer); + + translationUnits.setCurrentEditor(filePath); + + ASSERT_TRUE(translationUnit.isUsedByCurrentEditor()); +} + +TEST_F(TranslationUnits, IsNotCurrentEditor) +{ + translationUnits.create({fileContainer}); + auto translationUnit = translationUnits.translationUnit(fileContainer); + + translationUnits.setCurrentEditor(headerPath); + + ASSERT_FALSE(translationUnit.isUsedByCurrentEditor()); +} + +TEST_F(TranslationUnits, IsNotCurrentEditorAfterBeingCurrent) +{ + translationUnits.create({fileContainer}); + auto translationUnit = translationUnits.translationUnit(fileContainer); + translationUnits.setCurrentEditor(filePath); + + translationUnits.setCurrentEditor(headerPath); + + ASSERT_FALSE(translationUnit.isUsedByCurrentEditor()); +} + +TEST_F(TranslationUnits, IsVisibleEditor) +{ + translationUnits.create({fileContainer}); + auto translationUnit = translationUnits.translationUnit(fileContainer); + + translationUnits.setVisibleEditors({filePath}); + + ASSERT_TRUE(translationUnit.isVisibleInEditor()); +} + +TEST_F(TranslationUnits, IsNotVisibleEditor) +{ + translationUnits.create({fileContainer}); + auto translationUnit = translationUnits.translationUnit(fileContainer); + + translationUnits.setVisibleEditors({headerPath}); + + ASSERT_FALSE(translationUnit.isVisibleInEditor()); +} + +TEST_F(TranslationUnits, IsNotVisibleEditorAfterBeingVisible) +{ + translationUnits.create({fileContainer}); + auto translationUnit = translationUnits.translationUnit(fileContainer); + translationUnits.setVisibleEditors({filePath}); + + translationUnits.setVisibleEditors({headerPath}); + + ASSERT_FALSE(translationUnit.isVisibleInEditor()); +} + +TEST_F(TranslationUnits, DoNotSendDiagnosticsIfThereIsNothingToSend) +{ + EXPECT_CALL(mockSendDiagnosticCallback, sendDiagnostic()).Times(0); + + sendAllDiagnostics(); +} + +TEST_F(TranslationUnits, SendDiagnosticsAfterTranslationUnitCreation) +{ + translationUnits.create({fileContainer, headerContainer}); + + EXPECT_CALL(mockSendDiagnosticCallback, sendDiagnostic()).Times(2); + + sendAllDiagnostics(); +} + +TEST_F(TranslationUnits, DoNotSendDiagnosticsAfterGettingDiagnostics) +{ + translationUnits.create({fileContainer, headerContainer}); + auto translationUnit = translationUnits.translationUnit(fileContainer); + translationUnit.diagnostics(); + + EXPECT_CALL(mockSendDiagnosticCallback, sendDiagnostic()).Times(1); + + sendAllDiagnostics(); +} + +TEST_F(TranslationUnits, SendDiagnosticsForCurrentEditor) +{ + translationUnits.create({fileContainer, headerContainer}); + auto translationUnit = translationUnits.translationUnit(fileContainer); + translationUnit.setIsUsedByCurrentEditor(true); + + EXPECT_CALL(mockSendDiagnosticCallback, sendDiagnostic()).Times(1); + + sendAllCurrentEditorDiagnostics(); +} + +TEST_F(TranslationUnits, DoNotSendDiagnosticsForCurrentEditorIfThereIsNoCurrentEditor) +{ + translationUnits.create({fileContainer, headerContainer}); + + EXPECT_CALL(mockSendDiagnosticCallback, sendDiagnostic()).Times(0); + + sendAllCurrentEditorDiagnostics(); +} + +TEST_F(TranslationUnits, DoNotSendDiagnosticsForCurrentEditorAfterGettingDiagnostics) +{ + translationUnits.create({fileContainer, headerContainer}); + auto translationUnit = translationUnits.translationUnit(fileContainer); + translationUnit.setIsUsedByCurrentEditor(true); + translationUnit.diagnostics(); + + EXPECT_CALL(mockSendDiagnosticCallback, sendDiagnostic()).Times(0); + + sendAllCurrentEditorDiagnostics(); +} + +TEST_F(TranslationUnits, DoNotSendDiagnosticsForVisibleEditorIfThereAreNoVisibleEditors) +{ + translationUnits.create({fileContainer, headerContainer}); + + EXPECT_CALL(mockSendDiagnosticCallback, sendDiagnostic()).Times(0); + + translationUnits.sendChangedDiagnosticsForVisibleEditors(); +} + +TEST_F(TranslationUnits, SendDiagnosticsForVisibleEditors) +{ + translationUnits.create({fileContainer, headerContainer}); + auto fileTranslationUnit = translationUnits.translationUnit(fileContainer); + fileTranslationUnit.setIsVisibleInEditor(true); + auto headerTranslationUnit = translationUnits.translationUnit(headerContainer); + headerTranslationUnit.setIsVisibleInEditor(true); + + EXPECT_CALL(mockSendDiagnosticCallback, sendDiagnostic()).Times(2); + + sendAllVisibleEditorsDiagnostics(); +} + +TEST_F(TranslationUnits, SendOnlyOneDiagnosticsForVisibleEditor) +{ + translationUnits.create({fileContainer, headerContainer}); + auto fileTranslationUnit = translationUnits.translationUnit(fileContainer); + fileTranslationUnit.setIsVisibleInEditor(true); + auto headerTranslationUnit = translationUnits.translationUnit(headerContainer); + headerTranslationUnit.setIsVisibleInEditor(true); + headerTranslationUnit.diagnostics(); + + EXPECT_CALL(mockSendDiagnosticCallback, sendDiagnostic()).Times(1); + + sendAllVisibleEditorsDiagnostics(); +} + +void TranslationUnits::SetUp() +{ + projects.createOrUpdate({ClangBackEnd::ProjectPartContainer(projectPartId)}); + + auto callback = [&] (const DiagnosticsChangedMessage &) { mockSendDiagnosticCallback.sendDiagnostic(); }; + translationUnits.setSendChangeDiagnosticsCallback(callback); +} + +void TranslationUnits::sendAllDiagnostics() +{ + auto diagnosticSendState = DiagnosticSendState::MaybeThereAreMoreDiagnostics; + + while (diagnosticSendState == DiagnosticSendState::MaybeThereAreMoreDiagnostics) + diagnosticSendState = translationUnits.sendChangedDiagnostics(); +} + +void TranslationUnits::sendAllCurrentEditorDiagnostics() +{ + auto diagnosticSendState = DiagnosticSendState::MaybeThereAreMoreDiagnostics; + + while (diagnosticSendState == DiagnosticSendState::MaybeThereAreMoreDiagnostics) + diagnosticSendState = translationUnits.sendChangedDiagnosticsForCurrentEditor(); +} + +void TranslationUnits::sendAllVisibleEditorsDiagnostics() +{ + auto diagnosticSendState = DiagnosticSendState::MaybeThereAreMoreDiagnostics; + + while (diagnosticSendState == DiagnosticSendState::MaybeThereAreMoreDiagnostics) + diagnosticSendState = translationUnits.sendChangedDiagnosticsForVisibleEditors(); +} + } diff --git a/tests/unit/unittest/translationunittest.cpp b/tests/unit/unittest/translationunittest.cpp index 452aa171aec..4bc2d110611 100644 --- a/tests/unit/unittest/translationunittest.cpp +++ b/tests/unit/unittest/translationunittest.cpp @@ -194,6 +194,38 @@ TEST_F(TranslationUnit, DependedFilePaths) Contains(Utf8StringLiteral(TESTDATA_DIR"/translationunits.h")))); } +TEST_F(TranslationUnit, NeedsNoReparseAfterCreation) +{ + translationUnit.cxTranslationUnit(); + + ASSERT_FALSE(translationUnit.isNeedingReparse()); +} + +TEST_F(TranslationUnit, HasNewDiagnosticsAfterCreation) +{ + translationUnit.cxTranslationUnit(); + + ASSERT_TRUE(translationUnit.hasNewDiagnostics()); +} + +TEST_F(TranslationUnit, NeedsReparseAfterChangeOfMainFile) +{ + translationUnit.cxTranslationUnit(); + + translationUnit.setDirtyIfDependencyIsMet(translationUnitFilePath); + + ASSERT_TRUE(translationUnit.isNeedingReparse()); +} + +TEST_F(TranslationUnit, HasNewDiagnosticsAfterChangeOfMainFile) +{ + translationUnit.cxTranslationUnit(); + + translationUnit.setDirtyIfDependencyIsMet(translationUnitFilePath); + + ASSERT_TRUE(translationUnit.hasNewDiagnostics()); +} + TEST_F(TranslationUnit, NoNeedForReparsingForIndependendFile) { translationUnit.cxTranslationUnit(); @@ -234,6 +266,7 @@ TEST_F(TranslationUnit, NeedsNoReparsingAfterReparsing) TEST_F(TranslationUnit, HasNoNewDiagnosticsForIndependendFile) { translationUnit.cxTranslationUnit(); + translationUnit.diagnostics(); // Reset hasNewDiagnostics translationUnit.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/otherfiles.h")); diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index 6fe2d25f2e2..b2d209d4dca 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -63,6 +63,7 @@ HEADERS += \ mockipclient.h \ mockipcserver.h \ spydummy.h \ - matcher-diagnosticcontainer.h + matcher-diagnosticcontainer.h \ + mocksenddiagnosticscallback.h OTHER_FILES += $$files(data/*)