Merge remote-tracking branch 'origin/4.6'

Conflicts:
	tests/unit/unittest/gtest-creator-printing.cpp
	tests/unit/unittest/gtest-creator-printing.h

Change-Id: I43d2571617bfbf41c0fcf23502ab77975540eba4
This commit is contained in:
Eike Ziller
2018-01-17 09:30:57 +01:00
113 changed files with 3769 additions and 434 deletions

View File

@@ -18,14 +18,16 @@ Module {
+ ide_compat_version_minor + '.' + ide_compat_version_release + ide_compat_version_minor + '.' + ide_compat_version_release
property string qtcreator_copyright_year: '2017' 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_display_name: 'Qt Creator'
property string ide_id: 'qtcreator' property string ide_id: 'qtcreator'
property string ide_cased_id: 'QtCreator' property string ide_cased_id: 'QtCreator'
property string ide_bundle_identifier: 'org.qt-project.qtcreator'
property string libDirName: "lib" property string libDirName: "lib"
property string ide_app_path: qbs.targetOS.contains("macos") ? "" : "bin" 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: { property string ide_library_path: {
if (qbs.targetOS.contains("macos")) if (qbs.targetOS.contains("macos"))
return ide_app_target + ".app/Contents/Frameworks" return ide_app_target + ".app/Contents/Frameworks"

View File

@@ -12,6 +12,8 @@ isEmpty(IDE_DISPLAY_NAME): IDE_DISPLAY_NAME = Qt Creator
isEmpty(IDE_ID): IDE_ID = qtcreator isEmpty(IDE_ID): IDE_ID = qtcreator
isEmpty(IDE_CASED_ID): IDE_CASED_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 CONFIG += c++14
defineReplace(qtLibraryTargetName) { defineReplace(qtLibraryTargetName) {
@@ -100,7 +102,7 @@ isEmpty(IDE_BUILD_TREE) {
IDE_APP_PATH = $$IDE_BUILD_TREE/bin IDE_APP_PATH = $$IDE_BUILD_TREE/bin
osx { osx {
IDE_APP_TARGET = "Qt Creator" IDE_APP_TARGET = "$$IDE_DISPLAY_NAME"
# check if IDE_BUILD_TREE is actually an existing Qt Creator.app, # check if IDE_BUILD_TREE is actually an existing Qt Creator.app,
# for building against a binary package # for building against a binary package
@@ -130,7 +132,7 @@ osx {
INSTALL_APP_PATH = $$QTC_PREFIX/ INSTALL_APP_PATH = $$QTC_PREFIX/
} else { } else {
contains(TEMPLATE, vc.*):vcproj = 1 contains(TEMPLATE, vc.*):vcproj = 1
IDE_APP_TARGET = qtcreator IDE_APP_TARGET = $$IDE_ID
# target output path if not set manually # target output path if not set manually
isEmpty(IDE_OUTPUT_PATH): IDE_OUTPUT_PATH = $$IDE_BUILD_TREE isEmpty(IDE_OUTPUT_PATH): IDE_OUTPUT_PATH = $$IDE_BUILD_TREE

View File

@@ -245,9 +245,9 @@
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>Qt Creator</string> <string>@EXECUTABLE@</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>org.qt-project.qtcreator</string> <string>@PRODUCT_BUNDLE_IDENTIFIER@</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>@FULL_VERSION@</string> <string>@FULL_VERSION@</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>

View File

@@ -62,6 +62,7 @@ win32 {
infoplist = $$cat($$PWD/app-Info.plist, blob) infoplist = $$cat($$PWD/app-Info.plist, blob)
infoplist = $$replace(infoplist, @MACOSX_DEPLOYMENT_TARGET@, $$QMAKE_MACOSX_DEPLOYMENT_TARGET) infoplist = $$replace(infoplist, @MACOSX_DEPLOYMENT_TARGET@, $$QMAKE_MACOSX_DEPLOYMENT_TARGET)
infoplist = $$replace(infoplist, @QTCREATOR_COPYRIGHT_YEAR@, $$QTCREATOR_COPYRIGHT_YEAR) 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) write_file($$OUT_PWD/Info.plist, infoplist)
QMAKE_INFO_PLIST = $$OUT_PWD/Info.plist QMAKE_INFO_PLIST = $$OUT_PWD/Info.plist

View File

@@ -25,6 +25,11 @@ QtcProduct {
installTags: (isBundle ? ["bundle.content"] : base).concat(["debuginfo_app"]) installTags: (isBundle ? ["bundle.content"] : base).concat(["debuginfo_app"])
property bool qtcRunnable: true 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"] cpp.rpaths: qbs.targetOS.contains("macos") ? ["@executable_path/../Frameworks"]
: ["$ORIGIN/../" + qtc.libDirName + "/qtcreator"] : ["$ORIGIN/../" + qtc.libDirName + "/qtcreator"]
cpp.includePaths: [ cpp.includePaths: [

View File

@@ -53,6 +53,9 @@ void ClangCodeModelClientInterface::dispatch(const MessageEnvelop &messageEnvelo
case MessageType::FollowSymbolMessage: case MessageType::FollowSymbolMessage:
followSymbol(messageEnvelop.message<FollowSymbolMessage>()); followSymbol(messageEnvelop.message<FollowSymbolMessage>());
break; break;
case MessageType::ToolTipMessage:
tooltip(messageEnvelop.message<ToolTipMessage>());
break;
default: default:
qWarning() << "Unknown ClangCodeModelClientMessage"; qWarning() << "Unknown ClangCodeModelClientMessage";
} }

View File

@@ -43,6 +43,8 @@ class RegisterUnsavedFilesForEditorMessage;
class RequestDocumentAnnotationsMessage; class RequestDocumentAnnotationsMessage;
class RequestReferencesMessage; class RequestReferencesMessage;
class RequestFollowSymbolMessage; class RequestFollowSymbolMessage;
class RequestToolTipMessage;
class ToolTipMessage;
class UnregisterProjectPartsForEditorMessage; class UnregisterProjectPartsForEditorMessage;
class UnregisterTranslationUnitsForEditorMessage; class UnregisterTranslationUnitsForEditorMessage;
class UnregisterUnsavedFilesForEditorMessage; class UnregisterUnsavedFilesForEditorMessage;
@@ -60,6 +62,7 @@ public:
virtual void documentAnnotationsChanged(const DocumentAnnotationsChangedMessage &message) = 0; virtual void documentAnnotationsChanged(const DocumentAnnotationsChangedMessage &message) = 0;
virtual void references(const ReferencesMessage &message) = 0; virtual void references(const ReferencesMessage &message) = 0;
virtual void followSymbol(const FollowSymbolMessage &message) = 0; virtual void followSymbol(const FollowSymbolMessage &message) = 0;
virtual void tooltip(const ToolTipMessage &message) = 0;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -31,3 +31,4 @@
#include "documentannotationschangedmessage.h" #include "documentannotationschangedmessage.h"
#include "referencesmessage.h" #include "referencesmessage.h"
#include "followsymbolmessage.h" #include "followsymbolmessage.h"
#include "tooltipmessage.h"

View File

@@ -95,6 +95,11 @@ void ClangCodeModelClientProxy::followSymbol(const FollowSymbolMessage &message)
m_writeMessageBlock.write(message); m_writeMessageBlock.write(message);
} }
void ClangCodeModelClientProxy::tooltip(const ToolTipMessage &message)
{
m_writeMessageBlock.write(message);
}
void ClangCodeModelClientProxy::readMessages() void ClangCodeModelClientProxy::readMessages()
{ {
for (const MessageEnvelop &message : m_readMessageBlock.readAll()) for (const MessageEnvelop &message : m_readMessageBlock.readAll())

View File

@@ -57,6 +57,7 @@ public:
void documentAnnotationsChanged(const DocumentAnnotationsChangedMessage &message) override; void documentAnnotationsChanged(const DocumentAnnotationsChangedMessage &message) override;
void references(const ReferencesMessage &message) override; void references(const ReferencesMessage &message) override;
void followSymbol(const FollowSymbolMessage &message) override; void followSymbol(const FollowSymbolMessage &message) override;
void tooltip(const ToolTipMessage &message) override;
void readMessages(); void readMessages();

View File

@@ -71,6 +71,9 @@ void ClangCodeModelServerInterface::dispatch(const MessageEnvelop &messageEnvelo
case MessageType::RequestFollowSymbolMessage: case MessageType::RequestFollowSymbolMessage:
requestFollowSymbol(messageEnvelop.message<RequestFollowSymbolMessage>()); requestFollowSymbol(messageEnvelop.message<RequestFollowSymbolMessage>());
break; break;
case MessageType::RequestToolTipMessage:
requestToolTip(messageEnvelop.message<RequestToolTipMessage>());
break;
case MessageType::UpdateVisibleTranslationUnitsMessage: case MessageType::UpdateVisibleTranslationUnitsMessage:
updateVisibleTranslationUnits(messageEnvelop.message<UpdateVisibleTranslationUnitsMessage>()); updateVisibleTranslationUnits(messageEnvelop.message<UpdateVisibleTranslationUnitsMessage>());
break; break;

View File

@@ -50,6 +50,7 @@ public:
virtual void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) = 0; virtual void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) = 0;
virtual void requestReferences(const RequestReferencesMessage &message) = 0; virtual void requestReferences(const RequestReferencesMessage &message) = 0;
virtual void requestFollowSymbol(const RequestFollowSymbolMessage &message) = 0; virtual void requestFollowSymbol(const RequestFollowSymbolMessage &message) = 0;
virtual void requestToolTip(const RequestToolTipMessage &message) = 0;
virtual void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) = 0; virtual void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) = 0;
}; };

View File

@@ -36,6 +36,7 @@
#include "requestdocumentannotations.h" #include "requestdocumentannotations.h"
#include "requestreferencesmessage.h" #include "requestreferencesmessage.h"
#include "requestfollowsymbolmessage.h" #include "requestfollowsymbolmessage.h"
#include "requesttooltipmessage.h"
#include "unregisterunsavedfilesforeditormessage.h" #include "unregisterunsavedfilesforeditormessage.h"
#include "updatetranslationunitsforeditormessage.h" #include "updatetranslationunitsforeditormessage.h"
#include "updatevisibletranslationunitsmessage.h" #include "updatevisibletranslationunitsmessage.h"

View File

@@ -96,6 +96,11 @@ void ClangCodeModelServerProxy::requestFollowSymbol(const RequestFollowSymbolMes
m_writeMessageBlock.write(message); m_writeMessageBlock.write(message);
} }
void ClangCodeModelServerProxy::requestToolTip(const RequestToolTipMessage &message)
{
m_writeMessageBlock.write(message);
}
void ClangCodeModelServerProxy::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) void ClangCodeModelServerProxy::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message)
{ {
m_writeMessageBlock.write(message); m_writeMessageBlock.write(message);

View File

@@ -60,6 +60,7 @@ public:
void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) override; void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) override;
void requestReferences(const RequestReferencesMessage &message) override; void requestReferences(const RequestReferencesMessage &message) override;
void requestFollowSymbol(const RequestFollowSymbolMessage &message) override; void requestFollowSymbol(const RequestFollowSymbolMessage &message) override;
void requestToolTip(const RequestToolTipMessage &message) override;
void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override; void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override;
}; };

View File

@@ -77,7 +77,7 @@ using IdCache = StringCache<Utils::SmallString,
template <typename FileSystemWatcher, template <typename FileSystemWatcher,
typename Timer> typename Timer>
class ClangPathWatcher : public ClangPathWatcherInterface class CLANGSUPPORT_EXPORT ClangPathWatcher : public ClangPathWatcherInterface
{ {
public: public:
ClangPathWatcher(FilePathCachingInterface &pathCache, ClangPathWatcher(FilePathCachingInterface &pathCache,

View File

@@ -68,6 +68,7 @@ SOURCES += \
$$PWD/requestsourcelocationforrenamingmessage.cpp \ $$PWD/requestsourcelocationforrenamingmessage.cpp \
$$PWD/requestsourcerangesanddiagnosticsforquerymessage.cpp \ $$PWD/requestsourcerangesanddiagnosticsforquerymessage.cpp \
$$PWD/requestsourcerangesforquerymessage.cpp \ $$PWD/requestsourcerangesforquerymessage.cpp \
$$PWD/requesttooltipmessage.cpp \
$$PWD/sourcelocationcontainer.cpp \ $$PWD/sourcelocationcontainer.cpp \
$$PWD/sourcelocationcontainerv2.cpp \ $$PWD/sourcelocationcontainerv2.cpp \
$$PWD/sourcelocationscontainer.cpp \ $$PWD/sourcelocationscontainer.cpp \
@@ -82,6 +83,8 @@ SOURCES += \
$$PWD/sourcerangesforquerymessage.cpp \ $$PWD/sourcerangesforquerymessage.cpp \
$$PWD/sourcerangewithtextcontainer.cpp \ $$PWD/sourcerangewithtextcontainer.cpp \
$$PWD/tokeninfocontainer.cpp \ $$PWD/tokeninfocontainer.cpp \
$$PWD/tooltipmessage.cpp \
$$PWD/tooltipinfo.cpp \
$$PWD/unregisterunsavedfilesforeditormessage.cpp \ $$PWD/unregisterunsavedfilesforeditormessage.cpp \
$$PWD/updatepchprojectpartsmessage.cpp \ $$PWD/updatepchprojectpartsmessage.cpp \
$$PWD/updatetranslationunitsforeditormessage.cpp \ $$PWD/updatetranslationunitsforeditormessage.cpp \
@@ -159,6 +162,7 @@ HEADERS += \
$$PWD/requestsourcelocationforrenamingmessage.h \ $$PWD/requestsourcelocationforrenamingmessage.h \
$$PWD/requestsourcerangesanddiagnosticsforquerymessage.h \ $$PWD/requestsourcerangesanddiagnosticsforquerymessage.h \
$$PWD/requestsourcerangesforquerymessage.h \ $$PWD/requestsourcerangesforquerymessage.h \
$$PWD/requesttooltipmessage.h \
$$PWD/sourcelocationcontainer.h \ $$PWD/sourcelocationcontainer.h \
$$PWD/sourcelocationcontainerv2.h \ $$PWD/sourcelocationcontainerv2.h \
$$PWD/sourcelocationscontainer.h \ $$PWD/sourcelocationscontainer.h \
@@ -176,6 +180,8 @@ HEADERS += \
$$PWD/sourcerangewithtextcontainer.h \ $$PWD/sourcerangewithtextcontainer.h \
$$PWD/stringcache.h \ $$PWD/stringcache.h \
$$PWD/tokeninfocontainer.h \ $$PWD/tokeninfocontainer.h \
$$PWD/tooltipmessage.h \
$$PWD/tooltipinfo.h \
$$PWD/unregisterunsavedfilesforeditormessage.h \ $$PWD/unregisterunsavedfilesforeditormessage.h \
$$PWD/updatepchprojectpartsmessage.h \ $$PWD/updatepchprojectpartsmessage.h \
$$PWD/updatetranslationunitsforeditormessage.h \ $$PWD/updatetranslationunitsforeditormessage.h \

View File

@@ -116,6 +116,9 @@ enum class MessageType : quint8 {
RequestFollowSymbolMessage, RequestFollowSymbolMessage,
FollowSymbolMessage, FollowSymbolMessage,
RequestToolTipMessage,
ToolTipMessage,
UpdateVisibleTranslationUnitsMessage, UpdateVisibleTranslationUnitsMessage,
CompleteCodeMessage, CompleteCodeMessage,

View File

@@ -37,7 +37,8 @@ QDebug operator<<(QDebug debug, const FileContainer &container)
<< container.filePath() << ", " << container.filePath() << ", "
<< container.projectPartId() << ", " << container.projectPartId() << ", "
<< container.fileArguments() << ", " << container.fileArguments() << ", "
<< container.documentRevision(); << container.documentRevision() << ", "
<< container.textCodecName();
if (container.hasUnsavedFileContent()) { if (container.hasUnsavedFileContent()) {
const Utf8String fileWithContent = debugWriteFileForInspection( const Utf8String fileWithContent = debugWriteFileForInspection(

View File

@@ -42,10 +42,12 @@ public:
const Utf8String &projectPartId, const Utf8String &projectPartId,
const Utf8String &unsavedFileContent = Utf8String(), const Utf8String &unsavedFileContent = Utf8String(),
bool hasUnsavedFileContent = false, bool hasUnsavedFileContent = false,
quint32 documentRevision = 0) quint32 documentRevision = 0,
const Utf8String &textCodecName = Utf8String())
: m_filePath(filePath), : m_filePath(filePath),
m_projectPartId(projectPartId), m_projectPartId(projectPartId),
m_unsavedFileContent(unsavedFileContent), m_unsavedFileContent(unsavedFileContent),
m_textCodecName(textCodecName),
m_documentRevision(documentRevision), m_documentRevision(documentRevision),
m_hasUnsavedFileContent(hasUnsavedFileContent) m_hasUnsavedFileContent(hasUnsavedFileContent)
{ {
@@ -98,6 +100,11 @@ public:
return m_unsavedFileContent; return m_unsavedFileContent;
} }
const Utf8String &textCodecName() const
{
return m_textCodecName;
}
bool hasUnsavedFileContent() const bool hasUnsavedFileContent() const
{ {
return m_hasUnsavedFileContent; return m_hasUnsavedFileContent;
@@ -114,6 +121,7 @@ public:
out << container.m_projectPartId; out << container.m_projectPartId;
out << container.m_fileArguments; out << container.m_fileArguments;
out << container.m_unsavedFileContent; out << container.m_unsavedFileContent;
out << container.m_textCodecName;
out << container.m_documentRevision; out << container.m_documentRevision;
out << container.m_hasUnsavedFileContent; out << container.m_hasUnsavedFileContent;
@@ -126,6 +134,7 @@ public:
in >> container.m_projectPartId; in >> container.m_projectPartId;
in >> container.m_fileArguments; in >> container.m_fileArguments;
in >> container.m_unsavedFileContent; in >> container.m_unsavedFileContent;
in >> container.m_textCodecName;
in >> container.m_documentRevision; in >> container.m_documentRevision;
in >> container.m_hasUnsavedFileContent; in >> container.m_hasUnsavedFileContent;
@@ -142,6 +151,7 @@ private:
Utf8String m_projectPartId; Utf8String m_projectPartId;
Utf8StringVector m_fileArguments; Utf8StringVector m_fileArguments;
Utf8String m_unsavedFileContent; Utf8String m_unsavedFileContent;
Utf8String m_textCodecName;
quint32 m_documentRevision = 0; quint32 m_documentRevision = 0;
bool m_hasUnsavedFileContent = false; bool m_hasUnsavedFileContent = false;
}; };

View File

@@ -36,7 +36,7 @@
namespace ClangBackEnd { namespace ClangBackEnd {
template <typename FilePathStorage> template <typename FilePathStorage>
class FilePathCache class CLANGSUPPORT_EXPORT FilePathCache
{ {
using DirectoryPathCache = StringCache<Utils::PathString, using DirectoryPathCache = StringCache<Utils::PathString,
int, int,

View File

@@ -68,6 +68,9 @@ QDebug operator<<(QDebug debug, const MessageEnvelop &messageEnvelop)
case MessageType::RequestReferencesMessage: case MessageType::RequestReferencesMessage:
qDebug() << messageEnvelop.message<RequestReferencesMessage>(); qDebug() << messageEnvelop.message<RequestReferencesMessage>();
break; break;
case MessageType::RequestToolTipMessage:
qDebug() << messageEnvelop.message<RequestToolTipMessage>();
break;
case MessageType::UpdateVisibleTranslationUnitsMessage: case MessageType::UpdateVisibleTranslationUnitsMessage:
qDebug() << messageEnvelop.message<UpdateVisibleTranslationUnitsMessage>(); qDebug() << messageEnvelop.message<UpdateVisibleTranslationUnitsMessage>();
break; break;
@@ -83,6 +86,9 @@ QDebug operator<<(QDebug debug, const MessageEnvelop &messageEnvelop)
case MessageType::ReferencesMessage: case MessageType::ReferencesMessage:
qDebug() << messageEnvelop.message<ReferencesMessage>(); qDebug() << messageEnvelop.message<ReferencesMessage>();
break; break;
case MessageType::ToolTipMessage:
qDebug() << messageEnvelop.message<ToolTipMessage>();
break;
case MessageType::DocumentAnnotationsChangedMessage: case MessageType::DocumentAnnotationsChangedMessage:
qDebug() << messageEnvelop.message<DocumentAnnotationsChangedMessage>(); qDebug() << messageEnvelop.message<DocumentAnnotationsChangedMessage>();
break; break;

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -43,6 +43,47 @@
namespace qmt { 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 class StereotypeController::StereotypeControllerPrivate
{ {
public: public:
@@ -51,6 +92,7 @@ public:
QHash<QString, CustomRelation> m_relationIdToCustomRelationMap; QHash<QString, CustomRelation> m_relationIdToCustomRelationMap;
QList<Toolbar> m_toolbars; QList<Toolbar> m_toolbars;
QList<Toolbar> m_elementToolbars; QList<Toolbar> m_elementToolbars;
QHash<IconKey, QIcon> m_iconMap;
}; };
StereotypeController::StereotypeController(QObject *parent) : 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 QString &defaultIconPath, const Style *style, const QSize &size,
const QMarginsF &margins, qreal lineWidth) const QMarginsF &margins, qreal lineWidth)
{ {
// TODO implement cache with key build from element, stereotypes, defaultIconPath, style, size and margins IconKey key(element, stereotypes, defaultIconPath, style->uid(), size, margins, lineWidth);
// TODO implement unique id for style which can be used as key QIcon icon = d->m_iconMap.value(key);
QIcon icon; if (!icon.isNull())
return icon;
QString stereotypeIconId = findStereotypeIconId(element, stereotypes); QString stereotypeIconId = findStereotypeIconId(element, stereotypes);
if (!stereotypeIconId.isEmpty()) { if (!stereotypeIconId.isEmpty()) {
StereotypeIcon stereotypeIcon = findStereotypeIcon(stereotypeIconId); StereotypeIcon stereotypeIcon = findStereotypeIcon(stereotypeIconId);
@@ -202,6 +245,7 @@ QIcon StereotypeController::createIcon(StereotypeIcon::Element element, const QL
} }
if (icon.isNull() && !defaultIconPath.isEmpty()) if (icon.isNull() && !defaultIconPath.isEmpty())
icon = QIcon(defaultIconPath); icon = QIcon(defaultIconPath);
d->m_iconMap.insert(key, icon);
return icon; return icon;
} }

View File

@@ -26,6 +26,7 @@
#pragma once #pragma once
#include "qmt/infrastructure/qmt_global.h" #include "qmt/infrastructure/qmt_global.h"
#include "qmt/infrastructure/uid.h"
#include <QString> #include <QString>
#include <QPen> #include <QPen>
@@ -45,6 +46,7 @@ public:
explicit Style(Type type); explicit Style(Type type);
virtual ~Style(); virtual ~Style();
Uid uid() const { return m_uid; }
Type type() const { return m_type; } Type type() const { return m_type; }
QPen linePen() const { return m_linePen; } QPen linePen() const { return m_linePen; }
void setLinePen(const QPen &pen); void setLinePen(const QPen &pen);
@@ -68,6 +70,7 @@ public:
void setHeaderFont(const QFont &font); void setHeaderFont(const QFont &font);
private: private:
Uid m_uid;
Type m_type; Type m_type;
QPen m_linePen; QPen m_linePen;
QPen m_outerLinePen; QPen m_outerLinePen;

View File

@@ -171,7 +171,8 @@ public:
byteArray.reserve(reserveSize); 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)); return Utf8String::fromByteArray(QByteArray::number(number, base));
} }

View File

@@ -271,6 +271,13 @@ static QtTestCodeLocationList tagLocationsFor(const QtTestParseResult *func,
return QtTestCodeLocationList(); 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, static bool handleQtTest(QFutureInterface<TestParseResultPtr> futureInterface,
CPlusPlus::Document::Ptr document, CPlusPlus::Document::Ptr document,
const CPlusPlus::Snapshot &snapshot, const CPlusPlus::Snapshot &snapshot,
@@ -303,6 +310,10 @@ static bool handleQtTest(QFutureInterface<TestParseResultPtr> futureInterface,
fetchAndMergeBaseTestFunctions( fetchAndMergeBaseTestFunctions(
visitor.baseClasses(), testFunctions, declaringDoc, snapshot); 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); const QSet<QString> &files = filesWithDataFunctionDefinitions(testFunctions);
// TODO: change to QHash<> // TODO: change to QHash<>

View File

@@ -392,6 +392,15 @@ QFuture<CppTools::CursorInfo> BackendCommunicator::requestLocalReferences(
return m_receiver.addExpectedReferencesMessage(message.ticketNumber(), textDocument); 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( QFuture<CppTools::SymbolInfo> BackendCommunicator::requestFollowSymbol(
const FileContainer &curFileContainer, const FileContainer &curFileContainer,
quint32 line, quint32 line,

View File

@@ -82,6 +82,9 @@ public:
quint32 line, quint32 line,
quint32 column, quint32 column,
QTextDocument *textDocument); QTextDocument *textDocument);
QFuture<CppTools::ToolTipInfo> requestToolTip(const FileContainer &fileContainer,
quint32 line,
quint32 column);
QFuture<CppTools::SymbolInfo> requestFollowSymbol(const FileContainer &curFileContainer, QFuture<CppTools::SymbolInfo> requestFollowSymbol(const FileContainer &curFileContainer,
quint32 line, quint32 line,
quint32 column); quint32 column);

View File

@@ -128,6 +128,18 @@ QFuture<CppTools::SymbolInfo> BackendReceiver::addExpectedRequestFollowSymbolMes
return futureInterface.future(); 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 bool BackendReceiver::isExpectingCodeCompletedMessage() const
{ {
return !m_assistProcessorsTable.isEmpty(); return !m_assistProcessorsTable.isEmpty();
@@ -272,6 +284,72 @@ void BackendReceiver::references(const ReferencesMessage &message)
futureInterface.reportFinished(); 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) void BackendReceiver::followSymbol(const ClangBackEnd::FollowSymbolMessage &message)
{ {
qCDebugIpc() << "FollowSymbolMessage with" qCDebugIpc() << "FollowSymbolMessage with"

View File

@@ -27,6 +27,7 @@
#include <cpptools/cppcursorinfo.h> #include <cpptools/cppcursorinfo.h>
#include <cpptools/cppsymbolinfo.h> #include <cpptools/cppsymbolinfo.h>
#include <cpptools/baseeditordocumentprocessor.h>
#include <clangsupport/clangcodemodelclientinterface.h> #include <clangsupport/clangcodemodelclientinterface.h>
@@ -59,6 +60,7 @@ public:
const CppTools::SemanticInfo::LocalUseMap &localUses const CppTools::SemanticInfo::LocalUseMap &localUses
= CppTools::SemanticInfo::LocalUseMap()); = CppTools::SemanticInfo::LocalUseMap());
QFuture<CppTools::SymbolInfo> addExpectedRequestFollowSymbolMessage(quint64 ticket); QFuture<CppTools::SymbolInfo> addExpectedRequestFollowSymbolMessage(quint64 ticket);
QFuture<CppTools::ToolTipInfo> addExpectedToolTipMessage(quint64 ticket);
bool isExpectingCodeCompletedMessage() const; bool isExpectingCodeCompletedMessage() const;
void reset(); void reset();
@@ -70,6 +72,7 @@ private:
void documentAnnotationsChanged(const ClangBackEnd::DocumentAnnotationsChangedMessage &message) override; void documentAnnotationsChanged(const ClangBackEnd::DocumentAnnotationsChangedMessage &message) override;
void references(const ClangBackEnd::ReferencesMessage &message) override; void references(const ClangBackEnd::ReferencesMessage &message) override;
void tooltip(const ClangBackEnd::ToolTipMessage &message) override;
void followSymbol(const ClangBackEnd::FollowSymbolMessage &message) override; void followSymbol(const ClangBackEnd::FollowSymbolMessage &message) override;
private: private:
@@ -89,7 +92,7 @@ private:
CppTools::SemanticInfo::LocalUseMap localUses; CppTools::SemanticInfo::LocalUseMap localUses;
}; };
QHash<quint64, ReferencesEntry> m_referencesTable; QHash<quint64, ReferencesEntry> m_referencesTable;
QHash<quint64, QFutureInterface<CppTools::ToolTipInfo>> m_toolTipsTable;
QHash<quint64, QFutureInterface<CppTools::SymbolInfo>> m_followTable; QHash<quint64, QFutureInterface<CppTools::SymbolInfo>> m_followTable;
}; };

View File

@@ -120,6 +120,13 @@ void BackendSender::requestReferences(const RequestReferencesMessage &message)
m_connection->serverProxy().requestReferences(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) void BackendSender::requestFollowSymbol(const RequestFollowSymbolMessage &message)
{ {
QTC_CHECK(m_connection->isConnected()); QTC_CHECK(m_connection->isConnected());

View File

@@ -48,6 +48,7 @@ public:
void completeCode(const ClangBackEnd::CompleteCodeMessage &message) override; void completeCode(const ClangBackEnd::CompleteCodeMessage &message) override;
void requestDocumentAnnotations(const ClangBackEnd::RequestDocumentAnnotationsMessage &message) override; void requestDocumentAnnotations(const ClangBackEnd::RequestDocumentAnnotationsMessage &message) override;
void requestReferences(const ClangBackEnd::RequestReferencesMessage &message) override; void requestReferences(const ClangBackEnd::RequestReferencesMessage &message) override;
void requestToolTip(const ClangBackEnd::RequestToolTipMessage &message) override;
void requestFollowSymbol(const ClangBackEnd::RequestFollowSymbolMessage &message) override; void requestFollowSymbol(const ClangBackEnd::RequestFollowSymbolMessage &message) override;
void updateVisibleTranslationUnits(const ClangBackEnd::UpdateVisibleTranslationUnitsMessage &message) override; void updateVisibleTranslationUnits(const ClangBackEnd::UpdateVisibleTranslationUnitsMessage &message) override;

View File

@@ -30,6 +30,7 @@ SOURCES += \
clangfixitoperationsextractor.cpp \ clangfixitoperationsextractor.cpp \
clangfollowsymbol.cpp \ clangfollowsymbol.cpp \
clangfunctionhintmodel.cpp \ clangfunctionhintmodel.cpp \
clanghoverhandler.cpp \
clangtokeninfosreporter.cpp \ clangtokeninfosreporter.cpp \
clangmodelmanagersupport.cpp \ clangmodelmanagersupport.cpp \
clangpreprocessorassistproposalitem.cpp \ clangpreprocessorassistproposalitem.cpp \
@@ -66,6 +67,7 @@ HEADERS += \
clangfixitoperationsextractor.h \ clangfixitoperationsextractor.h \
clangfollowsymbol.h \ clangfollowsymbol.h \
clangfunctionhintmodel.h \ clangfunctionhintmodel.h \
clanghoverhandler.h \
clangisdiagnosticrelatedtolocation.h \ clangisdiagnosticrelatedtolocation.h \
clangmodelmanagersupport.h \ clangmodelmanagersupport.h \
clangpreprocessorassistproposalitem.h \ clangpreprocessorassistproposalitem.h \

View File

@@ -80,6 +80,8 @@ QtcPlugin {
"clangfollowsymbol.h", "clangfollowsymbol.h",
"clangfunctionhintmodel.cpp", "clangfunctionhintmodel.cpp",
"clangfunctionhintmodel.h", "clangfunctionhintmodel.h",
"clanghoverhandler.cpp",
"clanghoverhandler.h",
"clangtokeninfosreporter.cpp", "clangtokeninfosreporter.cpp",
"clangtokeninfosreporter.h", "clangtokeninfosreporter.h",
"clangisdiagnosticrelatedtolocation.h", "clangisdiagnosticrelatedtolocation.h",

View File

@@ -375,6 +375,15 @@ ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column)
static_cast<quint32>(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 ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithArguments() const
{ {
return fileContainerWithArguments(m_projectPart.data()); 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; Utf8String projectPartId;
if (m_projectPart) if (m_projectPart)
projectPartId = m_projectPart->id(); 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) static CppTools::ProjectPart projectPartForLanguageOption(CppTools::ProjectPart *projectPart)

View File

@@ -88,6 +88,9 @@ public:
QFuture<CppTools::CursorInfo> cursorInfo(const CppTools::CursorInfoParams &params) override; QFuture<CppTools::CursorInfo> cursorInfo(const CppTools::CursorInfoParams &params) override;
QFuture<CppTools::CursorInfo> requestLocalReferences(const QTextCursor &cursor) override; QFuture<CppTools::CursorInfo> requestLocalReferences(const QTextCursor &cursor) override;
QFuture<CppTools::SymbolInfo> requestFollowSymbol(int line, int column) 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; ClangBackEnd::FileContainer fileContainerWithArguments() const;
@@ -106,7 +109,7 @@ private:
void requestDocumentAnnotations(const QString &projectpartId); void requestDocumentAnnotations(const QString &projectpartId);
HeaderErrorDiagnosticWidgetCreator creatorForHeaderErrorDiagnosticWidget( HeaderErrorDiagnosticWidgetCreator creatorForHeaderErrorDiagnosticWidget(
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic); 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 fileContainerWithArguments(CppTools::ProjectPart *projectPart) const;
ClangBackEnd::FileContainer fileContainerWithArgumentsAndDocumentContent( ClangBackEnd::FileContainer fileContainerWithArgumentsAndDocumentContent(
CppTools::ProjectPart *projectPart) const; CppTools::ProjectPart *projectPart) const;

View File

@@ -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

View File

@@ -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

View File

@@ -29,6 +29,7 @@
#include "clangeditordocumentprocessor.h" #include "clangeditordocumentprocessor.h"
#include "clangutils.h" #include "clangutils.h"
#include "clangfollowsymbol.h" #include "clangfollowsymbol.h"
#include "clanghoverhandler.h"
#include "clangrefactoringengine.h" #include "clangrefactoringengine.h"
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
@@ -111,6 +112,11 @@ CppTools::CppCompletionAssistProvider *ModelManagerSupportClang::completionAssis
return &m_completionAssistProvider; return &m_completionAssistProvider;
} }
TextEditor::BaseHoverHandler *ModelManagerSupportClang::createHoverHandler()
{
return new Internal::ClangHoverHandler;
}
CppTools::FollowSymbolInterface &ModelManagerSupportClang::followSymbolInterface() CppTools::FollowSymbolInterface &ModelManagerSupportClang::followSymbolInterface()
{ {
return *m_followSymbol; return *m_followSymbol;
@@ -121,7 +127,7 @@ CppTools::RefactoringEngineInterface &ModelManagerSupportClang::refactoringEngin
return *m_refactoringEngine; return *m_refactoringEngine;
} }
CppTools::BaseEditorDocumentProcessor *ModelManagerSupportClang::editorDocumentProcessor( CppTools::BaseEditorDocumentProcessor *ModelManagerSupportClang::createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) TextEditor::TextDocument *baseTextDocument)
{ {
return new ClangEditorDocumentProcessor(m_communicator, baseTextDocument); return new ClangEditorDocumentProcessor(m_communicator, baseTextDocument);

View File

@@ -61,7 +61,8 @@ public:
~ModelManagerSupportClang(); ~ModelManagerSupportClang();
CppTools::CppCompletionAssistProvider *completionAssistProvider() override; CppTools::CppCompletionAssistProvider *completionAssistProvider() override;
CppTools::BaseEditorDocumentProcessor *editorDocumentProcessor( TextEditor::BaseHoverHandler *createHoverHandler() override;
CppTools::BaseEditorDocumentProcessor *createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) override; TextEditor::TextDocument *baseTextDocument) override;
CppTools::FollowSymbolInterface &followSymbolInterface() override; CppTools::FollowSymbolInterface &followSymbolInterface() override;
CppTools::RefactoringEngineInterface &refactoringEngineInterface() override; CppTools::RefactoringEngineInterface &refactoringEngineInterface() override;

View File

@@ -26,12 +26,13 @@
#include "coreplugin.h" #include "coreplugin.h"
#include "designmode.h" #include "designmode.h"
#include "editmode.h" #include "editmode.h"
#include "idocument.h"
#include "helpmanager.h" #include "helpmanager.h"
#include "mainwindow.h" #include "idocument.h"
#include "modemanager.h"
#include "infobar.h" #include "infobar.h"
#include "iwizardfactory.h" #include "iwizardfactory.h"
#include "mainwindow.h"
#include "menubarfilter.h"
#include "modemanager.h"
#include "reaper_p.h" #include "reaper_p.h"
#include "themechooser.h" #include "themechooser.h"
@@ -162,6 +163,8 @@ bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage)
InfoBar::initialize(ICore::settings(), creatorTheme()); InfoBar::initialize(ICore::settings(), creatorTheme());
} }
addAutoReleasedObject(new MenuBarFilter);
IWizardFactory::initialize(); IWizardFactory::initialize();
// Make sure we respect the process's umask when creating new files // Make sure we respect the process's umask when creating new files

View File

@@ -111,7 +111,8 @@ SOURCES += corejsextensions.cpp \
externaltoolmanager.cpp \ externaltoolmanager.cpp \
systemsettings.cpp \ systemsettings.cpp \
coreicons.cpp \ coreicons.cpp \
diffservice.cpp diffservice.cpp \
menubarfilter.cpp
HEADERS += corejsextensions.h \ HEADERS += corejsextensions.h \
mainwindow.h \ mainwindow.h \
@@ -222,7 +223,8 @@ HEADERS += corejsextensions.h \
systemsettings.h \ systemsettings.h \
coreicons.h \ coreicons.h \
editormanager/documentmodel_p.h \ editormanager/documentmodel_p.h \
diffservice.h diffservice.h \
menubarfilter.h
FORMS += dialogs/newdialog.ui \ FORMS += dialogs/newdialog.ui \
dialogs/saveitemsdialog.ui \ dialogs/saveitemsdialog.ui \

View File

@@ -32,79 +32,154 @@ Project {
Group { Group {
name: "General" name: "General"
files: [ files: [
"basefilewizard.cpp", "basefilewizard.h", "basefilewizard.cpp",
"basefilewizardfactory.cpp", "basefilewizardfactory.h", "basefilewizard.h",
"basefilewizardfactory.cpp",
"basefilewizardfactory.h",
"core.qrc", "core.qrc",
"core_global.h", "core_global.h",
"coreconstants.h", "coreconstants.h",
"coreicons.cpp", "coreicons.h", "coreicons.cpp",
"corejsextensions.cpp", "corejsextensions.h", "coreicons.h",
"coreplugin.cpp", "coreplugin.h", "corejsextensions.cpp",
"designmode.cpp", "designmode.h", "corejsextensions.h",
"diffservice.cpp", "diffservice.h", "coreplugin.cpp",
"documentmanager.cpp", "documentmanager.h", "coreplugin.h",
"editmode.cpp", "editmode.h", "designmode.cpp",
"editortoolbar.cpp", "editortoolbar.h", "designmode.h",
"externaltool.cpp", "externaltool.h", "diffservice.cpp",
"externaltoolmanager.cpp", "externaltoolmanager.h", "diffservice.h",
"fancyactionbar.cpp", "fancyactionbar.h", "fancyactionbar.qrc", "documentmanager.cpp",
"fancytabwidget.cpp", "fancytabwidget.h", "documentmanager.h",
"featureprovider.cpp", "featureprovider.h", "editmode.cpp",
"fileiconprovider.cpp", "fileiconprovider.h", "editmode.h",
"fileutils.cpp", "fileutils.h", "editortoolbar.cpp",
"findplaceholder.cpp", "findplaceholder.h", "editortoolbar.h",
"generalsettings.cpp", "generalsettings.h", "generalsettings.ui", "externaltool.cpp",
"generatedfile.cpp", "generatedfile.h", "externaltool.h",
"helpmanager.cpp", "helpmanager.h", "externaltoolmanager.cpp",
"icontext.cpp", "icontext.h", "externaltoolmanager.h",
"icore.cpp", "icore.h", "fancyactionbar.cpp",
"id.cpp", "id.h", "fancyactionbar.h",
"idocument.cpp", "idocument.h", "fancyactionbar.qrc",
"idocumentfactory.cpp", "idocumentfactory.h", "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", "ifilewizardextension.h",
"imode.cpp", "imode.h", "imode.cpp",
"inavigationwidgetfactory.cpp", "inavigationwidgetfactory.h", "imode.h",
"infobar.cpp", "infobar.h", "inavigationwidgetfactory.cpp",
"ioutputpane.cpp", "ioutputpane.h", "inavigationwidgetfactory.h",
"iversioncontrol.cpp", "iversioncontrol.h", "infobar.cpp",
"iwelcomepage.cpp", "iwelcomepage.h", "infobar.h",
"iwizardfactory.cpp", "iwizardfactory.h", "ioutputpane.cpp",
"jsexpander.cpp", "jsexpander.h", "ioutputpane.h",
"mainwindow.cpp", "mainwindow.h", "iversioncontrol.cpp",
"manhattanstyle.cpp", "manhattanstyle.h", "iversioncontrol.h",
"messagebox.cpp", "messagebox.h", "iwelcomepage.cpp",
"messagemanager.cpp", "messagemanager.h", "iwelcomepage.h",
"messageoutputwindow.cpp", "messageoutputwindow.h", "iwizardfactory.cpp",
"mimetypemagicdialog.cpp", "mimetypemagicdialog.h", "mimetypemagicdialog.ui", "iwizardfactory.h",
"mimetypesettings.cpp", "mimetypesettings.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", "mimetypesettingspage.ui",
"minisplitter.cpp", "minisplitter.h", "minisplitter.cpp",
"modemanager.cpp", "modemanager.h", "minisplitter.h",
"navigationsubwidget.cpp", "navigationsubwidget.h", "modemanager.cpp",
"navigationwidget.cpp", "navigationwidget.h", "modemanager.h",
"opendocumentstreeview.cpp", "opendocumentstreeview.h", "navigationsubwidget.cpp",
"outputpane.cpp", "outputpane.h", "navigationsubwidget.h",
"outputpanemanager.cpp", "outputpanemanager.h", "navigationwidget.cpp",
"outputwindow.cpp", "outputwindow.h", "navigationwidget.h",
"patchtool.cpp", "patchtool.h", "opendocumentstreeview.cpp",
"plugindialog.cpp", "plugindialog.h", "opendocumentstreeview.h",
"reaper.cpp", "reaper.h", "reaper_p.h", "outputpane.cpp",
"rightpane.cpp", "rightpane.h", "outputpane.h",
"settingsdatabase.cpp", "settingsdatabase.h", "outputpanemanager.cpp",
"shellcommand.cpp", "shellcommand.h", "outputpanemanager.h",
"sidebar.cpp", "sidebar.h", "outputwindow.cpp",
"sidebarwidget.cpp", "sidebarwidget.h", "outputwindow.h",
"statusbarmanager.cpp", "statusbarmanager.h", "patchtool.cpp",
"statusbarwidget.cpp", "statusbarwidget.h", "patchtool.h",
"styleanimator.cpp", "styleanimator.h", "plugindialog.cpp",
"systemsettings.cpp", "systemsettings.h", "systemsettings.ui", "plugindialog.h",
"textdocument.cpp", "textdocument.h", "reaper.cpp",
"themechooser.cpp", "themechooser.h", "reaper.h",
"toolsettings.cpp", "toolsettings.h", "reaper_p.h",
"variablechooser.cpp", "variablechooser.h", "rightpane.cpp",
"vcsmanager.cpp", "vcsmanager.h", "rightpane.h",
"versiondialog.cpp", "versiondialog.h", "settingsdatabase.cpp",
"windowsupport.cpp", "windowsupport.h" "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", "filesystemfilter.ui",
"ilocatorfilter.cpp", "ilocatorfilter.cpp",
"ilocatorfilter.h", "ilocatorfilter.h",
"javascriptfilter.cpp",
"javascriptfilter.h",
"locatorconstants.h", "locatorconstants.h",
"locatorfiltersfilter.cpp", "locatorfiltersfilter.cpp",
"locatorfiltersfilter.h", "locatorfiltersfilter.h",

View File

@@ -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

View File

@@ -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

View File

@@ -27,6 +27,7 @@
#include "externaltoolsfilter.h" #include "externaltoolsfilter.h"
#include "filesystemfilter.h" #include "filesystemfilter.h"
#include "javascriptfilter.h"
#include "locatorconstants.h" #include "locatorconstants.h"
#include "locatorfiltersfilter.h" #include "locatorfiltersfilter.h"
#include "locatormanager.h" #include "locatormanager.h"
@@ -75,11 +76,13 @@ Locator::Locator()
Locator::~Locator() Locator::~Locator()
{ {
m_corePlugin->removeObject(m_javaScriptFilter);
m_corePlugin->removeObject(m_openDocumentsFilter); m_corePlugin->removeObject(m_openDocumentsFilter);
m_corePlugin->removeObject(m_fileSystemFilter); m_corePlugin->removeObject(m_fileSystemFilter);
m_corePlugin->removeObject(m_executeFilter); m_corePlugin->removeObject(m_executeFilter);
m_corePlugin->removeObject(m_settingsPage); m_corePlugin->removeObject(m_settingsPage);
m_corePlugin->removeObject(m_externalToolsFilter); m_corePlugin->removeObject(m_externalToolsFilter);
delete m_javaScriptFilter;
delete m_openDocumentsFilter; delete m_openDocumentsFilter;
delete m_fileSystemFilter; delete m_fileSystemFilter;
delete m_executeFilter; delete m_executeFilter;
@@ -119,6 +122,9 @@ void Locator::initialize(CorePlugin *corePlugin, const QStringList &, QString *)
new LocatorManager(this); new LocatorManager(this);
m_javaScriptFilter = new JavaScriptFilter;
m_corePlugin->addObject(m_javaScriptFilter);
m_openDocumentsFilter = new OpenDocumentsFilter; m_openDocumentsFilter = new OpenDocumentsFilter;
m_corePlugin->addObject(m_openDocumentsFilter); m_corePlugin->addObject(m_openDocumentsFilter);

View File

@@ -42,6 +42,7 @@ namespace Internal {
class CorePlugin; class CorePlugin;
class OpenDocumentsFilter; class OpenDocumentsFilter;
class FileSystemFilter; class FileSystemFilter;
class JavaScriptFilter;
class LocatorSettingsPage; class LocatorSettingsPage;
class ExternalToolsFilter; class ExternalToolsFilter;
@@ -85,6 +86,7 @@ private:
QList<ILocatorFilter *> m_customFilters; QList<ILocatorFilter *> m_customFilters;
QMap<Id, QAction *> m_filterActionMap; QMap<Id, QAction *> m_filterActionMap;
QTimer m_refreshTimer; QTimer m_refreshTimer;
JavaScriptFilter *m_javaScriptFilter = nullptr;
OpenDocumentsFilter *m_openDocumentsFilter = nullptr; OpenDocumentsFilter *m_openDocumentsFilter = nullptr;
FileSystemFilter *m_fileSystemFilter = nullptr; FileSystemFilter *m_fileSystemFilter = nullptr;
ExecuteFilter *m_executeFilter = nullptr; ExecuteFilter *m_executeFilter = nullptr;

View File

@@ -1,3 +1,5 @@
QT *= qml
HEADERS += \ HEADERS += \
$$PWD/locator.h \ $$PWD/locator.h \
$$PWD/commandlocator.h \ $$PWD/commandlocator.h \
@@ -13,7 +15,8 @@ HEADERS += \
$$PWD/executefilter.h \ $$PWD/executefilter.h \
$$PWD/locatorsearchutils.h \ $$PWD/locatorsearchutils.h \
$$PWD/locatorsettingspage.h \ $$PWD/locatorsettingspage.h \
$$PWD/externaltoolsfilter.h $$PWD/externaltoolsfilter.h \
$$PWD/javascriptfilter.h
SOURCES += \ SOURCES += \
$$PWD/locator.cpp \ $$PWD/locator.cpp \
@@ -29,7 +32,8 @@ SOURCES += \
$$PWD/executefilter.cpp \ $$PWD/executefilter.cpp \
$$PWD/locatorsearchutils.cpp \ $$PWD/locatorsearchutils.cpp \
$$PWD/locatorsettingspage.cpp \ $$PWD/locatorsettingspage.cpp \
$$PWD/externaltoolsfilter.cpp $$PWD/externaltoolsfilter.cpp \
$$PWD/javascriptfilter.cpp
FORMS += \ FORMS += \
$$PWD/filesystemfilter.ui \ $$PWD/filesystemfilter.ui \

View File

@@ -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);
}

View File

@@ -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

View File

@@ -12,10 +12,8 @@ HEADERS += \
cppeditorenums.h \ cppeditorenums.h \
cppeditorplugin.h \ cppeditorplugin.h \
cppeditorwidget.h \ cppeditorwidget.h \
cppelementevaluator.h \
cppfunctiondecldeflink.h \ cppfunctiondecldeflink.h \
cpphighlighter.h \ cpphighlighter.h \
cpphoverhandler.h \
cppparsecontext.h \ cppparsecontext.h \
cppincludehierarchy.h \ cppincludehierarchy.h \
cppinsertvirtualmethods.h \ cppinsertvirtualmethods.h \
@@ -38,10 +36,8 @@ SOURCES += \
cppeditordocument.cpp \ cppeditordocument.cpp \
cppeditorplugin.cpp \ cppeditorplugin.cpp \
cppeditorwidget.cpp \ cppeditorwidget.cpp \
cppelementevaluator.cpp \
cppfunctiondecldeflink.cpp \ cppfunctiondecldeflink.cpp \
cpphighlighter.cpp \ cpphighlighter.cpp \
cpphoverhandler.cpp \
cppparsecontext.cpp \ cppparsecontext.cpp \
cppincludehierarchy.cpp \ cppincludehierarchy.cpp \
cppinsertvirtualmethods.cpp \ cppinsertvirtualmethods.cpp \

View File

@@ -39,14 +39,10 @@ QtcPlugin {
"cppeditorenums.h", "cppeditorenums.h",
"cppeditorplugin.cpp", "cppeditorplugin.cpp",
"cppeditorplugin.h", "cppeditorplugin.h",
"cppelementevaluator.cpp",
"cppelementevaluator.h",
"cppfunctiondecldeflink.cpp", "cppfunctiondecldeflink.cpp",
"cppfunctiondecldeflink.h", "cppfunctiondecldeflink.h",
"cpphighlighter.cpp", "cpphighlighter.cpp",
"cpphighlighter.h", "cpphighlighter.h",
"cpphoverhandler.cpp",
"cpphoverhandler.h",
"cppincludehierarchy.cpp", "cppincludehierarchy.cpp",
"cppincludehierarchy.h", "cppincludehierarchy.h",
"cppinsertvirtualmethods.cpp", "cppinsertvirtualmethods.cpp",

View File

@@ -394,7 +394,7 @@ const MinimizableInfoBars &CppEditorDocument::minimizableInfoBars() const
CppTools::BaseEditorDocumentProcessor *CppEditorDocument::processor() CppTools::BaseEditorDocumentProcessor *CppEditorDocument::processor()
{ {
if (!m_processor) { if (!m_processor) {
m_processor.reset(mm()->editorDocumentProcessor(this)); m_processor.reset(mm()->createEditorDocumentProcessor(this));
connect(m_processor.data(), &CppTools::BaseEditorDocumentProcessor::projectPartInfoUpdated, connect(m_processor.data(), &CppTools::BaseEditorDocumentProcessor::projectPartInfoUpdated,
[this] (const CppTools::ProjectPartInfo &info) [this] (const CppTools::ProjectPartInfo &info)
{ {

View File

@@ -31,7 +31,6 @@
#include "cppeditorwidget.h" #include "cppeditorwidget.h"
#include "cppeditordocument.h" #include "cppeditordocument.h"
#include "cpphighlighter.h" #include "cpphighlighter.h"
#include "cpphoverhandler.h"
#include "cppincludehierarchy.h" #include "cppincludehierarchy.h"
#include "cppoutline.h" #include "cppoutline.h"
#include "cppquickfixassistant.h" #include "cppquickfixassistant.h"
@@ -53,6 +52,7 @@
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/navigationwidget.h> #include <coreplugin/navigationwidget.h>
#include <coreplugin/progressmanager/progressmanager.h> #include <coreplugin/progressmanager/progressmanager.h>
#include <cpptools/cpphoverhandler.h>
#include <cpptools/cpptoolsconstants.h> #include <cpptools/cpptoolsconstants.h>
#include <texteditor/texteditoractionhandler.h> #include <texteditor/texteditoractionhandler.h>
#include <texteditor/texteditorconstants.h> #include <texteditor/texteditorconstants.h>
@@ -105,7 +105,7 @@ public:
| TextEditorActionHandler::UnCollapseAll | TextEditorActionHandler::UnCollapseAll
| TextEditorActionHandler::FollowSymbolUnderCursor); | TextEditorActionHandler::FollowSymbolUnderCursor);
addHoverHandler(new CppHoverHandler); addHoverHandler(CppModelManager::instance()->createHoverHandler());
addHoverHandler(new ColorPreviewHoverHandler); addHoverHandler(new ColorPreviewHoverHandler);
addHoverHandler(new ResourcePreviewHoverHandler); addHoverHandler(new ResourcePreviewHoverHandler);
} }
@@ -145,7 +145,6 @@ bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err
{ {
Q_UNUSED(errorMessage) Q_UNUSED(errorMessage)
addAutoReleasedObject(new CppEditorFactory);
addAutoReleasedObject(new CppOutlineWidgetFactory); addAutoReleasedObject(new CppOutlineWidgetFactory);
addAutoReleasedObject(new CppTypeHierarchyFactory); addAutoReleasedObject(new CppTypeHierarchyFactory);
addAutoReleasedObject(new CppIncludeHierarchyFactory); addAutoReleasedObject(new CppIncludeHierarchyFactory);
@@ -268,6 +267,10 @@ bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err
void CppEditorPlugin::extensionsInitialized() 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()) { if (!HostOsInfo::isMacHost() && !HostOsInfo::isWindowsHost()) {
FileIconProvider::registerIconOverlayForMimeType( FileIconProvider::registerIconOverlayForMimeType(
QIcon(creatorTheme()->imageFile(Theme::IconOverlayCppSource, QLatin1String(":/cppeditor/images/qt_cpp.png"))), QIcon(creatorTheme()->imageFile(Theme::IconOverlayCppSource, QLatin1String(":/cppeditor/images/qt_cpp.png"))),

View File

@@ -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

View File

@@ -29,13 +29,13 @@
#include "cppeditorwidget.h" #include "cppeditorwidget.h"
#include "cppeditorconstants.h" #include "cppeditorconstants.h"
#include "cppeditorplugin.h" #include "cppeditorplugin.h"
#include "cppelementevaluator.h"
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/fileiconprovider.h> #include <coreplugin/fileiconprovider.h>
#include <coreplugin/find/itemviewfind.h> #include <coreplugin/find/itemviewfind.h>
#include <cpptools/baseeditordocumentprocessor.h> #include <cpptools/baseeditordocumentprocessor.h>
#include <cpptools/cppelementevaluator.h>
#include <cpptools/cppmodelmanager.h> #include <cpptools/cppmodelmanager.h>
#include <cpptools/cpptoolsbridge.h> #include <cpptools/cpptoolsbridge.h>
#include <cpptools/editordocumenthandle.h> #include <cpptools/editordocumenthandle.h>

View File

@@ -28,11 +28,11 @@
#include "cppeditorconstants.h" #include "cppeditorconstants.h"
#include "cppeditor.h" #include "cppeditor.h"
#include "cppeditorwidget.h" #include "cppeditorwidget.h"
#include "cppelementevaluator.h"
#include "cppeditorplugin.h" #include "cppeditorplugin.h"
#include <coreplugin/find/itemviewfind.h> #include <coreplugin/find/itemviewfind.h>
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <cpptools/cppelementevaluator.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/annotateditemdelegate.h> #include <utils/annotateditemdelegate.h>
#include <utils/navigationtreeview.h> #include <utils/navigationtreeview.h>
@@ -46,6 +46,7 @@
#include <QVBoxLayout> #include <QVBoxLayout>
using namespace CppEditor; using namespace CppEditor;
using namespace CppTools;
using namespace CppEditor::Internal; using namespace CppEditor::Internal;
using namespace Utils; using namespace Utils;

View File

@@ -47,11 +47,12 @@ class NavigationTreeView;
class AnnotatedItemDelegate; class AnnotatedItemDelegate;
} }
namespace CppTools { class CppClass; }
namespace CppEditor { namespace CppEditor {
namespace Internal { namespace Internal {
class CppEditorWidget; class CppEditorWidget;
class CppClass;
class CppTypeHierarchyModel : public QStandardItemModel class CppTypeHierarchyModel : public QStandardItemModel
{ {
@@ -75,8 +76,8 @@ public:
void perform(); void perform();
private: private:
typedef QList<CppClass> CppClass::*HierarchyMember; typedef QList<CppTools::CppClass> CppTools::CppClass::*HierarchyMember;
void buildHierarchy(const CppClass &cppClass, QStandardItem *parent, void buildHierarchy(const CppTools::CppClass &cppClass, QStandardItem *parent,
bool isRoot, HierarchyMember member); bool isRoot, HierarchyMember member);
void showNoTypeHierarchyLabel(); void showNoTypeHierarchyLabel();
void showTypeHierarchy(); void showTypeHierarchy();

View File

@@ -27,8 +27,8 @@
#include "cppeditorwidget.h" #include "cppeditorwidget.h"
#include "cppeditorplugin.h" #include "cppeditorplugin.h"
#include "cppeditortestcase.h" #include "cppeditortestcase.h"
#include "cppelementevaluator.h"
#include <cpptools/cppelementevaluator.h>
#include <cpptools/cppfollowsymbolundercursor.h> #include <cpptools/cppfollowsymbolundercursor.h>
#include <cpptools/cppvirtualfunctionassistprovider.h> #include <cpptools/cppvirtualfunctionassistprovider.h>
#include <cpptools/cppvirtualfunctionproposalitem.h> #include <cpptools/cppvirtualfunctionproposalitem.h>

View File

@@ -97,6 +97,13 @@ void BaseEditorDocumentProcessor::setParserConfig(
parser()->setConfiguration(config); parser()->setConfiguration(config);
} }
QFuture<ToolTipInfo> BaseEditorDocumentProcessor::toolTipInfo(const QByteArray &/*codecName*/,
int /*line*/,
int /*column*/)
{
return QFuture<ToolTipInfo>();
}
void BaseEditorDocumentProcessor::runParser(QFutureInterface<void> &future, void BaseEditorDocumentProcessor::runParser(QFutureInterface<void> &future,
BaseEditorDocumentParser::Ptr parser, BaseEditorDocumentParser::Ptr parser,
BaseEditorDocumentParser::UpdateParams updateParams) BaseEditorDocumentParser::UpdateParams updateParams)

View File

@@ -32,6 +32,7 @@
#include "cpptools_global.h" #include "cpptools_global.h"
#include <texteditor/codeassist/assistinterface.h> #include <texteditor/codeassist/assistinterface.h>
#include <texteditor/helpitem.h>
#include <texteditor/quickfix.h> #include <texteditor/quickfix.h>
#include <texteditor/texteditor.h> #include <texteditor/texteditor.h>
#include <texteditor/textdocument.h> #include <texteditor/textdocument.h>
@@ -48,6 +49,18 @@ class TextDocument;
namespace CppTools { 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 class CPPTOOLS_EXPORT BaseEditorDocumentProcessor : public QObject
{ {
Q_OBJECT Q_OBJECT
@@ -78,6 +91,7 @@ public:
virtual QFuture<CursorInfo> cursorInfo(const CursorInfoParams &params) = 0; virtual QFuture<CursorInfo> cursorInfo(const CursorInfoParams &params) = 0;
virtual QFuture<CursorInfo> requestLocalReferences(const QTextCursor &cursor) = 0; virtual QFuture<CursorInfo> requestLocalReferences(const QTextCursor &cursor) = 0;
virtual QFuture<SymbolInfo> requestFollowSymbol(int line, int column) = 0; virtual QFuture<SymbolInfo> requestFollowSymbol(int line, int column) = 0;
virtual QFuture<ToolTipInfo> toolTipInfo(const QByteArray &codecName, int line, int column);
public: public:
using HeaderErrorDiagnosticWidgetCreator = std::function<QWidget*()>; using HeaderErrorDiagnosticWidgetCreator = std::function<QWidget*()>;

View File

@@ -42,8 +42,7 @@
using namespace CPlusPlus; using namespace CPlusPlus;
namespace CppEditor { namespace CppTools {
namespace Internal {
static QStringList stripName(const QString &name) static QStringList stripName(const QString &name)
{ {
@@ -471,5 +470,4 @@ CppEnumerator::CppEnumerator(EnumeratorDeclaration *declaration)
tooltip.append(QLatin1String(" = ") + enumeratorValue); tooltip.append(QLatin1String(" = ") + enumeratorValue);
} }
} // namespace Internal } // namespace CppTools
} // namespace CppEditor

View File

@@ -25,6 +25,8 @@
#pragma once #pragma once
#include "cpptools_global.h"
#include <texteditor/texteditor.h> #include <texteditor/texteditor.h>
#include <texteditor/helpitem.h> #include <texteditor/helpitem.h>
@@ -41,14 +43,11 @@ class LookupItem;
class LookupContext; class LookupContext;
} }
namespace CppTools { class CppModelManager; } namespace CppTools {
namespace CppEditor {
namespace Internal {
class CppElement; class CppElement;
class CppModelManager;
class CppElementEvaluator class CPPTOOLS_EXPORT CppElementEvaluator
{ {
public: public:
explicit CppElementEvaluator(TextEditor::TextEditorWidget *editor); explicit CppElementEvaluator(TextEditor::TextEditorWidget *editor);
@@ -82,7 +81,7 @@ private:
QString m_diagnosis; QString m_diagnosis;
}; };
class CppElement class CPPTOOLS_EXPORT CppElement
{ {
protected: protected:
CppElement(); CppElement();
@@ -189,5 +188,4 @@ public:
explicit CppEnumerator(CPlusPlus::EnumeratorDeclaration *declaration); explicit CppEnumerator(CPlusPlus::EnumeratorDeclaration *declaration);
}; };
} // namespace Internal } // namespace CppTools
} // namespace CppEditor

View File

@@ -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

View File

@@ -25,21 +25,20 @@
#pragma once #pragma once
#include "cpptools_global.h"
#include <texteditor/basehoverhandler.h> #include <texteditor/basehoverhandler.h>
namespace CppEditor { namespace CppTools {
namespace Internal {
class CppHoverHandler : public TextEditor::BaseHoverHandler class CPPTOOLS_EXPORT CppHoverHandler : public TextEditor::BaseHoverHandler
{ {
public:
static QString tooltipTextForHelpItem(const TextEditor::HelpItem &help);
private: private:
void identifyMatch(TextEditor::TextEditorWidget *editorWidget, int pos) override; void identifyMatch(TextEditor::TextEditorWidget *editorWidget, int pos) override;
void decorateToolTip() override; void decorateToolTip() override;
void operateTooltip(TextEditor::TextEditorWidget *editorWidget, const QPoint &point) override;
private:
int m_positionForEditorDocumentProcessor = -1;
}; };
} // namespace Internal } // namespace CppTools
} // namespace CppEditor

View File

@@ -1293,10 +1293,15 @@ CppCompletionAssistProvider *CppModelManager::completionAssistProvider() const
return d->m_activeModelManagerSupport->completionAssistProvider(); return d->m_activeModelManagerSupport->completionAssistProvider();
} }
BaseEditorDocumentProcessor *CppModelManager::editorDocumentProcessor( TextEditor::BaseHoverHandler *CppModelManager::createHoverHandler() const
{
return d->m_activeModelManagerSupport->createHoverHandler();
}
BaseEditorDocumentProcessor *CppModelManager::createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) const TextEditor::TextDocument *baseTextDocument) const
{ {
return d->m_activeModelManagerSupport->editorDocumentProcessor(baseTextDocument); return d->m_activeModelManagerSupport->createEditorDocumentProcessor(baseTextDocument);
} }
void CppModelManager::setIndexingSupport(CppIndexingSupport *indexingSupport) void CppModelManager::setIndexingSupport(CppIndexingSupport *indexingSupport)

View File

@@ -44,7 +44,10 @@ class IEditor;
} }
namespace CPlusPlus { class LookupContext; } namespace CPlusPlus { class LookupContext; }
namespace ProjectExplorer { class Project; } namespace ProjectExplorer { class Project; }
namespace TextEditor { class TextDocument; } namespace TextEditor {
class BaseHoverHandler;
class TextDocument;
} // namespace TextEditor
namespace CppTools { namespace CppTools {
@@ -172,8 +175,9 @@ public:
void activateClangCodeModel(ModelManagerSupportProvider *modelManagerSupportProvider); void activateClangCodeModel(ModelManagerSupportProvider *modelManagerSupportProvider);
CppCompletionAssistProvider *completionAssistProvider() const; CppCompletionAssistProvider *completionAssistProvider() const;
BaseEditorDocumentProcessor *editorDocumentProcessor( BaseEditorDocumentProcessor *createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) const; TextEditor::TextDocument *baseTextDocument) const;
TextEditor::BaseHoverHandler *createHoverHandler() const;
FollowSymbolInterface &followSymbolInterface() const; FollowSymbolInterface &followSymbolInterface() const;
void setIndexingSupport(CppIndexingSupport *indexingSupport); void setIndexingSupport(CppIndexingSupport *indexingSupport);

View File

@@ -30,7 +30,10 @@
#include <QSharedPointer> #include <QSharedPointer>
#include <QString> #include <QString>
namespace TextEditor { class TextDocument; } namespace TextEditor {
class TextDocument;
class BaseHoverHandler;
} // namespace TextEditor
namespace CppTools { namespace CppTools {
@@ -48,7 +51,8 @@ public:
virtual ~ModelManagerSupport() = 0; virtual ~ModelManagerSupport() = 0;
virtual CppCompletionAssistProvider *completionAssistProvider() = 0; virtual CppCompletionAssistProvider *completionAssistProvider() = 0;
virtual BaseEditorDocumentProcessor *editorDocumentProcessor( virtual TextEditor::BaseHoverHandler *createHoverHandler() = 0;
virtual BaseEditorDocumentProcessor *createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) = 0; TextEditor::TextDocument *baseTextDocument) = 0;
virtual FollowSymbolInterface &followSymbolInterface() = 0; virtual FollowSymbolInterface &followSymbolInterface() = 0;
virtual RefactoringEngineInterface &refactoringEngineInterface() = 0; virtual RefactoringEngineInterface &refactoringEngineInterface() = 0;

View File

@@ -26,6 +26,7 @@
#include "cppcompletionassist.h" #include "cppcompletionassist.h"
#include "cppmodelmanagersupportinternal.h" #include "cppmodelmanagersupportinternal.h"
#include "cppfollowsymbolundercursor.h" #include "cppfollowsymbolundercursor.h"
#include "cpphoverhandler.h"
#include "cpprefactoringengine.h" #include "cpprefactoringengine.h"
#include "builtineditordocumentprocessor.h" #include "builtineditordocumentprocessor.h"
@@ -63,7 +64,7 @@ ModelManagerSupportInternal::~ModelManagerSupportInternal()
{ {
} }
BaseEditorDocumentProcessor *ModelManagerSupportInternal::editorDocumentProcessor( BaseEditorDocumentProcessor *ModelManagerSupportInternal::createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) TextEditor::TextDocument *baseTextDocument)
{ {
return new BuiltinEditorDocumentProcessor(baseTextDocument); return new BuiltinEditorDocumentProcessor(baseTextDocument);
@@ -74,6 +75,11 @@ CppCompletionAssistProvider *ModelManagerSupportInternal::completionAssistProvid
return m_completionAssistProvider.data(); return m_completionAssistProvider.data();
} }
TextEditor::BaseHoverHandler *ModelManagerSupportInternal::createHoverHandler()
{
return new CppHoverHandler;
}
FollowSymbolInterface &ModelManagerSupportInternal::followSymbolInterface() FollowSymbolInterface &ModelManagerSupportInternal::followSymbolInterface()
{ {
return *m_followSymbol; return *m_followSymbol;

View File

@@ -41,7 +41,8 @@ public:
virtual ~ModelManagerSupportInternal(); virtual ~ModelManagerSupportInternal();
CppCompletionAssistProvider *completionAssistProvider() final; CppCompletionAssistProvider *completionAssistProvider() final;
BaseEditorDocumentProcessor *editorDocumentProcessor( TextEditor::BaseHoverHandler *createHoverHandler() final;
BaseEditorDocumentProcessor *createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) final; TextEditor::TextDocument *baseTextDocument) final;
FollowSymbolInterface &followSymbolInterface() final; FollowSymbolInterface &followSymbolInterface() final;
RefactoringEngineInterface &refactoringEngineInterface() final; RefactoringEngineInterface &refactoringEngineInterface() final;

View File

@@ -32,11 +32,13 @@ HEADERS += \
cppdoxygen.h \ cppdoxygen.h \
cppeditoroutline.h \ cppeditoroutline.h \
cppeditorwidgetinterface.h \ cppeditorwidgetinterface.h \
cppelementevaluator.h \
cppfileiterationorder.h \ cppfileiterationorder.h \
cppfilesettingspage.h \ cppfilesettingspage.h \
cppfindreferences.h \ cppfindreferences.h \
cppfollowsymbolundercursor.h \ cppfollowsymbolundercursor.h \
cppfunctionsfilter.h \ cppfunctionsfilter.h \
cpphoverhandler.h \
cppincludesfilter.h \ cppincludesfilter.h \
cppindexingsupport.h \ cppindexingsupport.h \
cpplocalsymbols.h \ cpplocalsymbols.h \
@@ -125,11 +127,13 @@ SOURCES += \
cppcurrentdocumentfilter.cpp \ cppcurrentdocumentfilter.cpp \
cppeditoroutline.cpp \ cppeditoroutline.cpp \
cppdoxygen.cpp \ cppdoxygen.cpp \
cppelementevaluator.cpp \
cppfileiterationorder.cpp \ cppfileiterationorder.cpp \
cppfilesettingspage.cpp \ cppfilesettingspage.cpp \
cppfindreferences.cpp \ cppfindreferences.cpp \
cppfollowsymbolundercursor.cpp \ cppfollowsymbolundercursor.cpp \
cppfunctionsfilter.cpp \ cppfunctionsfilter.cpp \
cpphoverhandler.cpp \
cppincludesfilter.cpp \ cppincludesfilter.cpp \
cppindexingsupport.cpp \ cppindexingsupport.cpp \
cpplocalsymbols.cpp \ cpplocalsymbols.cpp \

View File

@@ -90,6 +90,8 @@ Project {
"cppeditoroutline.cpp", "cppeditoroutline.cpp",
"cppeditoroutline.h", "cppeditoroutline.h",
"cppeditorwidgetinterface.h", "cppeditorwidgetinterface.h",
"cppelementevaluator.cpp",
"cppelementevaluator.h",
"cppfileiterationorder.cpp", "cppfileiterationorder.cpp",
"cppfileiterationorder.h", "cppfileiterationorder.h",
"cppfilesettingspage.cpp", "cppfilesettingspage.cpp",
@@ -101,6 +103,8 @@ Project {
"cppfollowsymbolundercursor.h", "cppfollowsymbolundercursor.h",
"cppfunctionsfilter.cpp", "cppfunctionsfilter.cpp",
"cppfunctionsfilter.h", "cppfunctionsfilter.h",
"cpphoverhandler.cpp",
"cpphoverhandler.h",
"cppincludesfilter.cpp", "cppincludesfilter.cpp",
"cppincludesfilter.h", "cppincludesfilter.h",
"cppindexingsupport.cpp", "cppindexingsupport.cpp",

View File

@@ -3179,7 +3179,8 @@ QWidget *mainWindow()
void raiseWatchersWindow() void raiseWatchersWindow()
{ {
return dd->m_mainWindow->raiseDock(DOCKWIDGET_WATCHERS); if (currentEngine()->state() != DebuggerNotReady)
dd->m_mainWindow->raiseDock(DOCKWIDGET_WATCHERS);
} }
bool isRegistersWindowVisible() bool isRegistersWindowVisible()

View File

@@ -133,6 +133,7 @@ private:
private: private:
qmt::ModelController *m_modelController = nullptr; qmt::ModelController *m_modelController = nullptr;
QMultiHash<QString, Node> m_filePaths; QMultiHash<QString, Node> m_filePaths;
QHash<QString, qmt::MComponent *> m_filePathComponentsMap;
}; };
void UpdateIncludeDependenciesVisitor::setModelController(qmt::ModelController *modelController) void UpdateIncludeDependenciesVisitor::setModelController(qmt::ModelController *modelController)
@@ -161,6 +162,16 @@ void UpdateIncludeDependenciesVisitor::visitMComponent(qmt::MComponent *componen
if (document) { if (document) {
foreach (const CPlusPlus::Document::Include &include, document->resolvedIncludes()) { foreach (const CPlusPlus::Document::Include &include, document->resolvedIncludes()) {
QString includeFilePath = include.resolvedFileName(); 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); qmt::MComponent *includeComponent = findComponentFromFilePath(includeFilePath);
if (includeComponent && includeComponent != component) { if (includeComponent && includeComponent != component) {
// add dependency between components // add dependency between components
@@ -312,10 +323,16 @@ void UpdateIncludeDependenciesVisitor::collectElementPaths(const ProjectExplorer
qmt::MComponent *UpdateIncludeDependenciesVisitor::findComponentFromFilePath(const QString &filePath) qmt::MComponent *UpdateIncludeDependenciesVisitor::findComponentFromFilePath(const QString &filePath)
{ {
const auto it = m_filePathComponentsMap.find(filePath);
if (it != m_filePathComponentsMap.cend())
return it.value();
FindComponentFromFilePath visitor; FindComponentFromFilePath visitor;
visitor.setFilePath(filePath); visitor.setFilePath(filePath);
m_modelController->rootPackage()->accept(&visitor); 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, bool UpdateIncludeDependenciesVisitor::haveDependency(const qmt::MObject *source,
@@ -390,7 +407,8 @@ void ComponentViewController::createComponentModel(const QString &filePath,
const QString &anchorFolder) const QString &anchorFolder)
{ {
d->diagramSceneController->modelController()->startResetModel(); d->diagramSceneController->modelController()->startResetModel();
doCreateComponentModel(filePath, diagram, anchorFolder); doCreateComponentModel(filePath, diagram, anchorFolder, false);
doCreateComponentModel(filePath, diagram, anchorFolder, true);
d->diagramSceneController->modelController()->finishResetModel(true); d->diagramSceneController->modelController()->finishResetModel(true);
} }
@@ -404,7 +422,8 @@ void ComponentViewController::updateIncludeDependencies(qmt::MPackage *rootPacka
d->diagramSceneController->modelController()->finishResetModel(true); 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)) { for (const QString &fileName : QDir(filePath).entryList(QDir::Files)) {
QString file = filePath + "/" + fileName; QString file = filePath + "/" + fileName;
@@ -413,18 +432,20 @@ void ComponentViewController::doCreateComponentModel(const QString &filePath, qm
bool isSource = false; bool isSource = false;
CppTools::ProjectFile::Kind kind = CppTools::ProjectFile::classify(file); CppTools::ProjectFile::Kind kind = CppTools::ProjectFile::classify(file);
switch (kind) { switch (kind) {
case CppTools::ProjectFile::AmbiguousHeader:
case CppTools::ProjectFile::CHeader:
case CppTools::ProjectFile::CSource: case CppTools::ProjectFile::CSource:
case CppTools::ProjectFile::CXXHeader:
case CppTools::ProjectFile::CXXSource: case CppTools::ProjectFile::CXXSource:
case CppTools::ProjectFile::ObjCSource: case CppTools::ProjectFile::ObjCSource:
case CppTools::ProjectFile::ObjCHeader:
case CppTools::ProjectFile::ObjCXXSource: case CppTools::ProjectFile::ObjCXXSource:
case CppTools::ProjectFile::ObjCXXHeader:
case CppTools::ProjectFile::CudaSource: case CppTools::ProjectFile::CudaSource:
case CppTools::ProjectFile::OpenCLSource: 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; break;
case CppTools::ProjectFile::Unclassified: case CppTools::ProjectFile::Unclassified:
case CppTools::ProjectFile::Unsupported: 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)) { for (const QString &fileName : QDir(filePath).entryList(QDir::Dirs|QDir::NoDotAndDotDot)) {
QString file = filePath + "/" + fileName; 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 Internal
} // namespace ModelEditor } // namespace ModelEditor

View File

@@ -58,8 +58,9 @@ public:
void updateIncludeDependencies(qmt::MPackage *rootPackage); void updateIncludeDependencies(qmt::MPackage *rootPackage);
private: private:
void doCreateComponentModel(const QString &filePath, void doCreateComponentModel(const QString &filePath, qmt::MDiagram *diagram,
qmt::MDiagram *diagram, const QString &anchorFolder); const QString &anchorFolder, bool scanHeaders);
bool isProxyHeader(const QString &file) const;
ComponentViewControllerPrivate *d; ComponentViewControllerPrivate *d;
}; };

View File

@@ -382,15 +382,15 @@ QString BaseQtVersion::defaultUnexpandedDisplayName(const FileName &qmakePath, b
QDir dir = qmakePath.toFileInfo().absoluteDir(); QDir dir = qmakePath.toFileInfo().absoluteDir();
do { do {
const QString dirName = dir.dirName(); const QString dirName = dir.dirName();
if (dirName == QLatin1String("usr")) { // System-installed Qt. if (dirName == "usr") { // System-installed Qt.
location = QCoreApplication::translate("QtVersion", "System"); location = QCoreApplication::translate("QtVersion", "System");
break; break;
} }
location = dirName; location = dirName;
// Also skip default checkouts named 'qt'. Parent dir might have descriptive name. // Also skip default checkouts named 'qt'. Parent dir might have descriptive name.
if (dirName.compare(QLatin1String("bin"), Qt::CaseInsensitive) if (dirName.compare("bin", Qt::CaseInsensitive)
&& dirName.compare(QLatin1String("qtbase"), Qt::CaseInsensitive) && dirName.compare("qtbase", Qt::CaseInsensitive)
&& dirName.compare(QLatin1String("qt"), Qt::CaseInsensitive)) { && dirName.compare("qt", Qt::CaseInsensitive)) {
break; break;
} }
} while (!dir.isRoot() && dir.cdUp()); } while (!dir.isRoot() && dir.cdUp());
@@ -527,7 +527,7 @@ QList<Task> BaseQtVersion::validateKit(const Kit *k)
QString qtAbiString; QString qtAbiString;
foreach (const Abi &qtAbi, qtAbis) { foreach (const Abi &qtAbi, qtAbis) {
if (!qtAbiString.isEmpty()) if (!qtAbiString.isEmpty())
qtAbiString.append(QLatin1Char(' ')); qtAbiString.append(' ');
qtAbiString.append(qtAbi.toString()); qtAbiString.append(qtAbi.toString());
if (!fullMatch) if (!fullMatch)
@@ -589,13 +589,13 @@ FileName BaseQtVersion::mkspecsPath() const
if (result.isEmpty()) if (result.isEmpty())
result = FileName::fromUserInput(qmakeProperty("QMAKE_MKSPECS")); result = FileName::fromUserInput(qmakeProperty("QMAKE_MKSPECS"));
else else
result.appendPath(QLatin1String("mkspecs")); result.appendPath("mkspecs");
return result; return result;
} }
FileName BaseQtVersion::qmlBinPath() const 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 FileName BaseQtVersion::librarySearchPath() const
@@ -623,13 +623,13 @@ FileNameList BaseQtVersion::directoriesToIgnoreInProjectTree() const
QString BaseQtVersion::qtNamespace() const QString BaseQtVersion::qtNamespace() const
{ {
ensureMkSpecParsed(); ensureMkSpecParsed();
return m_mkspecValues.value(QLatin1String(MKSPEC_VALUE_NAMESPACE)); return m_mkspecValues.value(MKSPEC_VALUE_NAMESPACE);
} }
QString BaseQtVersion::qtLibInfix() const QString BaseQtVersion::qtLibInfix() const
{ {
ensureMkSpecParsed(); ensureMkSpecParsed();
return m_mkspecValues.value(QLatin1String(MKSPEC_VALUE_LIBINFIX)); return m_mkspecValues.value(MKSPEC_VALUE_LIBINFIX);
} }
bool BaseQtVersion::isFrameworkBuild() const bool BaseQtVersion::isFrameworkBuild() const
@@ -655,15 +655,15 @@ void BaseQtVersion::setId(int id)
void BaseQtVersion::fromMap(const QVariantMap &map) 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 if (m_id == -1) // this happens on adding from installer, see updateFromInstaller => get a new unique id
m_id = QtVersionManager::getUniqueId(); m_id = QtVersionManager::getUniqueId();
m_unexpandedDisplayName = map.value(QLatin1String(Constants::QTVERSIONNAME)).toString(); m_unexpandedDisplayName = map.value(Constants::QTVERSIONNAME).toString();
m_isAutodetected = map.value(QLatin1String(QTVERSIONAUTODETECTED)).toBool(); m_isAutodetected = map.value(QTVERSIONAUTODETECTED).toBool();
if (m_isAutodetected) if (m_isAutodetected)
m_autodetectionSource = map.value(QLatin1String(QTVERSIONAUTODETECTIONSOURCE)).toString(); m_autodetectionSource = map.value(QTVERSIONAUTODETECTIONSOURCE).toString();
QString string = map.value(QLatin1String(QTVERSIONQMAKEPATH)).toString(); QString string = map.value(QTVERSIONQMAKEPATH).toString();
if (string.startsWith(QLatin1Char('~'))) if (string.startsWith('~'))
string.remove(0, 1).prepend(QDir::homePath()); string.remove(0, 1).prepend(QDir::homePath());
m_qtSources = Utils::FileName::fromUserInput( m_qtSources = Utils::FileName::fromUserInput(
@@ -683,12 +683,12 @@ void BaseQtVersion::fromMap(const QVariantMap &map)
QVariantMap BaseQtVersion::toMap() const QVariantMap BaseQtVersion::toMap() const
{ {
QVariantMap result; QVariantMap result;
result.insert(QLatin1String(Constants::QTVERSIONID), uniqueId()); result.insert(Constants::QTVERSIONID, uniqueId());
result.insert(QLatin1String(Constants::QTVERSIONNAME), unexpandedDisplayName()); result.insert(Constants::QTVERSIONNAME, unexpandedDisplayName());
result.insert(QLatin1String(QTVERSIONAUTODETECTED), isAutodetected()); result.insert(QTVERSIONAUTODETECTED, isAutodetected());
if (isAutodetected()) if (isAutodetected())
result.insert(QLatin1String(QTVERSIONAUTODETECTIONSOURCE), autodetectionSource()); result.insert(QTVERSIONAUTODETECTIONSOURCE, autodetectionSource());
result.insert(QLatin1String(QTVERSIONQMAKEPATH), qmakeCommand().toString()); result.insert(QTVERSIONQMAKEPATH, qmakeCommand().toString());
return result; return result;
} }
@@ -858,16 +858,16 @@ QString BaseQtVersion::toHtml(bool verbose) const
foreach (const ProKey &key, keys) { foreach (const ProKey &key, keys) {
const QString &value = vInfo.value(key).toQString(); const QString &value = vInfo.value(key).toQString();
QString variableName = key.toQString(); QString variableName = key.toQString();
if (variableName != QLatin1String("QMAKE_MKSPECS") if (variableName != "QMAKE_MKSPECS"
&& !variableName.endsWith(QLatin1String("/raw"))) { && !variableName.endsWith("/raw")) {
bool isPath = false; bool isPath = false;
if (variableName.contains(QLatin1String("_HOST_")) if (variableName.contains("_HOST_")
|| variableName.contains(QLatin1String("_INSTALL_"))) { || variableName.contains("_INSTALL_")) {
if (!variableName.endsWith(QLatin1String("/get"))) if (!variableName.endsWith("/get"))
continue; continue;
variableName.chop(4); variableName.chop(4);
isPath = true; isPath = true;
} else if (variableName == QLatin1String("QT_SYSROOT")) { } else if (variableName == "QT_SYSROOT") {
isPath = true; isPath = true;
} }
str << "<tr><td><pre>" << variableName << "</pre></td><td>"; str << "<tr><td><pre>" << variableName << "</pre></td><td>";
@@ -946,7 +946,7 @@ QString BaseQtVersion::findHostBinary(HostBinaries binary) const
switch (binary) { switch (binary) {
case Designer: case Designer:
case Linguist: case Linguist:
baseDir = m_mkspecValues.value(QLatin1String("QT.designer.bins")); baseDir = m_mkspecValues.value("QT.designer.bins");
break; break;
case Uic: case Uic:
case QScxmlc: case QScxmlc:
@@ -960,33 +960,32 @@ QString BaseQtVersion::findHostBinary(HostBinaries binary) const
if (baseDir.isEmpty()) if (baseDir.isEmpty())
return QString(); return QString();
if (!baseDir.endsWith(QLatin1Char('/'))) if (!baseDir.endsWith('/'))
baseDir += QLatin1Char('/'); baseDir += '/';
QStringList possibleCommands; QStringList possibleCommands;
switch (binary) { switch (binary) {
case Designer: case Designer:
if (HostOsInfo::isMacHost()) if (HostOsInfo::isMacHost())
possibleCommands << QLatin1String("Designer.app/Contents/MacOS/Designer"); possibleCommands << "Designer.app/Contents/MacOS/Designer";
else else
possibleCommands << HostOsInfo::withExecutableSuffix(QLatin1String("designer")); possibleCommands << HostOsInfo::withExecutableSuffix("designer");
break; break;
case Linguist: case Linguist:
if (HostOsInfo::isMacHost()) if (HostOsInfo::isMacHost())
possibleCommands << QLatin1String("Linguist.app/Contents/MacOS/Linguist"); possibleCommands << "Linguist.app/Contents/MacOS/Linguist";
else else
possibleCommands << HostOsInfo::withExecutableSuffix(QLatin1String("linguist")); possibleCommands << HostOsInfo::withExecutableSuffix("linguist");
break; break;
case Uic: case Uic:
if (HostOsInfo::isWindowsHost()) { if (HostOsInfo::isWindowsHost()) {
possibleCommands << QLatin1String("uic.exe"); possibleCommands << "uic.exe";
} else { } else {
possibleCommands << QLatin1String("uic-qt4") << QLatin1String("uic4") possibleCommands << "uic-qt4" << "uic4" << "uic";
<< QLatin1String("uic");
} }
break; break;
case QScxmlc: case QScxmlc:
possibleCommands << HostOsInfo::withExecutableSuffix(QLatin1String("qscxmlc")); possibleCommands << HostOsInfo::withExecutableSuffix("qscxmlc");
break; break;
default: default:
Q_ASSERT(false); Q_ASSERT(false);
@@ -1027,7 +1026,7 @@ void BaseQtVersion::updateMkspec() const
m_mkspec = m_mkspec.relativeChildPath(baseMkspecDir); m_mkspec = m_mkspec.relativeChildPath(baseMkspecDir);
// qDebug() << "Setting mkspec to"<<mkspec; // qDebug() << "Setting mkspec to"<<mkspec;
} else { } else {
FileName sourceMkSpecPath = sourcePath().appendPath(QLatin1String("mkspecs")); FileName sourceMkSpecPath = sourcePath().appendPath("mkspecs");
if (m_mkspec.isChildOf(sourceMkSpecPath)) { if (m_mkspec.isChildOf(sourceMkSpecPath)) {
m_mkspec = m_mkspec.relativeChildPath(sourceMkSpecPath); m_mkspec = m_mkspec.relativeChildPath(sourceMkSpecPath);
} else { } else {
@@ -1062,25 +1061,25 @@ void BaseQtVersion::ensureMkSpecParsed() const
void BaseQtVersion::parseMkSpec(ProFileEvaluator *evaluator) const void BaseQtVersion::parseMkSpec(ProFileEvaluator *evaluator) const
{ {
m_configValues = evaluator->values(QLatin1String("CONFIG")); m_configValues = evaluator->values("CONFIG");
m_qtConfigValues = evaluator->values(QLatin1String("QT_CONFIG")); m_qtConfigValues = evaluator->values("QT_CONFIG");
m_defaultConfigIsDebugAndRelease = false; m_defaultConfigIsDebugAndRelease = false;
m_frameworkBuild = false; m_frameworkBuild = false;
foreach (const QString &value, m_configValues) { foreach (const QString &value, m_configValues) {
if (value == QLatin1String("debug")) if (value == "debug")
m_defaultConfigIsDebug = true; m_defaultConfigIsDebug = true;
else if (value == QLatin1String("release")) else if (value == "release")
m_defaultConfigIsDebug = false; m_defaultConfigIsDebug = false;
else if (value == QLatin1String("build_all")) else if (value == "build_all")
m_defaultConfigIsDebugAndRelease = true; m_defaultConfigIsDebugAndRelease = true;
else if (value == QLatin1String("qt_framework")) else if (value == "qt_framework")
m_frameworkBuild = true; m_frameworkBuild = true;
} }
const QString designerBins = QLatin1String("QT.designer.bins"); const QString designerBins = "QT.designer.bins";
const QString qmlBins = QLatin1String("QT.qml.bins"); const QString qmlBins = "QT.qml.bins";
const QString declarativeBins = QLatin1String("QT.declarative.bins"); const QString declarativeBins = "QT.declarative.bins";
const QString libinfix = QLatin1String(MKSPEC_VALUE_LIBINFIX); const QString libinfix = MKSPEC_VALUE_LIBINFIX;
const QString ns = QLatin1String(MKSPEC_VALUE_NAMESPACE); const QString ns = MKSPEC_VALUE_NAMESPACE;
m_mkspecValues.insert(designerBins, evaluator->value(designerBins)); m_mkspecValues.insert(designerBins, evaluator->value(designerBins));
m_mkspecValues.insert(qmlBins, evaluator->value(qmlBins)); m_mkspecValues.insert(qmlBins, evaluator->value(qmlBins));
m_mkspecValues.insert(declarativeBins, evaluator->value(declarativeBins)); 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 return true; // default spec of a Qt version
QDir mkspecDir = QDir(QDir::fromNativeSeparators(qmakeProperty("QT_HOST_DATA")) QDir mkspecDir = QDir(QDir::fromNativeSeparators(qmakeProperty("QT_HOST_DATA"))
+ QLatin1String("/mkspecs/")); + "/mkspecs/");
const QString absSpec = mkspecDir.absoluteFilePath(spec.toString()); const QString absSpec = mkspecDir.absoluteFilePath(spec.toString());
if (QFileInfo(absSpec).isDir() && QFileInfo(absSpec + "/qmake.conf").isFile()) if (QFileInfo(absSpec).isDir() && QFileInfo(absSpec + "/qmake.conf").isFile())
return true; return true;
mkspecDir.setPath(sourcePath().toString() + QLatin1String("/mkspecs/")); mkspecDir.setPath(sourcePath().toString() + "/mkspecs/");
const QString absSrcSpec = mkspecDir.absoluteFilePath(spec.toString()); const QString absSrcSpec = mkspecDir.absoluteFilePath(spec.toString());
return absSrcSpec != absSpec return absSrcSpec != absSpec
&& QFileInfo(absSrcSpec).isDir() && QFileInfo(absSrcSpec).isDir()
@@ -1239,7 +1238,7 @@ QString BaseQtVersion::qmakeProperty(const QHash<ProKey,ProString> &versionInfo,
variant == PropertyVariantGet ? "/get" : "/src")))).toQString(); variant == PropertyVariantGet ? "/get" : "/src")))).toQString();
if (!val.isNull()) if (!val.isNull())
return val; 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 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 void BaseQtVersion::addToEnvironment(const Kit *k, Environment &env) const
{ {
Q_UNUSED(k); 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 // 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; QProcess process;
process.setEnvironment(env.toStringList()); process.setEnvironment(env.toStringList());
process.start(binary.toString(), QStringList(QLatin1String("-query")), QIODevice::ReadOnly); process.start(binary.toString(), QStringList("-query"), QIODevice::ReadOnly);
if (!process.waitForStarted()) { if (!process.waitForStarted()) {
*error = QCoreApplication::translate("QtVersion", "Cannot start \"%1\": %2").arg(binary.toUserOutput()).arg(process.errorString()); *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); QString dataDir = qmakeProperty(versionInfo, "QT_HOST_DATA", PropertyVariantSrc);
if (dataDir.isEmpty()) if (dataDir.isEmpty())
return FileName(); return FileName();
return FileName::fromUserInput(dataDir + QLatin1String("/mkspecs")); return FileName::fromUserInput(dataDir + "/mkspecs");
} }
FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &versionInfo) FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &versionInfo)
@@ -1533,7 +1532,7 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve
bool qt5 = false; bool qt5 = false;
QString theSpec = qmakeProperty(versionInfo, "QMAKE_XSPEC"); QString theSpec = qmakeProperty(versionInfo, "QMAKE_XSPEC");
if (theSpec.isEmpty()) if (theSpec.isEmpty())
theSpec = QLatin1String("default"); theSpec = "default";
else else
qt5 = true; qt5 = true;
@@ -1544,7 +1543,7 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve
if (HostOsInfo::isWindowsHost()) { if (HostOsInfo::isWindowsHost()) {
if (!qt5) { if (!qt5) {
QFile f2(mkspecFullPath.toString() + QLatin1String("/qmake.conf")); QFile f2(mkspecFullPath.toString() + "/qmake.conf");
if (f2.exists() && f2.open(QIODevice::ReadOnly)) { if (f2.exists() && f2.open(QIODevice::ReadOnly)) {
while (!f2.atEnd()) { while (!f2.atEnd()) {
QByteArray line = f2.readLine(); QByteArray line = f2.readLine();
@@ -1552,16 +1551,16 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve
const QList<QByteArray> &temp = line.split('='); const QList<QByteArray> &temp = line.split('=');
if (temp.size() == 2) { if (temp.size() == 2) {
QString possibleFullPath = QString::fromLocal8Bit(temp.at(1).trimmed().constData()); QString possibleFullPath = QString::fromLocal8Bit(temp.at(1).trimmed().constData());
if (possibleFullPath.contains(QLatin1Char('$'))) { // QTBUG-28792 if (possibleFullPath.contains('$')) { // QTBUG-28792
const QRegularExpression rex(QLatin1String("\\binclude\\(([^)]+)/qmake\\.conf\\)")); const QRegularExpression rex("\\binclude\\(([^)]+)/qmake\\.conf\\)");
const QRegularExpressionMatch match = rex.match(QString::fromLocal8Bit(f2.readAll())); const QRegularExpressionMatch match = rex.match(QString::fromLocal8Bit(f2.readAll()));
if (match.hasMatch()) { if (match.hasMatch()) {
possibleFullPath = mkspecFullPath.toString() + QLatin1Char('/') possibleFullPath = mkspecFullPath.toString() + '/'
+ match.captured(1); + match.captured(1);
} }
} }
// We sometimes get a mix of different slash styles here... // 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 if (QFileInfo::exists(possibleFullPath)) // Only if the path exists
mkspecFullPath = FileName::fromUserInput(possibleFullPath); mkspecFullPath = FileName::fromUserInput(possibleFullPath);
} }
@@ -1573,7 +1572,7 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve
} }
} else { } else {
if (HostOsInfo::isMacHost()) { if (HostOsInfo::isMacHost()) {
QFile f2(mkspecFullPath.toString() + QLatin1String("/qmake.conf")); QFile f2(mkspecFullPath.toString() + "/qmake.conf");
if (f2.exists() && f2.open(QIODevice::ReadOnly)) { if (f2.exists() && f2.open(QIODevice::ReadOnly)) {
while (!f2.atEnd()) { while (!f2.atEnd()) {
QByteArray line = f2.readLine(); QByteArray line = f2.readLine();
@@ -1584,7 +1583,7 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve
if (value.contains("XCODE")) { if (value.contains("XCODE")) {
// we don't want to generate xcode projects... // we don't want to generate xcode projects...
// qDebug() << "default mkspec is xcode, falling back to g++"; // qDebug() << "default mkspec is xcode, falling back to g++";
return baseMkspecDir.appendPath(QLatin1String("macx-g++")); return baseMkspecDir.appendPath("macx-g++");
} }
} }
break; break;
@@ -1612,14 +1611,14 @@ FileName BaseQtVersion::sourcePath(const QHash<ProKey, ProString> &versionInfo)
const QString installData = qmakeProperty(versionInfo, "QT_INSTALL_PREFIX"); const QString installData = qmakeProperty(versionInfo, "QT_INSTALL_PREFIX");
QString sourcePath = installData; QString sourcePath = installData;
QFile qmakeCache(installData + QLatin1String("/.qmake.cache")); QFile qmakeCache(installData + "/.qmake.cache");
if (qmakeCache.exists() && qmakeCache.open(QIODevice::ReadOnly | QIODevice::Text)) { if (qmakeCache.exists() && qmakeCache.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream stream(&qmakeCache); QTextStream stream(&qmakeCache);
while (!stream.atEnd()) { while (!stream.atEnd()) {
QString line = stream.readLine().trimmed(); QString line = stream.readLine().trimmed();
if (line.startsWith(QLatin1String("QT_SOURCE_TREE"))) { if (line.startsWith("QT_SOURCE_TREE")) {
sourcePath = line.split(QLatin1Char('=')).at(1).trimmed(); sourcePath = line.split('=').at(1).trimmed();
if (sourcePath.startsWith(QLatin1String("$$quote("))) { if (sourcePath.startsWith("$$quote(")) {
sourcePath.remove(0, 8); sourcePath.remove(0, 8);
sourcePath.chop(1); sourcePath.chop(1);
} }
@@ -1636,7 +1635,7 @@ bool BaseQtVersion::isInSourceDirectory(const Utils::FileName &filePath)
if (source.isEmpty()) if (source.isEmpty())
return false; return false;
QDir dir = QDir(source.toString()); QDir dir = QDir(source.toString());
if (dir.dirName() == QLatin1String("qtbase")) if (dir.dirName() == "qtbase")
dir.cdUp(); dir.cdUp();
return filePath.isChildOf(dir); return filePath.isChildOf(dir);
} }
@@ -1646,7 +1645,7 @@ bool BaseQtVersion::isSubProject(const Utils::FileName &filePath) const
const Utils::FileName &source = sourcePath(); const Utils::FileName &source = sourcePath();
if (!source.isEmpty()) { if (!source.isEmpty()) {
QDir dir = QDir(source.toString()); QDir dir = QDir(source.toString());
if (dir.dirName() == QLatin1String("qtbase")) if (dir.dirName() == "qtbase")
dir.cdUp(); dir.cdUp();
if (filePath.isChildOf(dir)) if (filePath.isChildOf(dir))
@@ -1720,7 +1719,7 @@ bool BaseQtVersion::isQtQuickCompilerSupported(QString *reason) const
} }
const QString qtQuickCompilerExecutable = const QString qtQuickCompilerExecutable =
HostOsInfo::withExecutableSuffix(binPath().toString() + QLatin1String("/qtquickcompiler")); HostOsInfo::withExecutableSuffix(binPath().toString() + "/qtquickcompiler");
if (!QFileInfo::exists(qtQuickCompilerExecutable)) { if (!QFileInfo::exists(qtQuickCompilerExecutable)) {
if (reason) if (reason)
*reason = QCoreApplication::translate("BaseQtVersion", "This Qt Version does not contain Qt Quick Compiler."); *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) { foreach (const QFileInfo &info, infoList) {
const QString file = info.fileName(); const QString file = info.fileName();
if (info.isDir() if (info.isDir()
&& file.startsWith(QLatin1String("QtCore")) && file.startsWith("QtCore")
&& file.endsWith(QLatin1String(".framework"))) { && file.endsWith(".framework")) {
// handle Framework // handle Framework
FileName lib(info); FileName lib(info);
dynamicLibs.append(lib.appendPath(file.left(file.lastIndexOf(QLatin1Char('.'))))); dynamicLibs.append(lib.appendPath(file.left(file.lastIndexOf('.'))));
} else if (info.isReadable()) { } else if (info.isReadable()) {
if (file.startsWith(QLatin1String("libQtCore")) if (file.startsWith("libQtCore")
|| file.startsWith(QLatin1String("libQt5Core")) || file.startsWith("libQt5Core")
|| file.startsWith(QLatin1String("QtCore")) || file.startsWith("QtCore")
|| file.startsWith(QLatin1String("Qt5Core"))) { || file.startsWith("Qt5Core")) {
if (file.endsWith(QLatin1String(".a")) || file.endsWith(QLatin1String(".lib"))) if (file.endsWith(".a") || file.endsWith(".lib"))
staticLibs.append(FileName(info)); staticLibs.append(FileName(info));
else if (file.endsWith(QLatin1String(".dll")) else if (file.endsWith(".dll")
|| file.endsWith(QString::fromLatin1(".so.") + versionString) || file.endsWith(QString::fromLatin1(".so.") + versionString)
|| file.endsWith(QLatin1String(".so")) || file.endsWith(".so")
|| file.endsWith(QLatin1Char('.') + versionString + QLatin1String(".dylib"))) || file.endsWith(QLatin1Char('.') + versionString + ".dylib"))
dynamicLibs.append(FileName(info)); dynamicLibs.append(FileName(info));
} }
} }

View File

@@ -36,4 +36,9 @@ enum class PreferredTranslationUnit
LastUninitialized, 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 } // namespace ClangBackEnd

View File

@@ -29,10 +29,12 @@ HEADERS += \
$$PWD/clangreparsesupportivetranslationunitjob.h \ $$PWD/clangreparsesupportivetranslationunitjob.h \
$$PWD/clangrequestdocumentannotationsjob.h \ $$PWD/clangrequestdocumentannotationsjob.h \
$$PWD/clangrequestreferencesjob.h \ $$PWD/clangrequestreferencesjob.h \
$$PWD/clangrequesttooltipjob.h \
$$PWD/clangresumedocumentjob.h \ $$PWD/clangresumedocumentjob.h \
$$PWD/clangstring.h \ $$PWD/clangstring.h \
$$PWD/clangsupportivetranslationunitinitializer.h \ $$PWD/clangsupportivetranslationunitinitializer.h \
$$PWD/clangsuspenddocumentjob.h \ $$PWD/clangsuspenddocumentjob.h \
$$PWD/clangtooltipinfocollector.h \
$$PWD/clangtranslationunit.h \ $$PWD/clangtranslationunit.h \
$$PWD/clangtranslationunits.h \ $$PWD/clangtranslationunits.h \
$$PWD/clangtranslationunitupdater.h \ $$PWD/clangtranslationunitupdater.h \
@@ -86,8 +88,10 @@ SOURCES += \
$$PWD/clangreparsesupportivetranslationunitjob.cpp \ $$PWD/clangreparsesupportivetranslationunitjob.cpp \
$$PWD/clangrequestdocumentannotationsjob.cpp \ $$PWD/clangrequestdocumentannotationsjob.cpp \
$$PWD/clangrequestreferencesjob.cpp \ $$PWD/clangrequestreferencesjob.cpp \
$$PWD/clangrequesttooltipjob.cpp \
$$PWD/clangsuspenddocumentjob.cpp \ $$PWD/clangsuspenddocumentjob.cpp \
$$PWD/clangsupportivetranslationunitinitializer.cpp \ $$PWD/clangsupportivetranslationunitinitializer.cpp \
$$PWD/clangtooltipinfocollector.cpp \
$$PWD/clangtranslationunit.cpp \ $$PWD/clangtranslationunit.cpp \
$$PWD/clangtranslationunits.cpp \ $$PWD/clangtranslationunits.cpp \
$$PWD/clangtranslationunitupdater.cpp \ $$PWD/clangtranslationunitupdater.cpp \

View File

@@ -258,6 +258,7 @@ static void fillJobRequest(JobRequest &jobRequest, const MessageType &message)
jobRequest.line = message.line(); jobRequest.line = message.line();
jobRequest.column = message.column(); jobRequest.column = message.column();
jobRequest.ticketNumber = message.ticketNumber(); jobRequest.ticketNumber = message.ticketNumber();
jobRequest.textCodecName = message.fileContainer().textCodecName();
// The unsaved files might get updater later, so take the current // The unsaved files might get updater later, so take the current
// revision for the request. // revision for the request.
jobRequest.documentRevision = message.fileContainer().documentRevision(); 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) void ClangCodeModelServer::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message)
{ {
qCDebug(serverLog) << "########## updateVisibleTranslationUnits"; qCDebug(serverLog) << "########## updateVisibleTranslationUnits";

View File

@@ -61,6 +61,7 @@ public:
void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) override; void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) override;
void requestReferences(const RequestReferencesMessage &message) override; void requestReferences(const RequestReferencesMessage &message) override;
void requestFollowSymbol(const RequestFollowSymbolMessage &message) override; void requestFollowSymbol(const RequestFollowSymbolMessage &message) override;
void requestToolTip(const RequestToolTipMessage &message) override;
public: // for tests public: // for tests
const Documents &documentsForTestOnly() const; const Documents &documentsForTestOnly() const;

View File

@@ -32,6 +32,7 @@
#include "clangreparsesupportivetranslationunitjob.h" #include "clangreparsesupportivetranslationunitjob.h"
#include "clangrequestdocumentannotationsjob.h" #include "clangrequestdocumentannotationsjob.h"
#include "clangrequestreferencesjob.h" #include "clangrequestreferencesjob.h"
#include "clangrequesttooltipjob.h"
#include "clangresumedocumentjob.h" #include "clangresumedocumentjob.h"
#include "clangsuspenddocumentjob.h" #include "clangsuspenddocumentjob.h"
#include "clangupdatedocumentannotationsjob.h" #include "clangupdatedocumentannotationsjob.h"
@@ -40,6 +41,7 @@
#include <clangsupport/cmbcodecompletedmessage.h> #include <clangsupport/cmbcodecompletedmessage.h>
#include <clangsupport/followsymbolmessage.h> #include <clangsupport/followsymbolmessage.h>
#include <clangsupport/referencesmessage.h> #include <clangsupport/referencesmessage.h>
#include <clangsupport/tooltipmessage.h>
#include <utils/qtcassert.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(RequestDocumentAnnotations);
RETURN_TEXT_FOR_CASE(RequestReferences); RETURN_TEXT_FOR_CASE(RequestReferences);
RETURN_TEXT_FOR_CASE(FollowSymbol); RETURN_TEXT_FOR_CASE(FollowSymbol);
RETURN_TEXT_FOR_CASE(RequestToolTip);
RETURN_TEXT_FOR_CASE(SuspendDocument); RETURN_TEXT_FOR_CASE(SuspendDocument);
RETURN_TEXT_FOR_CASE(ResumeDocument); RETURN_TEXT_FOR_CASE(ResumeDocument);
} }
@@ -126,6 +129,7 @@ static JobRequest::ExpirationConditions expirationConditionsForType(JobRequest::
return Conditions(Condition::AnythingChanged); return Conditions(Condition::AnythingChanged);
case Type::RequestReferences: case Type::RequestReferences:
case Type::RequestDocumentAnnotations: case Type::RequestDocumentAnnotations:
case Type::RequestToolTip:
case Type::FollowSymbol: case Type::FollowSymbol:
return Conditions(Condition::DocumentClosed) return Conditions(Condition::DocumentClosed)
| Conditions(Condition::DocumentRevisionChanged); | Conditions(Condition::DocumentRevisionChanged);
@@ -153,8 +157,10 @@ static JobRequest::RunConditions conditionsForType(JobRequest::Type type)
Conditions conditions = Conditions(Condition::DocumentUnsuspended) Conditions conditions = Conditions(Condition::DocumentUnsuspended)
| Conditions(Condition::DocumentVisible); | Conditions(Condition::DocumentVisible);
if (type == Type::RequestReferences || type == Type::FollowSymbol) if (type == Type::RequestReferences || type == Type::FollowSymbol
|| type == Type::RequestToolTip) {
conditions |= Condition::CurrentDocumentRevision; conditions |= Condition::CurrentDocumentRevision;
}
if (type != Type::UpdateDocumentAnnotations && type != Type::ParseSupportiveTranslationUnit) if (type != Type::UpdateDocumentAnnotations && type != Type::ParseSupportiveTranslationUnit)
conditions |= Condition::DocumentParsed; conditions |= Condition::DocumentParsed;
@@ -192,6 +198,8 @@ IAsyncJob *JobRequest::createJob() const
return new RequestDocumentAnnotationsJob(); return new RequestDocumentAnnotationsJob();
case JobRequest::Type::RequestReferences: case JobRequest::Type::RequestReferences:
return new RequestReferencesJob(); return new RequestReferencesJob();
case JobRequest::Type::RequestToolTip:
return new RequestToolTipJob();
case JobRequest::Type::FollowSymbol: case JobRequest::Type::FollowSymbol:
return new FollowSymbolJob(); return new FollowSymbolJob();
case JobRequest::Type::SuspendDocument: case JobRequest::Type::SuspendDocument:
@@ -224,6 +232,11 @@ void JobRequest::cancelJob(ClangCodeModelClientInterface &client) const
false, false,
ticketNumber)); ticketNumber));
break; break;
case JobRequest::Type::RequestToolTip:
client.tooltip(ToolTipMessage(FileContainer(),
ToolTipInfo(),
ticketNumber));
break;
case JobRequest::Type::CompleteCode: case JobRequest::Type::CompleteCode:
client.codeCompleted(CodeCompletedMessage(CodeCompletions(), client.codeCompleted(CodeCompletedMessage(CodeCompletions(),
CompletionCorrection::NoCorrection, CompletionCorrection::NoCorrection,

View File

@@ -59,6 +59,7 @@ public:
RequestDocumentAnnotations, RequestDocumentAnnotations,
RequestReferences, RequestReferences,
FollowSymbol, FollowSymbol,
RequestToolTip,
SuspendDocument, SuspendDocument,
ResumeDocument, ResumeDocument,
@@ -118,6 +119,7 @@ public:
qint32 funcNameStartLine = -1; qint32 funcNameStartLine = -1;
qint32 funcNameStartColumn = -1; qint32 funcNameStartColumn = -1;
quint64 ticketNumber = 0; quint64 ticketNumber = 0;
Utf8String textCodecName;
bool localReferences = false; bool localReferences = false;
}; };

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -27,6 +27,7 @@
#include "clangbackend_global.h" #include "clangbackend_global.h"
#include "clangreferencescollector.h" #include "clangreferencescollector.h"
#include "clangtooltipinfocollector.h"
#include "clangtranslationunitupdater.h" #include "clangtranslationunitupdater.h"
#include "clangfollowsymbol.h" #include "clangfollowsymbol.h"
#include "clangfollowsymboljob.h" #include "clangfollowsymboljob.h"
@@ -139,6 +140,20 @@ void TranslationUnit::extractDocumentAnnotations(
skippedSourceRanges = this->skippedSourceRanges().toSourceRangeContainers(); 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 ReferencesResult TranslationUnit::references(uint line, uint column, bool localReferences) const
{ {
return collectReferences(m_cxTranslationUnit, line, column, localReferences); return collectReferences(m_cxTranslationUnit, line, column, localReferences);

View File

@@ -41,6 +41,7 @@ class SkippedSourceRanges;
class SourceLocation; class SourceLocation;
class SourceRange; class SourceRange;
class SourceRangeContainer; class SourceRangeContainer;
class ToolTipInfo;
class TranslationUnitUpdateInput; class TranslationUnitUpdateInput;
class TranslationUnitUpdateResult; class TranslationUnitUpdateResult;
class UnsavedFiles; class UnsavedFiles;
@@ -86,6 +87,10 @@ public:
ReferencesResult references(uint line, uint column, bool localReferences = false) const; 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; DiagnosticSet diagnostics() const;
SourceLocation sourceLocationAt(uint line, uint column) const; SourceLocation sourceLocationAt(uint line, uint column) const;

View File

@@ -84,6 +84,16 @@ bool Type::isBuiltinType() const
return cxType.kind >= CXType_FirstBuiltin && cxType.kind <= CXType_LastBuiltin; 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 Utf8String Type::utf8Spelling() const
{ {
return ClangString(clang_getTypeSpelling(cxType)); return ClangString(clang_getTypeSpelling(cxType));
@@ -94,6 +104,83 @@ ClangString Type::spelling() const
return ClangString(clang_getTypeSpelling(cxType)); 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 int Type::argumentCount() const
{ {
return clang_getNumArgTypes(cxType); return clang_getNumArgTypes(cxType);
@@ -129,6 +216,16 @@ Cursor Type::declaration() const
return clang_getTypeDeclaration(cxType); 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 CXTypeKind Type::kind() const
{ {
return cxType.kind; return cxType.kind;

View File

@@ -53,9 +53,11 @@ public:
bool isReferencingConstant() const; bool isReferencingConstant() const;
bool isOutputArgument() const; bool isOutputArgument() const;
bool isBuiltinType() const; bool isBuiltinType() const;
bool isUnsigned() const;
Utf8String utf8Spelling() const; Utf8String utf8Spelling() const;
ClangString spelling() const; ClangString spelling() const;
Utf8String builtinTypeToString() const;
int argumentCount() const; int argumentCount() const;
Type alias() const; Type alias() const;
@@ -66,6 +68,8 @@ public:
Cursor declaration() const; Cursor declaration() const;
long long sizeOf(bool *isValid) const;
CXTypeKind kind() const; CXTypeKind kind() const;
private: private:

View File

@@ -158,6 +158,14 @@ bool Cursor::isTemplateLike() const
Q_UNREACHABLE(); 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 Cursor::hasFinalFunctionAttribute() const
{ {
bool hasFinal = false; bool hasFinal = false;
@@ -248,11 +256,31 @@ Type Cursor::nonPointerTupe() const
return typeResult; 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 Cursor Cursor::specializedCursorTemplate() const
{ {
return clang_getSpecializedCursorTemplate(cxCursor); return clang_getSpecializedCursorTemplate(cxCursor);
} }
CXFile Cursor::includedFile() const
{
return clang_getIncludedFile(cxCursor);
}
SourceLocation Cursor::sourceLocation() const SourceLocation Cursor::sourceLocation() const
{ {
return clang_getCursorLocation(cxCursor); return clang_getCursorLocation(cxCursor);
@@ -341,6 +369,11 @@ Cursor Cursor::functionBase() const
return functionBaseCursor; return functionBaseCursor;
} }
Type Cursor::resultType() const
{
return clang_getResultType(type().cxType);
}
Cursor Cursor::argument(int index) const Cursor Cursor::argument(int index) const
{ {
return clang_Cursor_getArgument(cxCursor, index); return clang_Cursor_getArgument(cxCursor, index);
@@ -398,6 +431,11 @@ CXCursorKind Cursor::kind() const
return clang_getCursorKind(cxCursor); return clang_getCursorKind(cxCursor);
} }
CXCursor Cursor::cx() const
{
return cxCursor;
}
bool operator==(const Cursor &first, const Cursor &second) bool operator==(const Cursor &first, const Cursor &second)
{ {
return clang_equalCursors(first.cxCursor, second.cxCursor); return clang_equalCursors(first.cxCursor, second.cxCursor);

View File

@@ -67,6 +67,7 @@ public:
bool isFunctionLike() const; bool isFunctionLike() const;
bool isConstructorOrDestructor() const; bool isConstructorOrDestructor() const;
bool isTemplateLike() const; bool isTemplateLike() const;
bool isAnyTypeAlias() const;
bool hasFinalFunctionAttribute() const; bool hasFinalFunctionAttribute() const;
bool hasFinalClassAttribute() const; bool hasFinalClassAttribute() const;
bool isUnexposed() const; bool isUnexposed() const;
@@ -81,6 +82,10 @@ public:
Type type() const; Type type() const;
Type nonPointerTupe() const; Type nonPointerTupe() const;
Type enumType() const;
long long enumConstantValue() const;
unsigned long long enumConstantUnsignedValue() const;
SourceLocation sourceLocation() const; SourceLocation sourceLocation() const;
CXSourceLocation cxSourceLocation() const; CXSourceLocation cxSourceLocation() const;
@@ -92,17 +97,19 @@ public:
Cursor definition() const; Cursor definition() const;
Cursor canonical() const; Cursor canonical() const;
Cursor alias() const;
Cursor referenced() const; Cursor referenced() const;
Cursor semanticParent() const; Cursor semanticParent() const;
Cursor lexicalParent() const; Cursor lexicalParent() const;
Cursor functionBaseDeclaration() const; Cursor functionBaseDeclaration() const;
Cursor functionBase() const; Cursor functionBase() const;
Type resultType() const;
Cursor argument(int index) const; Cursor argument(int index) const;
unsigned overloadedDeclarationsCount() const; unsigned overloadedDeclarationsCount() const;
Cursor overloadedDeclaration(unsigned index) const; Cursor overloadedDeclaration(unsigned index) const;
Cursor specializedCursorTemplate() const; Cursor specializedCursorTemplate() const;
CXFile includedFile() const;
void collectOutputArgumentRangesTo( void collectOutputArgumentRangesTo(
std::vector<CXSourceRange> &outputArgumentRanges) const; std::vector<CXSourceRange> &outputArgumentRanges) const;
std::vector<CXSourceRange> outputArgumentRanges() const; std::vector<CXSourceRange> outputArgumentRanges() const;
@@ -112,6 +119,8 @@ public:
template <class VisitorCallback> template <class VisitorCallback>
void visit(VisitorCallback visitorCallback) const; void visit(VisitorCallback visitorCallback) const;
CXCursor cx() const;
private: private:
CXCursor cxCursor; CXCursor cxCursor;
}; };

View File

@@ -30,6 +30,8 @@
#include <ostream> #include <ostream>
#include <utils/qtcassert.h>
namespace ClangBackEnd { namespace ClangBackEnd {
UnsavedFile::UnsavedFile() UnsavedFile::UnsavedFile()
@@ -79,6 +81,25 @@ bool UnsavedFile::hasCharacterAt(uint line, uint column, char character) const
return positionIsOk && hasCharacterAt(utf8Position, character); 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 bool UnsavedFile::hasCharacterAt(uint position, char character) const
{ {
if (position < uint(m_fileContent.byteSize())) if (position < uint(m_fileContent.byteSize()))

View File

@@ -46,6 +46,7 @@ public:
// 1-based line and column // 1-based line and column
uint toUtf8Position(uint line, uint column, bool *ok) const; uint toUtf8Position(uint line, uint column, bool *ok) const;
bool hasCharacterAt(uint line, uint column, char character) const; bool hasCharacterAt(uint line, uint column, char character) const;
Utf8String lineRange(uint fromLine, uint toLine) const;
// 0-based position // 0-based position
bool hasCharacterAt(uint position, char character) const; bool hasCharacterAt(uint position, char character) const;

Some files were not shown because too many files have changed in this diff Show More