Commit ca72c294 authored by Nikolai Kosjar's avatar Nikolai Kosjar

Clang: Provide highlighting for identifier under cursor

Change-Id: I80ffe23cbcc84ab7323124581d9dd6afbe974fd0
Reviewed-by: Marco Bubke's avatarMarco Bubke <marco.bubke@qt.io>
parent 9de9da74
......@@ -39,6 +39,7 @@ SOURCES += $$PWD/clangcodemodelserverinterface.cpp \
$$PWD/sourcelocationcontainer.cpp \
$$PWD/fixitcontainer.cpp \
$$PWD/requestdocumentannotations.cpp \
$$PWD/requestreferencesmessage.cpp \
$$PWD/registerunsavedfilesforeditormessage.cpp \
$$PWD/unregisterunsavedfilesforeditormessage.cpp \
$$PWD/updatetranslationunitsforeditormessage.cpp \
......@@ -52,6 +53,7 @@ SOURCES += $$PWD/clangcodemodelserverinterface.cpp \
$$PWD/ipcserverinterface.cpp \
$$PWD/clangcodemodelconnectionclient.cpp \
$$PWD/documentannotationschangedmessage.cpp \
$$PWD/referencesmessage.cpp \
$$PWD/refactoringclientproxy.cpp \
$$PWD/sourcelocationscontainer.cpp \
$$PWD/sourcelocationcontainerv2.cpp \
......@@ -112,6 +114,8 @@ HEADERS += \
$$PWD/sourcelocationcontainer.h \
$$PWD/fixitcontainer.h \
$$PWD/requestdocumentannotations.h \
$$PWD/referencesmessage.h \
$$PWD/requestreferencesmessage.h \
$$PWD/registerunsavedfilesforeditormessage.h \
$$PWD/unregisterunsavedfilesforeditormessage.h \
$$PWD/updatetranslationunitsforeditormessage.h \
......
......@@ -113,6 +113,9 @@ enum class MessageType : quint8 {
RequestDocumentAnnotationsMessage,
DocumentAnnotationsChangedMessage,
RequestReferencesMessage,
ReferencesMessage,
UpdateVisibleTranslationUnitsMessage,
CompleteCodeMessage,
......
......@@ -28,6 +28,7 @@
#include "cmbcodecompletedmessage.h"
#include "cmbechomessage.h"
#include "documentannotationschangedmessage.h"
#include "referencesmessage.h"
#include "messageenvelop.h"
#include "projectpartsdonotexistmessage.h"
#include "translationunitdoesnotexistmessage.h"
......@@ -58,6 +59,9 @@ void ClangCodeModelClientInterface::dispatch(const MessageEnvelop &messageEnvelo
case MessageType::DocumentAnnotationsChangedMessage:
documentAnnotationsChanged(messageEnvelop.message<DocumentAnnotationsChangedMessage>());
break;
case MessageType::ReferencesMessage:
references(messageEnvelop.message<ReferencesMessage>());
break;
default:
qWarning() << "Unknown ClangCodeModelClientMessage";
}
......
......@@ -44,6 +44,8 @@ class RegisterUnsavedFilesForEditorMessage;
class UnregisterUnsavedFilesForEditorMessage;
class UpdateVisibleTranslationUnitsMessage;
class RequestDocumentAnnotationsMessage;
class RequestReferencesMessage;
class ReferencesMessage;
class DocumentAnnotationsChangedMessage;
class CMBIPC_EXPORT ClangCodeModelClientInterface : public IpcClientInterface
......@@ -57,6 +59,7 @@ public:
virtual void translationUnitDoesNotExist(const TranslationUnitDoesNotExistMessage &message) = 0;
virtual void projectPartsDoNotExist(const ProjectPartsDoNotExistMessage &message) = 0;
virtual void documentAnnotationsChanged(const DocumentAnnotationsChangedMessage &message) = 0;
virtual void references(const ReferencesMessage &message) = 0;
};
} // namespace ClangBackEnd
......@@ -30,6 +30,7 @@
#include "cmbechomessage.h"
#include "cmbregistertranslationunitsforeditormessage.h"
#include "documentannotationschangedmessage.h"
#include "referencesmessage.h"
#include "clangcodemodelserverinterface.h"
#include "ipcserverinterface.h"
#include "messageenvelop.h"
......@@ -101,6 +102,11 @@ void ClangCodeModelClientProxy::documentAnnotationsChanged(const DocumentAnnotat
m_writeMessageBlock.write(message);
}
void ClangCodeModelClientProxy::references(const ReferencesMessage &message)
{
m_writeMessageBlock.write(message);
}
void ClangCodeModelClientProxy::readMessages()
{
for (const MessageEnvelop &message : m_readMessageBlock.readAll())
......
......@@ -57,6 +57,7 @@ public:
void translationUnitDoesNotExist(const TranslationUnitDoesNotExistMessage &message) override;
void projectPartsDoNotExist(const ProjectPartsDoNotExistMessage &message) override;
void documentAnnotationsChanged(const DocumentAnnotationsChangedMessage &message) override;
void references(const ReferencesMessage &message) override;
void readMessages();
......
......@@ -33,6 +33,7 @@
#include "messageenvelop.h"
#include "registerunsavedfilesforeditormessage.h"
#include "requestdocumentannotations.h"
#include "requestreferencesmessage.h"
#include "unregisterunsavedfilesforeditormessage.h"
#include "updatetranslationunitsforeditormessage.h"
#include "updatevisibletranslationunitsmessage.h"
......@@ -75,6 +76,9 @@ void ClangCodeModelServerInterface::dispatch(const MessageEnvelop &messageEnvelo
case MessageType::RequestDocumentAnnotationsMessage:
requestDocumentAnnotations(messageEnvelop.message<RequestDocumentAnnotationsMessage>());
break;
case MessageType::RequestReferencesMessage:
requestReferences(messageEnvelop.message<RequestReferencesMessage>());
break;
case MessageType::UpdateVisibleTranslationUnitsMessage:
updateVisibleTranslationUnits(messageEnvelop.message<UpdateVisibleTranslationUnitsMessage>());
break;
......
......@@ -48,6 +48,7 @@ public:
virtual void unregisterUnsavedFilesForEditor(const UnregisterUnsavedFilesForEditorMessage &message) = 0;
virtual void completeCode(const CompleteCodeMessage &message) = 0;
virtual void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) = 0;
virtual void requestReferences(const RequestReferencesMessage &message) = 0;
virtual void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) = 0;
};
......
......@@ -36,6 +36,7 @@
#include <messageenvelop.h>
#include <registerunsavedfilesforeditormessage.h>
#include <requestdocumentannotations.h>
#include <requestreferencesmessage.h>
#include <unregisterunsavedfilesforeditormessage.h>
#include <updatetranslationunitsforeditormessage.h>
#include <updatevisibletranslationunitsmessage.h>
......@@ -116,6 +117,11 @@ void ClangCodeModelServerProxy::requestDocumentAnnotations(const RequestDocument
m_writeMessageBlock.write(message);
}
void ClangCodeModelServerProxy::requestReferences(const RequestReferencesMessage &message)
{
m_writeMessageBlock.write(message);
}
void ClangCodeModelServerProxy::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message)
{
m_writeMessageBlock.write(message);
......
......@@ -59,6 +59,7 @@ public:
void unregisterUnsavedFilesForEditor(const UnregisterUnsavedFilesForEditorMessage &message) override;
void completeCode(const CompleteCodeMessage &message) override;
void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) override;
void requestReferences(const RequestReferencesMessage &message) override;
void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override;
void readMessages();
......
......@@ -33,11 +33,13 @@
#include "cmbunregisterprojectsforeditormessage.h"
#include "cmbunregistertranslationunitsforeditormessage.h"
#include "documentannotationschangedmessage.h"
#include "referencesmessage.h"
#include "messageenvelop.h"
#include "messageenvelop.h"
#include "projectpartsdonotexistmessage.h"
#include "registerunsavedfilesforeditormessage.h"
#include "requestdocumentannotations.h"
#include "requestreferencesmessage.h"
#include "translationunitdoesnotexistmessage.h"
#include "unregisterunsavedfilesforeditormessage.h"
#include "updatetranslationunitsforeditormessage.h"
......@@ -80,6 +82,9 @@ QDebug operator<<(QDebug debug, const MessageEnvelop &messageEnvelop)
case MessageType::RequestDocumentAnnotationsMessage:
qDebug() << messageEnvelop.message<RequestDocumentAnnotationsMessage>();
break;
case MessageType::RequestReferencesMessage:
qDebug() << messageEnvelop.message<RequestReferencesMessage>();
break;
case MessageType::UpdateVisibleTranslationUnitsMessage:
qDebug() << messageEnvelop.message<UpdateVisibleTranslationUnitsMessage>();
break;
......@@ -92,6 +97,9 @@ QDebug operator<<(QDebug debug, const MessageEnvelop &messageEnvelop)
case MessageType::CodeCompletedMessage:
qDebug() << messageEnvelop.message<CodeCompletedMessage>();
break;
case MessageType::ReferencesMessage:
qDebug() << messageEnvelop.message<ReferencesMessage>();
break;
case MessageType::TranslationUnitDoesNotExistMessage:
qDebug() << messageEnvelop.message<TranslationUnitDoesNotExistMessage>();
break;
......
/****************************************************************************
**
** Copyright (C) 2017 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 "referencesmessage.h"
#include <QDebug>
#include <ostream>
namespace ClangBackEnd {
QDebug operator<<(QDebug debug, const ReferencesMessage &message)
{
debug.nospace() << "ReferencesMessage("
<< message.fileContainer()
<< ", " << message.m_ticketNumber
<< ", " << message.m_isLocalVariable
<< ", " << message.m_references;
debug.nospace() << ")";
return debug;
}
std::ostream &operator<<(std::ostream &os, const ReferencesMessage &message)
{
os << "("
<< message.m_fileContainer << ", "
<< message.m_ticketNumber << ", "
<< message.m_isLocalVariable << ", "
<< message.m_references << ", "
<< ")";
return os;
}
} // namespace ClangBackEnd
/****************************************************************************
**
** Copyright (C) 2017 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 "sourcerangecontainer.h"
#include <QDataStream>
#include <QVector>
namespace ClangBackEnd {
class ReferencesMessage
{
public:
ReferencesMessage() = default;
ReferencesMessage(const FileContainer &fileContainer,
const QVector<SourceRangeContainer> &references,
bool isLocalVariable,
quint64 ticketNumber)
: m_fileContainer(fileContainer)
, m_references(references)
, m_ticketNumber(ticketNumber)
, m_isLocalVariable(isLocalVariable)
{
}
const FileContainer &fileContainer() const
{
return m_fileContainer;
}
bool isLocalVariable() const
{
return m_isLocalVariable;
}
const QVector<SourceRangeContainer> &references() const
{
return m_references;
}
quint64 ticketNumber() const
{
return m_ticketNumber;
}
friend QDataStream &operator<<(QDataStream &out, const ReferencesMessage &message)
{
out << message.m_fileContainer;
out << message.m_isLocalVariable;
out << message.m_references;
out << message.m_ticketNumber;
return out;
}
friend QDataStream &operator>>(QDataStream &in, ReferencesMessage &message)
{
in >> message.m_fileContainer;
in >> message.m_isLocalVariable;
in >> message.m_references;
in >> message.m_ticketNumber;
return in;
}
friend bool operator==(const ReferencesMessage &first, const ReferencesMessage &second)
{
return first.m_ticketNumber == second.m_ticketNumber
&& first.m_isLocalVariable == second.m_isLocalVariable
&& first.m_fileContainer == second.m_fileContainer
&& first.m_references == second.m_references;
}
friend CMBIPC_EXPORT QDebug operator<<(QDebug debug, const ReferencesMessage &message);
friend std::ostream &operator<<(std::ostream &os, const ReferencesMessage &message);
private:
FileContainer m_fileContainer;
QVector<SourceRangeContainer> m_references;
quint64 m_ticketNumber = 0;
bool m_isLocalVariable = false;
};
DECLARE_MESSAGE(ReferencesMessage)
} // namespace ClangBackEnd
/****************************************************************************
**
** Copyright (C) 2017 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 "requestreferencesmessage.h"
#include <QDebug>
#include <ostream>
namespace ClangBackEnd {
quint64 RequestReferencesMessage::ticketCounter = 0;
QDebug operator<<(QDebug debug, const RequestReferencesMessage &message)
{
debug.nospace() << "RequestReferencesMessage(";
debug.nospace() << message.m_fileContainer << ", ";
debug.nospace() << message.m_ticketNumber << ", ";
debug.nospace() << message.m_line << ", ";
debug.nospace() << message.m_column << ", ";
debug.nospace() << ")";
return debug;
}
std::ostream &operator<<(std::ostream &os, const RequestReferencesMessage &message)
{
os << "("
<< message.m_fileContainer << ", "
<< message.m_ticketNumber << ", "
<< message.m_line << ", "
<< message.m_column << ", "
<< ")";
return os;
}
} // namespace ClangBackEnd
/****************************************************************************
**
** Copyright (C) 2017 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 "clangbackendipc_global.h"
#include "filecontainer.h"
#include <QDataStream>
namespace ClangBackEnd {
class RequestReferencesMessage
{
public:
RequestReferencesMessage() = default;
RequestReferencesMessage(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 RequestReferencesMessage &message)
{
out << message.m_fileContainer;
out << message.m_ticketNumber;
out << message.m_line;
out << message.m_column;
return out;
}
friend QDataStream &operator>>(QDataStream &in, RequestReferencesMessage &message)
{
in >> message.m_fileContainer;
in >> message.m_ticketNumber;
in >> message.m_line;
in >> message.m_column;
return in;
}
friend bool operator==(const RequestReferencesMessage &first,
const RequestReferencesMessage &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 CMBIPC_EXPORT QDebug operator<<(QDebug debug, const RequestReferencesMessage &message);
friend std::ostream &operator<<(std::ostream &os, const RequestReferencesMessage &message);
private:
FileContainer m_fileContainer;
quint64 m_ticketNumber = 0;
quint32 m_line = 0;
quint32 m_column = 0;
static CMBIPC_EXPORT quint64 ticketCounter;
};
DECLARE_MESSAGE(RequestReferencesMessage);
} // namespace ClangBackEnd
......@@ -58,8 +58,11 @@
#include <clangbackendipc/cmbunregistertranslationunitsforeditormessage.h>
#include <clangbackendipc/cmbunregisterprojectsforeditormessage.h>
#include <clangbackendipc/documentannotationschangedmessage.h>
#include <clangbackendipc/referencesmessage.h>
#include <clangbackendipc/requestreferencesmessage.h>
#include <clangbackendipc/registerunsavedfilesforeditormessage.h>
#include <clangbackendipc/requestdocumentannotations.h>
#include <clangbackendipc/requestreferencesmessage.h>
#include <clangbackendipc/filecontainer.h>
#include <clangbackendipc/projectpartsdonotexistmessage.h>
#include <clangbackendipc/translationunitdoesnotexistmessage.h>
......@@ -74,6 +77,7 @@
#include <QElapsedTimer>
#include <QLoggingCategory>
#include <QProcess>
#include <QTextBlock>
static Q_LOGGING_CATEGORY(log, "qtc.clangcodemodel.ipc")
......@@ -150,6 +154,21 @@ void IpcReceiver::deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *t
}
}
QFuture<CppTools::CursorInfo> IpcReceiver::addExpectedReferencesMessage(quint64 ticket,
QTextDocument *textDocument)
{
QTC_CHECK(textDocument);
QTC_CHECK(!m_referencesTable.contains(ticket));
QFutureInterface<CppTools::CursorInfo> futureInterface;
futureInterface.reportStarted();
const ReferencesEntry entry{futureInterface, textDocument};
m_referencesTable.insert(ticket, entry);
return futureInterface.future();
}
bool IpcReceiver::isExpectingCodeCompletedMessage() const
{
return !m_assistProcessorsTable.isEmpty();
......@@ -205,6 +224,56 @@ void IpcReceiver::documentAnnotationsChanged(const DocumentAnnotationsChangedMes
}
}
static
CppTools::CursorInfo::Range toCursorInfoRange(const QTextDocument &textDocument,
const SourceRangeContainer &sourceRange)
{
const SourceLocationContainer start = sourceRange.start();
const SourceLocationContainer end = sourceRange.end();
const unsigned length = end.column() - start.column();
const QTextBlock block = textDocument.findBlockByNumber(static_cast<int>(start.line()) - 1);
const int shift = ClangCodeModel::Utils::extraUtf8CharsShift(block.text(),
static_cast<int>(start.column()));
const uint column = start.column() - static_cast<uint>(shift);
return CppTools::CursorInfo::Range(start.line(), column, length);
}
static
CppTools::CursorInfo toCursorInfo(const QTextDocument &textDocument,
const ReferencesMessage &message)
{
CppTools::CursorInfo result;
const QVector<SourceRangeContainer> references = message.references();
result.areUseRangesForLocalVariable = message.isLocalVariable();
for (const SourceRangeContainer &reference : references)
result.useRanges.append(toCursorInfoRange(textDocument, reference));
result.useRanges.reserve(references.size());
return result;
}
void IpcReceiver::references(const ReferencesMessage &message)
{
qCDebug(log) << "<<< ReferencesMessage with"
<< message.references().size() << "references";
const quint64 ticket = message.ticketNumber();
const ReferencesEntry entry = m_referencesTable.take(ticket);
QFutureInterface<CppTools::CursorInfo> futureInterface = entry.futureInterface;
QTC_CHECK(futureInterface != QFutureInterface<CppTools::CursorInfo>());
if (futureInterface.isCanceled())
return; // A new request was issued making this one outdated.
QTC_CHECK(entry.textDocument);
futureInterface.reportResult(toCursorInfo(*entry.textDocument, message));
futureInterface.reportFinished();
}
class IpcSender : public IpcSenderInterface
{
public:
......@@ -222,6 +291,7 @@ public:
void unregisterUnsavedFilesForEditor(const ClangBackEnd::UnregisterUnsavedFilesForEditorMessage &message) override;
void completeCode(const ClangBackEnd::CompleteCodeMessage &message) override;
void requestDocumentAnnotations(const ClangBackEnd::RequestDocumentAnnotationsMessage &message) override;
void requestReferences(const ClangBackEnd::RequestReferencesMessage &message) override;
void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override;
private:
......@@ -298,6 +368,13 @@ void IpcSender::requestDocumentAnnotations(const RequestDocumentAnnotationsMessa
m_connection.serverProxy().requestDocumentAnnotations(message);
}
void IpcSender::requestReferences(const RequestReferencesMessage &message)
{
QTC_CHECK(m_connection.isConnected());
qCDebug(log) << ">>>" << message;
m_connection.serverProxy().requestReferences(message);
}
void IpcSender::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message)
{
QTC_CHECK(m_connection.isConnected());
......@@ -318,6 +395,7 @@ public:
void unregisterUnsavedFilesForEditor(const ClangBackEnd::UnregisterUnsavedFilesForEditorMessage &) override {}
void completeCode(const ClangBackEnd::CompleteCodeMessage &) override {}
void requestDocumentAnnotations(const ClangBackEnd::RequestDocumentAnnotationsMessage &) override {}
void requestReferences(const ClangBackEnd::RequestReferencesMessage &) override {}
void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &) override {}
};
......@@ -603,6 +681,18 @@ void IpcCommunicator::requestDocumentAnnotations(const FileContainer &fileContai
m_ipcSender->requestDocumentAnnotations(message);
}
QFuture<CppTools::CursorInfo> IpcCommunicator::requestReferences(
const FileContainer &fileContainer,
quint32 line,
quint32 column,
QTextDocument *textDocument)
{
const RequestReferencesMessage message(fileContainer, line, column);
m_ipcSender->requestReferences(message);
return m_ipcReceiver.addExpectedReferencesMessage(message.ticketNumber(), textDocument);
}
void IpcCommunicator::updateTranslationUnitWithRevisionCheck(Core::IDocument *document)