forked from qt-creator/qt-creator
Clang: Provide highlighting for identifier under cursor
Change-Id: I80ffe23cbcc84ab7323124581d9dd6afbe974fd0 Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
@@ -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)
|
||||
{
|
||||
const auto textDocument = qobject_cast<TextDocument*>(document);
|
||||
|
||||
@@ -32,8 +32,10 @@
|
||||
#include <clangbackendipc/clangcodemodelclientinterface.h>
|
||||
#include <clangbackendipc/projectpartcontainer.h>
|
||||
|
||||
#include <QFuture>
|
||||
#include <QObject>
|
||||
#include <QSharedPointer>
|
||||
#include <QTextDocument>
|
||||
#include <QVector>
|
||||
|
||||
#include <functional>
|
||||
@@ -43,6 +45,10 @@ class IEditor;
|
||||
class IDocument;
|
||||
}
|
||||
|
||||
namespace CppTools {
|
||||
class CursorInfo;
|
||||
}
|
||||
|
||||
namespace ClangBackEnd {
|
||||
class DocumentAnnotationsChangedMessage;
|
||||
}
|
||||
@@ -72,6 +78,9 @@ public:
|
||||
void deleteAndClearWaitingAssistProcessors();
|
||||
void deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *textEditorWidget);
|
||||
|
||||
QFuture<CppTools::CursorInfo> addExpectedReferencesMessage(quint64 ticket,
|
||||
QTextDocument *textDocument);
|
||||
|
||||
bool isExpectingCodeCompletedMessage() const;
|
||||
|
||||
private:
|
||||
@@ -80,6 +89,7 @@ private:
|
||||
void codeCompleted(const ClangBackEnd::CodeCompletedMessage &message) override;
|
||||
|
||||
void documentAnnotationsChanged(const ClangBackEnd::DocumentAnnotationsChangedMessage &message) override;
|
||||
void references(const ClangBackEnd::ReferencesMessage &message) override;
|
||||
|
||||
void translationUnitDoesNotExist(const ClangBackEnd::TranslationUnitDoesNotExistMessage &) override {}
|
||||
void projectPartsDoNotExist(const ClangBackEnd::ProjectPartsDoNotExistMessage &) override {}
|
||||
@@ -87,6 +97,12 @@ private:
|
||||
private:
|
||||
AliveHandler m_aliveHandler;
|
||||
QHash<quint64, ClangCompletionAssistProcessor *> m_assistProcessorsTable;
|
||||
|
||||
struct ReferencesEntry {
|
||||
QFutureInterface<CppTools::CursorInfo> futureInterface;
|
||||
QTextDocument *textDocument = nullptr;
|
||||
};
|
||||
QHash<quint64, ReferencesEntry> m_referencesTable;
|
||||
const bool m_printAliveMessage = false;
|
||||
};
|
||||
|
||||
@@ -105,6 +121,7 @@ public:
|
||||
virtual void unregisterUnsavedFilesForEditor(const ClangBackEnd::UnregisterUnsavedFilesForEditorMessage &message) = 0;
|
||||
virtual void completeCode(const ClangBackEnd::CompleteCodeMessage &message) = 0;
|
||||
virtual void requestDocumentAnnotations(const ClangBackEnd::RequestDocumentAnnotationsMessage &message) = 0;
|
||||
virtual void requestReferences(const ClangBackEnd::RequestReferencesMessage &message) = 0;
|
||||
virtual void updateVisibleTranslationUnits(const ClangBackEnd::UpdateVisibleTranslationUnitsMessage &message) = 0;
|
||||
};
|
||||
|
||||
@@ -114,6 +131,7 @@ class IpcCommunicator : public QObject
|
||||
|
||||
public:
|
||||
using Ptr = QSharedPointer<IpcCommunicator>;
|
||||
using FileContainer = ClangBackEnd::FileContainer;
|
||||
using FileContainers = QVector<ClangBackEnd::FileContainer>;
|
||||
using ProjectPartContainers = QVector<ClangBackEnd::ProjectPartContainer>;
|
||||
|
||||
@@ -129,6 +147,9 @@ public:
|
||||
void registerUnsavedFilesForEditor(const FileContainers &fileContainers);
|
||||
void unregisterUnsavedFilesForEditor(const FileContainers &fileContainers);
|
||||
void requestDocumentAnnotations(const ClangBackEnd::FileContainer &fileContainer);
|
||||
QFuture<CppTools::CursorInfo> requestReferences(const FileContainer &fileContainer,
|
||||
quint32 line,
|
||||
quint32 column, QTextDocument *textDocument);
|
||||
void completeCode(ClangCompletionAssistProcessor *assistProcessor, const QString &filePath,
|
||||
quint32 line,
|
||||
quint32 column,
|
||||
|
||||
@@ -68,6 +68,7 @@ ClangEditorDocumentProcessor::ClangEditorDocumentProcessor(
|
||||
IpcCommunicator &ipcCommunicator,
|
||||
TextEditor::TextDocument *document)
|
||||
: BaseEditorDocumentProcessor(document->document(), document->filePath().toString())
|
||||
, m_document(*document)
|
||||
, m_diagnosticManager(document)
|
||||
, m_ipcCommunicator(ipcCommunicator)
|
||||
, m_parser(new ClangEditorDocumentParser(document->filePath().toString()))
|
||||
@@ -287,10 +288,48 @@ void ClangEditorDocumentProcessor::setParserConfig(
|
||||
m_builtinProcessor.parser()->setConfiguration(config);
|
||||
}
|
||||
|
||||
static bool isCursorOnIdentifier(const QTextCursor &textCursor)
|
||||
{
|
||||
QTextDocument *document = textCursor.document();
|
||||
return CppTools::isValidIdentifierChar(document->characterAt(textCursor.position()));
|
||||
}
|
||||
|
||||
static QFuture<CppTools::CursorInfo> defaultCursorInfoFuture()
|
||||
{
|
||||
QFutureInterface<CppTools::CursorInfo> futureInterface;
|
||||
futureInterface.reportResult(CppTools::CursorInfo());
|
||||
futureInterface.reportFinished();
|
||||
|
||||
return futureInterface.future();
|
||||
}
|
||||
|
||||
static bool convertPosition(const QTextCursor &textCursor, int *line, int *column)
|
||||
{
|
||||
const bool converted = TextEditor::Convenience::convertPosition(textCursor.document(),
|
||||
textCursor.position(),
|
||||
line,
|
||||
column);
|
||||
QTC_CHECK(converted);
|
||||
return converted;
|
||||
}
|
||||
|
||||
QFuture<CppTools::CursorInfo>
|
||||
ClangEditorDocumentProcessor::cursorInfo(const CppTools::CursorInfoParams ¶ms)
|
||||
{
|
||||
return m_builtinProcessor.cursorInfo(params);
|
||||
int line, column;
|
||||
convertPosition(params.textCursor, &line, &column);
|
||||
++column; // for 1-based columns
|
||||
|
||||
if (!isCursorOnIdentifier(params.textCursor))
|
||||
return defaultCursorInfoFuture();
|
||||
|
||||
const QTextBlock block = params.textCursor.document()->findBlockByNumber(line - 1);
|
||||
column += ClangCodeModel::Utils::extraUtf8CharsShift(block.text(), column);
|
||||
|
||||
return m_ipcCommunicator.requestReferences(simpleFileContainer(),
|
||||
static_cast<quint32>(line),
|
||||
static_cast<quint32>(column),
|
||||
textDocument());
|
||||
}
|
||||
|
||||
ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithArguments() const
|
||||
@@ -396,6 +435,15 @@ ClangEditorDocumentProcessor::creatorForHeaderErrorDiagnosticWidget(
|
||||
};
|
||||
}
|
||||
|
||||
ClangBackEnd::FileContainer ClangEditorDocumentProcessor::simpleFileContainer() const
|
||||
{
|
||||
Utf8String projectPartId;
|
||||
if (m_projectPart)
|
||||
projectPartId = m_projectPart->id();
|
||||
|
||||
return ClangBackEnd::FileContainer(filePath(), projectPartId, Utf8String(), false, revision());
|
||||
}
|
||||
|
||||
static CppTools::ProjectPart projectPartForLanguageOption(CppTools::ProjectPart *projectPart)
|
||||
{
|
||||
if (projectPart)
|
||||
|
||||
@@ -101,12 +101,14 @@ private:
|
||||
void requestDocumentAnnotations(const QString &projectpartId);
|
||||
HeaderErrorDiagnosticWidgetCreator creatorForHeaderErrorDiagnosticWidget(
|
||||
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic);
|
||||
ClangBackEnd::FileContainer simpleFileContainer() const;
|
||||
ClangBackEnd::FileContainer fileContainerWithArguments(CppTools::ProjectPart *projectPart) const;
|
||||
ClangBackEnd::FileContainer fileContainerWithArgumentsAndDocumentContent(
|
||||
CppTools::ProjectPart *projectPart) const;
|
||||
ClangBackEnd::FileContainer fileContainerWithDocumentContent(const QString &projectpartId) const;
|
||||
|
||||
private:
|
||||
TextEditor::TextDocument &m_document;
|
||||
ClangDiagnosticManager m_diagnosticManager;
|
||||
IpcCommunicator &m_ipcCommunicator;
|
||||
QSharedPointer<ClangEditorDocumentParser> m_parser;
|
||||
|
||||
@@ -325,6 +325,10 @@ QString toString(const RequestDocumentAnnotationsMessage &)
|
||||
return QStringLiteral("RequestDocumentAnnotationsMessage\n");
|
||||
}
|
||||
|
||||
QString toString(const RequestReferencesMessage &)
|
||||
{
|
||||
return QStringLiteral("RequestReferencesMessage\n");
|
||||
}
|
||||
|
||||
QString toString(const UpdateVisibleTranslationUnitsMessage &)
|
||||
{
|
||||
@@ -364,6 +368,9 @@ public:
|
||||
void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) override
|
||||
{ senderLog.append(toString(message)); }
|
||||
|
||||
void requestReferences(const RequestReferencesMessage &message) override
|
||||
{ senderLog.append(toString(message)); }
|
||||
|
||||
void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override
|
||||
{ senderLog.append(toString(message)); }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user