aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--qbs/modules/qtc/qtc.qbs4
-rw-r--r--qtcreator.pri12
-rw-r--r--src/app/app-Info.plist4
-rw-r--r--src/app/app.pro1
-rw-r--r--src/app/app.qbs5
-rw-r--r--src/libs/clangsupport/clangcodemodelclientinterface.cpp3
-rw-r--r--src/libs/clangsupport/clangcodemodelclientinterface.h3
-rw-r--r--src/libs/clangsupport/clangcodemodelclientmessages.h1
-rw-r--r--src/libs/clangsupport/clangcodemodelclientproxy.cpp5
-rw-r--r--src/libs/clangsupport/clangcodemodelclientproxy.h1
-rw-r--r--src/libs/clangsupport/clangcodemodelserverinterface.cpp3
-rw-r--r--src/libs/clangsupport/clangcodemodelserverinterface.h1
-rw-r--r--src/libs/clangsupport/clangcodemodelservermessages.h1
-rw-r--r--src/libs/clangsupport/clangcodemodelserverproxy.cpp5
-rw-r--r--src/libs/clangsupport/clangcodemodelserverproxy.h1
-rw-r--r--src/libs/clangsupport/clangpathwatcher.h2
-rw-r--r--src/libs/clangsupport/clangsupport-lib.pri6
-rw-r--r--src/libs/clangsupport/clangsupport_global.h3
-rw-r--r--src/libs/clangsupport/filecontainer.cpp3
-rw-r--r--src/libs/clangsupport/filecontainer.h12
-rw-r--r--src/libs/clangsupport/filepathcache.h2
-rw-r--r--src/libs/clangsupport/messageenvelop.cpp6
-rw-r--r--src/libs/clangsupport/requesttooltipmessage.cpp48
-rw-r--r--src/libs/clangsupport/requesttooltipmessage.h94
-rw-r--r--src/libs/clangsupport/tooltipinfo.cpp65
-rw-r--r--src/libs/clangsupport/tooltipinfo.h124
-rw-r--r--src/libs/clangsupport/tooltipmessage.cpp44
-rw-r--r--src/libs/clangsupport/tooltipmessage.h87
-rw-r--r--src/libs/modelinglib/qmt/stereotype/stereotypecontroller.cpp50
-rw-r--r--src/libs/modelinglib/qmt/style/style.h3
-rw-r--r--src/libs/sqlite/utf8string.h3
-rw-r--r--src/plugins/autotest/qtest/qttestparser.cpp11
-rw-r--r--src/plugins/clangcodemodel/clangbackendcommunicator.cpp9
-rw-r--r--src/plugins/clangcodemodel/clangbackendcommunicator.h3
-rw-r--r--src/plugins/clangcodemodel/clangbackendreceiver.cpp78
-rw-r--r--src/plugins/clangcodemodel/clangbackendreceiver.h5
-rw-r--r--src/plugins/clangcodemodel/clangbackendsender.cpp7
-rw-r--r--src/plugins/clangcodemodel/clangbackendsender.h1
-rw-r--r--src/plugins/clangcodemodel/clangcodemodel.pro2
-rw-r--r--src/plugins/clangcodemodel/clangcodemodel.qbs2
-rw-r--r--src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp19
-rw-r--r--src/plugins/clangcodemodel/clangeditordocumentprocessor.h5
-rw-r--r--src/plugins/clangcodemodel/clanghoverhandler.cpp232
-rw-r--r--src/plugins/clangcodemodel/clanghoverhandler.h60
-rw-r--r--src/plugins/clangcodemodel/clangmodelmanagersupport.cpp8
-rw-r--r--src/plugins/clangcodemodel/clangmodelmanagersupport.h3
-rw-r--r--src/plugins/coreplugin/coreplugin.cpp9
-rw-r--r--src/plugins/coreplugin/coreplugin.pro6
-rw-r--r--src/plugins/coreplugin/coreplugin.qbs213
-rw-r--r--src/plugins/coreplugin/locator/javascriptfilter.cpp123
-rw-r--r--src/plugins/coreplugin/locator/javascriptfilter.h58
-rw-r--r--src/plugins/coreplugin/locator/locator.cpp6
-rw-r--r--src/plugins/coreplugin/locator/locator.h2
-rw-r--r--src/plugins/coreplugin/locator/locator.pri8
-rw-r--r--src/plugins/coreplugin/menubarfilter.cpp162
-rw-r--r--src/plugins/coreplugin/menubarfilter.h58
-rw-r--r--src/plugins/cppeditor/cppeditor.pro4
-rw-r--r--src/plugins/cppeditor/cppeditor.qbs4
-rw-r--r--src/plugins/cppeditor/cppeditordocument.cpp2
-rw-r--r--src/plugins/cppeditor/cppeditorplugin.cpp9
-rw-r--r--src/plugins/cppeditor/cpphoverhandler.cpp190
-rw-r--r--src/plugins/cppeditor/cppincludehierarchy.cpp2
-rw-r--r--src/plugins/cppeditor/cpptypehierarchy.cpp3
-rw-r--r--src/plugins/cppeditor/cpptypehierarchy.h7
-rw-r--r--src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp2
-rw-r--r--src/plugins/cpptools/baseeditordocumentprocessor.cpp7
-rw-r--r--src/plugins/cpptools/baseeditordocumentprocessor.h14
-rw-r--r--src/plugins/cpptools/cppelementevaluator.cpp (renamed from src/plugins/cppeditor/cppelementevaluator.cpp)6
-rw-r--r--src/plugins/cpptools/cppelementevaluator.h (renamed from src/plugins/cppeditor/cppelementevaluator.h)16
-rw-r--r--src/plugins/cpptools/cpphoverhandler.cpp121
-rw-r--r--src/plugins/cpptools/cpphoverhandler.h (renamed from src/plugins/cppeditor/cpphoverhandler.h)17
-rw-r--r--src/plugins/cpptools/cppmodelmanager.cpp11
-rw-r--r--src/plugins/cpptools/cppmodelmanager.h10
-rw-r--r--src/plugins/cpptools/cppmodelmanagersupport.h8
-rw-r--r--src/plugins/cpptools/cppmodelmanagersupportinternal.cpp8
-rw-r--r--src/plugins/cpptools/cppmodelmanagersupportinternal.h3
-rw-r--r--src/plugins/cpptools/cpptools.pro4
-rw-r--r--src/plugins/cpptools/cpptools.qbs4
-rw-r--r--src/plugins/debugger/debuggerplugin.cpp3
-rw-r--r--src/plugins/modeleditor/componentviewcontroller.cpp56
-rw-r--r--src/plugins/modeleditor/componentviewcontroller.h5
-rw-r--r--src/plugins/qtsupport/baseqtversion.cpp161
-rw-r--r--src/tools/clangbackend/source/clangbackend_global.h5
-rw-r--r--src/tools/clangbackend/source/clangbackendclangipc-source.pri4
-rw-r--r--src/tools/clangbackend/source/clangcodemodelserver.cpp20
-rw-r--r--src/tools/clangbackend/source/clangcodemodelserver.h1
-rw-r--r--src/tools/clangbackend/source/clangjobrequest.cpp15
-rw-r--r--src/tools/clangbackend/source/clangjobrequest.h2
-rw-r--r--src/tools/clangbackend/source/clangrequesttooltipjob.cpp67
-rw-r--r--src/tools/clangbackend/source/clangrequesttooltipjob.h43
-rw-r--r--src/tools/clangbackend/source/clangtooltipinfocollector.cpp531
-rw-r--r--src/tools/clangbackend/source/clangtooltipinfocollector.h45
-rw-r--r--src/tools/clangbackend/source/clangtranslationunit.cpp15
-rw-r--r--src/tools/clangbackend/source/clangtranslationunit.h5
-rw-r--r--src/tools/clangbackend/source/clangtype.cpp97
-rw-r--r--src/tools/clangbackend/source/clangtype.h4
-rw-r--r--src/tools/clangbackend/source/cursor.cpp38
-rw-r--r--src/tools/clangbackend/source/cursor.h11
-rw-r--r--src/tools/clangbackend/source/unsavedfile.cpp21
-rw-r--r--src/tools/clangbackend/source/unsavedfile.h1
-rw-r--r--tests/unit/echoserver/echoclangcodemodelserver.cpp5
-rw-r--r--tests/unit/echoserver/echoclangcodemodelserver.h1
-rw-r--r--tests/unit/unittest/clangtooltipinfo-test.cpp628
-rw-r--r--tests/unit/unittest/conditionally-disabled-tests.h6
-rw-r--r--tests/unit/unittest/data/tooltipinfo.cpp180
-rw-r--r--tests/unit/unittest/data/tooltipinfo.h3
-rw-r--r--tests/unit/unittest/dummyclangipcclient.h1
-rw-r--r--tests/unit/unittest/gtest-creator-printing.cpp46
-rw-r--r--tests/unit/unittest/gtest-creator-printing.h6
-rw-r--r--tests/unit/unittest/mockclangcodemodelclient.h2
-rw-r--r--tests/unit/unittest/mockclangcodemodelserver.h2
-rw-r--r--tests/unit/unittest/unittest.pro1
-rw-r--r--tests/unit/unittest/unsavedfile-test.cpp28
113 files changed, 3769 insertions, 434 deletions
diff --git a/qbs/modules/qtc/qtc.qbs b/qbs/modules/qtc/qtc.qbs
index 4b4796e63a7..0177c205643 100644
--- a/qbs/modules/qtc/qtc.qbs
+++ b/qbs/modules/qtc/qtc.qbs
@@ -18,14 +18,16 @@ Module {
+ ide_compat_version_minor + '.' + ide_compat_version_release
property string qtcreator_copyright_year: '2017'
+ property string qtcreator_copyright_string: "(C) " + qtcreator_copyright_year + " The Qt Company Ltd"
property string ide_display_name: 'Qt Creator'
property string ide_id: 'qtcreator'
property string ide_cased_id: 'QtCreator'
+ property string ide_bundle_identifier: 'org.qt-project.qtcreator'
property string libDirName: "lib"
property string ide_app_path: qbs.targetOS.contains("macos") ? "" : "bin"
- property string ide_app_target: qbs.targetOS.contains("macos") ? "Qt Creator" : "qtcreator"
+ property string ide_app_target: qbs.targetOS.contains("macos") ? ide_display_name : ide_id
property string ide_library_path: {
if (qbs.targetOS.contains("macos"))
return ide_app_target + ".app/Contents/Frameworks"
diff --git a/qtcreator.pri b/qtcreator.pri
index 09557fe15fd..8ef4e06e2b0 100644
--- a/qtcreator.pri
+++ b/qtcreator.pri
@@ -8,9 +8,11 @@ QTCREATOR_DISPLAY_VERSION = 4.6.0-beta1
QTCREATOR_COPYRIGHT_YEAR = 2017
BINARY_ARTIFACTS_BRANCH = master
-isEmpty(IDE_DISPLAY_NAME): IDE_DISPLAY_NAME = Qt Creator
-isEmpty(IDE_ID): IDE_ID = qtcreator
-isEmpty(IDE_CASED_ID): IDE_CASED_ID = QtCreator
+isEmpty(IDE_DISPLAY_NAME): IDE_DISPLAY_NAME = Qt Creator
+isEmpty(IDE_ID): IDE_ID = qtcreator
+isEmpty(IDE_CASED_ID): IDE_CASED_ID = QtCreator
+
+isEmpty(PRODUCT_BUNDLE_IDENTIFIER): PRODUCT_BUNDLE_IDENTIFIER = org.qt-project.$$IDE_ID
CONFIG += c++14
@@ -100,7 +102,7 @@ isEmpty(IDE_BUILD_TREE) {
IDE_APP_PATH = $$IDE_BUILD_TREE/bin
osx {
- IDE_APP_TARGET = "Qt Creator"
+ IDE_APP_TARGET = "$$IDE_DISPLAY_NAME"
# check if IDE_BUILD_TREE is actually an existing Qt Creator.app,
# for building against a binary package
@@ -130,7 +132,7 @@ osx {
INSTALL_APP_PATH = $$QTC_PREFIX/
} else {
contains(TEMPLATE, vc.*):vcproj = 1
- IDE_APP_TARGET = qtcreator
+ IDE_APP_TARGET = $$IDE_ID
# target output path if not set manually
isEmpty(IDE_OUTPUT_PATH): IDE_OUTPUT_PATH = $$IDE_BUILD_TREE
diff --git a/src/app/app-Info.plist b/src/app/app-Info.plist
index 8940f2bd9ab..91104f163d5 100644
--- a/src/app/app-Info.plist
+++ b/src/app/app-Info.plist
@@ -245,9 +245,9 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleExecutable</key>
- <string>Qt Creator</string>
+ <string>@EXECUTABLE@</string>
<key>CFBundleIdentifier</key>
- <string>org.qt-project.qtcreator</string>
+ <string>@PRODUCT_BUNDLE_IDENTIFIER@</string>
<key>CFBundleVersion</key>
<string>@FULL_VERSION@</string>
<key>CFBundleShortVersionString</key>
diff --git a/src/app/app.pro b/src/app/app.pro
index f8abf4d7659..a64c357020d 100644
--- a/src/app/app.pro
+++ b/src/app/app.pro
@@ -62,6 +62,7 @@ win32 {
infoplist = $$cat($$PWD/app-Info.plist, blob)
infoplist = $$replace(infoplist, @MACOSX_DEPLOYMENT_TARGET@, $$QMAKE_MACOSX_DEPLOYMENT_TARGET)
infoplist = $$replace(infoplist, @QTCREATOR_COPYRIGHT_YEAR@, $$QTCREATOR_COPYRIGHT_YEAR)
+ infoplist = $$replace(infoplist, @PRODUCT_BUNDLE_IDENTIFIER@, $$PRODUCT_BUNDLE_IDENTIFIER)
write_file($$OUT_PWD/Info.plist, infoplist)
QMAKE_INFO_PLIST = $$OUT_PWD/Info.plist
diff --git a/src/app/app.qbs b/src/app/app.qbs
index e3d9f027f0c..3ed4eb8fdef 100644
--- a/src/app/app.qbs
+++ b/src/app/app.qbs
@@ -25,6 +25,11 @@ QtcProduct {
installTags: (isBundle ? ["bundle.content"] : base).concat(["debuginfo_app"])
property bool qtcRunnable: true
+ bundle.identifier: qtc.ide_bundle_identifier
+ bundle.infoPlist: ({
+ "NSHumanReadableCopyright": qtc.qtcreator_copyright_string
+ })
+
cpp.rpaths: qbs.targetOS.contains("macos") ? ["@executable_path/../Frameworks"]
: ["$ORIGIN/../" + qtc.libDirName + "/qtcreator"]
cpp.includePaths: [
diff --git a/src/libs/clangsupport/clangcodemodelclientinterface.cpp b/src/libs/clangsupport/clangcodemodelclientinterface.cpp
index 0de9f39044a..492ea7896fe 100644
--- a/src/libs/clangsupport/clangcodemodelclientinterface.cpp
+++ b/src/libs/clangsupport/clangcodemodelclientinterface.cpp
@@ -53,6 +53,9 @@ void ClangCodeModelClientInterface::dispatch(const MessageEnvelop &messageEnvelo
case MessageType::FollowSymbolMessage:
followSymbol(messageEnvelop.message<FollowSymbolMessage>());
break;
+ case MessageType::ToolTipMessage:
+ tooltip(messageEnvelop.message<ToolTipMessage>());
+ break;
default:
qWarning() << "Unknown ClangCodeModelClientMessage";
}
diff --git a/src/libs/clangsupport/clangcodemodelclientinterface.h b/src/libs/clangsupport/clangcodemodelclientinterface.h
index b6b878baaf0..6e8f3dd2485 100644
--- a/src/libs/clangsupport/clangcodemodelclientinterface.h
+++ b/src/libs/clangsupport/clangcodemodelclientinterface.h
@@ -43,6 +43,8 @@ class RegisterUnsavedFilesForEditorMessage;
class RequestDocumentAnnotationsMessage;
class RequestReferencesMessage;
class RequestFollowSymbolMessage;
+class RequestToolTipMessage;
+class ToolTipMessage;
class UnregisterProjectPartsForEditorMessage;
class UnregisterTranslationUnitsForEditorMessage;
class UnregisterUnsavedFilesForEditorMessage;
@@ -60,6 +62,7 @@ public:
virtual void documentAnnotationsChanged(const DocumentAnnotationsChangedMessage &message) = 0;
virtual void references(const ReferencesMessage &message) = 0;
virtual void followSymbol(const FollowSymbolMessage &message) = 0;
+ virtual void tooltip(const ToolTipMessage &message) = 0;
};
} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/clangcodemodelclientmessages.h b/src/libs/clangsupport/clangcodemodelclientmessages.h
index 5b5c9b42edb..2903cda2079 100644
--- a/src/libs/clangsupport/clangcodemodelclientmessages.h
+++ b/src/libs/clangsupport/clangcodemodelclientmessages.h
@@ -31,3 +31,4 @@
#include "documentannotationschangedmessage.h"
#include "referencesmessage.h"
#include "followsymbolmessage.h"
+#include "tooltipmessage.h"
diff --git a/src/libs/clangsupport/clangcodemodelclientproxy.cpp b/src/libs/clangsupport/clangcodemodelclientproxy.cpp
index 6a285c23668..fc75a226ed5 100644
--- a/src/libs/clangsupport/clangcodemodelclientproxy.cpp
+++ b/src/libs/clangsupport/clangcodemodelclientproxy.cpp
@@ -95,6 +95,11 @@ void ClangCodeModelClientProxy::followSymbol(const FollowSymbolMessage &message)
m_writeMessageBlock.write(message);
}
+void ClangCodeModelClientProxy::tooltip(const ToolTipMessage &message)
+{
+ m_writeMessageBlock.write(message);
+}
+
void ClangCodeModelClientProxy::readMessages()
{
for (const MessageEnvelop &message : m_readMessageBlock.readAll())
diff --git a/src/libs/clangsupport/clangcodemodelclientproxy.h b/src/libs/clangsupport/clangcodemodelclientproxy.h
index 0665d6e8faa..58b87a05d8b 100644
--- a/src/libs/clangsupport/clangcodemodelclientproxy.h
+++ b/src/libs/clangsupport/clangcodemodelclientproxy.h
@@ -57,6 +57,7 @@ public:
void documentAnnotationsChanged(const DocumentAnnotationsChangedMessage &message) override;
void references(const ReferencesMessage &message) override;
void followSymbol(const FollowSymbolMessage &message) override;
+ void tooltip(const ToolTipMessage &message) override;
void readMessages();
diff --git a/src/libs/clangsupport/clangcodemodelserverinterface.cpp b/src/libs/clangsupport/clangcodemodelserverinterface.cpp
index bdaa802a47e..d50e97367d5 100644
--- a/src/libs/clangsupport/clangcodemodelserverinterface.cpp
+++ b/src/libs/clangsupport/clangcodemodelserverinterface.cpp
@@ -71,6 +71,9 @@ void ClangCodeModelServerInterface::dispatch(const MessageEnvelop &messageEnvelo
case MessageType::RequestFollowSymbolMessage:
requestFollowSymbol(messageEnvelop.message<RequestFollowSymbolMessage>());
break;
+ case MessageType::RequestToolTipMessage:
+ requestToolTip(messageEnvelop.message<RequestToolTipMessage>());
+ break;
case MessageType::UpdateVisibleTranslationUnitsMessage:
updateVisibleTranslationUnits(messageEnvelop.message<UpdateVisibleTranslationUnitsMessage>());
break;
diff --git a/src/libs/clangsupport/clangcodemodelserverinterface.h b/src/libs/clangsupport/clangcodemodelserverinterface.h
index e4e897afc4d..eb24fa4dfed 100644
--- a/src/libs/clangsupport/clangcodemodelserverinterface.h
+++ b/src/libs/clangsupport/clangcodemodelserverinterface.h
@@ -50,6 +50,7 @@ public:
virtual void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) = 0;
virtual void requestReferences(const RequestReferencesMessage &message) = 0;
virtual void requestFollowSymbol(const RequestFollowSymbolMessage &message) = 0;
+ virtual void requestToolTip(const RequestToolTipMessage &message) = 0;
virtual void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) = 0;
};
diff --git a/src/libs/clangsupport/clangcodemodelservermessages.h b/src/libs/clangsupport/clangcodemodelservermessages.h
index b1ba7a07016..0e577b08ddd 100644
--- a/src/libs/clangsupport/clangcodemodelservermessages.h
+++ b/src/libs/clangsupport/clangcodemodelservermessages.h
@@ -36,6 +36,7 @@
#include "requestdocumentannotations.h"
#include "requestreferencesmessage.h"
#include "requestfollowsymbolmessage.h"
+#include "requesttooltipmessage.h"
#include "unregisterunsavedfilesforeditormessage.h"
#include "updatetranslationunitsforeditormessage.h"
#include "updatevisibletranslationunitsmessage.h"
diff --git a/src/libs/clangsupport/clangcodemodelserverproxy.cpp b/src/libs/clangsupport/clangcodemodelserverproxy.cpp
index f51bcb2802b..23a80284802 100644
--- a/src/libs/clangsupport/clangcodemodelserverproxy.cpp
+++ b/src/libs/clangsupport/clangcodemodelserverproxy.cpp
@@ -96,6 +96,11 @@ void ClangCodeModelServerProxy::requestFollowSymbol(const RequestFollowSymbolMes
m_writeMessageBlock.write(message);
}
+void ClangCodeModelServerProxy::requestToolTip(const RequestToolTipMessage &message)
+{
+ m_writeMessageBlock.write(message);
+}
+
void ClangCodeModelServerProxy::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message)
{
m_writeMessageBlock.write(message);
diff --git a/src/libs/clangsupport/clangcodemodelserverproxy.h b/src/libs/clangsupport/clangcodemodelserverproxy.h
index e93e05d3f54..62ea90eebe2 100644
--- a/src/libs/clangsupport/clangcodemodelserverproxy.h
+++ b/src/libs/clangsupport/clangcodemodelserverproxy.h
@@ -60,6 +60,7 @@ public:
void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) override;
void requestReferences(const RequestReferencesMessage &message) override;
void requestFollowSymbol(const RequestFollowSymbolMessage &message) override;
+ void requestToolTip(const RequestToolTipMessage &message) override;
void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override;
};
diff --git a/src/libs/clangsupport/clangpathwatcher.h b/src/libs/clangsupport/clangpathwatcher.h
index 127dc18e9c0..610e42cccf2 100644
--- a/src/libs/clangsupport/clangpathwatcher.h
+++ b/src/libs/clangsupport/clangpathwatcher.h
@@ -77,7 +77,7 @@ using IdCache = StringCache<Utils::SmallString,
template <typename FileSystemWatcher,
typename Timer>
-class ClangPathWatcher : public ClangPathWatcherInterface
+class CLANGSUPPORT_EXPORT ClangPathWatcher : public ClangPathWatcherInterface
{
public:
ClangPathWatcher(FilePathCachingInterface &pathCache,
diff --git a/src/libs/clangsupport/clangsupport-lib.pri b/src/libs/clangsupport/clangsupport-lib.pri
index a32f78c1868..952fd72a10d 100644
--- a/src/libs/clangsupport/clangsupport-lib.pri
+++ b/src/libs/clangsupport/clangsupport-lib.pri
@@ -68,6 +68,7 @@ SOURCES += \
$$PWD/requestsourcelocationforrenamingmessage.cpp \
$$PWD/requestsourcerangesanddiagnosticsforquerymessage.cpp \
$$PWD/requestsourcerangesforquerymessage.cpp \
+ $$PWD/requesttooltipmessage.cpp \
$$PWD/sourcelocationcontainer.cpp \
$$PWD/sourcelocationcontainerv2.cpp \
$$PWD/sourcelocationscontainer.cpp \
@@ -82,6 +83,8 @@ SOURCES += \
$$PWD/sourcerangesforquerymessage.cpp \
$$PWD/sourcerangewithtextcontainer.cpp \
$$PWD/tokeninfocontainer.cpp \
+ $$PWD/tooltipmessage.cpp \
+ $$PWD/tooltipinfo.cpp \
$$PWD/unregisterunsavedfilesforeditormessage.cpp \
$$PWD/updatepchprojectpartsmessage.cpp \
$$PWD/updatetranslationunitsforeditormessage.cpp \
@@ -159,6 +162,7 @@ HEADERS += \
$$PWD/requestsourcelocationforrenamingmessage.h \
$$PWD/requestsourcerangesanddiagnosticsforquerymessage.h \
$$PWD/requestsourcerangesforquerymessage.h \
+ $$PWD/requesttooltipmessage.h \
$$PWD/sourcelocationcontainer.h \
$$PWD/sourcelocationcontainerv2.h \
$$PWD/sourcelocationscontainer.h \
@@ -176,6 +180,8 @@ HEADERS += \
$$PWD/sourcerangewithtextcontainer.h \
$$PWD/stringcache.h \
$$PWD/tokeninfocontainer.h \
+ $$PWD/tooltipmessage.h \
+ $$PWD/tooltipinfo.h \
$$PWD/unregisterunsavedfilesforeditormessage.h \
$$PWD/updatepchprojectpartsmessage.h \
$$PWD/updatetranslationunitsforeditormessage.h \
diff --git a/src/libs/clangsupport/clangsupport_global.h b/src/libs/clangsupport/clangsupport_global.h
index f8dc8c30117..34f65cdcad0 100644
--- a/src/libs/clangsupport/clangsupport_global.h
+++ b/src/libs/clangsupport/clangsupport_global.h
@@ -116,6 +116,9 @@ enum class MessageType : quint8 {
RequestFollowSymbolMessage,
FollowSymbolMessage,
+ RequestToolTipMessage,
+ ToolTipMessage,
+
UpdateVisibleTranslationUnitsMessage,
CompleteCodeMessage,
diff --git a/src/libs/clangsupport/filecontainer.cpp b/src/libs/clangsupport/filecontainer.cpp
index e2efc70b896..05f888aebf8 100644
--- a/src/libs/clangsupport/filecontainer.cpp
+++ b/src/libs/clangsupport/filecontainer.cpp
@@ -37,7 +37,8 @@ QDebug operator<<(QDebug debug, const FileContainer &container)
<< container.filePath() << ", "
<< container.projectPartId() << ", "
<< container.fileArguments() << ", "
- << container.documentRevision();
+ << container.documentRevision() << ", "
+ << container.textCodecName();
if (container.hasUnsavedFileContent()) {
const Utf8String fileWithContent = debugWriteFileForInspection(
diff --git a/src/libs/clangsupport/filecontainer.h b/src/libs/clangsupport/filecontainer.h
index c7cb3f10053..b19c0daa46a 100644
--- a/src/libs/clangsupport/filecontainer.h
+++ b/src/libs/clangsupport/filecontainer.h
@@ -42,10 +42,12 @@ public:
const Utf8String &projectPartId,
const Utf8String &unsavedFileContent = Utf8String(),
bool hasUnsavedFileContent = false,
- quint32 documentRevision = 0)
+ quint32 documentRevision = 0,
+ const Utf8String &textCodecName = Utf8String())
: m_filePath(filePath),
m_projectPartId(projectPartId),
m_unsavedFileContent(unsavedFileContent),
+ m_textCodecName(textCodecName),
m_documentRevision(documentRevision),
m_hasUnsavedFileContent(hasUnsavedFileContent)
{
@@ -98,6 +100,11 @@ public:
return m_unsavedFileContent;
}
+ const Utf8String &textCodecName() const
+ {
+ return m_textCodecName;
+ }
+
bool hasUnsavedFileContent() const
{
return m_hasUnsavedFileContent;
@@ -114,6 +121,7 @@ public:
out << container.m_projectPartId;
out << container.m_fileArguments;
out << container.m_unsavedFileContent;
+ out << container.m_textCodecName;
out << container.m_documentRevision;
out << container.m_hasUnsavedFileContent;
@@ -126,6 +134,7 @@ public:
in >> container.m_projectPartId;
in >> container.m_fileArguments;
in >> container.m_unsavedFileContent;
+ in >> container.m_textCodecName;
in >> container.m_documentRevision;
in >> container.m_hasUnsavedFileContent;
@@ -142,6 +151,7 @@ private:
Utf8String m_projectPartId;
Utf8StringVector m_fileArguments;
Utf8String m_unsavedFileContent;
+ Utf8String m_textCodecName;
quint32 m_documentRevision = 0;
bool m_hasUnsavedFileContent = false;
};
diff --git a/src/libs/clangsupport/filepathcache.h b/src/libs/clangsupport/filepathcache.h
index 0e8fa7e4dfe..81bc3f40cc8 100644
--- a/src/libs/clangsupport/filepathcache.h
+++ b/src/libs/clangsupport/filepathcache.h
@@ -36,7 +36,7 @@
namespace ClangBackEnd {
template <typename FilePathStorage>
-class FilePathCache
+class CLANGSUPPORT_EXPORT FilePathCache
{
using DirectoryPathCache = StringCache<Utils::PathString,
int,
diff --git a/src/libs/clangsupport/messageenvelop.cpp b/src/libs/clangsupport/messageenvelop.cpp
index 58139c4c8fd..134616a5b93 100644
--- a/src/libs/clangsupport/messageenvelop.cpp
+++ b/src/libs/clangsupport/messageenvelop.cpp
@@ -68,6 +68,9 @@ QDebug operator<<(QDebug debug, const MessageEnvelop &messageEnvelop)
case MessageType::RequestReferencesMessage:
qDebug() << messageEnvelop.message<RequestReferencesMessage>();
break;
+ case MessageType::RequestToolTipMessage:
+ qDebug() << messageEnvelop.message<RequestToolTipMessage>();
+ break;
case MessageType::UpdateVisibleTranslationUnitsMessage:
qDebug() << messageEnvelop.message<UpdateVisibleTranslationUnitsMessage>();
break;
@@ -83,6 +86,9 @@ QDebug operator<<(QDebug debug, const MessageEnvelop &messageEnvelop)
case MessageType::ReferencesMessage:
qDebug() << messageEnvelop.message<ReferencesMessage>();
break;
+ case MessageType::ToolTipMessage:
+ qDebug() << messageEnvelop.message<ToolTipMessage>();
+ break;
case MessageType::DocumentAnnotationsChangedMessage:
qDebug() << messageEnvelop.message<DocumentAnnotationsChangedMessage>();
break;
diff --git a/src/libs/clangsupport/requesttooltipmessage.cpp b/src/libs/clangsupport/requesttooltipmessage.cpp
new file mode 100644
index 00000000000..77ffdb46d80
--- /dev/null
+++ b/src/libs/clangsupport/requesttooltipmessage.cpp
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "requesttooltipmessage.h"
+
+#include <QDebug>
+
+namespace ClangBackEnd {
+
+quint64 RequestToolTipMessage::ticketCounter = 0;
+
+QDebug operator<<(QDebug debug, const RequestToolTipMessage &message)
+{
+ debug.nospace() << "RequestToolTipMessage(";
+
+ debug.nospace() << message.m_fileContainer << ", ";
+ debug.nospace() << message.m_ticketNumber << ", ";
+ debug.nospace() << message.m_line << ", ";
+ debug.nospace() << message.m_column << ", ";
+
+ debug.nospace() << ")";
+
+ return debug;
+}
+
+} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/requesttooltipmessage.h b/src/libs/clangsupport/requesttooltipmessage.h
new file mode 100644
index 00000000000..066d7358786
--- /dev/null
+++ b/src/libs/clangsupport/requesttooltipmessage.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "clangsupport_global.h"
+
+#include "filecontainer.h"
+
+#include <QDataStream>
+
+namespace ClangBackEnd {
+
+// TODO: De-duplicate with RequestReferencesMessage?
+class RequestToolTipMessage
+{
+public:
+ RequestToolTipMessage() = default;
+ RequestToolTipMessage(const FileContainer &fileContainer, quint32 line, quint32 column)
+ : m_fileContainer(fileContainer)
+ , m_ticketNumber(++ticketCounter)
+ , m_line(line)
+ , m_column(column)
+ {
+ }
+
+ const FileContainer fileContainer() const { return m_fileContainer; }
+ quint32 line() const { return m_line; }
+ quint32 column() const { return m_column; }
+ quint64 ticketNumber() const { return m_ticketNumber; }
+
+ friend QDataStream &operator<<(QDataStream &out, const RequestToolTipMessage &message)
+ {
+ out << message.m_fileContainer;
+ out << message.m_ticketNumber;
+ out << message.m_line;
+ out << message.m_column;
+
+ return out;
+ }
+
+ friend QDataStream &operator>>(QDataStream &in, RequestToolTipMessage &message)
+ {
+ in >> message.m_fileContainer;
+ in >> message.m_ticketNumber;
+ in >> message.m_line;
+ in >> message.m_column;
+
+ return in;
+ }
+
+ friend bool operator==(const RequestToolTipMessage &first,
+ const RequestToolTipMessage &second)
+ {
+ return first.m_ticketNumber == second.m_ticketNumber
+ && first.m_line == second.m_line
+ && first.m_column == second.m_column
+ && first.m_fileContainer == second.m_fileContainer;
+ }
+
+ friend CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const RequestToolTipMessage &message);
+
+private:
+ FileContainer m_fileContainer;
+ quint64 m_ticketNumber = 0;
+ quint32 m_line = 0;
+ quint32 m_column = 0;
+ static CLANGSUPPORT_EXPORT quint64 ticketCounter;
+};
+
+DECLARE_MESSAGE(RequestToolTipMessage);
+} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/tooltipinfo.cpp b/src/libs/clangsupport/tooltipinfo.cpp
new file mode 100644
index 00000000000..fc9a3394214
--- /dev/null
+++ b/src/libs/clangsupport/tooltipinfo.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "tooltipinfo.h"
+
+#include <QDebug>
+
+namespace ClangBackEnd {
+
+#define RETURN_TEXT_FOR_CASE(enumValue) case ToolTipInfo::enumValue: return #enumValue
+const char *qdocCategoryToString(ToolTipInfo::QdocCategory category)
+{
+ switch (category) {
+ RETURN_TEXT_FOR_CASE(Unknown);
+ RETURN_TEXT_FOR_CASE(ClassOrNamespace);
+ RETURN_TEXT_FOR_CASE(Enum);
+ RETURN_TEXT_FOR_CASE(Typedef);
+ RETURN_TEXT_FOR_CASE(Macro);
+ RETURN_TEXT_FOR_CASE(Brief);
+ RETURN_TEXT_FOR_CASE(Function);
+ }
+
+ return "UnhandledQdocCategory";
+}
+#undef RETURN_TEXT_FOR_CASE
+
+QDebug operator<<(QDebug debug, const ToolTipInfo &message)
+{
+ debug.nospace() << "ToolTipInfo(";
+
+ debug.nospace() << message.m_text << ", ";
+ debug.nospace() << message.m_briefComment << ", ";
+ debug.nospace() << message.m_qdocIdCandidates << ", ";
+ debug.nospace() << message.m_qdocMark << ", ";
+ debug.nospace() << qdocCategoryToString(message.m_qdocCategory) << ", ";
+ debug.nospace() << message.m_sizeInBytes << ", ";
+
+ debug.nospace() << ")";
+
+ return debug;
+}
+
+} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/tooltipinfo.h b/src/libs/clangsupport/tooltipinfo.h
new file mode 100644
index 00000000000..b210d0dfe66
--- /dev/null
+++ b/src/libs/clangsupport/tooltipinfo.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <utf8string.h>
+#include <utf8stringvector.h>
+
+namespace ClangBackEnd {
+
+class ToolTipInfo
+{
+public:
+ enum QdocCategory : quint8 {
+ Unknown,
+ ClassOrNamespace,
+ Enum,
+ Typedef,
+ Macro,
+ Brief,
+ Function,
+ };
+
+public:
+ ToolTipInfo() = default;
+ ToolTipInfo(const Utf8String &text) : m_text(text) {}
+
+ const Utf8String &text() const { return m_text; }
+ void setText(const Utf8String &text) { m_text = text; }
+
+ const Utf8String &briefComment() const { return m_briefComment; }
+ void setBriefComment(const Utf8String &briefComment) { m_briefComment = briefComment; }
+
+ const Utf8StringVector &qdocIdCandidates() const { return m_qdocIdCandidates; }
+ void setQdocIdCandidates(const Utf8StringVector &qdocIdCandidates)
+ { m_qdocIdCandidates = qdocIdCandidates; }
+
+ const Utf8String &qdocMark() const { return m_qdocMark; }
+ void setQdocMark(const Utf8String &qdocMark) { m_qdocMark = qdocMark; }
+
+ const QdocCategory &qdocCategory() const { return m_qdocCategory; }
+ void setQdocCategory(const QdocCategory &qdocCategory) { m_qdocCategory = qdocCategory; }
+
+ const Utf8String &sizeInBytes() const { return m_sizeInBytes; }
+ void setSizeInBytes(const Utf8String &sizeInBytes) { m_sizeInBytes = sizeInBytes; }
+
+ friend QDataStream &operator<<(QDataStream &out, const ToolTipInfo &message)
+ {
+ out << message.m_text;
+ out << message.m_briefComment;
+ out << message.m_qdocIdCandidates;
+ out << message.m_qdocMark;
+ out << static_cast<quint8>(message.m_qdocCategory);
+ out << message.m_sizeInBytes;
+
+ return out;
+ }
+
+ friend QDataStream &operator>>(QDataStream &in, ToolTipInfo &message)
+ {
+ quint8 qdocCategory;
+
+ in >> message.m_text;
+ in >> message.m_briefComment;
+ in >> message.m_qdocIdCandidates;
+ in >> message.m_qdocMark;
+ in >> qdocCategory;
+ in >> message.m_sizeInBytes;
+
+ message.m_qdocCategory = static_cast<QdocCategory>(qdocCategory);
+
+ return in;
+ }
+
+ friend bool operator==(const ToolTipInfo &first, const ToolTipInfo &second)
+ {
+ return first.m_text == second.m_text
+ && first.m_briefComment == second.m_briefComment
+ && first.m_qdocIdCandidates == second.m_qdocIdCandidates
+ && first.m_qdocMark == second.m_qdocMark
+ && first.m_qdocCategory == second.m_qdocCategory
+ && first.m_sizeInBytes == second.m_sizeInBytes;
+ }
+
+ friend QDebug operator<<(QDebug debug, const ToolTipInfo &message);
+ friend std::ostream &operator<<(std::ostream &os, const ToolTipInfo &message);
+
+private:
+ Utf8String m_text;
+ Utf8String m_briefComment;
+
+ Utf8StringVector m_qdocIdCandidates;
+ Utf8String m_qdocMark;
+ QdocCategory m_qdocCategory = Unknown;
+
+ // For class definition and for class fields.
+ Utf8String m_sizeInBytes;
+};
+
+const char *qdocCategoryToString(ToolTipInfo::QdocCategory category);
+
+} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/tooltipmessage.cpp b/src/libs/clangsupport/tooltipmessage.cpp
new file mode 100644
index 00000000000..6e64fe33694
--- /dev/null
+++ b/src/libs/clangsupport/tooltipmessage.cpp
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "tooltipmessage.h"
+
+#include <QDebug>
+
+namespace ClangBackEnd {
+
+QDebug operator<<(QDebug debug, const ToolTipMessage &message)
+{
+ debug.nospace() << "ToolTipMessage("
+ << message.fileContainer()
+ << ", " << message.m_ticketNumber
+ << ", " << message.m_toolTipInfo;
+
+ debug.nospace() << ")";
+
+ return debug;
+}
+
+} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/tooltipmessage.h b/src/libs/clangsupport/tooltipmessage.h
new file mode 100644
index 00000000000..5d748179a66
--- /dev/null
+++ b/src/libs/clangsupport/tooltipmessage.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "filecontainer.h"
+#include "tooltipinfo.h"
+
+#include <QDataStream>
+
+namespace ClangBackEnd {
+
+class ToolTipMessage
+{
+public:
+ ToolTipMessage() = default;
+ ToolTipMessage(const FileContainer &fileContainer,
+ const ToolTipInfo &toolTipInfo,
+ quint64 ticketNumber)
+ : m_fileContainer(fileContainer)
+ , m_toolTipInfo(toolTipInfo)
+ , m_ticketNumber(ticketNumber)
+ {
+ }
+
+ const FileContainer &fileContainer() const { return m_fileContainer; }
+ const ToolTipInfo &toolTipInfo() const { return m_toolTipInfo; }
+ quint64 ticketNumber() const { return m_ticketNumber; }
+
+ friend QDataStream &operator<<(QDataStream &out, const ToolTipMessage &message)
+ {
+ out << message.m_fileContainer;
+ out << message.m_toolTipInfo;;
+ out << message.m_ticketNumber;
+
+ return out;
+ }
+
+ friend QDataStream &operator>>(QDataStream &in, ToolTipMessage &message)
+ {
+ in >> message.m_fileContainer;
+ in >> message.m_toolTipInfo;
+ in >> message.m_ticketNumber;
+
+ return in;
+ }
+
+ friend bool operator==(const ToolTipMessage &first, const ToolTipMessage &second)
+ {
+ return first.m_ticketNumber == second.m_ticketNumber
+ && first.m_fileContainer == second.m_fileContainer
+ && first.m_toolTipInfo == second.m_toolTipInfo;
+ }
+
+ friend CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const ToolTipMessage &message);
+ friend std::ostream &operator<<(std::ostream &os, const ToolTipMessage &message);
+
+private:
+ FileContainer m_fileContainer;
+ ToolTipInfo m_toolTipInfo;
+ quint64 m_ticketNumber = 0;
+};
+
+DECLARE_MESSAGE(ToolTipMessage)
+} // namespace ClangBackEnd
diff --git a/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.cpp b/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.cpp
index 0db6b692467..5f70cb77da0 100644
--- a/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.cpp
+++ b/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.cpp
@@ -43,6 +43,47 @@
namespace qmt {
+namespace {
+
+struct IconKey {
+ IconKey(StereotypeIcon::Element element, const QList<QString> &stereotypes, const QString &defaultIconPath,
+ const Uid &styleUid, const QSize &size, const QMarginsF &margins, qreal lineWidth)
+ : m_element(element),
+ m_stereotypes(stereotypes),
+ m_defaultIconPath(defaultIconPath),
+ m_styleUid(styleUid),
+ m_size(size),
+ m_margins(margins),
+ m_lineWidth(lineWidth)
+ {
+ }
+
+ const StereotypeIcon::Element m_element;
+ const QList<QString> m_stereotypes;
+ const QString m_defaultIconPath;
+ const Uid m_styleUid;
+ const QSize m_size;
+ const QMarginsF m_margins;
+ const qreal m_lineWidth;
+};
+
+bool operator==(const IconKey &lhs, const IconKey &rhs) {
+ return lhs.m_element == rhs.m_element
+ && lhs.m_stereotypes == rhs.m_stereotypes
+ && lhs.m_defaultIconPath == rhs.m_defaultIconPath
+ && lhs.m_styleUid == rhs.m_styleUid
+ && lhs.m_size == rhs.m_size
+ && lhs.m_margins == rhs.m_margins
+ && lhs.m_lineWidth == rhs.m_lineWidth;
+}
+
+uint qHash(const IconKey &key) {
+ return ::qHash(key.m_element) + qHash(key.m_stereotypes) + qHash(key.m_defaultIconPath)
+ + qHash(key.m_styleUid) + ::qHash(key.m_size.width()) + ::qHash(key.m_size.height());
+}
+
+}
+
class StereotypeController::StereotypeControllerPrivate
{
public:
@@ -51,6 +92,7 @@ public:
QHash<QString, CustomRelation> m_relationIdToCustomRelationMap;
QList<Toolbar> m_toolbars;
QList<Toolbar> m_elementToolbars;
+ QHash<IconKey, QIcon> m_iconMap;
};
StereotypeController::StereotypeController(QObject *parent) :
@@ -131,9 +173,10 @@ QIcon StereotypeController::createIcon(StereotypeIcon::Element element, const QL
const QString &defaultIconPath, const Style *style, const QSize &size,
const QMarginsF &margins, qreal lineWidth)
{
- // TODO implement cache with key build from element, stereotypes, defaultIconPath, style, size and margins
- // TODO implement unique id for style which can be used as key
- QIcon icon;
+ IconKey key(element, stereotypes, defaultIconPath, style->uid(), size, margins, lineWidth);
+ QIcon icon = d->m_iconMap.value(key);
+ if (!icon.isNull())
+ return icon;
QString stereotypeIconId = findStereotypeIconId(element, stereotypes);
if (!stereotypeIconId.isEmpty()) {
StereotypeIcon stereotypeIcon = findStereotypeIcon(stereotypeIconId);
@@ -202,6 +245,7 @@ QIcon StereotypeController::createIcon(StereotypeIcon::Element element, const QL
}
if (icon.isNull() && !defaultIconPath.isEmpty())
icon = QIcon(defaultIconPath);
+ d->m_iconMap.insert(key, icon);
return icon;
}
diff --git a/src/libs/modelinglib/qmt/style/style.h b/src/libs/modelinglib/qmt/style/style.h
index 9add43d26e8..b2012e4f042 100644
--- a/src/libs/modelinglib/qmt/style/style.h
+++ b/src/libs/modelinglib/qmt/style/style.h
@@ -26,6 +26,7 @@
#pragma once
#include "qmt/infrastructure/qmt_global.h"
+#include "qmt/infrastructure/uid.h"
#include <QString>
#include <QPen>
@@ -45,6 +46,7 @@ public:
explicit Style(Type type);
virtual ~Style();
+ Uid uid() const { return m_uid; }
Type type() const { return m_type; }
QPen linePen() const { return m_linePen; }
void setLinePen(const QPen &pen);
@@ -68,6 +70,7 @@ public:
void setHeaderFont(const QFont &font);
private:
+ Uid m_uid;
Type m_type;
QPen m_linePen;
QPen m_outerLinePen;
diff --git a/src/libs/sqlite/utf8string.h b/src/libs/sqlite/utf8string.h
index 17460ae82d4..cd1d6fdb550 100644
--- a/src/libs/sqlite/utf8string.h
+++ b/src/libs/sqlite/utf8string.h
@@ -171,7 +171,8 @@ public:
byteArray.reserve(reserveSize);
}
- static Utf8String number(int number, int base=10)
+ template<typename T>
+ static Utf8String number(T number, int base = 10)
{
return Utf8String::fromByteArray(QByteArray::number(number, base));
}
diff --git a/src/plugins/autotest/qtest/qttestparser.cpp b/src/plugins/autotest/qtest/qttestparser.cpp
index 1e885ac73a6..1bfabb42db8 100644
--- a/src/plugins/autotest/qtest/qttestparser.cpp
+++ b/src/plugins/autotest/qtest/qttestparser.cpp
@@ -271,6 +271,13 @@ static QtTestCodeLocationList tagLocationsFor(const QtTestParseResult *func,
return QtTestCodeLocationList();
}
+static bool isQObject(const CPlusPlus::Document::Ptr &declaringDoc)
+{
+ const QString file = declaringDoc->fileName();
+ return (Utils::HostOsInfo::isMacHost() && file.endsWith("QtCore.framework/Headers/qobject.h"))
+ || file.endsWith("QtCore/qobject.h") || file.endsWith("kernel/qobject.h");
+}
+
static bool handleQtTest(QFutureInterface<TestParseResultPtr> futureInterface,
CPlusPlus::Document::Ptr document,
const CPlusPlus::Snapshot &snapshot,
@@ -303,6 +310,10 @@ static bool handleQtTest(QFutureInterface<TestParseResultPtr> futureInterface,
fetchAndMergeBaseTestFunctions(
visitor.baseClasses(), testFunctions, declaringDoc, snapshot);
+ // handle tests that are not runnable without more information (plugin unit test of QC)
+ if (testFunctions.isEmpty() && testCaseName == "QObject" && isQObject(declaringDoc))
+ return true; // we did not handle it, but we do not expect any test defined there either
+
const QSet<QString> &files = filesWithDataFunctionDefinitions(testFunctions);
// TODO: change to QHash<>
diff --git a/src/plugins/clangcodemodel/clangbackendcommunicator.cpp b/src/plugins/clangcodemodel/clangbackendcommunicator.cpp
index 56504793122..1abd6982edf 100644
--- a/src/plugins/clangcodemodel/clangbackendcommunicator.cpp
+++ b/src/plugins/clangcodemodel/clangbackendcommunicator.cpp
@@ -392,6 +392,15 @@ QFuture<CppTools::CursorInfo> BackendCommunicator::requestLocalReferences(
return m_receiver.addExpectedReferencesMessage(message.ticketNumber(), textDocument);
}
+QFuture<CppTools::ToolTipInfo> BackendCommunicator::requestToolTip(
+ const FileContainer &fileContainer, quint32 line, quint32 column)
+{
+ const RequestToolTipMessage message(fileContainer, line, column);
+ m_sender->requestToolTip(message);
+
+ return m_receiver.addExpectedToolTipMessage(message.ticketNumber());
+}
+
QFuture<CppTools::SymbolInfo> BackendCommunicator::requestFollowSymbol(
const FileContainer &curFileContainer,
quint32 line,
diff --git a/src/plugins/clangcodemodel/clangbackendcommunicator.h b/src/plugins/clangcodemodel/clangbackendcommunicator.h
index bd7494a6c20..b3cb166a391 100644
--- a/src/plugins/clangcodemodel/clangbackendcommunicator.h
+++ b/src/plugins/clangcodemodel/clangbackendcommunicator.h
@@ -82,6 +82,9 @@ public:
quint32 line,
quint32 column,
QTextDocument *textDocument);
+ QFuture<CppTools::ToolTipInfo> requestToolTip(const FileContainer &fileContainer,
+ quint32 line,
+ quint32 column);
QFuture<CppTools::SymbolInfo> requestFollowSymbol(const FileContainer &curFileContainer,
quint32 line,
quint32 column);
diff --git a/src/plugins/clangcodemodel/clangbackendreceiver.cpp b/src/plugins/clangcodemodel/clangbackendreceiver.cpp
index 8d5ec92d00d..f2606d74cc5 100644
--- a/src/plugins/clangcodemodel/clangbackendreceiver.cpp
+++ b/src/plugins/clangcodemodel/clangbackendreceiver.cpp
@@ -128,6 +128,18 @@ QFuture<CppTools::SymbolInfo> BackendReceiver::addExpectedRequestFollowSymbolMes
return futureInterface.future();
}
+QFuture<CppTools::ToolTipInfo> BackendReceiver::addExpectedToolTipMessage(quint64 ticket)
+{
+ QTC_CHECK(!m_toolTipsTable.contains(ticket));
+
+ QFutureInterface<CppTools::ToolTipInfo> futureInterface;
+ futureInterface.reportStarted();
+
+ m_toolTipsTable.insert(ticket, futureInterface);
+
+ return futureInterface.future();
+}
+
bool BackendReceiver::isExpectingCodeCompletedMessage() const
{
return !m_assistProcessorsTable.isEmpty();
@@ -272,6 +284,72 @@ void BackendReceiver::references(const ReferencesMessage &message)
futureInterface.reportFinished();
}
+static TextEditor::HelpItem::Category toHelpItemCategory(ToolTipInfo::QdocCategory category)
+{
+ switch (category) {
+ case ToolTipInfo::Unknown:
+ return TextEditor::HelpItem::Unknown;
+ case ToolTipInfo::ClassOrNamespace:
+ return TextEditor::HelpItem::ClassOrNamespace;
+ case ToolTipInfo::Enum:
+ return TextEditor::HelpItem::Enum;
+ case ToolTipInfo::Typedef:
+ return TextEditor::HelpItem::Typedef;
+ case ToolTipInfo::Macro:
+ return TextEditor::HelpItem::Macro;
+ case ToolTipInfo::Brief:
+ return TextEditor::HelpItem::Brief;
+ case ToolTipInfo::Function:
+ return TextEditor::HelpItem::Function;
+ }
+
+ return TextEditor::HelpItem::Unknown;
+}
+
+static QStringList toStringList(const Utf8StringVector &utf8StringVector)
+{
+ QStringList list;
+ list.reserve(utf8StringVector.size());
+
+ for (const Utf8String &utf8String : utf8StringVector)
+ list << utf8String.toString();
+
+ return list;
+}
+
+static CppTools::ToolTipInfo toToolTipInfo(const ToolTipMessage &message)
+{
+ CppTools::ToolTipInfo info;
+
+ const ToolTipInfo backendInfo = message.toolTipInfo();
+
+ info.text = backendInfo.text();
+ info.briefComment = backendInfo.briefComment();
+
+ info.qDocIdCandidates = toStringList(backendInfo.qdocIdCandidates());
+ info.qDocMark = backendInfo.qdocMark();
+ info.qDocCategory = toHelpItemCategory(backendInfo.qdocCategory());
+
+ info.sizeInBytes = backendInfo.sizeInBytes();
+
+ return info;
+}
+
+void BackendReceiver::tooltip(const ToolTipMessage &message)
+{
+ qCDebugIpc() << "ToolTipMessage" << message.toolTipInfo().text();
+
+ const quint64 ticket = message.ticketNumber();
+ QFutureInterface<CppTools::ToolTipInfo> futureInterface = m_toolTipsTable.take(ticket);
+ QTC_CHECK(futureInterface != QFutureInterface<CppTools::ToolTipInfo>());
+
+ if (futureInterface.isCanceled())
+ return; // A new request was issued making this one outdated.
+
+ futureInterface.reportResult(toToolTipInfo(message));
+ futureInterface.reportFinished();
+}
+
void BackendReceiver::followSymbol(const ClangBackEnd::FollowSymbolMessage &message)
{
qCDebugIpc() << "FollowSymbolMessage with"
diff --git a/src/plugins/clangcodemodel/clangbackendreceiver.h b/src/plugins/clangcodemodel/clangbackendreceiver.h
index d7a966eae98..921150a52dc 100644
--- a/src/plugins/clangcodemodel/clangbackendreceiver.h
+++ b/src/plugins/clangcodemodel/clangbackendreceiver.h
@@ -27,6 +27,7 @@
#include <cpptools/cppcursorinfo.h>
#include <cpptools/cppsymbolinfo.h>
+#include <cpptools/baseeditordocumentprocessor.h>
#include <clangsupport/clangcodemodelclientinterface.h>
@@ -59,6 +60,7 @@ public:
const CppTools::SemanticInfo::LocalUseMap &localUses
= CppTools::SemanticInfo::LocalUseMap());
QFuture<CppTools::SymbolInfo> addExpectedRequestFollowSymbolMessage(quint64 ticket);
+ QFuture<CppTools::ToolTipInfo> addExpectedToolTipMessage(quint64 ticket);
bool isExpectingCodeCompletedMessage() const;
void reset();
@@ -70,6 +72,7 @@ private:
void documentAnnotationsChanged(const ClangBackEnd::DocumentAnnotationsChangedMessage &message) override;
void references(const ClangBackEnd::ReferencesMessage &message) override;
+ void tooltip(const ClangBackEnd::ToolTipMessage &message) override;
void followSymbol(const ClangBackEnd::FollowSymbolMessage &message) override;
private:
@@ -89,7 +92,7 @@ private:
CppTools::SemanticInfo::LocalUseMap localUses;
};
QHash<quint64, ReferencesEntry> m_referencesTable;
-
+ QHash<quint64, QFutureInterface<CppTools::ToolTipInfo>> m_toolTipsTable;
QHash<quint64, QFutureInterface<CppTools::SymbolInfo>> m_followTable;
};
diff --git a/src/plugins/clangcodemodel/clangbackendsender.cpp b/src/plugins/clangcodemodel/clangbackendsender.cpp
index 089377083fb..f6f8aea1cf8 100644
--- a/src/plugins/clangcodemodel/clangbackendsender.cpp
+++ b/src/plugins/clangcodemodel/clangbackendsender.cpp
@@ -120,6 +120,13 @@ void BackendSender::requestReferences(const RequestReferencesMessage &message)
m_connection->serverProxy().requestReferences(message);
}
+void BackendSender::requestToolTip(const RequestToolTipMessage &message)
+{
+ QTC_CHECK(m_connection->isConnected());
+ qCDebug(ipcLog) << ">>>" << message;
+ m_connection->serverProxy().requestToolTip(message);
+}
+
void BackendSender::requestFollowSymbol(const RequestFollowSymbolMessage &message)
{
QTC_CHECK(m_connection->isConnected());
diff --git a/src/plugins/clangcodemodel/clangbackendsender.h b/src/plugins/clangcodemodel/clangbackendsender.h
index ca9238ae651..f01326a4dc3 100644
--- a/src/plugins/clangcodemodel/clangbackendsender.h
+++ b/src/plugins/clangcodemodel/clangbackendsender.h
@@ -48,6 +48,7 @@ public:
void completeCode(const ClangBackEnd::CompleteCodeMessage &message) override;
void requestDocumentAnnotations(const ClangBackEnd::RequestDocumentAnnotationsMessage &message) override;
void requestReferences(const ClangBackEnd::RequestReferencesMessage &message) override;
+ void requestToolTip(const ClangBackEnd::RequestToolTipMessage &message) override;
void requestFollowSymbol(const ClangBackEnd::RequestFollowSymbolMessage &message) override;
void updateVisibleTranslationUnits(const ClangBackEnd::UpdateVisibleTranslationUnitsMessage &message) override;
diff --git a/src/plugins/clangcodemodel/clangcodemodel.pro b/src/plugins/clangcodemodel/clangcodemodel.pro
index 9136db5db5c..0e444a350e2 100644
--- a/src/plugins/clangcodemodel/clangcodemodel.pro
+++ b/src/plugins/clangcodemodel/clangcodemodel.pro
@@ -30,6 +30,7 @@ SOURCES += \
clangfixitoperationsextractor.cpp \
clangfollowsymbol.cpp \
clangfunctionhintmodel.cpp \
+ clanghoverhandler.cpp \
clangtokeninfosreporter.cpp \
clangmodelmanagersupport.cpp \
clangpreprocessorassistproposalitem.cpp \
@@ -66,6 +67,7 @@ HEADERS += \
clangfixitoperationsextractor.h \
clangfollowsymbol.h \
clangfunctionhintmodel.h \
+ clanghoverhandler.h \
clangisdiagnosticrelatedtolocation.h \
clangmodelmanagersupport.h \
clangpreprocessorassistproposalitem.h \
diff --git a/src/plugins/clangcodemodel/clangcodemodel.qbs b/src/plugins/clangcodemodel/clangcodemodel.qbs
index cc81025925f..90105b86d38 100644
--- a/src/plugins/clangcodemodel/clangcodemodel.qbs
+++ b/src/plugins/clangcodemodel/clangcodemodel.qbs
@@ -80,6 +80,8 @@ QtcPlugin {
"clangfollowsymbol.h",
"clangfunctionhintmodel.cpp",
"clangfunctionhintmodel.h",
+ "clanghoverhandler.cpp",
+ "clanghoverhandler.h",
"clangtokeninfosreporter.cpp",
"clangtokeninfosreporter.h",
"clangisdiagnosticrelatedtolocation.h",
diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
index 6eb98b2c92f..a282350f246 100644
--- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
+++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
@@ -375,6 +375,15 @@ ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column)
static_cast<quint32>(column));
}
+QFuture<CppTools::ToolTipInfo> ClangEditorDocumentProcessor::toolTipInfo(const QByteArray &codecName,
+ int line,
+ int column)
+{
+ return m_communicator.requestToolTip(simpleFileContainer(codecName),
+ static_cast<quint32>(line),
+ static_cast<quint32>(column));
+}
+
ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithArguments() const
{
return fileContainerWithArguments(m_projectPart.data());
@@ -480,13 +489,19 @@ ClangEditorDocumentProcessor::creatorForHeaderErrorDiagnosticWidget(
};
}
-ClangBackEnd::FileContainer ClangEditorDocumentProcessor::simpleFileContainer() const
+ClangBackEnd::FileContainer ClangEditorDocumentProcessor::simpleFileContainer(
+ const QByteArray &codecName) const
{
Utf8String projectPartId;
if (m_projectPart)
projectPartId = m_projectPart->id();
- return ClangBackEnd::FileContainer(filePath(), projectPartId, Utf8String(), false, revision());
+ return ClangBackEnd::FileContainer(filePath(),
+ projectPartId,
+ Utf8String(),
+ false,
+ revision(),
+ Utf8String::fromByteArray(codecName));
}
static CppTools::ProjectPart projectPartForLanguageOption(CppTools::ProjectPart *projectPart)
diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h
index 2bb7ca04633..67745b582cb 100644
--- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h
+++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h
@@ -88,6 +88,9 @@ public:
QFuture<CppTools::CursorInfo> cursorInfo(const CppTools::CursorInfoParams &params) override;
QFuture<CppTools::CursorInfo> requestLocalReferences(const QTextCursor &cursor) override;
QFuture<CppTools::SymbolInfo> requestFollowSymbol(int line, int column) override;
+ QFuture<CppTools::ToolTipInfo> toolTipInfo(const QByteArray &codecName,
+ int line,
+ int column) override;
ClangBackEnd::FileContainer fileContainerWithArguments() const;
@@ -106,7 +109,7 @@ private:
void requestDocumentAnnotations(const QString &projectpartId);
HeaderErrorDiagnosticWidgetCreator creatorForHeaderErrorDiagnosticWidget(
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic);
- ClangBackEnd::FileContainer simpleFileContainer() const;
+ ClangBackEnd::FileContainer simpleFileContainer(const QByteArray &codecName = QByteArray()) const;
ClangBackEnd::FileContainer fileContainerWithArguments(CppTools::ProjectPart *projectPart) const;
ClangBackEnd::FileContainer fileContainerWithArgumentsAndDocumentContent(
CppTools::ProjectPart *projectPart) const;
diff --git a/src/plugins/clangcodemodel/clanghoverhandler.cpp b/src/plugins/clangcodemodel/clanghoverhandler.cpp
new file mode 100644
index 00000000000..6610b555c22
--- /dev/null
+++ b/src/plugins/clangcodemodel/clanghoverhandler.cpp
@@ -0,0 +1,232 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clanghoverhandler.h"
+
+#include <coreplugin/helpmanager.h>
+#include <cpptools/baseeditordocumentprocessor.h>
+#include <cpptools/cppmodelmanager.h>
+#include <cpptools/editordocumenthandle.h>
+#include <texteditor/texteditor.h>
+
+#include <utils/qtcassert.h>
+#include <utils/textutils.h>
+#include <utils/tooltip/tooltip.h>
+
+#include <QFutureWatcher>
+#include <QLoggingCategory>
+#include <QTextCodec>
+#include <QVBoxLayout>
+
+Q_LOGGING_CATEGORY(hoverLog, "qtc.clangcodemodel.hover");
+
+using namespace TextEditor;
+
+namespace ClangCodeModel {
+namespace Internal {
+
+static CppTools::BaseEditorDocumentProcessor *editorDocumentProcessor(TextEditorWidget *editorWidget)
+{
+ const QString filePath = editorWidget->textDocument()->filePath().toString();
+ auto cppModelManager = CppTools::CppModelManager::instance();
+ CppTools::CppEditorDocumentHandle *editorHandle = cppModelManager->cppEditorDocument(filePath);
+
+ if (editorHandle)
+ return editorHandle->processor();
+
+ return 0;
+}
+
+static bool editorDocumentProcessorHasDiagnosticAt(TextEditorWidget *editorWidget, int pos)
+{
+ if (CppTools::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) {
+ int line, column;
+ if (Utils::Text::convertPosition(editorWidget->document(), pos, &line, &column))
+ return processor->hasDiagnosticsAt(line, column);
+ }
+
+ return false;
+}
+
+static void processWithEditorDocumentProcessor(TextEditorWidget *editorWidget,
+ const QPoint &point,
+ int position,
+ const QString &helpId)
+{
+ if (CppTools::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) {
+ int line, column;
+ if (Utils::Text::convertPosition(editorWidget->document(), position, &line, &column)) {
+ auto layout = new QVBoxLayout;
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(2);
+ processor->addDiagnosticToolTipToLayout(line, column, layout);
+ Utils::ToolTip::show(point, layout, editorWidget, helpId);
+ }
+ }
+}
+
+static QFuture<CppTools::ToolTipInfo> editorDocumentHandlesToolTipInfo(
+ TextEditorWidget *editorWidget, int pos)
+{
+ const QByteArray textCodecName = editorWidget->textDocument()->codec()->name();
+ if (CppTools::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) {
+ int line, column;
+ if (Utils::Text::convertPosition(editorWidget->document(), pos, &line, &column))
+ return processor->toolTipInfo(textCodecName, line, column + 1);
+ }
+
+ return QFuture<CppTools::ToolTipInfo>();
+}
+
+ClangHoverHandler::ClangHoverHandler()
+{
+ setIsAsyncHandler(true);
+}
+
+ClangHoverHandler::~ClangHoverHandler()
+{
+ cancelAsyncCheck();
+}
+
+void ClangHoverHandler::identifyMatchAsync(TextEditorWidget *editorWidget,
+ int pos,
+ BaseHoverHandler::ReportPriority report)
+{
+ // Reset
+ m_futureWatcher.reset();
+ m_cursorPosition = -1;
+
+ // Check for diagnostics (sync)
+ if (editorDocumentProcessorHasDiagnosticAt(editorWidget, pos)) {
+ qCDebug(hoverLog) << "Checking for diagnostic at" << pos;
+ setPriority(Priority_Diagnostic);
+ m_cursorPosition = pos;
+ report(priority());
+ return;
+ }
+
+ // Check for tooltips (async)
+ QFuture<CppTools::ToolTipInfo> future = editorDocumentHandlesToolTipInfo(editorWidget, pos);
+ if (QTC_GUARD(future.isRunning())) {
+ qCDebug(hoverLog) << "Requesting tooltip info at" << pos;
+ m_reportPriority = report;
+ m_futureWatcher.reset(new QFutureWatcher<CppTools::ToolTipInfo>());
+ QObject::connect(m_futureWatcher.data(), &QFutureWatcherBase::finished, [this]() {
+ processToolTipInfo(m_futureWatcher->result());
+ });
+ m_futureWatcher->setFuture(future);
+ return;
+ }
+
+ report(Priority_None); // Ops, something went wrong.
+}
+
+void ClangHoverHandler::cancelAsyncCheck()
+{
+ if (m_futureWatcher)
+ m_futureWatcher->cancel();
+}
+
+#define RETURN_TEXT_FOR_CASE(enumValue) case TextEditor::HelpItem::enumValue: return #enumValue
+static const char *helpItemCategoryAsString(TextEditor::HelpItem::Category category)
+{
+ switch (category) {
+ RETURN_TEXT_FOR_CASE(Unknown);
+ RETURN_TEXT_FOR_CASE(ClassOrNamespace);
+ RETURN_TEXT_FOR_CASE(Enum);
+ RETURN_TEXT_FOR_CASE(Typedef);
+ RETURN_TEXT_FOR_CASE(Macro);
+ RETURN_TEXT_FOR_CASE(Brief);
+ RETURN_TEXT_FOR_CASE(Function);
+ RETURN_TEXT_FOR_CASE(QmlComponent);
+ RETURN_TEXT_FOR_CASE(QmlProperty);
+ RETURN_TEXT_FOR_CASE(QMakeVariableOfFunction);
+ }
+
+ return "UnhandledHelpItemCategory";
+}
+#undef RETURN_TEXT_FOR_CASE
+
+void ClangHoverHandler::processToolTipInfo(const CppTools::ToolTipInfo &info)
+{
+ qCDebug(hoverLog) << "Processing tooltip info" << info.text;
+
+ QString text = info.text;
+ if (!info.briefComment.isEmpty())
+ text.append("\n\n" + info.briefComment);
+
+ for (const QString &qdocIdCandidate : info.qDocIdCandidates) {
+ qCDebug(hoverLog) << "Querying help manager with"
+ << qdocIdCandidate
+ << info.qDocMark
+ << helpItemCategoryAsString(info.qDocCategory);
+ const QMap<QString, QUrl> helpLinks = Core::HelpManager::linksForIdentifier(qdocIdCandidate);
+ if (!helpLinks.isEmpty()) {
+ qCDebug(hoverLog) << " Match!";
+ setLastHelpItemIdentified(
+ HelpItem(qdocIdCandidate, info.qDocMark, info.qDocCategory, helpLinks));
+ break;
+ }
+ }
+
+ if (!info.sizeInBytes.isEmpty())
+ text.append(tr("\n\n%1 bytes").arg(info.sizeInBytes));
+
+ setToolTip(text);
+ m_reportPriority(priority());
+}
+
+void ClangHoverHandler::decorateToolTip()
+{
+ if (priority() == Priority_Diagnostic)
+ return;
+
+ if (Qt::mightBeRichText(toolTip()))
+ setToolTip(toolTip().toHtmlEscaped());
+
+ const HelpItem &help = lastHelpItemIdentified();
+ if (help.isValid()) {
+ const QString text = CppTools::CppHoverHandler::tooltipTextForHelpItem(help);
+ if (!text.isEmpty())
+ setToolTip(text);
+ }
+}
+
+void ClangHoverHandler::operateTooltip(TextEditor::TextEditorWidget *editorWidget,
+ const QPoint &point)
+{
+ if (priority() == Priority_Diagnostic) {
+ const HelpItem helpItem = lastHelpItemIdentified();
+ const QString helpId = helpItem.isValid() ? helpItem.helpId() : QString();
+ processWithEditorDocumentProcessor(editorWidget, point, m_cursorPosition, helpId);
+ return;
+ }
+
+ // Priority_Tooltip / Priority_Help
+ BaseHoverHandler::operateTooltip(editorWidget, point);
+}
+
+} // namespace Internal
+} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clanghoverhandler.h b/src/plugins/clangcodemodel/clanghoverhandler.h
new file mode 100644
index 00000000000..85b7999f94b
--- /dev/null
+++ b/src/plugins/clangcodemodel/clanghoverhandler.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <cpptools/baseeditordocumentprocessor.h>
+#include <cpptools/cpphoverhandler.h>
+#include <texteditor/basehoverhandler.h>
+
+namespace ClangCodeModel {
+namespace Internal {
+
+class ClangHoverHandler : public TextEditor::BaseHoverHandler
+{
+ Q_DECLARE_TR_FUNCTIONS(ClangHoverHandler)
+
+public:
+ ClangHoverHandler();
+ ~ClangHoverHandler() override;
+
+ void identifyMatchAsync(TextEditor::TextEditorWidget *editorWidget,
+ int pos,
+ ReportPriority report) override;
+ void decorateToolTip() override;
+ void operateTooltip(TextEditor::TextEditorWidget *editorWidget, const QPoint &point) override;
+
+private:
+ void cancelAsyncCheck() override;
+ void processToolTipInfo(const CppTools::ToolTipInfo &info);
+
+private:
+ int m_cursorPosition = -1;
+ QScopedPointer<QFutureWatcher<CppTools::ToolTipInfo>> m_futureWatcher;
+ ReportPriority m_reportPriority;
+};
+
+} // namespace Internal
+} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
index f73c5fe4e4a..9495e6d5ebc 100644
--- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
+++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
@@ -29,6 +29,7 @@
#include "clangeditordocumentprocessor.h"
#include "clangutils.h"
#include "clangfollowsymbol.h"
+#include "clanghoverhandler.h"
#include "clangrefactoringengine.h"
#include <coreplugin/editormanager/editormanager.h>
@@ -111,6 +112,11 @@ CppTools::CppCompletionAssistProvider *ModelManagerSupportClang::completionAssis
return &m_completionAssistProvider;
}
+TextEditor::BaseHoverHandler *ModelManagerSupportClang::createHoverHandler()
+{
+ return new Internal::ClangHoverHandler;
+}
+
CppTools::FollowSymbolInterface &ModelManagerSupportClang::followSymbolInterface()
{
return *m_followSymbol;
@@ -121,7 +127,7 @@ CppTools::RefactoringEngineInterface &ModelManagerSupportClang::refactoringEngin
return *m_refactoringEngine;
}
-CppTools::BaseEditorDocumentProcessor *ModelManagerSupportClang::editorDocumentProcessor(
+CppTools::BaseEditorDocumentProcessor *ModelManagerSupportClang::createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument)
{
return new ClangEditorDocumentProcessor(m_communicator, baseTextDocument);
diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.h b/src/plugins/clangcodemodel/clangmodelmanagersupport.h
index e87a7f162e8..92f253c5a8b 100644
--- a/src/plugins/clangcodemodel/clangmodelmanagersupport.h
+++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.h
@@ -61,7 +61,8 @@ public:
~ModelManagerSupportClang();
CppTools::CppCompletionAssistProvider *completionAssistProvider() override;
- CppTools::BaseEditorDocumentProcessor *editorDocumentProcessor(
+ TextEditor::BaseHoverHandler *createHoverHandler() override;
+ CppTools::BaseEditorDocumentProcessor *createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) override;
CppTools::FollowSymbolInterface &followSymbolInterface() override;
CppTools::RefactoringEngineInterface &refactoringEngineInterface() override;
diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp
index 65fba9709f9..577a9f9487b 100644
--- a/src/plugins/coreplugin/coreplugin.cpp
+++ b/src/plugins/coreplugin/coreplugin.cpp
@@ -26,12 +26,13 @@
#include "coreplugin.h"
#include "designmode.h"
#include "editmode.h"
-#include "idocument.h"
#include "helpmanager.h"
-#include "mainwindow.h"
-#include "modemanager.h"
+#include "idocument.h"
#include "infobar.h"
#include "iwizardfactory.h"
+#include "mainwindow.h"
+#include "menubarfilter.h"
+#include "modemanager.h"
#include "reaper_p.h"
#include "themechooser.h"
@@ -162,6 +163,8 @@ bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage)
InfoBar::initialize(ICore::settings(), creatorTheme());
}
+ addAutoReleasedObject(new MenuBarFilter);
+
IWizardFactory::initialize();
// Make sure we respect the process's umask when creating new files
diff --git a/src/plugins/coreplugin/coreplugin.pro b/src/plugins/coreplugin/coreplugin.pro
index dd6f03bdaa7..d5f1f7f51ed 100644
--- a/src/plugins/coreplugin/coreplugin.pro
+++ b/src/plugins/coreplugin/coreplugin.pro
@@ -111,7 +111,8 @@ SOURCES += corejsextensions.cpp \
externaltoolmanager.cpp \
systemsettings.cpp \
coreicons.cpp \
- diffservice.cpp
+ diffservice.cpp \
+ menubarfilter.cpp
HEADERS += corejsextensions.h \
mainwindow.h \
@@ -222,7 +223,8 @@ HEADERS += corejsextensions.h \
systemsettings.h \
coreicons.h \
editormanager/documentmodel_p.h \
- diffservice.h
+ diffservice.h \
+ menubarfilter.h
FORMS += dialogs/newdialog.ui \
dialogs/saveitemsdialog.ui \
diff --git a/src/plugins/coreplugin/coreplugin.qbs b/src/plugins/coreplugin/coreplugin.qbs
index eabf668df71..ce47658daad 100644
--- a/src/plugins/coreplugin/coreplugin.qbs
+++ b/src/plugins/coreplugin/coreplugin.qbs
@@ -32,79 +32,154 @@ Project {
Group {
name: "General"
files: [
- "basefilewizard.cpp", "basefilewizard.h",
- "basefilewizardfactory.cpp", "basefilewizardfactory.h",
+ "basefilewizard.cpp",
+ "basefilewizard.h",
+ "basefilewizardfactory.cpp",
+ "basefilewizardfactory.h",
"core.qrc",
"core_global.h",
"coreconstants.h",
- "coreicons.cpp", "coreicons.h",
- "corejsextensions.cpp", "corejsextensions.h",
- "coreplugin.cpp", "coreplugin.h",
- "designmode.cpp", "designmode.h",
- "diffservice.cpp", "diffservice.h",
- "documentmanager.cpp", "documentmanager.h",
- "editmode.cpp", "editmode.h",
- "editortoolbar.cpp", "editortoolbar.h",
- "externaltool.cpp", "externaltool.h",
- "externaltoolmanager.cpp", "externaltoolmanager.h",
- "fancyactionbar.cpp", "fancyactionbar.h", "fancyactionbar.qrc",
- "fancytabwidget.cpp", "fancytabwidget.h",
- "featureprovider.cpp", "featureprovider.h",
- "fileiconprovider.cpp", "fileiconprovider.h",
- "fileutils.cpp", "fileutils.h",
- "findplaceholder.cpp", "findplaceholder.h",
- "generalsettings.cpp", "generalsettings.h", "generalsettings.ui",
- "generatedfile.cpp", "generatedfile.h",
- "helpmanager.cpp", "helpmanager.h",
- "icontext.cpp", "icontext.h",
- "icore.cpp", "icore.h",
- "id.cpp", "id.h",
- "idocument.cpp", "idocument.h",
- "idocumentfactory.cpp", "idocumentfactory.h",
+ "coreicons.cpp",
+ "coreicons.h",
+ "corejsextensions.cpp",
+ "corejsextensions.h",
+ "coreplugin.cpp",
+ "coreplugin.h",
+ "designmode.cpp",
+ "designmode.h",
+ "diffservice.cpp",
+ "diffservice.h",
+ "documentmanager.cpp",
+ "documentmanager.h",
+ "editmode.cpp",
+ "editmode.h",
+ "editortoolbar.cpp",
+ "editortoolbar.h",
+ "externaltool.cpp",
+ "externaltool.h",
+ "externaltoolmanager.cpp",
+ "externaltoolmanager.h",
+ "fancyactionbar.cpp",
+ "fancyactionbar.h",
+ "fancyactionbar.qrc",
+ "fancytabwidget.cpp",
+ "fancytabwidget.h",
+ "featureprovider.cpp",
+ "featureprovider.h",
+ "fileiconprovider.cpp",
+ "fileiconprovider.h",
+ "fileutils.cpp",
+ "fileutils.h",
+ "findplaceholder.cpp",
+ "findplaceholder.h",
+ "generalsettings.cpp",
+ "generalsettings.h",
+ "generalsettings.ui",
+ "generatedfile.cpp",
+ "generatedfile.h",
+ "helpmanager.cpp",
+ "helpmanager.h",
+ "icontext.cpp",
+ "icontext.h",
+ "icore.cpp",
+ "icore.h",
+ "id.cpp",
+ "id.h",
+ "idocument.cpp",
+ "idocument.h",
+ "idocumentfactory.cpp",
+ "idocumentfactory.h",
"ifilewizardextension.h",
- "imode.cpp", "imode.h",
- "inavigationwidgetfactory.cpp", "inavigationwidgetfactory.h",
- "infobar.cpp", "infobar.h",
- "ioutputpane.cpp", "ioutputpane.h",
- "iversioncontrol.cpp", "iversioncontrol.h",
- "iwelcomepage.cpp", "iwelcomepage.h",
- "iwizardfactory.cpp", "iwizardfactory.h",
- "jsexpander.cpp", "jsexpander.h",
- "mainwindow.cpp", "mainwindow.h",
- "manhattanstyle.cpp", "manhattanstyle.h",
- "messagebox.cpp", "messagebox.h",
- "messagemanager.cpp", "messagemanager.h",
- "messageoutputwindow.cpp", "messageoutputwindow.h",
- "mimetypemagicdialog.cpp", "mimetypemagicdialog.h", "mimetypemagicdialog.ui",
- "mimetypesettings.cpp", "mimetypesettings.h",
+ "imode.cpp",
+ "imode.h",
+ "inavigationwidgetfactory.cpp",
+ "inavigationwidgetfactory.h",
+ "infobar.cpp",
+ "infobar.h",
+ "ioutputpane.cpp",
+ "ioutputpane.h",
+ "iversioncontrol.cpp",
+ "iversioncontrol.h",
+ "iwelcomepage.cpp",
+ "iwelcomepage.h",
+ "iwizardfactory.cpp",
+ "iwizardfactory.h",
+ "jsexpander.cpp",
+ "jsexpander.h",
+ "mainwindow.cpp",
+ "mainwindow.h",
+ "manhattanstyle.cpp",
+ "manhattanstyle.h",
+ "menubarfilter.cpp",
+ "menubarfilter.h",
+ "messagebox.cpp",
+ "messagebox.h",
+ "messagemanager.cpp",
+ "messagemanager.h",
+ "messageoutputwindow.cpp",
+ "messageoutputwindow.h",
+ "mimetypemagicdialog.cpp",
+ "mimetypemagicdialog.h",
+ "mimetypemagicdialog.ui",
+ "mimetypesettings.cpp",
+ "mimetypesettings.h",
"mimetypesettingspage.ui",
- "minisplitter.cpp", "minisplitter.h",
- "modemanager.cpp", "modemanager.h",
- "navigationsubwidget.cpp", "navigationsubwidget.h",
- "navigationwidget.cpp", "navigationwidget.h",
- "opendocumentstreeview.cpp", "opendocumentstreeview.h",
- "outputpane.cpp", "outputpane.h",
- "outputpanemanager.cpp", "outputpanemanager.h",
- "outputwindow.cpp", "outputwindow.h",
- "patchtool.cpp", "patchtool.h",
- "plugindialog.cpp", "plugindialog.h",
- "reaper.cpp", "reaper.h", "reaper_p.h",
- "rightpane.cpp", "rightpane.h",
- "settingsdatabase.cpp", "settingsdatabase.h",
- "shellcommand.cpp", "shellcommand.h",
- "sidebar.cpp", "sidebar.h",
- "sidebarwidget.cpp", "sidebarwidget.h",
- "statusbarmanager.cpp", "statusbarmanager.h",
- "statusbarwidget.cpp", "statusbarwidget.h",
- "styleanimator.cpp", "styleanimator.h",
- "systemsettings.cpp", "systemsettings.h", "systemsettings.ui",
- "textdocument.cpp", "textdocument.h",
- "themechooser.cpp", "themechooser.h",
- "toolsettings.cpp", "toolsettings.h",
- "variablechooser.cpp", "variablechooser.h",
- "vcsmanager.cpp", "vcsmanager.h",
- "versiondialog.cpp", "versiondialog.h",
- "windowsupport.cpp", "windowsupport.h"
+ "minisplitter.cpp",
+ "minisplitter.h",
+ "modemanager.cpp",
+ "modemanager.h",
+ "navigationsubwidget.cpp",
+ "navigationsubwidget.h",
+ "navigationwidget.cpp",
+ "navigationwidget.h",
+ "opendocumentstreeview.cpp",
+ "opendocumentstreeview.h",
+ "outputpane.cpp",
+ "outputpane.h",
+ "outputpanemanager.cpp",
+ "outputpanemanager.h",
+ "outputwindow.cpp",
+ "outputwindow.h",
+ "patchtool.cpp",
+ "patchtool.h",
+ "plugindialog.cpp",
+ "plugindialog.h",
+ "reaper.cpp",
+ "reaper.h",
+ "reaper_p.h",
+ "rightpane.cpp",
+ "rightpane.h",
+ "settingsdatabase.cpp",
+ "settingsdatabase.h",
+ "shellcommand.cpp",
+ "shellcommand.h",
+ "sidebar.cpp",
+ "sidebar.h",
+ "sidebarwidget.cpp",
+ "sidebarwidget.h",
+ "statusbarmanager.cpp",
+ "statusbarmanager.h",
+ "statusbarwidget.cpp",
+ "statusbarwidget.h",
+ "styleanimator.cpp",
+ "styleanimator.h",
+ "systemsettings.cpp",
+ "systemsettings.h",
+ "systemsettings.ui",
+ "textdocument.cpp",
+ "textdocument.h",
+ "themechooser.cpp",
+ "themechooser.h",
+ "toolsettings.cpp",
+ "toolsettings.h",
+ "variablechooser.cpp",
+ "variablechooser.h",
+ "vcsmanager.cpp",
+ "vcsmanager.h",
+ "versiondialog.cpp",
+ "versiondialog.h",
+ "windowsupport.cpp",
+ "windowsupport.h",
]
}
@@ -268,6 +343,8 @@ Project {
"filesystemfilter.ui",
"ilocatorfilter.cpp",
"ilocatorfilter.h",
+ "javascriptfilter.cpp",
+ "javascriptfilter.h",
"locatorconstants.h",
"locatorfiltersfilter.cpp",
"locatorfiltersfilter.h",
diff --git a/src/plugins/coreplugin/locator/javascriptfilter.cpp b/src/plugins/coreplugin/locator/javascriptfilter.cpp
new file mode 100644
index 00000000000..02803ecf728
--- /dev/null
+++ b/src/plugins/coreplugin/locator/javascriptfilter.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Andre Hartmann <aha_1980@gmx.de>
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "javascriptfilter.h"
+
+#include <QClipboard>
+#include <QGuiApplication>
+#include <QJSEngine>
+
+namespace Core {
+namespace Internal {
+
+JavaScriptFilter::JavaScriptFilter()
+{
+ setId("JavaScriptFilter");
+ setDisplayName(tr("Evaluate JavaScript"));
+ setIncludedByDefault(false);
+ setShortcutString("=");
+}
+
+JavaScriptFilter::~JavaScriptFilter()
+{
+}
+
+void JavaScriptFilter::prepareSearch(const QString &entry)
+{
+ Q_UNUSED(entry);
+
+ setupEngine();
+}
+
+QList<LocatorFilterEntry> JavaScriptFilter::matchesFor(
+ QFutureInterface<Core::LocatorFilterEntry> &future, const QString &entry)
+{
+ Q_UNUSED(future);
+
+ const QString result = m_engine->evaluate(entry).toString();
+ const QString expression = entry + " = " + result;
+
+ QList<LocatorFilterEntry> entries;
+ entries.append({this, expression, QVariant()});
+ entries.append({this, tr("Copy to clipboard: %1").arg(result), result});
+ entries.append({this, tr("Copy to clipboard: %1").arg(expression), expression});
+
+ return entries;
+}
+
+void JavaScriptFilter::accept(Core::LocatorFilterEntry selection, QString *newText,
+ int *selectionStart, int *selectionLength) const
+{
+ Q_UNUSED(newText);
+ Q_UNUSED(selectionStart);
+ Q_UNUSED(selectionLength);
+
+ if (selection.internalData.isNull())
+ return;
+
+ QClipboard *clipboard = QGuiApplication::clipboard();
+ clipboard->setText(selection.internalData.toString());
+}
+
+void JavaScriptFilter::refresh(QFutureInterface<void> &future)
+{
+ Q_UNUSED(future);
+ // Nothing to refresh
+}
+
+void JavaScriptFilter::setupEngine()
+{
+ if (m_engine)
+ return;
+
+ m_engine = new QJSEngine(this);
+ m_engine->evaluate(
+ "function abs(x) { return Math.abs(x); }\n"
+ "function acos(x) { return Math.acos(x); }\n"
+ "function asin(x) { return Math.asin(x); }\n"
+ "function atan(x) { return Math.atan(x); }\n"
+ "function atan2(x, y) { return Math.atan2(x, y); }\n"
+ "function bin(x) { return '0b' + x.toString(2); }\n"
+ "function ceil(x) { return Math.ceil(x); }\n"
+ "function cos(x) { return Math.cos(x); }\n"
+ "function exp(x) { return Math.exp(x); }\n"
+ "function e() { return Math.E; }\n"
+ "function floor(x) { return Math.floor(x); }\n"
+ "function hex(x) { return '0x' + x.toString(16); }\n"
+ "function log(x) { return Math.log(x); }\n"
+ "function max(x, y) { return Math.max(x, y); }\n"
+ "function min(x, y) { return Math.min(x, y); }\n"
+ "function oct(x) { return '0' + x.toString(8); }\n"
+ "function pi() { return Math.PI; }\n"
+ "function pow(x, y) { return Math.pow(x, y); }\n"
+ "function random() { return Math.random(); }\n"
+ "function round(x) { return Math.round(x); }\n"
+ "function sin(x) { return Math.sin(x); }\n"
+ "function sqrt(x) { return Math.sqrt(x); }\n"
+ "function tan(x) { return Math.tan(x); }\n");
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/src/plugins/coreplugin/locator/javascriptfilter.h b/src/plugins/coreplugin/locator/javascriptfilter.h
new file mode 100644
index 00000000000..50f5e85c3b1
--- /dev/null
+++ b/src/plugins/coreplugin/locator/javascriptfilter.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Andre Hartmann <aha_1980@gmx.de>
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <coreplugin/locator/ilocatorfilter.h>
+
+QT_BEGIN_NAMESPACE
+class QJSEngine;
+QT_END_NAMESPACE
+
+namespace Core {
+namespace Internal {
+
+class JavaScriptFilter : public Core::ILocatorFilter
+{
+ Q_OBJECT
+public:
+ JavaScriptFilter();
+ ~JavaScriptFilter();
+
+ virtual void prepareSearch(const QString &entry) override;
+ QList<Core::LocatorFilterEntry> matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future,
+ const QString &entry) override;
+ void accept(Core::LocatorFilterEntry selection, QString *newText,
+ int *selectionStart, int *selectionLength) const override;
+ void refresh(QFutureInterface<void> &future) override;
+
+private:
+ void setupEngine();
+
+ QJSEngine *m_engine = nullptr;
+};
+
+} // namespace Internal
+} // namespace Core
diff --git a/src/plugins/coreplugin/locator/locator.cpp b/src/plugins/coreplugin/locator/locator.cpp
index 6daab8026e8..e57f20241ac 100644
--- a/src/plugins/coreplugin/locator/locator.cpp
+++ b/src/plugins/coreplugin/locator/locator.cpp
@@ -27,6 +27,7 @@
#include "externaltoolsfilter.h"
#include "filesystemfilter.h"
+#include "javascriptfilter.h"
#include "locatorconstants.h"
#include "locatorfiltersfilter.h"
#include "locatormanager.h"
@@ -75,11 +76,13 @@ Locator::Locator()
Locator::~Locator()
{
+ m_corePlugin->removeObject(m_javaScriptFilter);
m_corePlugin->removeObject(m_openDocumentsFilter);
m_corePlugin->removeObject(m_fileSystemFilter);
m_corePlugin->removeObject(m_executeFilter);
m_corePlugin->removeObject(m_settingsPage);
m_corePlugin->removeObject(m_externalToolsFilter);
+ delete m_javaScriptFilter;
delete m_openDocumentsFilter;
delete m_fileSystemFilter;
delete m_executeFilter;
@@ -119,6 +122,9 @@ void Locator::initialize(CorePlugin *corePlugin, const QStringList &, QString *)
new LocatorManager(this);
+ m_javaScriptFilter = new JavaScriptFilter;
+ m_corePlugin->addObject(m_javaScriptFilter);
+
m_openDocumentsFilter = new OpenDocumentsFilter;
m_corePlugin->addObject(m_openDocumentsFilter);
diff --git a/src/plugins/coreplugin/locator/locator.h b/src/plugins/coreplugin/locator/locator.h
index 325bcc11304..5d5d379a887 100644
--- a/src/plugins/coreplugin/locator/locator.h
+++ b/src/plugins/coreplugin/locator/locator.h
@@ -42,6 +42,7 @@ namespace Internal {
class CorePlugin;
class OpenDocumentsFilter;
class FileSystemFilter;
+class JavaScriptFilter;
class LocatorSettingsPage;
class ExternalToolsFilter;
@@ -85,6 +86,7 @@ private:
QList<ILocatorFilter *> m_customFilters;
QMap<Id, QAction *> m_filterActionMap;
QTimer m_refreshTimer;
+ JavaScriptFilter *m_javaScriptFilter = nullptr;
OpenDocumentsFilter *m_openDocumentsFilter = nullptr;
FileSystemFilter *m_fileSystemFilter = nullptr;
ExecuteFilter *m_executeFilter = nullptr;
diff --git a/src/plugins/coreplugin/locator/locator.pri b/src/plugins/coreplugin/locator/locator.pri
index e80765bfc5f..183d7fde515 100644
--- a/src/plugins/coreplugin/locator/locator.pri
+++ b/src/plugins/coreplugin/locator/locator.pri
@@ -1,3 +1,5 @@
+QT *= qml
+
HEADERS += \
$$PWD/locator.h \
$$PWD/commandlocator.h \
@@ -13,7 +15,8 @@ HEADERS += \
$$PWD/executefilter.h \
$$PWD/locatorsearchutils.h \
$$PWD/locatorsettingspage.h \
- $$PWD/externaltoolsfilter.h
+ $$PWD/externaltoolsfilter.h \
+ $$PWD/javascriptfilter.h
SOURCES += \
$$PWD/locator.cpp \
@@ -29,7 +32,8 @@ SOURCES += \
$$PWD/executefilter.cpp \
$$PWD/locatorsearchutils.cpp \
$$PWD/locatorsettingspage.cpp \
- $$PWD/externaltoolsfilter.cpp
+ $$PWD/externaltoolsfilter.cpp \
+ $$PWD/javascriptfilter.cpp
FORMS += \
$$PWD/filesystemfilter.ui \
diff --git a/src/plugins/coreplugin/menubarfilter.cpp b/src/plugins/coreplugin/menubarfilter.cpp
new file mode 100644
index 00000000000..5c3c4414db8
--- /dev/null
+++ b/src/plugins/coreplugin/menubarfilter.cpp
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "menubarfilter.h"
+
+#include "actionmanager/actioncontainer.h"
+#include "actionmanager/actionmanager.h"
+#include "coreconstants.h"
+
+#include <utils/algorithm.h>
+#include <utils/asconst.h>
+#include <utils/qtcassert.h>
+#include <utils/stringutils.h>
+
+#include <QMenuBar>
+#include <QPointer>
+#include <QRegularExpression>
+
+using namespace Core::Internal;
+using namespace Core;
+
+MenuBarFilter::MenuBarFilter()
+{
+ setId("Actions from the menu");
+ setDisplayName(tr("Actions from the Menu"));
+ setShortcutString("t");
+}
+
+static const QList<QAction *> menuBarActions()
+{
+ QMenuBar *menuBar = Core::ActionManager::actionContainer(Constants::MENU_BAR)->menuBar();
+ QTC_ASSERT(menuBar, return {});
+ return menuBar->actions();
+}
+
+QList<LocatorFilterEntry> MenuBarFilter::matchesFor(QFutureInterface<LocatorFilterEntry> &future,
+ const QString &entry)
+{
+ Q_UNUSED(future);
+ static const QString separators = ". >/";
+ static const QRegularExpression seperatorRegExp(QString("[%1]").arg(separators));
+ QList<LocatorFilterEntry> entries;
+ QString normalized = entry;
+ normalized.replace(seperatorRegExp, separators.at(0));
+ const QStringList entryPath = normalized.split(separators.at(0), QString::SkipEmptyParts);
+ QVector<const QMenu *> processedMenus;
+ for (QAction* action : menuBarActions())
+ entries << matchesForAction(action, entryPath, QStringList(), processedMenus);
+
+ return entries;
+}
+
+void MenuBarFilter::accept(LocatorFilterEntry selection, QString *newText,
+ int *selectionStart, int *selectionLength) const
+{
+ Q_UNUSED(newText);
+ Q_UNUSED(selectionStart);
+ Q_UNUSED(selectionLength);
+ if (auto action = selection.internalData.value<QPointer<QAction>>())
+ action->trigger();
+}
+
+void MenuBarFilter::refresh(QFutureInterface<void> &future)
+{
+ Q_UNUSED(future);
+}
+
+QList<LocatorFilterEntry> MenuBarFilter::matchesForAction(QAction *action,
+ const QStringList &entryPath,
+ const QStringList &path,
+ QVector<const QMenu *> &processedMenus)
+{
+ QList<LocatorFilterEntry> entries;
+ if (!action->isEnabled())
+ return entries;
+ const QString text = Utils::stripAccelerator(action->text());
+ if (QMenu *menu = action->menu()) {
+ if (processedMenus.contains(menu))
+ return entries;
+ processedMenus.append(menu);
+ if (menu->isEnabled()) {
+ const QList<QAction *> &actions = menu->actions();
+ QStringList menuPath(path);
+ menuPath << text;
+ for (QAction *menuAction : actions)
+ entries << matchesForAction(menuAction, entryPath, menuPath, processedMenus);
+ }
+ } else if (!text.isEmpty()) {
+ int entryIndex = 0;
+ int entryLength = 0;
+ int pathIndex = 0;
+ LocatorFilterEntry::HighlightInfo::DataType highlightType =
+ LocatorFilterEntry::HighlightInfo::DisplayName;
+ const QString pathText = path.join(" > ");
+ QStringList actionPath(path);
+ if (!entryPath.isEmpty()) {
+ actionPath << text;
+ for (const QString &entry : entryPath) {
+ const QRegularExpression re(".*" + entry + ".*",
+ QRegularExpression::CaseInsensitiveOption);
+ pathIndex = actionPath.indexOf(re, pathIndex);
+ if (pathIndex < 0)
+ return entries;
+ }
+ const QString &lastEntry(entryPath.last());
+ entryLength = lastEntry.length();
+ entryIndex = text.indexOf(lastEntry, 0, Qt::CaseInsensitive);
+ if (entryIndex >= 0) {
+ highlightType = LocatorFilterEntry::HighlightInfo::DisplayName;
+ } else {
+ entryIndex = pathText.indexOf(lastEntry, 0, Qt::CaseInsensitive);
+ QTC_ASSERT(entryIndex >= 0, return entries);
+ highlightType = LocatorFilterEntry::HighlightInfo::ExtraInfo;
+ }
+ }
+ LocatorFilterEntry filterEntry(this, text, QVariant(), action->icon());
+ filterEntry.internalData.setValue(QPointer<QAction>(action));
+ filterEntry.extraInfo = pathText;
+ filterEntry.highlightInfo = {entryIndex, entryLength, highlightType};
+ entries << filterEntry;
+ }
+ return entries;
+}
+
+static void requestMenuUpdate(const QAction* action)
+{
+ if (QMenu *menu = action->menu()) {
+ emit menu->aboutToShow();
+ const QList<QAction *> &actions = menu->actions();
+ for (const QAction *menuActions : actions)
+ requestMenuUpdate(menuActions);
+ }
+}
+
+void Core::Internal::MenuBarFilter::prepareSearch(const QString &entry)
+{
+ Q_UNUSED(entry);
+ for (const QAction *action : menuBarActions())
+ requestMenuUpdate(action);
+}
diff --git a/src/plugins/coreplugin/menubarfilter.h b/src/plugins/coreplugin/menubarfilter.h
new file mode 100644
index 00000000000..9251df7da26
--- /dev/null
+++ b/src/plugins/coreplugin/menubarfilter.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <coreplugin/locator/ilocatorfilter.h>
+
+QT_BEGIN_NAMESPACE
+class QAction;
+class QMenu;
+QT_END_NAMESPACE
+
+namespace Core {
+namespace Internal {
+
+class MenuBarFilter : public ILocatorFilter
+{
+public:
+ MenuBarFilter();
+
+ QList<LocatorFilterEntry> matchesFor(QFutureInterface<LocatorFilterEntry> &future,
+ const QString &entry) override;
+ void accept(LocatorFilterEntry selection, QString *newText,
+ int *selectionStart, int *selectionLength) const override;
+ void refresh(QFutureInterface<void> &future) override;
+ void prepareSearch(const QString &entry) override;
+private:
+ QList<LocatorFilterEntry> matchesForAction(QAction *action,
+ const QStringList &entryPath,
+ const QStringList &path,
+ QVector<const QMenu *> &processedMenus);
+
+};
+
+} // namespace Internal
+} // namespace Core
diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro
index 0bc3391ce81..74b1daf63b3 100644
--- a/src/plugins/cppeditor/cppeditor.pro
+++ b/src/plugins/cppeditor/cppeditor.pro
@@ -12,10 +12,8 @@ HEADERS += \
cppeditorenums.h \
cppeditorplugin.h \
cppeditorwidget.h \
- cppelementevaluator.h \
cppfunctiondecldeflink.h \
cpphighlighter.h \
- cpphoverhandler.h \
cppparsecontext.h \
cppincludehierarchy.h \
cppinsertvirtualmethods.h \
@@ -38,10 +36,8 @@ SOURCES += \
cppeditordocument.cpp \
cppeditorplugin.cpp \
cppeditorwidget.cpp \
- cppelementevaluator.cpp \
cppfunctiondecldeflink.cpp \
cpphighlighter.cpp \
- cpphoverhandler.cpp \
cppparsecontext.cpp \
cppincludehierarchy.cpp \
cppinsertvirtualmethods.cpp \
diff --git a/src/plugins/cppeditor/cppeditor.qbs b/src/plugins/cppeditor/cppeditor.qbs
index 5d8b17adb41..5a44f175eb2 100644
--- a/src/plugins/cppeditor/cppeditor.qbs
+++ b/src/plugins/cppeditor/cppeditor.qbs
@@ -39,14 +39,10 @@ QtcPlugin {
"cppeditorenums.h",
"cppeditorplugin.cpp",
"cppeditorplugin.h",
- "cppelementevaluator.cpp",
- "cppelementevaluator.h",
"cppfunctiondecldeflink.cpp",
"cppfunctiondecldeflink.h",
"cpphighlighter.cpp",
"cpphighlighter.h",
- "cpphoverhandler.cpp",
- "cpphoverhandler.h",
"cppincludehierarchy.cpp",
"cppincludehierarchy.h",
"cppinsertvirtualmethods.cpp",
diff --git a/src/plugins/cppeditor/cppeditordocument.cpp b/src/plugins/cppeditor/cppeditordocument.cpp
index f168f1810b3..3fcbda6a1ee 100644
--- a/src/plugins/cppeditor/cppeditordocument.cpp
+++ b/src/plugins/cppeditor/cppeditordocument.cpp
@@ -394,7 +394,7 @@ const MinimizableInfoBars &CppEditorDocument::minimizableInfoBars() const
CppTools::BaseEditorDocumentProcessor *CppEditorDocument::processor()
{
if (!m_processor) {
- m_processor.reset(mm()->editorDocumentProcessor(this));
+ m_processor.reset(mm()->createEditorDocumentProcessor(this));
connect(m_processor.data(), &CppTools::BaseEditorDocumentProcessor::projectPartInfoUpdated,
[this] (const CppTools::ProjectPartInfo &info)
{
diff --git a/src/plugins/cppeditor/cppeditorplugin.cpp b/src/plugins/cppeditor/cppeditorplugin.cpp
index 3f352f1ffe8..27cbf4827e5 100644
--- a/src/plugins/cppeditor/cppeditorplugin.cpp
+++ b/src/plugins/cppeditor/cppeditorplugin.cpp
@@ -31,7 +31,6 @@
#include "cppeditorwidget.h"
#include "cppeditordocument.h"
#include "cpphighlighter.h"
-#include "cpphoverhandler.h"
#include "cppincludehierarchy.h"
#include "cppoutline.h"
#include "cppquickfixassistant.h"
@@ -53,6 +52,7 @@
#include <coreplugin/icore.h>
#include <coreplugin/navigationwidget.h>
#include <coreplugin/progressmanager/progressmanager.h>
+#include <cpptools/cpphoverhandler.h>
#include <cpptools/cpptoolsconstants.h>
#include <texteditor/texteditoractionhandler.h>
#include <texteditor/texteditorconstants.h>
@@ -105,7 +105,7 @@ public:
| TextEditorActionHandler::UnCollapseAll
| TextEditorActionHandler::FollowSymbolUnderCursor);
- addHoverHandler(new CppHoverHandler);
+ addHoverHandler(CppModelManager::instance()->createHoverHandler());
addHoverHandler(new ColorPreviewHoverHandler);
addHoverHandler(new ResourcePreviewHoverHandler);
}
@@ -145,7 +145,6 @@ bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err
{
Q_UNUSED(errorMessage)
- addAutoReleasedObject(new CppEditorFactory);
addAutoReleasedObject(new CppOutlineWidgetFactory);
addAutoReleasedObject(new CppTypeHierarchyFactory);
addAutoReleasedObject(new CppIncludeHierarchyFactory);
@@ -268,6 +267,10 @@ bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err
void CppEditorPlugin::extensionsInitialized()
{
+ // Add the editor factory here instead of in initialize()
+ // so that the Clang Code Model has a chance to hook in.
+ addAutoReleasedObject(new CppEditorFactory);
+
if (!HostOsInfo::isMacHost() && !HostOsInfo::isWindowsHost()) {
FileIconProvider::registerIconOverlayForMimeType(
QIcon(creatorTheme()->imageFile(Theme::IconOverlayCppSource, QLatin1String(":/cppeditor/images/qt_cpp.png"))),
diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp
deleted file mode 100644
index d480c12c61b..00000000000
--- a/src/plugins/cppeditor/cpphoverhandler.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://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 https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://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 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "cpphoverhandler.h"
-
-#include "cppeditorconstants.h"
-#include "cppelementevaluator.h"
-
-#include <coreplugin/helpmanager.h>
-#include <cpptools/baseeditordocumentprocessor.h>
-#include <cpptools/cppmodelmanager.h>
-#include <cpptools/editordocumenthandle.h>
-#include <texteditor/texteditor.h>
-
-#include <utils/textutils.h>
-#include <utils/qtcassert.h>
-#include <utils/tooltip/tooltip.h>
-
-#include <QTextCursor>
-#include <QUrl>
-#include <QVBoxLayout>
-
-using namespace Core;
-using namespace TextEditor;
-
-namespace {
-
-CppTools::BaseEditorDocumentProcessor *editorDocumentProcessor(TextEditorWidget *editorWidget)
-{
- const QString filePath = editorWidget->textDocument()->filePath().toString();
- auto cppModelManager = CppTools::CppModelManager::instance();
- CppTools::CppEditorDocumentHandle *editorHandle = cppModelManager->cppEditorDocument(filePath);
-
- if (editorHandle)
- return editorHandle->processor();
-
- return 0;
-}
-
-bool editorDocumentProcessorHasDiagnosticAt(TextEditorWidget *editorWidget, int pos)
-{
- if (CppTools::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) {
- int line, column;
- if (Utils::Text::convertPosition(editorWidget->document(), pos, &line, &column))
- return processor->hasDiagnosticsAt(line, column);
- }
-
- return false;
-}
-
-void processWithEditorDocumentProcessor(TextEditorWidget *editorWidget,
- const QPoint &point,
- int position,
- const QString &helpId)
-{
- if (CppTools::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) {
- int line, column;
- if (Utils::Text::convertPosition(editorWidget->document(), position, &line, &column)) {
- auto layout = new QVBoxLayout;
- layout->setContentsMargins(0, 0, 0, 0);
- layout->setSpacing(2);
- processor->addDiagnosticToolTipToLayout(line, column, layout);
- Utils::ToolTip::show(point, layout, editorWidget, helpId);
- }
- }
-}
-
-} // anonymous namespace
-
-namespace CppEditor {
-namespace Internal {
-
-void CppHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos)
-{
- m_positionForEditorDocumentProcessor = -1;
-
- if (editorDocumentProcessorHasDiagnosticAt(editorWidget, pos)) {
- setPriority(Priority_Diagnostic);
- m_positionForEditorDocumentProcessor = pos;
- return;
- }
-
- QTextCursor tc(editorWidget->document());
- tc.setPosition(pos);
-
- CppElementEvaluator evaluator(editorWidget);
- evaluator.setTextCursor(tc);
- evaluator.execute();
- if (evaluator.hasDiagnosis()) {
- setToolTip(evaluator.diagnosis());
- setPriority(Priority_Diagnostic);
- } else if (evaluator.identifiedCppElement()) {
- const QSharedPointer<CppElement> &cppElement = evaluator.cppElement();
- if (priority() != Priority_Diagnostic) {
- setToolTip(cppElement->tooltip);
- setPriority(cppElement->tooltip.isEmpty() ? Priority_None : Priority_Tooltip);
- }
- QStringList candidates = cppElement->helpIdCandidates;
- candidates.removeDuplicates();
- foreach (const QString &helpId, candidates) {
- if (helpId.isEmpty())
- continue;
-
- const QMap<QString, QUrl> helpLinks = HelpManager::linksForIdentifier(helpId);
- if (!helpLinks.isEmpty()) {
- setLastHelpItemIdentified(HelpItem(helpId,
- cppElement->helpMark,
- cppElement->helpCategory,
- helpLinks));
- break;
- }
- }
- }
-}
-
-void CppHoverHandler::decorateToolTip()
-{
- if (m_positionForEditorDocumentProcessor != -1)
- return;
-
- if (Qt::mightBeRichText(toolTip()))
- setToolTip(toolTip().toHtmlEscaped());
-
- if (priority() != Priority_Diagnostic)
- return;
-
- const HelpItem &help = lastHelpItemIdentified();
- if (help.isValid()) {
- // If Qt is built with a namespace, we still show the tip without it, as
- // it is in the docs and for consistency with the doc extraction mechanism.
- const HelpItem::Category category = help.category();
- const QString &contents = help.extractContent(false);
- if (!contents.isEmpty()) {
- if (category == HelpItem::ClassOrNamespace)
- setToolTip(help.helpId() + contents);
- else
- setToolTip(contents);
- } else if (category == HelpItem::Typedef ||
- category == HelpItem::Enum ||
- category == HelpItem::ClassOrNamespace) {
- // This approach is a bit limited since it cannot be used for functions
- // because the help id doesn't really help in that case.
- QString prefix;
- if (category == HelpItem::Typedef)
- prefix = QLatin1String("typedef ");
- else if (category == HelpItem::Enum)
- prefix = QLatin1String("enum ");
- setToolTip(prefix + help.helpId());
- }
- }
-}
-
-void CppHoverHandler::operateTooltip(TextEditor::TextEditorWidget *editorWidget,
- const QPoint &point)
-{
- if (m_positionForEditorDocumentProcessor == -1) {
- BaseHoverHandler::operateTooltip(editorWidget, point);
- return;
- }
-
- const HelpItem helpItem = lastHelpItemIdentified();
- const QString helpId = helpItem.isValid() ? helpItem.helpId() : QString();
- processWithEditorDocumentProcessor(editorWidget, point, m_positionForEditorDocumentProcessor,
- helpId);
-}
-
-} // namespace Internal
-} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppincludehierarchy.cpp b/src/plugins/cppeditor/cppincludehierarchy.cpp
index 1f5f089181c..22bebf3dafa 100644
--- a/src/plugins/cppeditor/cppincludehierarchy.cpp
+++ b/src/plugins/cppeditor/cppincludehierarchy.cpp
@@ -29,13 +29,13 @@
#include "cppeditorwidget.h"
#include "cppeditorconstants.h"
#include "cppeditorplugin.h"
-#include "cppelementevaluator.h"
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/find/itemviewfind.h>
#include <cpptools/baseeditordocumentprocessor.h>
+#include <cpptools/cppelementevaluator.h>
#include <cpptools/cppmodelmanager.h>
#include <cpptools/cpptoolsbridge.h>
#include <cpptools/editordocumenthandle.h>
diff --git a/src/plugins/cppeditor/cpptypehierarchy.cpp b/src/plugins/cppeditor/cpptypehierarchy.cpp
index 54eaaf2f57c..0b3198d4c9f 100644
--- a/src/plugins/cppeditor/cpptypehierarchy.cpp
+++ b/src/plugins/cppeditor/cpptypehierarchy.cpp
@@ -28,11 +28,11 @@
#include "cppeditorconstants.h"
#include "cppeditor.h"
#include "cppeditorwidget.h"
-#include "cppelementevaluator.h"
#include "cppeditorplugin.h"
#include <coreplugin/find/itemviewfind.h>
#include <coreplugin/editormanager/editormanager.h>
+#include <cpptools/cppelementevaluator.h>
#include <utils/algorithm.h>
#include <utils/annotateditemdelegate.h>
#include <utils/navigationtreeview.h>
@@ -46,6 +46,7 @@
#include <QVBoxLayout>
using namespace CppEditor;
+using namespace CppTools;
using namespace CppEditor::Internal;
using namespace Utils;
diff --git a/src/plugins/cppeditor/cpptypehierarchy.h b/src/plugins/cppeditor/cpptypehierarchy.h
index 355f87065d9..e99d8a180e8 100644
--- a/src/plugins/cppeditor/cpptypehierarchy.h
+++ b/src/plugins/cppeditor/cpptypehierarchy.h
@@ -47,11 +47,12 @@ class NavigationTreeView;
class AnnotatedItemDelegate;
}
+namespace CppTools { class CppClass; }
+
namespace CppEditor {
namespace Internal {
class CppEditorWidget;
-class CppClass;
class CppTypeHierarchyModel : public QStandardItemModel
{
@@ -75,8 +76,8 @@ public:
void perform();
private:
- typedef QList<CppClass> CppClass::*HierarchyMember;
- void buildHierarchy(const CppClass &cppClass, QStandardItem *parent,
+ typedef QList<CppTools::CppClass> CppTools::CppClass::*HierarchyMember;
+ void buildHierarchy(const CppTools::CppClass &cppClass, QStandardItem *parent,
bool isRoot, HierarchyMember member);
void showNoTypeHierarchyLabel();
void showTypeHierarchy();
diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
index 1f7576c49b1..ef025a61795 100644
--- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
+++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
@@ -27,8 +27,8 @@
#include "cppeditorwidget.h"
#include "cppeditorplugin.h"
#include "cppeditortestcase.h"
-#include "cppelementevaluator.h"
+#include <cpptools/cppelementevaluator.h>
#include <cpptools/cppfollowsymbolundercursor.h>
#include <cpptools/cppvirtualfunctionassistprovider.h>
#include <cpptools/cppvirtualfunctionproposalitem.h>
diff --git a/src/plugins/cpptools/baseeditordocumentprocessor.cpp b/src/plugins/cpptools/baseeditordocumentprocessor.cpp
index 5bffb51a382..20632289c68 100644
--- a/src/plugins/cpptools/baseeditordocumentprocessor.cpp
+++ b/src/plugins/cpptools/baseeditordocumentprocessor.cpp
@@ -97,6 +97,13 @@ void BaseEditorDocumentProcessor::setParserConfig(
parser()->setConfiguration(config);
}
+QFuture<ToolTipInfo> BaseEditorDocumentProcessor::toolTipInfo(const QByteArray &/*codecName*/,
+ int /*line*/,
+ int /*column*/)
+{
+ return QFuture<ToolTipInfo>();
+}
+
void BaseEditorDocumentProcessor::runParser(QFutureInterface<void> &future,
BaseEditorDocumentParser::Ptr parser,
BaseEditorDocumentParser::UpdateParams updateParams)
diff --git a/src/plugins/cpptools/baseeditordocumentprocessor.h b/src/plugins/cpptools/baseeditordocumentprocessor.h
index b3f96d466de..d799c636b25 100644
--- a/src/plugins/cpptools/baseeditordocumentprocessor.h
+++ b/src/plugins/cpptools/baseeditordocumentprocessor.h
@@ -32,6 +32,7 @@
#include "cpptools_global.h"
#include <texteditor/codeassist/assistinterface.h>
+#include <texteditor/helpitem.h>
#include <texteditor/quickfix.h>
#include <texteditor/texteditor.h>
#include <texteditor/textdocument.h>
@@ -48,6 +49,18 @@ class TextDocument;
namespace CppTools {
+// For clang code model only, move?
+struct CPPTOOLS_EXPORT ToolTipInfo {
+ QString text;
+ QString briefComment;
+
+ QStringList qDocIdCandidates;
+ QString qDocMark;
+ TextEditor::HelpItem::Category qDocCategory;
+
+ QString sizeInBytes;
+};
+
class CPPTOOLS_EXPORT BaseEditorDocumentProcessor : public QObject
{
Q_OBJECT
@@ -78,6 +91,7 @@ public:
virtual QFuture<CursorInfo> cursorInfo(const CursorInfoParams &params) = 0;
virtual QFuture<CursorInfo> requestLocalReferences(const QTextCursor &cursor) = 0;
virtual QFuture<SymbolInfo> requestFollowSymbol(int line, int column) = 0;
+ virtual QFuture<ToolTipInfo> toolTipInfo(const QByteArray &codecName, int line, int column);
public:
using HeaderErrorDiagnosticWidgetCreator = std::function<QWidget*()>;
diff --git a/src/plugins/cppeditor/cppelementevaluator.cpp b/src/plugins/cpptools/cppelementevaluator.cpp
index 1e95850a18a..3281783ef26 100644
--- a/src/plugins/cppeditor/cppelementevaluator.cpp
+++ b/src/plugins/cpptools/cppelementevaluator.cpp
@@ -42,8 +42,7 @@
using namespace CPlusPlus;
-namespace CppEditor {
-namespace Internal {
+namespace CppTools {
static QStringList stripName(const QString &name)
{
@@ -471,5 +470,4 @@ CppEnumerator::CppEnumerator(EnumeratorDeclaration *declaration)
tooltip.append(QLatin1String(" = ") + enumeratorValue);
}
-} // namespace Internal
-} // namespace CppEditor
+} // namespace CppTools
diff --git a/src/plugins/cppeditor/cppelementevaluator.h b/src/plugins/cpptools/cppelementevaluator.h
index 91ef68e2d89..af994989edc 100644
--- a/src/plugins/cppeditor/cppelementevaluator.h
+++ b/src/plugins/cpptools/cppelementevaluator.h
@@ -25,6 +25,8 @@
#pragma once
+#include "cpptools_global.h"
+
#include <texteditor/texteditor.h>
#include <texteditor/helpitem.h>
@@ -41,14 +43,11 @@ class LookupItem;
class LookupContext;
}
-namespace CppTools { class CppModelManager; }
-
-namespace CppEditor {
-namespace Internal {
-
+namespace CppTools {
class CppElement;
+class CppModelManager;
-class CppElementEvaluator
+class CPPTOOLS_EXPORT CppElementEvaluator
{
public:
explicit CppElementEvaluator(TextEditor::TextEditorWidget *editor);
@@ -82,7 +81,7 @@ private:
QString m_diagnosis;
};
-class CppElement
+class CPPTOOLS_EXPORT CppElement
{
protected:
CppElement();
@@ -189,5 +188,4 @@ public:
explicit CppEnumerator(CPlusPlus::EnumeratorDeclaration *declaration);
};
-} // namespace Internal
-} // namespace CppEditor
+} // namespace CppTools
diff --git a/src/plugins/cpptools/cpphoverhandler.cpp b/src/plugins/cpptools/cpphoverhandler.cpp
new file mode 100644
index 00000000000..1ff41b7fdc3
--- /dev/null
+++ b/src/plugins/cpptools/cpphoverhandler.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "cpphoverhandler.h"
+
+#include "cppelementevaluator.h"
+
+#include <coreplugin/helpmanager.h>
+#include <texteditor/texteditor.h>
+
+#include <utils/textutils.h>
+
+#include <QTextCursor>
+#include <QUrl>
+
+using namespace Core;
+using namespace TextEditor;
+
+namespace CppTools {
+
+QString CppHoverHandler::tooltipTextForHelpItem(const HelpItem &helpItem)
+{
+ // If Qt is built with a namespace, we still show the tip without it, as
+ // it is in the docs and for consistency with the doc extraction mechanism.
+ const HelpItem::Category category = helpItem.category();
+ const QString &contents = helpItem.extractContent(false);
+ if (!contents.isEmpty()) {
+ if (category == HelpItem::ClassOrNamespace)
+ return helpItem.helpId() + contents;
+ else
+ return contents;
+ } else if (category == HelpItem::Typedef ||
+ category == HelpItem::Enum ||
+ category == HelpItem::ClassOrNamespace) {
+ // This approach is a bit limited since it cannot be used for functions
+ // because the help id doesn't really help in that case.
+ QString prefix;
+ if (category == HelpItem::Typedef)
+ prefix = QLatin1String("typedef ");
+ else if (category == HelpItem::Enum)
+ prefix = QLatin1String("enum ");
+ return prefix + helpItem.helpId();
+ }
+
+ return QString();
+}
+
+void CppHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos)
+{
+ QTextCursor tc(editorWidget->document());
+ tc.setPosition(pos);
+
+ CppElementEvaluator evaluator(editorWidget);
+ evaluator.setTextCursor(tc);
+ evaluator.execute();
+ if (evaluator.hasDiagnosis()) {
+ setToolTip(evaluator.diagnosis());
+ setPriority(Priority_Diagnostic);
+ } else if (evaluator.identifiedCppElement()) {
+ const QSharedPointer<CppElement> &cppElement = evaluator.cppElement();
+ if (priority() != Priority_Diagnostic) {
+ setToolTip(cppElement->tooltip);
+ setPriority(cppElement->tooltip.isEmpty() ? Priority_None : Priority_Tooltip);
+ }
+ QStringList candidates = cppElement->helpIdCandidates;
+ candidates.removeDuplicates();
+ foreach (const QString &helpId, candidates) {
+ if (helpId.isEmpty())
+ continue;
+
+ const QMap<QString, QUrl> helpLinks = HelpManager::linksForIdentifier(helpId);
+ if (!helpLinks.isEmpty()) {
+ setLastHelpItemIdentified(HelpItem(helpId,
+ cppElement->helpMark,
+ cppElement->helpCategory,
+ helpLinks));
+ break;
+ }
+ }
+ }
+}
+
+void CppHoverHandler::decorateToolTip()
+{
+ if (Qt::mightBeRichText(toolTip()))
+ setToolTip(toolTip().toHtmlEscaped());
+
+ if (priority() == Priority_Diagnostic)
+ return;
+
+ const HelpItem &help = lastHelpItemIdentified();
+ if (help.isValid()) {
+ const QString text = tooltipTextForHelpItem(help);
+ if (!text.isEmpty())
+ setToolTip(text);
+ }
+}
+
+} // namespace CppTools
diff --git a/src/plugins/cppeditor/cpphoverhandler.h b/src/plugins/cpptools/cpphoverhandler.h
index accc2751523..edfa6901cf8 100644
--- a/src/plugins/cppeditor/cpphoverhandler.h
+++ b/src/plugins/cpptools/cpphoverhandler.h
@@ -25,21 +25,20 @@
#pragma once
+#include "cpptools_global.h"
+
#include <texteditor/basehoverhandler.h>
-namespace CppEditor {
-namespace Internal {
+namespace CppTools {
-class CppHoverHandler : public TextEditor::BaseHoverHandler
+class CPPTOOLS_EXPORT CppHoverHandler : public TextEditor::BaseHoverHandler
{
+public:
+ static QString tooltipTextForHelpItem(const TextEditor::HelpItem &help);
+
private:
void identifyMatch(TextEditor::TextEditorWidget *editorWidget, int pos) override;
void decorateToolTip() override;
- void operateTooltip(TextEditor::TextEditorWidget *editorWidget, const QPoint &point) override;
-
-private:
- int m_positionForEditorDocumentProcessor = -1;
};
-} // namespace Internal
-} // namespace CppEditor
+} // namespace CppTools
diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp
index ad255459b2c..f1b1d2c2bd0 100644
--- a/src/plugins/cpptools/cppmodelmanager.cpp
+++ b/src/plugins/cpptools/cppmodelmanager.cpp
@@ -1293,10 +1293,15 @@ CppCompletionAssistProvider *CppModelManager::completionAssistProvider() const
return d->m_activeModelManagerSupport->completionAssistProvider();
}
-BaseEditorDocumentProcessor *CppModelManager::editorDocumentProcessor(
- TextEditor::TextDocument *baseTextDocument) const
+TextEditor::BaseHoverHandler *CppModelManager::createHoverHandler() const
{
- return d->m_activeModelManagerSupport->editorDocumentProcessor(baseTextDocument);
+ return d->m_activeModelManagerSupport->createHoverHandler();
+}
+
+BaseEditorDocumentProcessor *CppModelManager::createEditorDocumentProcessor(
+ TextEditor::TextDocument *baseTextDocument) const
+{
+ return d->m_activeModelManagerSupport->createEditorDocumentProcessor(baseTextDocument);
}
void CppModelManager::setIndexingSupport(CppIndexingSupport *indexingSupport)
diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h
index 3eb06eca653..d8b8d2f1922 100644
--- a/src/plugins/cpptools/cppmodelmanager.h
+++ b/src/plugins/cpptools/cppmodelmanager.h
@@ -44,7 +44,10 @@ class IEditor;
}
namespace CPlusPlus { class LookupContext; }
namespace ProjectExplorer { class Project; }
-namespace TextEditor { class TextDocument; }
+namespace TextEditor {
+class BaseHoverHandler;
+class TextDocument;
+} // namespace TextEditor
namespace CppTools {
@@ -172,8 +175,9 @@ public:
void activateClangCodeModel(ModelManagerSupportProvider *modelManagerSupportProvider);
CppCompletionAssistProvider *completionAssistProvider() const;
- BaseEditorDocumentProcessor *editorDocumentProcessor(
- TextEditor::TextDocument *baseTextDocument) const;
+ BaseEditorDocumentProcessor *createEditorDocumentProcessor(
+ TextEditor::TextDocument *baseTextDocument) const;
+ TextEditor::BaseHoverHandler *createHoverHandler() const;
FollowSymbolInterface &followSymbolInterface() const;
void setIndexingSupport(CppIndexingSupport *indexingSupport);
diff --git a/src/plugins/cpptools/cppmodelmanagersupport.h b/src/plugins/cpptools/cppmodelmanagersupport.h
index b1256aa51fa..06102f6007f 100644
--- a/src/plugins/cpptools/cppmodelmanagersupport.h
+++ b/src/plugins/cpptools/cppmodelmanagersupport.h
@@ -30,7 +30,10 @@
#include <QSharedPointer>
#include <QString>
-namespace TextEditor { class TextDocument; }
+namespace TextEditor {
+class TextDocument;
+class BaseHoverHandler;
+} // namespace TextEditor
namespace CppTools {
@@ -48,7 +51,8 @@ public:
virtual ~ModelManagerSupport() = 0;
virtual CppCompletionAssistProvider *completionAssistProvider() = 0;
- virtual BaseEditorDocumentProcessor *editorDocumentProcessor(
+ virtual TextEditor::BaseHoverHandler *createHoverHandler() = 0;
+ virtual BaseEditorDocumentProcessor *createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) = 0;
virtual FollowSymbolInterface &followSymbolInterface() = 0;
virtual RefactoringEngineInterface &refactoringEngineInterface() = 0;
diff --git a/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp b/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp
index 95b98bbdf38..51919955549 100644
--- a/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp
+++ b/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp
@@ -26,6 +26,7 @@
#include "cppcompletionassist.h"
#include "cppmodelmanagersupportinternal.h"
#include "cppfollowsymbolundercursor.h"
+#include "cpphoverhandler.h"
#include "cpprefactoringengine.h"
#include "builtineditordocumentprocessor.h"
@@ -63,7 +64,7 @@ ModelManagerSupportInternal::~ModelManagerSupportInternal()
{
}
-BaseEditorDocumentProcessor *ModelManagerSupportInternal::editorDocumentProcessor(
+BaseEditorDocumentProcessor *ModelManagerSupportInternal::createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument)
{
return new BuiltinEditorDocumentProcessor(baseTextDocument);
@@ -74,6 +75,11 @@ CppCompletionAssistProvider *ModelManagerSupportInternal::completionAssistProvid
return m_completionAssistProvider.data();
}
+TextEditor::BaseHoverHandler *ModelManagerSupportInternal::createHoverHandler()
+{
+ return new CppHoverHandler;
+}
+
FollowSymbolInterface &ModelManagerSupportInternal::followSymbolInterface()
{
return *m_followSymbol;
diff --git a/src/plugins/cpptools/cppmodelmanagersupportinternal.h b/src/plugins/cpptools/cppmodelmanagersupportinternal.h
index 6ac2d4d022c..e2954792ea4 100644
--- a/src/plugins/cpptools/cppmodelmanagersupportinternal.h
+++ b/src/plugins/cpptools/cppmodelmanagersupportinternal.h
@@ -41,7 +41,8 @@ public:
virtual ~ModelManagerSupportInternal();
CppCompletionAssistProvider *completionAssistProvider() final;
- BaseEditorDocumentProcessor *editorDocumentProcessor(
+ TextEditor::BaseHoverHandler *createHoverHandler() final;
+ BaseEditorDocumentProcessor *createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) final;
FollowSymbolInterface &followSymbolInterface() final;
RefactoringEngineInterface &refactoringEngineInterface() final;
diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro
index 4dfc0ceeced..e16e3ec0bcd 100644
--- a/src/plugins/cpptools/cpptools.pro
+++ b/src/plugins/cpptools/cpptools.pro
@@ -32,11 +32,13 @@ HEADERS += \
cppdoxygen.h \
cppeditoroutline.h \
cppeditorwidgetinterface.h \
+ cppelementevaluator.h \
cppfileiterationorder.h \
cppfilesettingspage.h \
cppfindreferences.h \
cppfollowsymbolundercursor.h \
cppfunctionsfilter.h \
+ cpphoverhandler.h \
cppincludesfilter.h \
cppindexingsupport.h \
cpplocalsymbols.h \
@@ -125,11 +127,13 @@ SOURCES += \
cppcurrentdocumentfilter.cpp \
cppeditoroutline.cpp \
cppdoxygen.cpp \
+ cppelementevaluator.cpp \
cppfileiterationorder.cpp \
cppfilesettingspage.cpp \
cppfindreferences.cpp \
cppfollowsymbolundercursor.cpp \
cppfunctionsfilter.cpp \
+ cpphoverhandler.cpp \
cppincludesfilter.cpp \
cppindexingsupport.cpp \
cpplocalsymbols.cpp \
diff --git a/src/plugins/cpptools/cpptools.qbs b/src/plugins/cpptools/cpptools.qbs
index a510f5a21d6..a258ce18a30 100644
--- a/src/plugins/cpptools/cpptools.qbs
+++ b/src/plugins/cpptools/cpptools.qbs
@@ -90,6 +90,8 @@ Project {
"cppeditoroutline.cpp",
"cppeditoroutline.h",
"cppeditorwidgetinterface.h",
+ "cppelementevaluator.cpp",
+ "cppelementevaluator.h",
"cppfileiterationorder.cpp",
"cppfileiterationorder.h",
"cppfilesettingspage.cpp",
@@ -101,6 +103,8 @@ Project {
"cppfollowsymbolundercursor.h",
"cppfunctionsfilter.cpp",
"cppfunctionsfilter.h",
+ "cpphoverhandler.cpp",
+ "cpphoverhandler.h",
"cppincludesfilter.cpp",
"cppincludesfilter.h",
"cppindexingsupport.cpp",
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index a71127e38f0..e0fa782c390 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -3179,7 +3179,8 @@ QWidget *mainWindow()
void raiseWatchersWindow()
{
- return dd->m_mainWindow->raiseDock(DOCKWIDGET_WATCHERS);
+ if (currentEngine()->state() != DebuggerNotReady)
+ dd->m_mainWindow->raiseDock(DOCKWIDGET_WATCHERS);
}
bool isRegistersWindowVisible()
diff --git a/src/plugins/modeleditor/componentviewcontroller.cpp b/src/plugins/modeleditor/componentviewcontroller.cpp
index 1c35e912021..52501649cd8 100644
--- a/src/plugins/modeleditor/componentviewcontroller.cpp
+++ b/src/plugins/modeleditor/componentviewcontroller.cpp
@@ -133,6 +133,7 @@ private:
private:
qmt::ModelController *m_modelController = nullptr;
QMultiHash<QString, Node> m_filePaths;
+ QHash<QString, qmt::MComponent *> m_filePathComponentsMap;
};
void UpdateIncludeDependenciesVisitor::setModelController(qmt::ModelController *modelController)
@@ -161,6 +162,16 @@ void UpdateIncludeDependenciesVisitor::visitMComponent(qmt::MComponent *componen
if (document) {
foreach (const CPlusPlus::Document::Include &include, document->resolvedIncludes()) {
QString includeFilePath = include.resolvedFileName();
+ // replace proxy header with real one
+ CPlusPlus::Document::Ptr includeDocument = snapshot.document(includeFilePath);
+ if (includeDocument) {
+ QList<CPlusPlus::Document::Include> includes = includeDocument->resolvedIncludes();
+ if (includes.count() == 1 &&
+ QFileInfo(includes.at(0).resolvedFileName()).fileName() == QFileInfo(includeFilePath).fileName())
+ {
+ includeFilePath = includes.at(0).resolvedFileName();
+ }
+ }
qmt::MComponent *includeComponent = findComponentFromFilePath(includeFilePath);
if (includeComponent && includeComponent != component) {
// add dependency between components
@@ -312,10 +323,16 @@ void UpdateIncludeDependenciesVisitor::collectElementPaths(const ProjectExplorer
qmt::MComponent *UpdateIncludeDependenciesVisitor::findComponentFromFilePath(const QString &filePath)
{
+ const auto it = m_filePathComponentsMap.find(filePath);
+ if (it != m_filePathComponentsMap.cend())
+ return it.value();
+
FindComponentFromFilePath visitor;
visitor.setFilePath(filePath);
m_modelController->rootPackage()->accept(&visitor);
- return visitor.component();
+ qmt::MComponent *component = visitor.component();
+ m_filePathComponentsMap.insert(filePath, component);
+ return component;
}
bool UpdateIncludeDependenciesVisitor::haveDependency(const qmt::MObject *source,
@@ -390,7 +407,8 @@ void ComponentViewController::createComponentModel(const QString &filePath,
const QString &anchorFolder)
{
d->diagramSceneController->modelController()->startResetModel();
- doCreateComponentModel(filePath, diagram, anchorFolder);
+ doCreateComponentModel(filePath, diagram, anchorFolder, false);
+ doCreateComponentModel(filePath, diagram, anchorFolder, true);
d->diagramSceneController->modelController()->finishResetModel(true);
}
@@ -404,7 +422,8 @@ void ComponentViewController::updateIncludeDependencies(qmt::MPackage *rootPacka
d->diagramSceneController->modelController()->finishResetModel(true);
}
-void ComponentViewController::doCreateComponentModel(const QString &filePath, qmt::MDiagram *diagram, const QString &anchorFolder)
+void ComponentViewController::doCreateComponentModel(const QString &filePath, qmt::MDiagram *diagram,
+ const QString &anchorFolder, bool scanHeaders)
{
for (const QString &fileName : QDir(filePath).entryList(QDir::Files)) {
QString file = filePath + "/" + fileName;
@@ -413,18 +432,20 @@ void ComponentViewController::doCreateComponentModel(const QString &filePath, qm
bool isSource = false;
CppTools::ProjectFile::Kind kind = CppTools::ProjectFile::classify(file);
switch (kind) {
- case CppTools::ProjectFile::AmbiguousHeader:
- case CppTools::ProjectFile::CHeader:
case CppTools::ProjectFile::CSource:
- case CppTools::ProjectFile::CXXHeader:
case CppTools::ProjectFile::CXXSource:
case CppTools::ProjectFile::ObjCSource:
- case CppTools::ProjectFile::ObjCHeader:
case CppTools::ProjectFile::ObjCXXSource:
- case CppTools::ProjectFile::ObjCXXHeader:
case CppTools::ProjectFile::CudaSource:
case CppTools::ProjectFile::OpenCLSource:
- isSource = true;
+ isSource = !scanHeaders;
+ break;
+ case CppTools::ProjectFile::AmbiguousHeader:
+ case CppTools::ProjectFile::CHeader:
+ case CppTools::ProjectFile::CXXHeader:
+ case CppTools::ProjectFile::ObjCHeader:
+ case CppTools::ProjectFile::ObjCXXHeader:
+ isSource = scanHeaders && !isProxyHeader(file);
break;
case CppTools::ProjectFile::Unclassified:
case CppTools::ProjectFile::Unsupported:
@@ -450,9 +471,24 @@ void ComponentViewController::doCreateComponentModel(const QString &filePath, qm
}
for (const QString &fileName : QDir(filePath).entryList(QDir::Dirs|QDir::NoDotAndDotDot)) {
QString file = filePath + "/" + fileName;
- doCreateComponentModel(file, diagram, anchorFolder);
+ doCreateComponentModel(file, diagram, anchorFolder, scanHeaders);
}
}
+bool ComponentViewController::isProxyHeader(const QString &file) const
+{
+ CppTools::CppModelManager *cppModelManager = CppTools::CppModelManager::instance();
+ CPlusPlus::Snapshot snapshot = cppModelManager->snapshot();
+
+ CPlusPlus::Document::Ptr document = snapshot.document(file);
+ if (document) {
+ QList<CPlusPlus::Document::Include> includes = document->resolvedIncludes();
+ if (includes.count() != 1)
+ return false;
+ return QFileInfo(includes.at(0).resolvedFileName()).fileName() == QFileInfo(file).fileName();
+ }
+ return false;
+}
+
} // namespace Internal
} // namespace ModelEditor
diff --git a/src/plugins/modeleditor/componentviewcontroller.h b/src/plugins/modeleditor/componentviewcontroller.h
index 98f4ac0ca6f..584bc55b50d 100644
--- a/src/plugins/modeleditor/componentviewcontroller.h
+++ b/src/plugins/modeleditor/componentviewcontroller.h
@@ -58,8 +58,9 @@ public:
void updateIncludeDependencies(qmt::MPackage *rootPackage);
private:
- void doCreateComponentModel(const QString &filePath,
- qmt::MDiagram *diagram, const QString &anchorFolder);
+ void doCreateComponentModel(const QString &filePath, qmt::MDiagram *diagram,
+ const QString &anchorFolder, bool scanHeaders);
+ bool isProxyHeader(const QString &file) const;
ComponentViewControllerPrivate *d;
};
diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp
index d8806023fb0..f2286bdc3c6 100644
--- a/src/plugins/qtsupport/baseqtversion.cpp
+++ b/src/plugins/qtsupport/baseqtversion.cpp
@@ -382,15 +382,15 @@ QString BaseQtVersion::defaultUnexpandedDisplayName(const FileName &qmakePath, b
QDir dir = qmakePath.toFileInfo().absoluteDir();
do {
const QString dirName = dir.dirName();
- if (dirName == QLatin1String("usr")) { // System-installed Qt.
+ if (dirName == "usr") { // System-installed Qt.
location = QCoreApplication::translate("QtVersion", "System");
break;
}
location = dirName;
// Also skip default checkouts named 'qt'. Parent dir might have descriptive name.
- if (dirName.compare(QLatin1String("bin"), Qt::CaseInsensitive)
- && dirName.compare(QLatin1String("qtbase"), Qt::CaseInsensitive)
- && dirName.compare(QLatin1String("qt"), Qt::CaseInsensitive)) {
+ if (dirName.compare("bin", Qt::CaseInsensitive)
+ && dirName.compare("qtbase", Qt::CaseInsensitive)
+ && dirName.compare("qt", Qt::CaseInsensitive)) {
break;
}
} while (!dir.isRoot() && dir.cdUp());
@@ -527,7 +527,7 @@ QList<Task> BaseQtVersion::validateKit(const Kit *k)
QString qtAbiString;
foreach (const Abi &qtAbi, qtAbis) {
if (!qtAbiString.isEmpty())
- qtAbiString.append(QLatin1Char(' '));
+ qtAbiString.append(' ');
qtAbiString.append(qtAbi.toString());
if (!fullMatch)
@@ -589,13 +589,13 @@ FileName BaseQtVersion::mkspecsPath() const
if (result.isEmpty())
result = FileName::fromUserInput(qmakeProperty("QMAKE_MKSPECS"));
else
- result.appendPath(QLatin1String("mkspecs"));
+ result.appendPath("mkspecs");
return result;
}
FileName BaseQtVersion::qmlBinPath() const
{
- return FileName::fromUserInput(m_mkspecValues.value(QLatin1String("QT.qml.bins")));
+ return FileName::fromUserInput(m_mkspecValues.value("QT.qml.bins"));
}
FileName BaseQtVersion::librarySearchPath() const
@@ -623,13 +623,13 @@ FileNameList BaseQtVersion::directoriesToIgnoreInProjectTree() const
QString BaseQtVersion::qtNamespace() const
{
ensureMkSpecParsed();
- return m_mkspecValues.value(QLatin1String(MKSPEC_VALUE_NAMESPACE));
+ return m_mkspecValues.value(MKSPEC_VALUE_NAMESPACE);
}
QString BaseQtVersion::qtLibInfix() const
{
ensureMkSpecParsed();
- return m_mkspecValues.value(QLatin1String(MKSPEC_VALUE_LIBINFIX));
+ return m_mkspecValues.value(MKSPEC_VALUE_LIBINFIX);
}
bool BaseQtVersion::isFrameworkBuild() const
@@ -655,15 +655,15 @@ void BaseQtVersion::setId(int id)
void BaseQtVersion::fromMap(const QVariantMap &map)
{
- m_id = map.value(QLatin1String(Constants::QTVERSIONID)).toInt();
+ m_id = map.value(Constants::QTVERSIONID).toInt();
if (m_id == -1) // this happens on adding from installer, see updateFromInstaller => get a new unique id
m_id = QtVersionManager::getUniqueId();
- m_unexpandedDisplayName = map.value(QLatin1String(Constants::QTVERSIONNAME)).toString();
- m_isAutodetected = map.value(QLatin1String(QTVERSIONAUTODETECTED)).toBool();
+ m_unexpandedDisplayName = map.value(Constants::QTVERSIONNAME).toString();
+ m_isAutodetected = map.value(QTVERSIONAUTODETECTED).toBool();
if (m_isAutodetected)
- m_autodetectionSource = map.value(QLatin1String(QTVERSIONAUTODETECTIONSOURCE)).toString();
- QString string = map.value(QLatin1String(QTVERSIONQMAKEPATH)).toString();
- if (string.startsWith(QLatin1Char('~')))
+ m_autodetectionSource = map.value(QTVERSIONAUTODETECTIONSOURCE).toString();
+ QString string = map.value(QTVERSIONQMAKEPATH).toString();
+ if (string.startsWith('~'))
string.remove(0, 1).prepend(QDir::homePath());
m_qtSources = Utils::FileName::fromUserInput(
@@ -683,12 +683,12 @@ void BaseQtVersion::fromMap(const QVariantMap &map)
QVariantMap BaseQtVersion::toMap() const
{
QVariantMap result;
- result.insert(QLatin1String(Constants::QTVERSIONID), uniqueId());
- result.insert(QLatin1String(Constants::QTVERSIONNAME), unexpandedDisplayName());
- result.insert(QLatin1String(QTVERSIONAUTODETECTED), isAutodetected());
+ result.insert(Constants::QTVERSIONID, uniqueId());
+ result.insert(Constants::QTVERSIONNAME, unexpandedDisplayName());
+ result.insert(QTVERSIONAUTODETECTED, isAutodetected());
if (isAutodetected())
- result.insert(QLatin1String(QTVERSIONAUTODETECTIONSOURCE), autodetectionSource());
- result.insert(QLatin1String(QTVERSIONQMAKEPATH), qmakeCommand().toString());
+ result.insert(QTVERSIONAUTODETECTIONSOURCE, autodetectionSource());
+ result.insert(QTVERSIONQMAKEPATH, qmakeCommand().toString());
return result;
}
@@ -858,16 +858,16 @@ QString BaseQtVersion::toHtml(bool verbose) const
foreach (const ProKey &key, keys) {
const QString &value = vInfo.value(key).toQString();
QString variableName = key.toQString();
- if (variableName != QLatin1String("QMAKE_MKSPECS")
- && !variableName.endsWith(QLatin1String("/raw"))) {
+ if (variableName != "QMAKE_MKSPECS"
+ && !variableName.endsWith("/raw")) {
bool isPath = false;
- if (variableName.contains(QLatin1String("_HOST_"))
- || variableName.contains(QLatin1String("_INSTALL_"))) {
- if (!variableName.endsWith(QLatin1String("/get")))
+ if (variableName.contains("_HOST_")
+ || variableName.contains("_INSTALL_")) {
+ if (!variableName.endsWith("/get"))
continue;
variableName.chop(4);
isPath = true;
- } else if (variableName == QLatin1String("QT_SYSROOT")) {
+ } else if (variableName == "QT_SYSROOT") {
isPath = true;
}
str << "<tr><td><pre>" << variableName << "</pre></td><td>";
@@ -946,7 +946,7 @@ QString BaseQtVersion::findHostBinary(HostBinaries binary) const
switch (binary) {
case Designer:
case Linguist:
- baseDir = m_mkspecValues.value(QLatin1String("QT.designer.bins"));
+ baseDir = m_mkspecValues.value("QT.designer.bins");
break;
case Uic:
case QScxmlc:
@@ -960,33 +960,32 @@ QString BaseQtVersion::findHostBinary(HostBinaries binary) const
if (baseDir.isEmpty())
return QString();
- if (!baseDir.endsWith(QLatin1Char('/')))
- baseDir += QLatin1Char('/');
+ if (!baseDir.endsWith('/'))
+ baseDir += '/';
QStringList possibleCommands;
switch (binary) {
case Designer:
if (HostOsInfo::isMacHost())
- possibleCommands << QLatin1String("Designer.app/Contents/MacOS/Designer");
+ possibleCommands << "Designer.app/Contents/MacOS/Designer";
else
- possibleCommands << HostOsInfo::withExecutableSuffix(QLatin1String("designer"));
+ possibleCommands << HostOsInfo::withExecutableSuffix("designer");
break;
case Linguist:
if (HostOsInfo::isMacHost())
- possibleCommands << QLatin1String("Linguist.app/Contents/MacOS/Linguist");
+ possibleCommands << "Linguist.app/Contents/MacOS/Linguist";
else
- possibleCommands << HostOsInfo::withExecutableSuffix(QLatin1String("linguist"));
+ possibleCommands << HostOsInfo::withExecutableSuffix("linguist");
break;
case Uic:
if (HostOsInfo::isWindowsHost()) {
- possibleCommands << QLatin1String("uic.exe");
+ possibleCommands << "uic.exe";
} else {
- possibleCommands << QLatin1String("uic-qt4") << QLatin1String("uic4")
- << QLatin1String("uic");
+ possibleCommands << "uic-qt4" << "uic4" << "uic";
}
break;
case QScxmlc:
- possibleCommands << HostOsInfo::withExecutableSuffix(QLatin1String("qscxmlc"));
+ possibleCommands << HostOsInfo::withExecutableSuffix("qscxmlc");
break;
default:
Q_ASSERT(false);
@@ -1027,7 +1026,7 @@ void BaseQtVersion::updateMkspec() const
m_mkspec = m_mkspec.relativeChildPath(baseMkspecDir);
// qDebug() << "Setting mkspec to"<<mkspec;
} else {
- FileName sourceMkSpecPath = sourcePath().appendPath(QLatin1String("mkspecs"));
+ FileName sourceMkSpecPath = sourcePath().appendPath("mkspecs");
if (m_mkspec.isChildOf(sourceMkSpecPath)) {
m_mkspec = m_mkspec.relativeChildPath(sourceMkSpecPath);
} else {
@@ -1062,25 +1061,25 @@ void BaseQtVersion::ensureMkSpecParsed() const
void BaseQtVersion::parseMkSpec(ProFileEvaluator *evaluator) const
{
- m_configValues = evaluator->values(QLatin1String("CONFIG"));
- m_qtConfigValues = evaluator->values(QLatin1String("QT_CONFIG"));
+ m_configValues = evaluator->values("CONFIG");
+ m_qtConfigValues = evaluator->values("QT_CONFIG");
m_defaultConfigIsDebugAndRelease = false;
m_frameworkBuild = false;
foreach (const QString &value, m_configValues) {
- if (value == QLatin1String("debug"))
+ if (value == "debug")
m_defaultConfigIsDebug = true;
- else if (value == QLatin1String("release"))
+ else if (value == "release")
m_defaultConfigIsDebug = false;
- else if (value == QLatin1String("build_all"))
+ else if (value == "build_all")
m_defaultConfigIsDebugAndRelease = true;
- else if (value == QLatin1String("qt_framework"))
+ else if (value == "qt_framework")
m_frameworkBuild = true;
}
- const QString designerBins = QLatin1String("QT.designer.bins");
- const QString qmlBins = QLatin1String("QT.qml.bins");
- const QString declarativeBins = QLatin1String("QT.declarative.bins");
- const QString libinfix = QLatin1String(MKSPEC_VALUE_LIBINFIX);
- const QString ns = QLatin1String(MKSPEC_VALUE_NAMESPACE);
+ const QString designerBins = "QT.designer.bins";
+ const QString qmlBins = "QT.qml.bins";
+ const QString declarativeBins = "QT.declarative.bins";
+ const QString libinfix = MKSPEC_VALUE_LIBINFIX;
+ const QString ns = MKSPEC_VALUE_NAMESPACE;
m_mkspecValues.insert(designerBins, evaluator->value(designerBins));
m_mkspecValues.insert(qmlBins, evaluator->value(qmlBins));
m_mkspecValues.insert(declarativeBins, evaluator->value(declarativeBins));
@@ -1123,11 +1122,11 @@ bool BaseQtVersion::hasMkspec(const FileName &spec) const
return true; // default spec of a Qt version
QDir mkspecDir = QDir(QDir::fromNativeSeparators(qmakeProperty("QT_HOST_DATA"))
- + QLatin1String("/mkspecs/"));
+ + "/mkspecs/");
const QString absSpec = mkspecDir.absoluteFilePath(spec.toString());
if (QFileInfo(absSpec).isDir() && QFileInfo(absSpec + "/qmake.conf").isFile())
return true;
- mkspecDir.setPath(sourcePath().toString() + QLatin1String("/mkspecs/"));
+ mkspecDir.setPath(sourcePath().toString() + "/mkspecs/");
const QString absSrcSpec = mkspecDir.absoluteFilePath(spec.toString());
return absSrcSpec != absSpec
&& QFileInfo(absSrcSpec).isDir()
@@ -1239,7 +1238,7 @@ QString BaseQtVersion::qmakeProperty(const QHash<ProKey,ProString> &versionInfo,
variant == PropertyVariantGet ? "/get" : "/src")))).toQString();
if (!val.isNull())
return val;
- return versionInfo.value(ProKey(QString::fromLatin1(name))).toQString();
+ return versionInfo.value(ProKey(name)).toQString();
}
QString BaseQtVersion::qmakeProperty(const QByteArray &name, PropertyVariant variant) const
@@ -1363,7 +1362,7 @@ void BaseQtVersion::populateQmlFileFinder(FileInProjectFinder *finder, const Tar
void BaseQtVersion::addToEnvironment(const Kit *k, Environment &env) const
{
Q_UNUSED(k);
- env.set(QLatin1String("QTDIR"), QDir::toNativeSeparators(qmakeProperty("QT_HOST_DATA")));
+ env.set("QTDIR", QDir::toNativeSeparators(qmakeProperty("QT_HOST_DATA")));
}
// Some Qt versions may require environment settings for qmake to work
@@ -1454,7 +1453,7 @@ static QByteArray runQmakeQuery(const FileName &binary, const Environment &env,
QProcess process;
process.setEnvironment(env.toStringList());
- process.start(binary.toString(), QStringList(QLatin1String("-query")), QIODevice::ReadOnly);
+ process.start(binary.toString(), QStringList("-query"), QIODevice::ReadOnly);
if (!process.waitForStarted()) {
*error = QCoreApplication::translate("QtVersion", "Cannot start \"%1\": %2").arg(binary.toUserOutput()).arg(process.errorString());
@@ -1521,7 +1520,7 @@ FileName BaseQtVersion::mkspecDirectoryFromVersionInfo(const QHash<ProKey, ProSt
QString dataDir = qmakeProperty(versionInfo, "QT_HOST_DATA", PropertyVariantSrc);
if (dataDir.isEmpty())
return FileName();
- return FileName::fromUserInput(dataDir + QLatin1String("/mkspecs"));
+ return FileName::fromUserInput(dataDir + "/mkspecs");
}
FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &versionInfo)
@@ -1533,7 +1532,7 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve
bool qt5 = false;
QString theSpec = qmakeProperty(versionInfo, "QMAKE_XSPEC");
if (theSpec.isEmpty())
- theSpec = QLatin1String("default");
+ theSpec = "default";
else
qt5 = true;
@@ -1544,7 +1543,7 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve
if (HostOsInfo::isWindowsHost()) {
if (!qt5) {
- QFile f2(mkspecFullPath.toString() + QLatin1String("/qmake.conf"));
+ QFile f2(mkspecFullPath.toString() + "/qmake.conf");
if (f2.exists() && f2.open(QIODevice::ReadOnly)) {
while (!f2.atEnd()) {
QByteArray line = f2.readLine();
@@ -1552,16 +1551,16 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve
const QList<QByteArray> &temp = line.split('=');
if (temp.size() == 2) {
QString possibleFullPath = QString::fromLocal8Bit(temp.at(1).trimmed().constData());
- if (possibleFullPath.contains(QLatin1Char('$'))) { // QTBUG-28792
- const QRegularExpression rex(QLatin1String("\\binclude\\(([^)]+)/qmake\\.conf\\)"));
+ if (possibleFullPath.contains('$')) { // QTBUG-28792
+ const QRegularExpression rex("\\binclude\\(([^)]+)/qmake\\.conf\\)");
const QRegularExpressionMatch match = rex.match(QString::fromLocal8Bit(f2.readAll()));
if (match.hasMatch()) {
- possibleFullPath = mkspecFullPath.toString() + QLatin1Char('/')
+ possibleFullPath = mkspecFullPath.toString() + '/'
+ match.captured(1);
}
}
// We sometimes get a mix of different slash styles here...
- possibleFullPath = possibleFullPath.replace(QLatin1Char('\\'), QLatin1Char('/'));
+ possibleFullPath = possibleFullPath.replace('\\', '/');
if (QFileInfo::exists(possibleFullPath)) // Only if the path exists
mkspecFullPath = FileName::fromUserInput(possibleFullPath);
}
@@ -1573,7 +1572,7 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve
}
} else {
if (HostOsInfo::isMacHost()) {
- QFile f2(mkspecFullPath.toString() + QLatin1String("/qmake.conf"));
+ QFile f2(mkspecFullPath.toString() + "/qmake.conf");
if (f2.exists() && f2.open(QIODevice::ReadOnly)) {
while (!f2.atEnd()) {
QByteArray line = f2.readLine();
@@ -1584,7 +1583,7 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve
if (value.contains("XCODE")) {
// we don't want to generate xcode projects...
// qDebug() << "default mkspec is xcode, falling back to g++";
- return baseMkspecDir.appendPath(QLatin1String("macx-g++"));
+ return baseMkspecDir.appendPath("macx-g++");
}
}
break;
@@ -1612,14 +1611,14 @@ FileName BaseQtVersion::sourcePath(const QHash<ProKey, ProString> &versionInfo)
const QString installData = qmakeProperty(versionInfo, "QT_INSTALL_PREFIX");
QString sourcePath = installData;
- QFile qmakeCache(installData + QLatin1String("/.qmake.cache"));
+ QFile qmakeCache(installData + "/.qmake.cache");
if (qmakeCache.exists() && qmakeCache.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream stream(&qmakeCache);
while (!stream.atEnd()) {
QString line = stream.readLine().trimmed();
- if (line.startsWith(QLatin1String("QT_SOURCE_TREE"))) {
- sourcePath = line.split(QLatin1Char('=')).at(1).trimmed();
- if (sourcePath.startsWith(QLatin1String("$$quote("))) {
+ if (line.startsWith("QT_SOURCE_TREE")) {
+ sourcePath = line.split('=').at(1).trimmed();
+ if (sourcePath.startsWith("$$quote(")) {
sourcePath.remove(0, 8);
sourcePath.chop(1);
}
@@ -1636,7 +1635,7 @@ bool BaseQtVersion::isInSourceDirectory(const Utils::FileName &filePath)
if (source.isEmpty())
return false;
QDir dir = QDir(source.toString());
- if (dir.dirName() == QLatin1String("qtbase"))
+ if (dir.dirName() == "qtbase")
dir.cdUp();
return filePath.isChildOf(dir);
}
@@ -1646,7 +1645,7 @@ bool BaseQtVersion::isSubProject(const Utils::FileName &filePath) const
const Utils::FileName &source = sourcePath();
if (!source.isEmpty()) {
QDir dir = QDir(source.toString());
- if (dir.dirName() == QLatin1String("qtbase"))
+ if (dir.dirName() == "qtbase")
dir.cdUp();
if (filePath.isChildOf(dir))
@@ -1720,7 +1719,7 @@ bool BaseQtVersion::isQtQuickCompilerSupported(QString *reason) const
}
const QString qtQuickCompilerExecutable =
- HostOsInfo::withExecutableSuffix(binPath().toString() + QLatin1String("/qtquickcompiler"));
+ HostOsInfo::withExecutableSuffix(binPath().toString() + "/qtquickcompiler");
if (!QFileInfo::exists(qtQuickCompilerExecutable)) {
if (reason)
*reason = QCoreApplication::translate("BaseQtVersion", "This Qt Version does not contain Qt Quick Compiler.");
@@ -1748,22 +1747,22 @@ FileNameList BaseQtVersion::qtCorePaths() const
foreach (const QFileInfo &info, infoList) {
const QString file = info.fileName();
if (info.isDir()
- && file.startsWith(QLatin1String("QtCore"))
- && file.endsWith(QLatin1String(".framework"))) {
+ && file.startsWith("QtCore")
+ && file.endsWith(".framework")) {
// handle Framework
FileName lib(info);
- dynamicLibs.append(lib.appendPath(file.left(file.lastIndexOf(QLatin1Char('.')))));
+ dynamicLibs.append(lib.appendPath(file.left(file.lastIndexOf('.'))));
} else if (info.isReadable()) {
- if (file.startsWith(QLatin1String("libQtCore"))
- || file.startsWith(QLatin1String("libQt5Core"))
- || file.startsWith(QLatin1String("QtCore"))
- || file.startsWith(QLatin1String("Qt5Core"))) {
- if (file.endsWith(QLatin1String(".a")) || file.endsWith(QLatin1String(".lib")))
+ if (file.startsWith("libQtCore")
+ || file.startsWith("libQt5Core")
+ || file.startsWith("QtCore")
+ || file.startsWith("Qt5Core")) {
+ if (file.endsWith(".a") || file.endsWith(".lib"))
staticLibs.append(FileName(info));
- else if (file.endsWith(QLatin1String(".dll"))
+ else if (file.endsWith(".dll")
|| file.endsWith(QString::fromLatin1(".so.") + versionString)
- || file.endsWith(QLatin1String(".so"))
- || file.endsWith(QLatin1Char('.') + versionString + QLatin1String(".dylib")))
+ || file.endsWith(".so")
+ || file.endsWith(QLatin1Char('.') + versionString + ".dylib"))
dynamicLibs.append(FileName(info));
}
}
diff --git a/src/tools/clangbackend/source/clangbackend_global.h b/src/tools/clangbackend/source/clangbackend_global.h
index e62c9a35130..a7ca7859587 100644
--- a/src/tools/clangbackend/source/clangbackend_global.h
+++ b/src/tools/clangbackend/source/clangbackend_global.h
@@ -36,4 +36,9 @@ enum class PreferredTranslationUnit
LastUninitialized,
};
+// CLANG-UPGRADE-CHECK: Remove IS_SUSPEND_SUPPORTED once we require clang >= 7.0
+#if defined(CINDEX_VERSION_HAS_PRETTYDECL_BACKPORTED) || CINDEX_VERSION_MINOR >= 47
+# define IS_PRETTY_DECL_SUPPORTED
+#endif
+
} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangbackendclangipc-source.pri b/src/tools/clangbackend/source/clangbackendclangipc-source.pri
index 3460e9d297d..154b5cc0194 100644
--- a/src/tools/clangbackend/source/clangbackendclangipc-source.pri
+++ b/src/tools/clangbackend/source/clangbackendclangipc-source.pri
@@ -29,10 +29,12 @@ HEADERS += \
$$PWD/clangreparsesupportivetranslationunitjob.h \
$$PWD/clangrequestdocumentannotationsjob.h \
$$PWD/clangrequestreferencesjob.h \
+ $$PWD/clangrequesttooltipjob.h \
$$PWD/clangresumedocumentjob.h \
$$PWD/clangstring.h \
$$PWD/clangsupportivetranslationunitinitializer.h \
$$PWD/clangsuspenddocumentjob.h \
+ $$PWD/clangtooltipinfocollector.h \
$$PWD/clangtranslationunit.h \
$$PWD/clangtranslationunits.h \
$$PWD/clangtranslationunitupdater.h \
@@ -86,8 +88,10 @@ SOURCES += \
$$PWD/clangreparsesupportivetranslationunitjob.cpp \
$$PWD/clangrequestdocumentannotationsjob.cpp \
$$PWD/clangrequestreferencesjob.cpp \
+ $$PWD/clangrequesttooltipjob.cpp \
$$PWD/clangsuspenddocumentjob.cpp \
$$PWD/clangsupportivetranslationunitinitializer.cpp \
+ $$PWD/clangtooltipinfocollector.cpp \
$$PWD/clangtranslationunit.cpp \
$$PWD/clangtranslationunits.cpp \
$$PWD/clangtranslationunitupdater.cpp \
diff --git a/src/tools/clangbackend/source/clangcodemodelserver.cpp b/src/tools/clangbackend/source/clangcodemodelserver.cpp
index 6e3a4290b80..609ac1da85c 100644
--- a/src/tools/clangbackend/source/clangcodemodelserver.cpp
+++ b/src/tools/clangbackend/source/clangcodemodelserver.cpp
@@ -258,6 +258,7 @@ static void fillJobRequest(JobRequest &jobRequest, const MessageType &message)
jobRequest.line = message.line();
jobRequest.column = message.column();
jobRequest.ticketNumber = message.ticketNumber();
+ jobRequest.textCodecName = message.fileContainer().textCodecName();
// The unsaved files might get updater later, so take the current
// revision for the request.
jobRequest.documentRevision = message.fileContainer().documentRevision();
@@ -303,6 +304,25 @@ void ClangCodeModelServer::requestFollowSymbol(const RequestFollowSymbolMessage
}
}
+void ClangCodeModelServer::requestToolTip(const RequestToolTipMessage &message)
+{
+ TIME_SCOPE_DURATION("ClangCodeModelServer::requestToolTip");
+
+ try {
+ const Document document = documents.document(message.fileContainer().filePath(),
+ message.fileContainer().projectPartId());
+ DocumentProcessor processor = documentProcessors().processor(document);
+
+ JobRequest jobRequest = processor.createJobRequest(JobRequest::Type::RequestToolTip);
+ fillJobRequest(jobRequest, message);
+
+ processor.addJob(jobRequest);
+ processor.process();
+ } catch (const std::exception &exception) {
+ qWarning() << "Error in ClangCodeModelServer::requestToolTip:" << exception.what();
+ }
+}
+
void ClangCodeModelServer::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message)
{
qCDebug(serverLog) << "########## updateVisibleTranslationUnits";
diff --git a/src/tools/clangbackend/source/clangcodemodelserver.h b/src/tools/clangbackend/source/clangcodemodelserver.h
index 1591d25743c..98508f348c5 100644
--- a/src/tools/clangbackend/source/clangcodemodelserver.h
+++ b/src/tools/clangbackend/source/clangcodemodelserver.h
@@ -61,6 +61,7 @@ public:
void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) override;
void requestReferences(const RequestReferencesMessage &message) override;
void requestFollowSymbol(const RequestFollowSymbolMessage &message) override;
+ void requestToolTip(const RequestToolTipMessage &message) override;
public: // for tests
const Documents &documentsForTestOnly() const;
diff --git a/src/tools/clangbackend/source/clangjobrequest.cpp b/src/tools/clangbackend/source/clangjobrequest.cpp
index b40ea424257..e2c6f8f6d49 100644
--- a/src/tools/clangbackend/source/clangjobrequest.cpp
+++ b/src/tools/clangbackend/source/clangjobrequest.cpp
@@ -32,6 +32,7 @@
#include "clangreparsesupportivetranslationunitjob.h"
#include "clangrequestdocumentannotationsjob.h"
#include "clangrequestreferencesjob.h"
+#include "clangrequesttooltipjob.h"
#include "clangresumedocumentjob.h"
#include "clangsuspenddocumentjob.h"
#include "clangupdatedocumentannotationsjob.h"
@@ -40,6 +41,7 @@
#include <clangsupport/cmbcodecompletedmessage.h>
#include <clangsupport/followsymbolmessage.h>
#include <clangsupport/referencesmessage.h>
+#include <clangsupport/tooltipmessage.h>
#include <utils/qtcassert.h>
@@ -62,6 +64,7 @@ static const char *JobRequestTypeToText(JobRequest::Type type)
RETURN_TEXT_FOR_CASE(RequestDocumentAnnotations);
RETURN_TEXT_FOR_CASE(RequestReferences);
RETURN_TEXT_FOR_CASE(FollowSymbol);
+ RETURN_TEXT_FOR_CASE(RequestToolTip);
RETURN_TEXT_FOR_CASE(SuspendDocument);
RETURN_TEXT_FOR_CASE(ResumeDocument);
}
@@ -126,6 +129,7 @@ static JobRequest::ExpirationConditions expirationConditionsForType(JobRequest::
return Conditions(Condition::AnythingChanged);
case Type::RequestReferences:
case Type::RequestDocumentAnnotations:
+ case Type::RequestToolTip:
case Type::FollowSymbol:
return Conditions(Condition::DocumentClosed)
| Conditions(Condition::DocumentRevisionChanged);
@@ -153,8 +157,10 @@ static JobRequest::RunConditions conditionsForType(JobRequest::Type type)
Conditions conditions = Conditions(Condition::DocumentUnsuspended)
| Conditions(Condition::DocumentVisible);
- if (type == Type::RequestReferences || type == Type::FollowSymbol)
+ if (type == Type::RequestReferences || type == Type::FollowSymbol
+ || type == Type::RequestToolTip) {
conditions |= Condition::CurrentDocumentRevision;
+ }
if (type != Type::UpdateDocumentAnnotations && type != Type::ParseSupportiveTranslationUnit)
conditions |= Condition::DocumentParsed;
@@ -192,6 +198,8 @@ IAsyncJob *JobRequest::createJob() const
return new RequestDocumentAnnotationsJob();
case JobRequest::Type::RequestReferences:
return new RequestReferencesJob();
+ case JobRequest::Type::RequestToolTip:
+ return new RequestToolTipJob();
case JobRequest::Type::FollowSymbol:
return new FollowSymbolJob();
case JobRequest::Type::SuspendDocument:
@@ -224,6 +232,11 @@ void JobRequest::cancelJob(ClangCodeModelClientInterface &client) const
false,
ticketNumber));
break;
+ case JobRequest::Type::RequestToolTip:
+ client.tooltip(ToolTipMessage(FileContainer(),
+ ToolTipInfo(),
+ ticketNumber));
+ break;
case JobRequest::Type::CompleteCode:
client.codeCompleted(CodeCompletedMessage(CodeCompletions(),
CompletionCorrection::NoCorrection,
diff --git a/src/tools/clangbackend/source/clangjobrequest.h b/src/tools/clangbackend/source/clangjobrequest.h
index 4b79f22792e..81c78ba9dbc 100644
--- a/src/tools/clangbackend/source/clangjobrequest.h
+++ b/src/tools/clangbackend/source/clangjobrequest.h
@@ -59,6 +59,7 @@ public:
RequestDocumentAnnotations,
RequestReferences,
FollowSymbol,
+ RequestToolTip,
SuspendDocument,
ResumeDocument,
@@ -118,6 +119,7 @@ public:
qint32 funcNameStartLine = -1;
qint32 funcNameStartColumn = -1;
quint64 ticketNumber = 0;
+ Utf8String textCodecName;
bool localReferences = false;
};
diff --git a/src/tools/clangbackend/source/clangrequesttooltipjob.cpp b/src/tools/clangbackend/source/clangrequesttooltipjob.cpp
new file mode 100644
index 00000000000..0e1249e4e8b
--- /dev/null
+++ b/src/tools/clangbackend/source/clangrequesttooltipjob.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangrequesttooltipjob.h"
+
+#include <clangsupport/clangsupportdebugutils.h>
+#include <clangsupport/clangcodemodelclientinterface.h>
+#include <clangsupport/tooltipmessage.h>
+
+#include <utils/qtcassert.h>
+
+namespace ClangBackEnd {
+
+IAsyncJob::AsyncPrepareResult RequestToolTipJob::prepareAsyncRun()
+{
+ const JobRequest jobRequest = context().jobRequest;
+ QTC_ASSERT(jobRequest.type == JobRequest::Type::RequestToolTip, return AsyncPrepareResult());
+ QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
+
+ const TranslationUnit translationUnit = *m_translationUnit;
+ const UnsavedFiles unsavedFiles = *context().unsavedFiles;
+ const quint32 line = jobRequest.line;
+ const quint32 column = jobRequest.column;
+ const Utf8String textCodecName = jobRequest.textCodecName;
+ setRunner([translationUnit, unsavedFiles, line, column, textCodecName]() {
+ TIME_SCOPE_DURATION("RequestToolTipJobRunner");
+
+ UnsavedFiles theUnsavedFiles = unsavedFiles;
+ return translationUnit.tooltip(theUnsavedFiles, textCodecName, line, column);
+ });
+ return AsyncPrepareResult{translationUnit.id()};
+}
+
+void RequestToolTipJob::finalizeAsyncRun()
+{
+ if (!context().isOutdated()) {
+ const AsyncResult result = asyncResult();
+
+ context().client->tooltip(ToolTipMessage(m_pinnedFileContainer,
+ result,
+ context().jobRequest.ticketNumber));
+ }
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangrequesttooltipjob.h b/src/tools/clangbackend/source/clangrequesttooltipjob.h
new file mode 100644
index 00000000000..eb121402cb2
--- /dev/null
+++ b/src/tools/clangbackend/source/clangrequesttooltipjob.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <clangsupport/tooltipinfo.h>
+
+#include "clangdocumentjob.h"
+
+namespace ClangBackEnd {
+
+class RequestToolTipJob : public DocumentJob<ToolTipInfo>
+{
+public:
+ using AsyncResult = ToolTipInfo;
+
+ AsyncPrepareResult prepareAsyncRun() override;
+ void finalizeAsyncRun() override;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangtooltipinfocollector.cpp b/src/tools/clangbackend/source/clangtooltipinfocollector.cpp
new file mode 100644
index 00000000000..44dde1edbbc
--- /dev/null
+++ b/src/tools/clangbackend/source/clangtooltipinfocollector.cpp
@@ -0,0 +1,531 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangtooltipinfocollector.h"
+
+#include "clangbackend_global.h"
+#include "clangstring.h"
+#include "cursor.h"
+#include "sourcerange.h"
+#include "unsavedfiles.h"
+#include "unsavedfile.h"
+
+#include <clangsupport/sourcerangecontainer.h>
+#include <utils/qtcassert.h>
+#include <utils/textfileformat.h>
+
+#include <utf8string.h>
+
+#include <QDebug>
+#include <QDir>
+#include <QTextCodec>
+
+namespace ClangBackEnd {
+
+namespace {
+
+Utf8StringVector qualificationPrefixAsVector(const Cursor &cursor)
+{
+ Utf8StringVector result;
+
+ for (Cursor parent = cursor.semanticParent();
+ parent.isValid() && (parent.kind() == CXCursor_Namespace || parent.isCompoundType());
+ parent = parent.semanticParent()) {
+ result.prepend(parent.spelling());
+ }
+
+ return result;
+}
+
+Utf8String qualificationPrefix(const Cursor &cursor)
+{
+ // TODO: Implement with qualificationPrefixAsVector()
+ Utf8String qualifiedName;
+
+ for (Cursor parent = cursor.semanticParent();
+ parent.isValid() && (parent.kind() == CXCursor_Namespace);
+ parent = parent.semanticParent()) {
+ qualifiedName = parent.spelling() + Utf8StringLiteral("::") + qualifiedName;
+ }
+
+ return qualifiedName;
+}
+
+Utf8String displayName(const Cursor &cursor)
+{
+ if (cursor.kind() == CXCursor_ClassTemplate) {
+ // TODO: The qualification should be part of the display name. Fix this in libclang.
+ return qualificationPrefix(cursor) + cursor.displayName();
+ }
+
+ return cursor.displayName();
+}
+
+Utf8String textForFunctionLike(const Cursor &cursor)
+{
+#ifdef IS_PRETTY_DECL_SUPPORTED
+ CXPrintingPolicy policy = clang_getCursorPrintingPolicy(cursor.cx());
+ clang_PrintingPolicy_setProperty(policy, CXPrintingPolicy_FullyQualifiedName, 1);
+ clang_PrintingPolicy_setProperty(policy, CXPrintingPolicy_TerseOutput, 1);
+ // Avoid printing attributes/pragmas
+ clang_PrintingPolicy_setProperty(policy, CXPrintingPolicy_PolishForDeclaration, 1);
+ clang_PrintingPolicy_setProperty(policy, CXPrintingPolicy_SuppressInitializers, 1);
+ const Utf8String prettyPrinted = ClangString(
+ clang_getCursorPrettyPrinted(cursor.cx(), policy));
+ clang_PrintingPolicy_dispose(policy);
+ return prettyPrinted;
+#else
+ // Printing function declarations with displayName() is quite limited:
+ // * result type is not included
+ // * parameter names are not included
+ // * templates in the result type are not included
+ // * no full qualification of the function name
+ return Utf8String(cursor.resultType().spelling())
+ + Utf8StringLiteral(" ")
+ + qualificationPrefix(cursor)
+ + Utf8String(cursor.displayName());
+#endif
+}
+
+Utf8String textForEnumConstantDecl(const Cursor &cursor)
+{
+ const Cursor semanticParent = cursor.semanticParent();
+ QTC_ASSERT(semanticParent.kind() == CXCursor_EnumDecl, return Utf8String());
+
+ const Type enumType = semanticParent.enumType();
+ if (enumType.isUnsigned())
+ return Utf8String::number(cursor.enumConstantUnsignedValue());
+ return Utf8String::number(cursor.enumConstantValue());
+}
+
+Utf8String textForInclusionDirective(const Cursor &cursor)
+{
+ const CXFile includedFile = cursor.includedFile();
+ const Utf8String fileName = ClangString(clang_getFileName(includedFile));
+
+ return QDir::toNativeSeparators(fileName.toString());
+}
+
+Utf8String textForAnyTypeAlias(const Cursor &cursor)
+{
+ // For a CXCursor_TypeAliasTemplateDecl the type of cursor/referenced
+ // is invalid, so we do not get the underlying type. This here solely
+ // reports the unresolved name instead of the empty string.
+ if (cursor.kind() == CXCursor_TypeAliasTemplateDecl)
+ return cursor.displayName();
+
+ return cursor.type().alias().utf8Spelling();
+}
+
+bool includeSizeForCursor(const Cursor &cursor)
+{
+ return cursor.isCompoundType()
+ || cursor.kind() == CXCursor_EnumDecl
+ || cursor.kind() == CXCursor_UnionDecl
+ || cursor.kind() == CXCursor_FieldDecl;
+}
+
+Utf8String sizeInBytes(const Cursor &cursor)
+{
+ if (includeSizeForCursor(cursor)) {
+ bool ok = false;
+ const long long size = cursor.type().sizeOf(&ok);
+ if (ok)
+ return Utf8String::number(size);
+ }
+
+ return Utf8String();
+}
+
+Cursor referencedCursor(const Cursor &cursor)
+{
+ // Query the referenced cursor directly instead of first testing with cursor.isReference().
+ // cursor.isReference() reports false for e.g. CXCursor_DeclRefExpr or CXCursor_CallExpr
+ // although it returns a valid cursor.
+ const Cursor referenced = cursor.referenced();
+ if (referenced.isValid())
+ return referenced;
+
+ const Cursor definition = cursor.definition();
+ if (definition.isValid())
+ return definition;
+
+ return cursor;
+}
+
+class ToolTipInfoCollector
+{
+public:
+ ToolTipInfoCollector(UnsavedFiles &unsavedFiles,
+ const Utf8String &textCodecName,
+ const Utf8String &mainFilePath,
+ CXTranslationUnit cxTranslationUnit);
+
+ ToolTipInfo collect(uint line, uint column) const;
+
+private:
+ Utf8String text(const Cursor &cursor, const Cursor &referenced) const;
+ Utf8String textForMacroExpansion(const Cursor &cursor) const;
+ Utf8String textForNamespaceAlias(const Cursor &cursor) const;
+
+ ToolTipInfo qDocInfo(const Cursor &cursor) const;
+
+ CXSourceLocation toCXSourceLocation(uint line, uint column) const;
+
+ UnsavedFile unsavedFile(const Utf8String &filePath) const;
+ Utf8String lineRange(const Utf8String &filePath, unsigned fromLine, unsigned toLine) const;
+
+private:
+ UnsavedFiles &m_unsavedFiles;
+ const Utf8String m_textCodecName;
+
+ const Utf8String m_mainFilePath;
+ CXTranslationUnit m_cxTranslationUnit = nullptr;
+
+};
+
+ToolTipInfoCollector::ToolTipInfoCollector(UnsavedFiles &unsavedFiles,
+ const Utf8String &textCodecName,
+ const Utf8String &mainFilePath,
+ CXTranslationUnit cxTranslationUnit)
+ : m_unsavedFiles(unsavedFiles)
+ , m_textCodecName(textCodecName)
+ , m_mainFilePath(mainFilePath)
+ , m_cxTranslationUnit(cxTranslationUnit)
+{
+}
+
+Utf8String ToolTipInfoCollector::text(const Cursor &cursor, const Cursor &referenced) const
+{
+ if (cursor.kind() == CXCursor_MacroExpansion)
+ return textForMacroExpansion(referenced);
+
+ if (referenced.kind() == CXCursor_EnumConstantDecl)
+ return textForEnumConstantDecl(referenced);
+
+ if (referenced.kind() == CXCursor_InclusionDirective)
+ return textForInclusionDirective(referenced);
+
+ if (referenced.kind() == CXCursor_Namespace)
+ return qualificationPrefix(referenced) + referenced.spelling();
+
+ if (referenced.kind() == CXCursor_NamespaceAlias)
+ return textForNamespaceAlias(referenced);
+
+ if (referenced.isAnyTypeAlias())
+ return textForAnyTypeAlias(referenced);
+
+ if (referenced.isFunctionLike())
+ return textForFunctionLike(referenced);
+
+ if (referenced.type().canonical().isBuiltinType())
+ return referenced.type().canonical().builtinTypeToString();
+
+ if (referenced.kind() == CXCursor_VarDecl)
+ return referenced.type().spelling(); // e.g. "Zii<int>"
+
+ const Type referencedType = referenced.type();
+ if (referencedType.isValid()) {
+ // Generally, the type includes the qualification but has this limitations:
+ // * namespace aliases are not resolved
+ // * outer class of a inner template class is not included
+ // The type includes the qualification, but not resolved namespace aliases.
+
+ // For a CXType_Record, this also includes e.g. "const " as prefix.
+ return referencedType.canonical().utf8Spelling();
+ }
+
+ return displayName(referenced);
+}
+
+Utf8String ToolTipInfoCollector::textForMacroExpansion(const Cursor &cursor) const
+{
+ QTC_ASSERT(cursor.kind() == CXCursor_MacroDefinition, return Utf8String());
+
+ const SourceRange sourceRange = cursor.sourceRange();
+ const SourceLocation start = sourceRange.start();
+ const SourceLocation end = sourceRange.end();
+
+ return lineRange(start.filePath(), start.line(), end.line());
+}
+
+Utf8String ToolTipInfoCollector::textForNamespaceAlias(const Cursor &cursor) const
+{
+ // TODO: Add some libclang API to get the aliased name straight away.
+
+ CXToken *cxTokens = nullptr;
+ uint cxTokenCount = 0;
+
+ clang_tokenize(m_cxTranslationUnit, cursor.cxSourceRange(), &cxTokens, &cxTokenCount);
+
+ Utf8String aliasedName;
+ // Start at 3 in order to skip these tokens: namespace X =
+ for (uint i = 3; i < cxTokenCount; ++i)
+ aliasedName += ClangString(clang_getTokenSpelling(m_cxTranslationUnit, cxTokens[i]));
+
+ clang_disposeTokens(m_cxTranslationUnit, cxTokens, cxTokenCount);
+
+ return aliasedName;
+}
+
+static Utf8String typeName(const Type &type)
+{
+ return type.declaration().spelling();
+}
+
+static Utf8String qdocMark(const Cursor &cursor)
+{
+ if (cursor.kind() == CXCursor_ClassTemplate)
+ return cursor.spelling();
+
+ if (cursor.type().kind() == CXType_Enum
+ || cursor.type().kind() == CXType_Typedef
+ || cursor.type().kind() == CXType_Record)
+ return typeName(cursor.type());
+
+ Utf8String text = cursor.displayName();
+ if (cursor.kind() == CXCursor_FunctionDecl) {
+ // TODO: Remove this workaround by fixing this in
+ // libclang with the help of CXPrintingPolicy.
+ text.replace(Utf8StringLiteral("<>"), Utf8String());
+ }
+
+ return text;
+}
+
+static ToolTipInfo::QdocCategory qdocCategory(const Cursor &cursor)
+{
+ if (cursor.isFunctionLike())
+ return ToolTipInfo::Function;
+
+ if (cursor.kind() == CXCursor_MacroDefinition)
+ return ToolTipInfo::Macro;
+
+ if (cursor.kind() == CXCursor_EnumConstantDecl)
+ return ToolTipInfo::Enum;
+
+ if (cursor.type().kind() == CXType_Enum)
+ return ToolTipInfo::Enum;
+
+ if (cursor.kind() == CXCursor_InclusionDirective)
+ return ToolTipInfo::Brief;
+
+ // TODO: Handle CXCursor_NamespaceAlias, too?!
+ if (cursor.kind() == CXCursor_Namespace)
+ return ToolTipInfo::ClassOrNamespace;
+
+ if (cursor.isCompoundType())
+ return ToolTipInfo::ClassOrNamespace;
+
+ if (cursor.kind() == CXCursor_NamespaceAlias)
+ return ToolTipInfo::ClassOrNamespace;
+
+ if (cursor.type().kind() == CXType_Typedef)
+ return ToolTipInfo::Typedef;
+
+ if (cursor.type().kind() == CXType_Record)
+ return ToolTipInfo::ClassOrNamespace;
+
+ if (cursor.kind() == CXCursor_TypeAliasTemplateDecl)
+ return ToolTipInfo::Typedef;
+
+ if (cursor.kind() == CXCursor_ClassTemplate)
+ return ToolTipInfo::ClassOrNamespace;
+
+ return ToolTipInfo::Unknown;
+}
+
+static Utf8String name(const Cursor &cursor)
+{
+ if (cursor.type().kind() == CXType_Record || cursor.kind() == CXCursor_EnumDecl)
+ return typeName(cursor.type());
+
+ return cursor.spelling();
+}
+
+static Utf8StringVector qDocIdCandidates(const Cursor &cursor)
+{
+ Utf8StringVector components = qualificationPrefixAsVector(cursor);
+ if (components.isEmpty())
+ return { name(cursor) };
+
+ components << name(cursor);
+ Utf8StringVector result;
+ Utf8String name;
+ for (auto it = components.rbegin(); it != components.rend(); ++it) {
+ if (name.isEmpty())
+ name = *it;
+ else
+ name = *it + (Utf8StringLiteral("::") + name);
+
+ result.prepend(name);
+ }
+
+ return result;
+}
+
+// TODO: Add libclang API for this?!
+static bool isBuiltinOrPointerToBuiltin(const Type &type)
+{
+ Type theType = type;
+
+ if (theType.isBuiltinType())
+ return true;
+
+ // TODO: Simplify
+ // TODO: Test with **
+ while (theType.pointeeType().isValid()) {
+ theType = theType.pointeeType();
+ if (theType.isBuiltinType())
+ return true;
+ }
+
+ return false;
+}
+
+ToolTipInfo ToolTipInfoCollector::qDocInfo(const Cursor &cursor) const
+{
+ ToolTipInfo result;
+
+ if (isBuiltinOrPointerToBuiltin(cursor.type()))
+ return result;
+
+ result.setQdocIdCandidates(qDocIdCandidates(cursor));
+ result.setQdocMark(qdocMark(cursor));
+ result.setQdocCategory(qdocCategory(cursor));
+
+ if (cursor.type().kind() == CXType_Record) {
+ result.setQdocIdCandidates(qDocIdCandidates(cursor.type().declaration()));
+ return result;
+ }
+
+ if (cursor.kind() == CXCursor_VarDecl || cursor.kind() == CXCursor_FieldDecl) {
+ result.setQdocMark(typeName(cursor.type()));
+ // maybe template instantiation
+ if (cursor.type().kind() == CXType_Unexposed && cursor.type().canonical().kind() == CXType_Record) {
+ result.setQdocIdCandidates(qDocIdCandidates(cursor.type().canonical().declaration()));
+ result.setQdocCategory(ToolTipInfo::ClassOrNamespace);
+ return result;
+ }
+ }
+
+ // TODO: Handle also RValueReference()
+ if (cursor.type().isLValueReference()) {
+ const Cursor pointeeTypeDeclaration = cursor.type().pointeeType().declaration();
+ result.setQdocIdCandidates(qDocIdCandidates(pointeeTypeDeclaration));
+ result.setQdocMark(pointeeTypeDeclaration.spelling());
+ result.setQdocCategory(qdocCategory(pointeeTypeDeclaration));
+ return result;
+ }
+
+ return result;
+}
+
+CXSourceLocation ToolTipInfoCollector::toCXSourceLocation(uint line, uint column) const
+{
+ return clang_getLocation(m_cxTranslationUnit,
+ clang_getFile(m_cxTranslationUnit,
+ m_mainFilePath.constData()),
+ line,
+ column);
+}
+
+UnsavedFile ToolTipInfoCollector::unsavedFile(const Utf8String &filePath) const
+{
+ const UnsavedFile &unsavedFile = m_unsavedFiles.unsavedFile(filePath);
+ if (!unsavedFile.filePath().isEmpty())
+ return unsavedFile;
+
+ // Create an unsaved file with the file content from disk.
+ // TODO: Make use of clang_getFileContents() instead of reading from disk.
+ QTextCodec *codec = QTextCodec::codecForName(m_textCodecName);
+ QByteArray fileContent;
+ QString errorString;
+ using namespace Utils;
+ const TextFileFormat::ReadResult readResult
+ = TextFileFormat::readFileUTF8(filePath.toString(), codec, &fileContent, &errorString);
+ if (readResult != TextFileFormat::ReadSuccess) {
+ qWarning() << "Failed to read file" << filePath << ":" << errorString;
+ return UnsavedFile();
+ }
+
+ return UnsavedFile(filePath, Utf8String::fromByteArray(fileContent));
+}
+
+Utf8String ToolTipInfoCollector::lineRange(const Utf8String &filePath,
+ unsigned fromLine,
+ unsigned toLine) const
+{
+ if (toLine < fromLine)
+ return Utf8String();
+
+ const UnsavedFile file = unsavedFile(filePath);
+ if (file.fileContent().isEmpty())
+ return Utf8String();
+
+ return file.lineRange(fromLine, toLine);
+}
+
+ToolTipInfo ToolTipInfoCollector::collect(uint line, uint column) const
+{
+ const Cursor cursor = clang_getCursor(m_cxTranslationUnit, toCXSourceLocation(line, column));
+ if (!cursor.isValid())
+ return ToolTipInfo(); // E.g. cursor on ifdeffed out range
+
+ const Cursor referenced = referencedCursor(cursor);
+ QTC_CHECK(referenced.isValid());
+
+ ToolTipInfo info;
+ info.setText(text(cursor, referenced));
+ info.setBriefComment(referenced.briefComment());
+
+ {
+ ToolTipInfo qDocToolTipInfo = qDocInfo(referenced);
+ info.setQdocIdCandidates(qDocToolTipInfo.qdocIdCandidates());
+ info.setQdocMark(qDocToolTipInfo.qdocMark());
+ info.setQdocCategory(qDocToolTipInfo.qdocCategory());
+ }
+
+ info.setSizeInBytes(sizeInBytes(cursor));
+
+ return info;
+}
+
+} // anonymous namespace
+
+ToolTipInfo collectToolTipInfo(UnsavedFiles &unsavedFiles,
+ const Utf8String &textCodecName,
+ const Utf8String &mainFilePath,
+ CXTranslationUnit cxTranslationUnit,
+ uint line,
+ uint column)
+{
+ ToolTipInfoCollector collector(unsavedFiles, textCodecName, mainFilePath, cxTranslationUnit);
+ const ToolTipInfo info = collector.collect(line, column);
+
+ return info;
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangtooltipinfocollector.h b/src/tools/clangbackend/source/clangtooltipinfocollector.h
new file mode 100644
index 00000000000..8009aa8bf4a
--- /dev/null
+++ b/src/tools/clangbackend/source/clangtooltipinfocollector.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <utf8string.h>
+
+#include <clangsupport/tooltipinfo.h>
+
+#include <clang-c/Index.h>
+
+namespace ClangBackEnd {
+
+class UnsavedFiles;
+
+ToolTipInfo collectToolTipInfo(UnsavedFiles &unsavedFiles,
+ const Utf8String &textCodecName,
+ const Utf8String &mainFilePath,
+ CXTranslationUnit cxTranslationUnit,
+ uint line,
+ uint column);
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangtranslationunit.cpp b/src/tools/clangbackend/source/clangtranslationunit.cpp
index 94827801136..da06999b614 100644
--- a/src/tools/clangbackend/source/clangtranslationunit.cpp
+++ b/src/tools/clangbackend/source/clangtranslationunit.cpp
@@ -27,6 +27,7 @@
#include "clangbackend_global.h"
#include "clangreferencescollector.h"
+#include "clangtooltipinfocollector.h"
#include "clangtranslationunitupdater.h"
#include "clangfollowsymbol.h"
#include "clangfollowsymboljob.h"
@@ -139,6 +140,20 @@ void TranslationUnit::extractDocumentAnnotations(
skippedSourceRanges = this->skippedSourceRanges().toSourceRangeContainers();
}
+
+ToolTipInfo TranslationUnit::tooltip(UnsavedFiles &unsavedFiles,
+ const Utf8String &textCodecName,
+ uint line,
+ uint column) const
+{
+ return collectToolTipInfo(unsavedFiles,
+ textCodecName,
+ filePath(),
+ m_cxTranslationUnit,
+ line,
+ column);
+}
+
ReferencesResult TranslationUnit::references(uint line, uint column, bool localReferences) const
{
return collectReferences(m_cxTranslationUnit, line, column, localReferences);
diff --git a/src/tools/clangbackend/source/clangtranslationunit.h b/src/tools/clangbackend/source/clangtranslationunit.h
index 76ba3f00551..150645cc362 100644
--- a/src/tools/clangbackend/source/clangtranslationunit.h
+++ b/src/tools/clangbackend/source/clangtranslationunit.h
@@ -41,6 +41,7 @@ class SkippedSourceRanges;
class SourceLocation;
class SourceRange;
class SourceRangeContainer;
+class ToolTipInfo;
class TranslationUnitUpdateInput;
class TranslationUnitUpdateResult;
class UnsavedFiles;
@@ -86,6 +87,10 @@ public:
ReferencesResult references(uint line, uint column, bool localReferences = false) const;
+ ToolTipInfo tooltip(UnsavedFiles &unsavedFiles,
+ const Utf8String &textCodecName,
+ uint line,
+ uint column) const;
DiagnosticSet diagnostics() const;
SourceLocation sourceLocationAt(uint line, uint column) const;
diff --git a/src/tools/clangbackend/source/clangtype.cpp b/src/tools/clangbackend/source/clangtype.cpp
index 8fc09d8c4af..970b9452c1d 100644
--- a/src/tools/clangbackend/source/clangtype.cpp
+++ b/src/tools/clangbackend/source/clangtype.cpp
@@ -84,6 +84,16 @@ bool Type::isBuiltinType() const
return cxType.kind >= CXType_FirstBuiltin && cxType.kind <= CXType_LastBuiltin;
}
+bool Type::isUnsigned() const
+{
+ return cxType.kind == CXType_UChar
+ || cxType.kind == CXType_UShort
+ || cxType.kind == CXType_UInt
+ || cxType.kind == CXType_ULong
+ || cxType.kind == CXType_ULongLong
+ || cxType.kind == CXType_UInt128;
+}
+
Utf8String Type::utf8Spelling() const
{
return ClangString(clang_getTypeSpelling(cxType));
@@ -94,6 +104,83 @@ ClangString Type::spelling() const
return ClangString(clang_getTypeSpelling(cxType));
}
+static const char *builtinTypeToText(CXTypeKind kind)
+{
+ // CLANG-UPGRADE-CHECK: Check for added built-in types.
+
+ switch (kind) {
+ case CXType_Void:
+ return "void";
+ case CXType_Bool:
+ return "bool";
+
+ // See also ${CLANG_REPOSITORY}/lib/Sema/SemaChecking.cpp - IsSameCharType().
+ case CXType_Char_U:
+ case CXType_UChar:
+ return "unsigned char";
+ case CXType_Char_S:
+ case CXType_SChar:
+ return "signed char";
+
+ case CXType_Char16:
+ return "char16_t";
+ case CXType_Char32:
+ return "char32_t";
+ case CXType_WChar:
+ return "wchar_t";
+
+ case CXType_UShort:
+ return "unsigned short";
+ case CXType_UInt:
+ return "unsigned int";
+ case CXType_ULong:
+ return "unsigned long";
+ case CXType_ULongLong:
+ return "unsigned long long";
+ case CXType_Short:
+ return "short";
+
+ case CXType_Int:
+ return "int";
+ case CXType_Long:
+ return "long";
+ case CXType_LongLong:
+ return "long long";
+
+ case CXType_Float:
+ return "float";
+ case CXType_Double:
+ return "double";
+ case CXType_LongDouble:
+ return "long double";
+
+ case CXType_NullPtr:
+ return "nullptr_t";
+
+ // https://gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html
+ case CXType_Int128: return "__int128";
+ case CXType_UInt128: return "unsigned __int128";
+
+ // https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html
+ case CXType_Float128: return "__float128";
+ // CLANG-UPGRADE-CHECK: CXType_Float16 available with >= clang-6.0:
+// case CXType_Float16: return "_Float16";
+
+ // https://www.khronos.org/registry/OpenCL/sdk/2.1/docs/man/xhtml/scalarDataTypes.html
+ case CXType_Half:
+ return "half";
+
+ default:
+ return "";
+ }
+}
+
+Utf8String Type::builtinTypeToString() const
+{
+ const char *text = builtinTypeToText(cxType.kind);
+ return Utf8String::fromByteArray(QByteArray::fromRawData(text, strlen(text)));
+}
+
int Type::argumentCount() const
{
return clang_getNumArgTypes(cxType);
@@ -129,6 +216,16 @@ Cursor Type::declaration() const
return clang_getTypeDeclaration(cxType);
}
+long long Type::sizeOf(bool *isValid) const
+{
+ const long long size = clang_Type_getSizeOf(cxType);
+ *isValid = size != CXTypeLayoutError_Invalid
+ && size != CXTypeLayoutError_Incomplete
+ && size != CXTypeLayoutError_Dependent;
+
+ return size;
+}
+
CXTypeKind Type::kind() const
{
return cxType.kind;
diff --git a/src/tools/clangbackend/source/clangtype.h b/src/tools/clangbackend/source/clangtype.h
index f26fe080f6b..6be968d3901 100644
--- a/src/tools/clangbackend/source/clangtype.h
+++ b/src/tools/clangbackend/source/clangtype.h
@@ -53,9 +53,11 @@ public:
bool isReferencingConstant() const;
bool isOutputArgument() const;
bool isBuiltinType() const;
+ bool isUnsigned() const;
Utf8String utf8Spelling() const;
ClangString spelling() const;
+ Utf8String builtinTypeToString() const;
int argumentCount() const;
Type alias() const;
@@ -66,6 +68,8 @@ public:
Cursor declaration() const;
+ long long sizeOf(bool *isValid) const;
+
CXTypeKind kind() const;
private:
diff --git a/src/tools/clangbackend/source/cursor.cpp b/src/tools/clangbackend/source/cursor.cpp
index 6ad50307cdd..41a0465e7a0 100644
--- a/src/tools/clangbackend/source/cursor.cpp
+++ b/src/tools/clangbackend/source/cursor.cpp
@@ -158,6 +158,14 @@ bool Cursor::isTemplateLike() const
Q_UNREACHABLE();
}
+bool Cursor::isAnyTypeAlias() const
+{
+ const CXCursorKind k = kind();
+ return k == CXCursor_TypeAliasDecl
+ || k == CXCursor_TypedefDecl
+ || k == CXCursor_TypeAliasTemplateDecl;
+}
+
bool Cursor::hasFinalFunctionAttribute() const
{
bool hasFinal = false;
@@ -248,11 +256,31 @@ Type Cursor::nonPointerTupe() const
return typeResult;
}
+Type Cursor::enumType() const
+{
+ return clang_getEnumDeclIntegerType(cxCursor);
+}
+
+long long Cursor::enumConstantValue() const
+{
+ return clang_getEnumConstantDeclValue(cxCursor);
+}
+
+unsigned long long Cursor::enumConstantUnsignedValue() const
+{
+ return clang_getEnumConstantDeclUnsignedValue(cxCursor);
+}
+
Cursor Cursor::specializedCursorTemplate() const
{
return clang_getSpecializedCursorTemplate(cxCursor);
}
+CXFile Cursor::includedFile() const
+{
+ return clang_getIncludedFile(cxCursor);
+}
+
SourceLocation Cursor::sourceLocation() const
{
return clang_getCursorLocation(cxCursor);
@@ -341,6 +369,11 @@ Cursor Cursor::functionBase() const
return functionBaseCursor;
}
+Type Cursor::resultType() const
+{
+ return clang_getResultType(type().cxType);
+}
+
Cursor Cursor::argument(int index) const
{
return clang_Cursor_getArgument(cxCursor, index);
@@ -398,6 +431,11 @@ CXCursorKind Cursor::kind() const
return clang_getCursorKind(cxCursor);
}
+CXCursor Cursor::cx() const
+{
+ return cxCursor;
+}
+
bool operator==(const Cursor &first, const Cursor &second)
{
return clang_equalCursors(first.cxCursor, second.cxCursor);
diff --git a/src/tools/clangbackend/source/cursor.h b/src/tools/clangbackend/source/cursor.h
index 6520366b36d..bef5a006f4f 100644
--- a/src/tools/clangbackend/source/cursor.h
+++ b/src/tools/clangbackend/source/cursor.h
@@ -67,6 +67,7 @@ public:
bool isFunctionLike() const;
bool isConstructorOrDestructor() const;
bool isTemplateLike() const;
+ bool isAnyTypeAlias() const;
bool hasFinalFunctionAttribute() const;
bool hasFinalClassAttribute() const;
bool isUnexposed() const;
@@ -81,6 +82,10 @@ public:
Type type() const;
Type nonPointerTupe() const;
+ Type enumType() const;
+
+ long long enumConstantValue() const;
+ unsigned long long enumConstantUnsignedValue() const;
SourceLocation sourceLocation() const;
CXSourceLocation cxSourceLocation() const;
@@ -92,17 +97,19 @@ public:
Cursor definition() const;
Cursor canonical() const;
- Cursor alias() const;
Cursor referenced() const;
Cursor semanticParent() const;
Cursor lexicalParent() const;
Cursor functionBaseDeclaration() const;
Cursor functionBase() const;
+ Type resultType() const;
Cursor argument(int index) const;
unsigned overloadedDeclarationsCount() const;
Cursor overloadedDeclaration(unsigned index) const;
Cursor specializedCursorTemplate() const;
+ CXFile includedFile() const;
+
void collectOutputArgumentRangesTo(
std::vector<CXSourceRange> &outputArgumentRanges) const;
std::vector<CXSourceRange> outputArgumentRanges() const;
@@ -112,6 +119,8 @@ public:
template <class VisitorCallback>
void visit(VisitorCallback visitorCallback) const;
+ CXCursor cx() const;
+
private:
CXCursor cxCursor;
};
diff --git a/src/tools/clangbackend/source/unsavedfile.cpp b/src/tools/clangbackend/source/unsavedfile.cpp
index 923d4456e8a..efcad4cad47 100644
--- a/src/tools/clangbackend/source/unsavedfile.cpp
+++ b/src/tools/clangbackend/source/unsavedfile.cpp
@@ -30,6 +30,8 @@
#include <ostream>
+#include <utils/qtcassert.h>
+
namespace ClangBackEnd {
UnsavedFile::UnsavedFile()
@@ -79,6 +81,25 @@ bool UnsavedFile::hasCharacterAt(uint line, uint column, char character) const
return positionIsOk && hasCharacterAt(utf8Position, character);
}
+Utf8String UnsavedFile::lineRange(uint fromLine, uint toLine) const
+{
+ QTC_ASSERT(fromLine <= toLine, return Utf8String());
+
+ // Find start of first line
+ bool ok = false;
+ const uint fromPosition = toUtf8Position(fromLine, 1, &ok);
+ QTC_ASSERT(ok, return Utf8String());
+
+ // Find end of last line
+ uint toPosition = toUtf8Position(toLine, 1, &ok);
+ QTC_ASSERT(ok, return Utf8String());
+ const uint endPosition = uint(m_fileContent.byteSize());
+ while (toPosition < endPosition && m_fileContent.constData()[toPosition] != '\n')
+ ++toPosition;
+
+ return m_fileContent.mid(int(fromPosition), int(toPosition - fromPosition));
+}
+
bool UnsavedFile::hasCharacterAt(uint position, char character) const
{
if (position < uint(m_fileContent.byteSize()))
diff --git a/src/tools/clangbackend/source/unsavedfile.h b/src/tools/clangbackend/source/unsavedfile.h
index 3021da89b5c..325139d240d 100644
--- a/src/tools/clangbackend/source/unsavedfile.h
+++ b/src/tools/clangbackend/source/unsavedfile.h
@@ -46,6 +46,7 @@ public:
// 1-based line and column
uint toUtf8Position(uint line, uint column, bool *ok) const;
bool hasCharacterAt(uint line, uint column, char character) const;
+ Utf8String lineRange(uint fromLine, uint toLine) const;
// 0-based position
bool hasCharacterAt(uint position, char character) const;
diff --git a/tests/unit/echoserver/echoclangcodemodelserver.cpp b/tests/unit/echoserver/echoclangcodemodelserver.cpp
index 2c0fea98c93..38d2d395444 100644
--- a/tests/unit/echoserver/echoclangcodemodelserver.cpp
+++ b/tests/unit/echoserver/echoclangcodemodelserver.cpp
@@ -98,6 +98,11 @@ void EchoClangCodeModelServer::requestFollowSymbol(const RequestFollowSymbolMess
echoMessage(message);
}
+void EchoClangCodeModelServer::requestToolTip(const RequestToolTipMessage &message)
+{
+ echoMessage(message);
+}
+
void EchoClangCodeModelServer::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message)
{
echoMessage(message);
diff --git a/tests/unit/echoserver/echoclangcodemodelserver.h b/tests/unit/echoserver/echoclangcodemodelserver.h
index 2dc8c30913a..d3452d2d321 100644
--- a/tests/unit/echoserver/echoclangcodemodelserver.h
+++ b/tests/unit/echoserver/echoclangcodemodelserver.h
@@ -47,6 +47,7 @@ public:
void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) override;
void requestReferences(const RequestReferencesMessage &message) override;
void requestFollowSymbol(const RequestFollowSymbolMessage &message) override;
+ void requestToolTip(const RequestToolTipMessage &message) override;
void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override;
private:
diff --git a/tests/unit/unittest/clangtooltipinfo-test.cpp b/tests/unit/unittest/clangtooltipinfo-test.cpp
new file mode 100644
index 00000000000..4f6c9806496
--- /dev/null
+++ b/tests/unit/unittest/clangtooltipinfo-test.cpp
@@ -0,0 +1,628 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "googletest.h"
+#include "rundocumentparse-utility.h"
+
+#include <clangdocument.h>
+#include <clangdocuments.h>
+#include <clangsupport_global.h>
+#include <clangtooltipinfocollector.h>
+#include <clangtranslationunit.h>
+#include <fixitcontainer.h>
+#include <projectpart.h>
+#include <projects.h>
+#include <sourcelocationcontainer.h>
+#include <sourcerangecontainer.h>
+#include <unsavedfiles.h>
+
+#include <utils/qtcassert.h>
+
+#include <clang-c/Index.h>
+
+using ::ClangBackEnd::ProjectPart;
+using ::ClangBackEnd::SourceLocationContainer;
+using ::ClangBackEnd::Document;
+using ::ClangBackEnd::UnsavedFiles;
+using ::ClangBackEnd::ToolTipInfo;
+using ::ClangBackEnd::SourceRangeContainer;
+
+namespace {
+
+#define CHECK_MEMBER(actual, expected, memberName) \
+ if (actual.memberName() != expected.memberName()) { \
+ *result_listener << #memberName " is " + PrintToString(actual.memberName()) \
+ << " and not " + PrintToString(expected.memberName()); \
+ return false; \
+ }
+
+MATCHER_P(IsToolTip, expected, std::string(negation ? "isn't" : "is") + PrintToString(expected))
+{
+ CHECK_MEMBER(arg, expected, text);
+ CHECK_MEMBER(arg, expected, briefComment);
+
+ CHECK_MEMBER(arg, expected, qdocIdCandidates);
+ CHECK_MEMBER(arg, expected, qdocMark);
+ CHECK_MEMBER(arg, expected, qdocCategory);
+
+ CHECK_MEMBER(arg, expected, sizeInBytes);
+
+ return true;
+}
+
+MATCHER_P(IsQdocToolTip, expected, std::string(negation ? "isn't" : "is") + PrintToString(expected))
+{
+ CHECK_MEMBER(arg, expected, qdocIdCandidates);
+ CHECK_MEMBER(arg, expected, qdocMark);
+ CHECK_MEMBER(arg, expected, qdocCategory);
+
+ return true;
+}
+
+#undef CHECK_MEMBER
+
+struct Data {
+ ProjectPart projectPart{Utf8StringLiteral("projectPartId"), {Utf8StringLiteral("-std=c++14")}};
+ ClangBackEnd::ProjectParts projects;
+ ClangBackEnd::UnsavedFiles unsavedFiles;
+ ClangBackEnd::Documents documents{projects, unsavedFiles};
+ Document document{Utf8StringLiteral(TESTDATA_DIR "/tooltipinfo.cpp"),
+ projectPart,
+ {},
+ documents};
+ UnitTest::RunDocumentParse _1{document};
+};
+
+class ToolTipInfo : public ::testing::Test
+{
+protected:
+ ::ToolTipInfo tooltip(uint line, uint column)
+ {
+ return d->document.translationUnit().tooltip(d->unsavedFiles,
+ Utf8StringLiteral("UTF-8"),
+ line,
+ column);
+ }
+
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+private:
+ static std::unique_ptr<Data> d;
+};
+
+TEST_F(ToolTipInfo, LocalVariableInt)
+{
+ const ::ToolTipInfo actual = tooltip(3, 5);
+
+ ASSERT_THAT(actual, IsToolTip(::ToolTipInfo(Utf8StringLiteral("int"))));
+}
+
+TEST_F(ToolTipInfo, LocalVariablePointerToConstInt)
+{
+ const ::ToolTipInfo actual = tooltip(4, 5);
+
+ ASSERT_THAT(actual, IsToolTip(::ToolTipInfo(Utf8StringLiteral("const int *"))));
+}
+
+TEST_F(ToolTipInfo, LocalParameterVariableConstRefCustomType)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("const Foo &"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("Foo")});
+ expected.setQdocMark(Utf8StringLiteral("Foo"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(12, 12);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, LocalNonParameterVariableConstRefCustomType)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("const Foo"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("Foo")});
+ expected.setQdocMark(Utf8StringLiteral("Foo"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(14, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, MemberVariable)
+{
+ const ::ToolTipInfo actual = tooltip(12, 16);
+
+ ASSERT_THAT(actual, IsToolTip(::ToolTipInfo(Utf8StringLiteral("int"))));
+}
+
+TEST_F(ToolTipInfo, DISABLED_WITHOUT_PRETTYDECL_PATCH(MemberFunctionCall_QualifiedName))
+{
+ const ::ToolTipInfo actual = tooltip(21, 9);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("int Bar::mem()"));
+}
+
+// ChangeLog: Show extra specifiers. For functions e.g.: virtual, inline, explicit, const, volatile
+TEST_F(ToolTipInfo, DISABLED_WITHOUT_PRETTYDECL_PATCH(MemberFunctionCall_ExtraSpecifiers))
+{
+ const ::ToolTipInfo actual = tooltip(22, 9);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("virtual int Bar::virtualConstMem() const"));
+}
+
+TEST_F(ToolTipInfo, MemberFunctionCall_qdocIdCandidates)
+{
+ const ::ToolTipInfo actual = tooltip(21, 9);
+
+ ASSERT_THAT(actual.qdocIdCandidates(), ElementsAre(Utf8StringLiteral("Bar::mem"),
+ Utf8StringLiteral("mem")));
+}
+
+TEST_F(ToolTipInfo, MemberFunctionCall_qdocMark_FIXLIBCLANG_CHECKED)
+{
+ const ::ToolTipInfo actual = tooltip(21, 9);
+
+ ASSERT_THAT(actual.qdocMark(), Utf8StringLiteral("mem()"));
+}
+
+// TODO: Check what is really needed for qdoc before implementing this one.
+TEST_F(ToolTipInfo, DISABLED_MemberFunctionCall_qdocMark_extraSpecifiers)
+{
+ const ::ToolTipInfo actual = tooltip(22, 9);
+
+ ASSERT_THAT(actual.qdocMark(), Utf8StringLiteral("virtualConstMem() const"));
+}
+
+TEST_F(ToolTipInfo, MemberFunctionCall_qdocCategory)
+{
+ const ::ToolTipInfo actual = tooltip(21, 9);
+
+ ASSERT_THAT(actual.qdocCategory(), ::ToolTipInfo::Function);
+}
+
+// TODO: Show the template parameter type, too: "template<typename T>...)"
+TEST_F(ToolTipInfo, DISABLED_WITHOUT_PRETTYDECL_PATCH(TemplateFunctionCall))
+{
+ const ::ToolTipInfo actual = tooltip(30, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("template<> void t<Foo>(int foo)"));
+}
+
+TEST_F(ToolTipInfo, TemplateFunctionCall_qdocIdCandidates)
+{
+ const ::ToolTipInfo actual = tooltip(30, 5);
+
+ ASSERT_THAT(actual.qdocIdCandidates(), ElementsAre(Utf8StringLiteral("t")));
+}
+
+TEST_F(ToolTipInfo, TemplateFunctionCall_qdocMark_FIXLIBCLANG_CHECKED)
+{
+ const ::ToolTipInfo actual = tooltip(30, 5);
+
+ ASSERT_THAT(actual.qdocMark(), Utf8StringLiteral("t(int)"));
+}
+
+TEST_F(ToolTipInfo, TemplateFunctionCall_qdocCategory)
+{
+ const ::ToolTipInfo actual = tooltip(30, 5);
+
+ ASSERT_THAT(actual.qdocCategory(), ::ToolTipInfo::Function);
+}
+
+TEST_F(ToolTipInfo, BriefComment)
+{
+ const ::ToolTipInfo actual = tooltip(41, 5);
+
+ ASSERT_THAT(actual.briefComment(), Utf8StringLiteral("This is a crazy function."));
+}
+
+TEST_F(ToolTipInfo, Enum)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("EnumType"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("EnumType")});
+ expected.setQdocMark(Utf8StringLiteral("EnumType"));
+ expected.setQdocCategory(::ToolTipInfo::Enum);
+
+ const ::ToolTipInfo actual = tooltip(49, 12);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, Enumerator)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("6"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("Custom")});
+ expected.setQdocMark(Utf8StringLiteral("EnumType"));
+ expected.setQdocCategory(::ToolTipInfo::Enum);
+
+ const ::ToolTipInfo actual = tooltip(49, 22);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, TemplateTypeFromParameter)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("const Baz<int> &"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("Baz")});
+ expected.setQdocMark(Utf8StringLiteral("Baz"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(55, 25);
+
+ ASSERT_THAT(actual, IsQdocToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, TemplateTypeFromNonParameter)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("Baz<int>"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("Baz")});
+ expected.setQdocMark(Utf8StringLiteral("Baz"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(56, 19);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, IncludeDirective)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral(TESTDATA_DIR"/tooltipinfo.h"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("tooltipinfo.h")});
+ expected.setQdocMark(Utf8StringLiteral("tooltipinfo.h"));
+ expected.setQdocCategory(::ToolTipInfo::Brief);
+
+ const ::ToolTipInfo actual = tooltip(59, 11);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, MacroUse_WithMacroFromSameFile)
+{
+ const ::ToolTipInfo actual = tooltip(66, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("#define MACRO_FROM_MAINFILE(x) x + 3"));
+}
+
+TEST_F(ToolTipInfo, MacroUse_WithMacroFromHeader)
+{
+ const ::ToolTipInfo actual = tooltip(67, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("#define MACRO_FROM_HEADER(x) x + \\\n x + \\\n x"));
+}
+
+TEST_F(ToolTipInfo, MacroUse_qdoc)
+{
+ ::ToolTipInfo expected;
+ expected.setQdocIdCandidates({Utf8StringLiteral("MACRO_FROM_MAINFILE")});
+ expected.setQdocMark(Utf8StringLiteral("MACRO_FROM_MAINFILE"));
+ expected.setQdocCategory(::ToolTipInfo::Macro);
+
+ const ::ToolTipInfo actual = tooltip(66, 5);
+
+ ASSERT_THAT(actual, IsQdocToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, TypeNameIntroducedByUsingDirectiveIsQualified)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("N::Muu"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("N::Muu"), Utf8StringLiteral("Muu")});
+ expected.setQdocMark(Utf8StringLiteral("Muu"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(77, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, TypeNameIntroducedByUsingDirectiveOfAliasIsResolvedAndQualified)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("N::Muu"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("N::Muu"), Utf8StringLiteral("Muu")});
+ expected.setQdocMark(Utf8StringLiteral("Muu"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(82, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, TypeNameIntroducedByUsingDeclarationIsQualified)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("N::Muu"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("N::Muu"), Utf8StringLiteral("Muu")});
+ expected.setQdocMark(Utf8StringLiteral("Muu"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(87, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, SizeForClassDefinition)
+{
+ const ::ToolTipInfo actual = tooltip(92, 8);
+
+ ASSERT_THAT(actual.sizeInBytes(), Utf8StringLiteral("2"));
+}
+
+TEST_F(ToolTipInfo, SizeForMemberField)
+{
+ const ::ToolTipInfo actual = tooltip(95, 10);
+
+ ASSERT_THAT(actual.sizeInBytes(), Utf8StringLiteral("1"));
+}
+
+TEST_F(ToolTipInfo, SizeForEnum)
+{
+ const ::ToolTipInfo actual = tooltip(97, 12);
+
+ ASSERT_THAT(actual.sizeInBytes(), Utf8StringLiteral("4"));
+}
+
+TEST_F(ToolTipInfo, SizeForUnion)
+{
+ const ::ToolTipInfo actual = tooltip(98, 7);
+
+ ASSERT_THAT(actual.sizeInBytes(), Utf8StringLiteral("1"));
+}
+
+TEST_F(ToolTipInfo, Namespace)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("X"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("X")});
+ expected.setQdocMark(Utf8StringLiteral("X"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(106, 11);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, NamespaceQualified)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("X::Y"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("X::Y"), Utf8StringLiteral("Y")});
+ expected.setQdocMark(Utf8StringLiteral("Y"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(107, 11);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+// TODO: Show unresolved and resolved name, for F1 try both.
+TEST_F(ToolTipInfo, TypeName_ResolveTypeDef)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("Ptr<Nuu>"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("PtrFromTypeDef")});
+ expected.setQdocMark(Utf8StringLiteral("PtrFromTypeDef"));
+ expected.setQdocCategory(::ToolTipInfo::Typedef);
+
+ const ::ToolTipInfo actual = tooltip(122, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+// TODO: Show unresolved and resolved name, for F1 try both.
+TEST_F(ToolTipInfo, TypeName_ResolveAlias)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("Ptr<Nuu>"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("PtrFromTypeAlias")});
+ expected.setQdocMark(Utf8StringLiteral("PtrFromTypeAlias"));
+ expected.setQdocCategory(::ToolTipInfo::Typedef);
+
+ const ::ToolTipInfo actual = tooltip(123, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+// The referenced cursor is a CXCursor_TypeAliasTemplateDecl, its type is invalid
+// and so probably clang_getTypedefDeclUnderlyingType() does not return anything useful.
+// TODO: Fix the cursor's type or add new API in libclang for querying the template type alias.
+TEST_F(ToolTipInfo, DISABLED_TypeName_ResolveTemplateTypeAlias)
+{
+ const ::ToolTipInfo actual = tooltip(124, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("Ptr<Nuu>"));
+}
+
+TEST_F(ToolTipInfo, TypeName_ResolveTemplateTypeAlias_qdoc)
+{
+ ::ToolTipInfo expected;
+ expected.setQdocIdCandidates({Utf8StringLiteral("PtrFromTemplateTypeAlias")});
+ expected.setQdocMark(Utf8StringLiteral("PtrFromTemplateTypeAlias"));
+ expected.setQdocCategory(::ToolTipInfo::Typedef);
+
+ const ::ToolTipInfo actual = tooltip(124, 5);
+
+ ASSERT_THAT(actual, IsQdocToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, TemplateClassReference)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("Zii<T>"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("Zii")});
+ expected.setQdocMark(Utf8StringLiteral("Zii"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(134, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, TemplateClassQualified)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("U::Yii<T>"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("U::Yii"), Utf8StringLiteral("Yii")});
+ expected.setQdocMark(Utf8StringLiteral("Yii"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(135, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, ResolveNamespaceAliasForType)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("A::X"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("A::X"), Utf8StringLiteral("X")});
+ expected.setQdocMark(Utf8StringLiteral("X"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(144, 8);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+// TODO: Show unresolved and resolved name, for F1 try both.
+TEST_F(ToolTipInfo, ResolveNamespaceAlias)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("A"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("B")});
+ expected.setQdocMark(Utf8StringLiteral("B"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(144, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, QualificationForTemplateClassInClassInNamespace)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("N::Outer::Inner<int>"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("N::Outer::Inner"),
+ Utf8StringLiteral("Outer::Inner"),
+ Utf8StringLiteral("Inner")});
+ expected.setQdocMark(Utf8StringLiteral("Inner"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+ expected.setSizeInBytes(Utf8StringLiteral("1"));
+
+ const ::ToolTipInfo actual = tooltip(153, 16);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, Function)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("void f()"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("f")});
+ expected.setQdocMark(Utf8StringLiteral("f()"));
+ expected.setQdocCategory(::ToolTipInfo::Function);
+
+ const ::ToolTipInfo actual = tooltip(165, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, Function_QualifiedName)
+{
+ const ::ToolTipInfo actual = tooltip(166, 8);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("void R::f()"));
+}
+
+TEST_F(ToolTipInfo, Function_qdocIdCandidatesAreQualified)
+{
+ const ::ToolTipInfo actual = tooltip(166, 8);
+
+ ASSERT_THAT(actual.qdocIdCandidates(), ElementsAre(Utf8StringLiteral("R::f"),
+ Utf8StringLiteral("f")));
+}
+
+TEST_F(ToolTipInfo, DISABLED_WITHOUT_PRETTYDECL_PATCH(Function_HasParameterName))
+{
+ const ::ToolTipInfo actual = tooltip(167, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("void f(int param)"));
+}
+
+// TODO: Implement with CXPrintingPolicy
+TEST_F(ToolTipInfo, DISABLED_Function_HasDefaultArgument)
+{
+ const ::ToolTipInfo actual = tooltip(168, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("void z(int = 1)"));
+}
+
+TEST_F(ToolTipInfo, Function_qdocMarkHasNoParameterName)
+{
+ const ::ToolTipInfo actual = tooltip(167, 5);
+
+ ASSERT_THAT(actual.qdocMark(), Utf8StringLiteral("f(int)"));
+}
+
+TEST_F(ToolTipInfo, Function_qdocMarkHasNoDefaultArgument)
+{
+ const ::ToolTipInfo actual = tooltip(168, 5);
+
+ ASSERT_THAT(actual.qdocMark(), Utf8StringLiteral("z(int)"));
+}
+
+TEST_F(ToolTipInfo, AutoTypeBuiltin)
+{
+ const ::ToolTipInfo actual = tooltip(176, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("int"));
+}
+
+// TODO: Test for qdoc entries, too.
+TEST_F(ToolTipInfo, AutoTypeEnum)
+{
+ const ::ToolTipInfo actual = tooltip(177, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("EnumType"));
+}
+
+// TODO: Test for qdoc entries, too.
+TEST_F(ToolTipInfo, AutoTypeClassType)
+{
+ const ::ToolTipInfo actual = tooltip(178, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("Bar"));
+}
+
+// TODO: Test for qdoc entries, too.
+// TODO: Deduced template arguments work, too?!
+TEST_F(ToolTipInfo, AutoTypeClassTemplateType)
+{
+ const ::ToolTipInfo actual = tooltip(179, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("Zii<int>"));
+}
+
+std::unique_ptr<Data> ToolTipInfo::d;
+
+void ToolTipInfo::SetUpTestCase()
+{
+ d.reset(new Data);
+}
+
+void ToolTipInfo::TearDownTestCase()
+{
+ d.reset();
+}
+
+} // anonymous namespace
diff --git a/tests/unit/unittest/conditionally-disabled-tests.h b/tests/unit/unittest/conditionally-disabled-tests.h
index 27e6fe173b2..8f55db10d7a 100644
--- a/tests/unit/unittest/conditionally-disabled-tests.h
+++ b/tests/unit/unittest/conditionally-disabled-tests.h
@@ -33,3 +33,9 @@
#else
# define DISABLED_ON_WINDOWS(x) x
#endif
+
+#ifdef IS_PRETTY_DECL_SUPPORTED
+# define DISABLED_WITHOUT_PRETTYDECL_PATCH(x) x
+#else
+# define DISABLED_WITHOUT_PRETTYDECL_PATCH(x) DISABLED_##x
+#endif
diff --git a/tests/unit/unittest/data/tooltipinfo.cpp b/tests/unit/unittest/data/tooltipinfo.cpp
new file mode 100644
index 00000000000..1945577b635
--- /dev/null
+++ b/tests/unit/unittest/data/tooltipinfo.cpp
@@ -0,0 +1,180 @@
+void f(int foo, const int *cfoo)
+{
+ foo++;
+ cfoo++;
+}
+
+
+
+struct Foo { int member = 0; };
+int g(const Foo &foo)
+{
+ return foo.member;
+ const Foo bar;
+ bar;
+}
+
+struct Bar { virtual ~Bar(); int mem(){} virtual int virtualConstMem() const; };
+void h(const Foo &foo, Bar &bar)
+{
+ g(foo);
+ bar.mem();
+ bar.virtualConstMem();
+}
+
+
+template <typename T>
+void t(int foo) { (void)foo; }
+void c()
+{
+ t<Foo>(3);
+}
+
+
+
+/**
+ * \brief This is a crazy function.
+ */
+void documentedFunction();
+void d()
+{
+ documentedFunction();
+}
+
+
+
+enum EnumType { V1, V2, Custom = V2 + 5 };
+EnumType e()
+{
+ return EnumType::Custom;
+}
+
+
+
+template <typename T> struct Baz { T member; };
+void t2(const Baz<int> &b) {
+ Baz<int> baz; baz = b;
+}
+
+#include "tooltipinfo.h"
+
+
+
+#define MACRO_FROM_MAINFILE(x) x + 3
+void foo()
+{
+ MACRO_FROM_MAINFILE(7);
+ MACRO_FROM_HEADER(7);
+}
+
+
+
+namespace N { struct Muu{}; }
+namespace G = N;
+void o()
+{
+ using namespace N;
+ Muu muu; (void)muu;
+}
+void n()
+{
+ using namespace G;
+ Muu muu; (void)muu;
+}
+void q()
+{
+ using N::Muu;
+ Muu muu; (void)muu;
+}
+
+
+
+struct Sizes
+{
+ char memberChar1;
+ char memberChar2;
+};
+enum class FancyEnumType { V1, V2 };
+union Union
+{
+ char memberChar1;
+ char memberChar2;
+};
+
+
+
+namespace X {
+namespace Y {
+}
+}
+
+
+
+template<typename T> struct Ptr {};
+struct Nuu {};
+
+typedef Ptr<Nuu> PtrFromTypeDef;
+using PtrFromTypeAlias = Ptr<Nuu>;
+template<typename T> using PtrFromTemplateTypeAlias = Ptr<T>;
+
+void y()
+{
+ PtrFromTypeDef b; (void)b;
+ PtrFromTypeAlias a; (void)a;
+ PtrFromTemplateTypeAlias<Nuu> c; (void)c;
+}
+
+
+
+template <typename T> struct Zii {};
+namespace U { template <typename T> struct Yii {}; }
+void mc()
+{
+ using namespace U;
+ Zii<int> zii; (void) zii;
+ Yii<int> yii; (void) yii;
+}
+
+
+
+namespace A { struct X {}; }
+namespace B = A;
+void ab()
+{
+ B::X x; (void)x;
+}
+
+
+
+namespace N {
+struct Outer
+{
+ template <typename T> struct Inner {};
+ Inner<int> inner;
+};
+}
+
+
+
+void f();
+namespace R { void f(); }
+void f(int param);
+void z(int = 1);
+void user()
+{
+ f();
+ R::f();
+ f(1);
+ z();
+}
+
+
+
+
+void autoTypes()
+{
+ auto a = 3; (void)a;
+ auto b = EnumType::V1; (void)b;
+ auto c = Bar(); (void)c;
+ auto d = Zii<int>(); (void)d;
+}
diff --git a/tests/unit/unittest/data/tooltipinfo.h b/tests/unit/unittest/data/tooltipinfo.h
new file mode 100644
index 00000000000..47d3bb92e75
--- /dev/null
+++ b/tests/unit/unittest/data/tooltipinfo.h
@@ -0,0 +1,3 @@
+#define MACRO_FROM_HEADER(x) x + \
+ x + \
+ x
diff --git a/tests/unit/unittest/dummyclangipcclient.h b/tests/unit/unittest/dummyclangipcclient.h
index 3908f9e89f2..e840b0a6c7a 100644
--- a/tests/unit/unittest/dummyclangipcclient.h
+++ b/tests/unit/unittest/dummyclangipcclient.h
@@ -38,4 +38,5 @@ public:
void documentAnnotationsChanged(const ClangBackEnd::DocumentAnnotationsChangedMessage &) override {}
void references(const ClangBackEnd::ReferencesMessage &) override {}
void followSymbol(const ClangBackEnd::FollowSymbolMessage &) override {}
+ void tooltip(const ClangBackEnd::ToolTipMessage &) override {}
};
diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp
index 16e5133c561..dc8edee24b4 100644
--- a/tests/unit/unittest/gtest-creator-printing.cpp
+++ b/tests/unit/unittest/gtest-creator-printing.cpp
@@ -42,6 +42,7 @@
#include <sourcelocationscontainer.h>
#include <tokeninfos.h>
#include <filepathview.h>
+#include <tooltipinfo.h>
#include <cpptools/usages.h>
@@ -290,6 +291,17 @@ std::ostream &operator<<(std::ostream &os, const ReferencesMessage &message)
return os;
}
+std::ostream &operator<<(std::ostream &os, const ToolTipMessage &message)
+{
+ os << "("
+ << message.fileContainer() << ", "
+ << message.ticketNumber() << ", "
+ << message.toolTipInfo() << ", "
+ << ")";
+
+ return os;
+}
+
std::ostream &operator<<(std::ostream &os, const EchoMessage &/*message*/)
{
return os << "()";
@@ -406,7 +418,8 @@ std::ostream &operator<<(std::ostream &os, const FileContainer &container)
<< container.filePath() << ", "
<< container.projectPartId() << ", "
<< container.fileArguments() << ", "
- << container.documentRevision();
+ << container.documentRevision() << ", "
+ << container.textCodecName();
if (container.hasUnsavedFileContent())
os << ", "
@@ -573,6 +586,37 @@ std::ostream &operator<<(std::ostream &os, const RequestReferencesMessage &messa
return os;
}
+std::ostream &operator<<(std::ostream &out, const RequestToolTipMessage &message)
+{
+ out << "("
+ << message.fileContainer() << ", "
+ << message.ticketNumber() << ", "
+ << message.line() << ", "
+ << message.column() << ", "
+ << ")";
+
+ return out;
+}
+
+std::ostream &operator<<(std::ostream &os, const ToolTipInfo::QdocCategory category)
+{
+ return os << qdocCategoryToString(category);
+}
+
+std::ostream &operator<<(std::ostream &out, const ToolTipInfo &info)
+{
+ out << "("
+ << info.m_text << ", "
+ << info.m_briefComment << ", "
+ << info.m_qdocIdCandidates << ", "
+ << info.m_qdocMark << ", "
+ << info.m_qdocCategory
+ << info.m_sizeInBytes << ", "
+ << ")";
+
+ return out;
+}
+
std::ostream &operator<<(std::ostream &os, const RequestSourceLocationsForRenamingMessage &message)
{
diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h
index 072719ff6d1..73848ba8541 100644
--- a/tests/unit/unittest/gtest-creator-printing.h
+++ b/tests/unit/unittest/gtest-creator-printing.h
@@ -79,6 +79,7 @@ class CodeCompletedMessage;
class EchoMessage;
class DocumentAnnotationsChangedMessage;
class ReferencesMessage;
+class ToolTipMessage;
class FollowSymbolMessage;
class CompleteCodeMessage;
class EndMessage;
@@ -103,6 +104,7 @@ class RemovePchProjectPartsMessage;
class RequestDocumentAnnotationsMessage;
class RequestFollowSymbolMessage;
class RequestReferencesMessage;
+class RequestToolTipMessage;
class RequestSourceLocationsForRenamingMessage;
class RequestSourceRangesAndDiagnosticsForQueryMessage;
class RequestSourceRangesForQueryMessage;
@@ -124,6 +126,7 @@ template <char WindowsSlash>
class AbstractFilePathView;
using FilePathView = AbstractFilePathView<'/'>;
using NativeFilePathView = AbstractFilePathView<'\\'>;
+class ToolTipInfo;
std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry);
std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths);
@@ -136,6 +139,7 @@ std::ostream &operator<<(std::ostream &out, const CodeCompletedMessage &message)
std::ostream &operator<<(std::ostream &out, const EchoMessage &message);
std::ostream &operator<<(std::ostream &out, const DocumentAnnotationsChangedMessage &message);
std::ostream &operator<<(std::ostream &out, const ReferencesMessage &message);
+std::ostream &operator<<(std::ostream &out, const ToolTipMessage &message);
std::ostream &operator<<(std::ostream &out, const FollowSymbolMessage &message);
std::ostream &operator<<(std::ostream &out, const CompleteCodeMessage &message);
std::ostream &operator<<(std::ostream &out, const EndMessage &message);
@@ -162,6 +166,8 @@ std::ostream &operator<<(std::ostream &out, const RemovePchProjectPartsMessage &
std::ostream &operator<<(std::ostream &out, const RequestDocumentAnnotationsMessage &message);
std::ostream &operator<<(std::ostream &out, const RequestFollowSymbolMessage &message);
std::ostream &operator<<(std::ostream &out, const RequestReferencesMessage &message);
+std::ostream &operator<<(std::ostream &out, const RequestToolTipMessage &message);
+std::ostream &operator<<(std::ostream &out, const ToolTipInfo &info);
std::ostream &operator<<(std::ostream &out, const RequestSourceLocationsForRenamingMessage &message);
std::ostream &operator<<(std::ostream &out, const RequestSourceRangesAndDiagnosticsForQueryMessage &message);
std::ostream &operator<<(std::ostream &out, const RequestSourceRangesForQueryMessage &message);
diff --git a/tests/unit/unittest/mockclangcodemodelclient.h b/tests/unit/unittest/mockclangcodemodelclient.h
index 2e287909ddf..3b5a3cfbf5a 100644
--- a/tests/unit/unittest/mockclangcodemodelclient.h
+++ b/tests/unit/unittest/mockclangcodemodelclient.h
@@ -45,4 +45,6 @@ public:
void(const ClangBackEnd::ReferencesMessage &message));
MOCK_METHOD1(followSymbol,
void(const ClangBackEnd::FollowSymbolMessage &message));
+ MOCK_METHOD1(tooltip,
+ void(const ClangBackEnd::ToolTipMessage &message));
};
diff --git a/tests/unit/unittest/mockclangcodemodelserver.h b/tests/unit/unittest/mockclangcodemodelserver.h
index 8b6c66b2a33..468f683bf53 100644
--- a/tests/unit/unittest/mockclangcodemodelserver.h
+++ b/tests/unit/unittest/mockclangcodemodelserver.h
@@ -55,6 +55,8 @@ public:
void(const ClangBackEnd::RequestReferencesMessage &message));
MOCK_METHOD1(requestFollowSymbol,
void(const ClangBackEnd::RequestFollowSymbolMessage &message));
+ MOCK_METHOD1(requestToolTip,
+ void(const ClangBackEnd::RequestToolTipMessage &message));
MOCK_METHOD1(updateVisibleTranslationUnits,
void(const ClangBackEnd::UpdateVisibleTranslationUnitsMessage &message));
};
diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro
index 3c9642a46a7..257a83370c9 100644
--- a/tests/unit/unittest/unittest.pro
+++ b/tests/unit/unittest/unittest.pro
@@ -118,6 +118,7 @@ SOURCES += \
clangstring-test.cpp \
clangsupportivetranslationunitinitializer-test.cpp \
clangsuspenddocumentjob-test.cpp \
+ clangtooltipinfo-test.cpp \
clangtranslationunits-test.cpp \
clangtranslationunit-test.cpp \
clangupdatedocumentannotationsjob-test.cpp \
diff --git a/tests/unit/unittest/unsavedfile-test.cpp b/tests/unit/unittest/unsavedfile-test.cpp
index 05783a33c32..7e4d3dae685 100644
--- a/tests/unit/unittest/unsavedfile-test.cpp
+++ b/tests/unit/unittest/unsavedfile-test.cpp
@@ -203,4 +203,32 @@ TEST_F(UnsavedFile, HasCharacterForLastLineColumn)
ASSERT_TRUE(unsavedFile.hasCharacterAt(1, 7, 't'));
}
+TEST_F(UnsavedFile, LineRangeForInvalidLines)
+{
+ ::UnsavedFile unsavedFile(filePath, fileContent);
+
+ ASSERT_THAT(unsavedFile.lineRange(2, 1), Utf8String());
+}
+
+TEST_F(UnsavedFile, LineRangeForSingleLine)
+{
+ ::UnsavedFile unsavedFile(filePath, Utf8StringLiteral("foo"));
+
+ ASSERT_THAT(unsavedFile.lineRange(1, 1), Utf8StringLiteral("foo"));
+}
+
+TEST_F(UnsavedFile, LineRangeForSingleLineInMultipleLines)
+{
+ ::UnsavedFile unsavedFile(filePath, Utf8StringLiteral("foo\nbar\n\baz"));
+
+ ASSERT_THAT(unsavedFile.lineRange(2, 2), Utf8StringLiteral("bar"));
+}
+
+TEST_F(UnsavedFile, LineRangeForTwoLines)
+{
+ ::UnsavedFile unsavedFile(filePath, Utf8StringLiteral("foo\nbar\n\baz"));
+
+ ASSERT_THAT(unsavedFile.lineRange(2, 3), Utf8StringLiteral("bar\n\baz"));
+}
+
} // anonymous namespace