Clang: implement requestFollowSymbol plug-in side

Invoke follow symbol in clang backend
if env variable QTC_CLANG_FOLLOW_SYMBOL is 1.
Does not include backend implementation.

Change-Id: Ia20a677830ebdd7f24800af5c5d6e8b1bf579205
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
Ivan Donchevskii
2017-07-27 11:42:37 +02:00
parent 4ad0e5295c
commit e6a50fd44a
17 changed files with 259 additions and 14 deletions

View File

@@ -144,6 +144,18 @@ QFuture<CppTools::CursorInfo> IpcReceiver::addExpectedReferencesMessage(quint64
return futureInterface.future();
}
QFuture<CppTools::SymbolInfo> IpcReceiver::addExpectedRequestFollowSymbolMessage(quint64 ticket)
{
QTC_CHECK(!m_followTable.contains(ticket));
QFutureInterface<CppTools::SymbolInfo> futureInterface;
futureInterface.reportStarted();
m_followTable.insert(ticket, futureInterface);
return futureInterface.future();
}
bool IpcReceiver::isExpectingCodeCompletedMessage() const
{
return !m_assistProcessorsTable.isEmpty();
@@ -159,6 +171,9 @@ void IpcReceiver::reset()
for (ReferencesEntry &entry : m_referencesTable)
entry.futureInterface.cancel();
m_referencesTable.clear();
for (QFutureInterface<CppTools::SymbolInfo> &futureInterface : m_followTable)
futureInterface.cancel();
m_followTable.clear();
}
void IpcReceiver::alive()
@@ -243,6 +258,24 @@ CppTools::CursorInfo toCursorInfo(const QTextDocument &textDocument,
return result;
}
static
CppTools::SymbolInfo toSymbolInfo(const FollowSymbolMessage &message)
{
CppTools::SymbolInfo result;
const SourceRangeContainer &range = message.sourceRange();
const SourceLocationContainer start = range.start();
const SourceLocationContainer end = range.end();
result.startLine = static_cast<int>(start.line());
result.startColumn = static_cast<int>(start.column());
result.endLine = static_cast<int>(end.line());
result.endColumn = static_cast<int>(end.column());
result.fileName = start.filePath();
result.failedToFollow = message.failedToFollow();
return result;
}
void IpcReceiver::references(const ReferencesMessage &message)
{
qCDebug(log) << "<<< ReferencesMessage with"
@@ -267,7 +300,14 @@ void IpcReceiver::followSymbol(const ClangBackEnd::FollowSymbolMessage &message)
<< message.sourceRange() << "range";
const quint64 ticket = message.ticketNumber();
// TODO: add implementation
QFutureInterface<CppTools::SymbolInfo> futureInterface = m_followTable.take(ticket);
QTC_CHECK(futureInterface != QFutureInterface<CppTools::SymbolInfo>());
if (futureInterface.isCanceled())
return; // Editor document closed or a new request was issued making this result outdated.
futureInterface.reportResult(toSymbolInfo(message));
futureInterface.reportFinished();
}
class IpcSender : public IpcSenderInterface
@@ -698,6 +738,23 @@ QFuture<CppTools::CursorInfo> IpcCommunicator::requestReferences(
return m_ipcReceiver.addExpectedReferencesMessage(message.ticketNumber(), textDocument);
}
QFuture<CppTools::SymbolInfo> IpcCommunicator::requestFollowSymbol(
const FileContainer &curFileContainer,
const QVector<Utf8String> &dependentFiles,
quint32 line,
quint32 column,
bool resolveTarget)
{
const RequestFollowSymbolMessage message(curFileContainer,
dependentFiles,
line,
column,
resolveTarget);
m_ipcSender->requestFollowSymbol(message);
return m_ipcReceiver.addExpectedRequestFollowSymbolMessage(message.ticketNumber());
}
void IpcCommunicator::updateTranslationUnitWithRevisionCheck(Core::IDocument *document)
{
const auto textDocument = qobject_cast<TextDocument*>(document);

View File

@@ -27,6 +27,7 @@
#include <cpptools/projectpart.h>
#include <cpptools/cppcursorinfo.h>
#include <cpptools/cppsymbolinfo.h>
#include <clangbackendipc/clangcodemodelconnectionclient.h>
#include <clangbackendipc/filecontainer.h>
@@ -77,6 +78,7 @@ public:
QFuture<CppTools::CursorInfo> addExpectedReferencesMessage(quint64 ticket,
QTextDocument *textDocument);
QFuture<CppTools::SymbolInfo> addExpectedRequestFollowSymbolMessage(quint64 ticket);
bool isExpectingCodeCompletedMessage() const;
void reset();
@@ -107,6 +109,8 @@ private:
QPointer<QTextDocument> textDocument;
};
QHash<quint64, ReferencesEntry> m_referencesTable;
QHash<quint64, QFutureInterface<CppTools::SymbolInfo>> m_followTable;
};
class IpcSenderInterface
@@ -154,6 +158,11 @@ public:
QFuture<CppTools::CursorInfo> requestReferences(const FileContainer &fileContainer,
quint32 line,
quint32 column, QTextDocument *textDocument);
QFuture<CppTools::SymbolInfo> requestFollowSymbol(const FileContainer &curFileContainer,
const QVector<Utf8String> &dependentFiles,
quint32 line,
quint32 column,
bool resolveTarget);
void completeCode(ClangCompletionAssistProcessor *assistProcessor, const QString &filePath,
quint32 line,
quint32 column,

View File

@@ -341,6 +341,55 @@ ClangEditorDocumentProcessor::cursorInfo(const CppTools::CursorInfoParams &param
textDocument());
}
static QVector<Utf8String> prioritizeByBaseName(const QString &curPath,
const ::Utils::FileNameList &fileDeps)
{
QList<Utf8String> dependentFiles;
dependentFiles.reserve(fileDeps.size());
for (const ::Utils::FileName &dep: fileDeps)
dependentFiles.push_back(dep.toString());
const QString curFilename = QFileInfo(curPath).fileName();
if (CppTools::ProjectFile::isHeader(CppTools::ProjectFile::classify(curFilename))) {
const QString withoutExt = QFileInfo(curFilename).baseName();
int posToMove = 0;
// Move exact match to the first place and partial matches after it
for (int i = 0; i < dependentFiles.size(); ++i) {
const QString baseName = QFileInfo(dependentFiles[i]).baseName();
if (withoutExt == baseName) {
dependentFiles.move(i, 0);
posToMove++;
continue;
}
if (baseName.contains(withoutExt))
dependentFiles.move(i, posToMove++);
}
}
// Limit the number of scans (don't search for overrides)
if (dependentFiles.size() > 5)
dependentFiles.erase(dependentFiles.begin() + 5, dependentFiles.end());
return QVector<Utf8String>::fromList(dependentFiles);
}
QFuture<CppTools::SymbolInfo>
ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column, bool resolveTarget)
{
QVector<Utf8String> dependentFiles;
CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
if (modelManager && !modelManager->projectPart(filePath()).isEmpty()) {
// This might be not so fast - index will change that
const ::Utils::FileNameList fileDeps
= modelManager->snapshot().filesDependingOn(filePath());
dependentFiles = prioritizeByBaseName(filePath(), fileDeps);
}
return m_ipcCommunicator.requestFollowSymbol(simpleFileContainer(),
dependentFiles,
static_cast<quint32>(line),
static_cast<quint32>(column),
resolveTarget);
}
ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithArguments() const
{
return fileContainerWithArguments(m_projectPart.data());

View File

@@ -86,6 +86,9 @@ public:
void setParserConfig(const CppTools::BaseEditorDocumentParser::Configuration config) override;
QFuture<CppTools::CursorInfo> cursorInfo(const CppTools::CursorInfoParams &params) override;
QFuture<CppTools::SymbolInfo> requestFollowSymbol(int line,
int column,
bool resolveTarget) override;
ClangBackEnd::FileContainer fileContainerWithArguments() const;