forked from qt-creator/qt-creator
Clang: Use follow symbol result from clang when global fails
When built-in code model fails to follow symbol under cursor fall back to the clang result even if it only follows to the decalration. Change-Id: I22d8c5fee6ab7594b1d1b7ce8104414db28383c7 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
@@ -29,12 +29,23 @@
|
|||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, const FollowSymbolResult &result)
|
||||||
|
{
|
||||||
|
debug.nospace() << "FollowSymbolResult("
|
||||||
|
<< result.range
|
||||||
|
<< ", " << result.isPureDeclarationForUsage;
|
||||||
|
|
||||||
|
debug.nospace() << ")";
|
||||||
|
|
||||||
|
return debug;
|
||||||
|
}
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, const FollowSymbolMessage &message)
|
QDebug operator<<(QDebug debug, const FollowSymbolMessage &message)
|
||||||
{
|
{
|
||||||
debug.nospace() << "FollowSymbolMessage("
|
debug.nospace() << "FollowSymbolMessage("
|
||||||
<< message.fileContainer
|
<< message.fileContainer
|
||||||
<< ", " << message.ticketNumber
|
<< ", " << message.ticketNumber
|
||||||
<< ", " << message.sourceRange;
|
<< ", " << message.result;
|
||||||
|
|
||||||
debug.nospace() << ")";
|
debug.nospace() << ")";
|
||||||
|
|
||||||
|
|||||||
@@ -33,15 +33,53 @@
|
|||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
|
class FollowSymbolResult
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FollowSymbolResult() = default;
|
||||||
|
FollowSymbolResult(SourceRangeContainer range)
|
||||||
|
: range(std::move(range))
|
||||||
|
{}
|
||||||
|
FollowSymbolResult(SourceRangeContainer range, bool isPureDeclarationForUsage)
|
||||||
|
: range(std::move(range))
|
||||||
|
, isPureDeclarationForUsage(isPureDeclarationForUsage)
|
||||||
|
{}
|
||||||
|
|
||||||
|
friend QDataStream &operator<<(QDataStream &out, const FollowSymbolResult &container)
|
||||||
|
{
|
||||||
|
out << container.range;
|
||||||
|
out << container.isPureDeclarationForUsage;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend QDataStream &operator>>(QDataStream &in, FollowSymbolResult &container)
|
||||||
|
{
|
||||||
|
in >> container.range;
|
||||||
|
in >> container.isPureDeclarationForUsage;
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator==(const FollowSymbolResult &first, const FollowSymbolResult &second)
|
||||||
|
{
|
||||||
|
return first.range == second.range
|
||||||
|
&& first.isPureDeclarationForUsage == second.isPureDeclarationForUsage;
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceRangeContainer range;
|
||||||
|
bool isPureDeclarationForUsage = false;
|
||||||
|
};
|
||||||
|
|
||||||
class FollowSymbolMessage
|
class FollowSymbolMessage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FollowSymbolMessage() = default;
|
FollowSymbolMessage() = default;
|
||||||
FollowSymbolMessage(const FileContainer &fileContainer,
|
FollowSymbolMessage(const FileContainer &fileContainer,
|
||||||
const SourceRangeContainer &range,
|
const FollowSymbolResult &result,
|
||||||
quint64 ticketNumber)
|
quint64 ticketNumber)
|
||||||
: fileContainer(fileContainer)
|
: fileContainer(fileContainer)
|
||||||
, sourceRange(range)
|
, result(result)
|
||||||
, ticketNumber(ticketNumber)
|
, ticketNumber(ticketNumber)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -49,7 +87,7 @@ public:
|
|||||||
friend QDataStream &operator<<(QDataStream &out, const FollowSymbolMessage &message)
|
friend QDataStream &operator<<(QDataStream &out, const FollowSymbolMessage &message)
|
||||||
{
|
{
|
||||||
out << message.fileContainer;
|
out << message.fileContainer;
|
||||||
out << message.sourceRange;
|
out << message.result;
|
||||||
out << message.ticketNumber;
|
out << message.ticketNumber;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -57,7 +95,7 @@ public:
|
|||||||
friend QDataStream &operator>>(QDataStream &in, FollowSymbolMessage &message)
|
friend QDataStream &operator>>(QDataStream &in, FollowSymbolMessage &message)
|
||||||
{
|
{
|
||||||
in >> message.fileContainer;
|
in >> message.fileContainer;
|
||||||
in >> message.sourceRange;
|
in >> message.result;
|
||||||
in >> message.ticketNumber;
|
in >> message.ticketNumber;
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
@@ -66,15 +104,16 @@ public:
|
|||||||
{
|
{
|
||||||
return first.ticketNumber == second.ticketNumber
|
return first.ticketNumber == second.ticketNumber
|
||||||
&& first.fileContainer == second.fileContainer
|
&& first.fileContainer == second.fileContainer
|
||||||
&& first.sourceRange == second.sourceRange;
|
&& first.result == second.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FileContainer fileContainer;
|
FileContainer fileContainer;
|
||||||
SourceRangeContainer sourceRange;
|
FollowSymbolResult result;
|
||||||
quint64 ticketNumber = 0;
|
quint64 ticketNumber = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const FollowSymbolResult &result);
|
||||||
CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const FollowSymbolMessage &message);
|
CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const FollowSymbolMessage &message);
|
||||||
|
|
||||||
DECLARE_MESSAGE(FollowSymbolMessage);
|
DECLARE_MESSAGE(FollowSymbolMessage);
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ static
|
|||||||
CppTools::SymbolInfo toSymbolInfo(const FollowSymbolMessage &message)
|
CppTools::SymbolInfo toSymbolInfo(const FollowSymbolMessage &message)
|
||||||
{
|
{
|
||||||
CppTools::SymbolInfo result;
|
CppTools::SymbolInfo result;
|
||||||
const SourceRangeContainer &range = message.sourceRange;
|
const SourceRangeContainer &range = message.result.range;
|
||||||
|
|
||||||
const SourceLocationContainer &start = range.start;
|
const SourceLocationContainer &start = range.start;
|
||||||
const SourceLocationContainer &end = range.end;
|
const SourceLocationContainer &end = range.end;
|
||||||
@@ -265,6 +265,8 @@ CppTools::SymbolInfo toSymbolInfo(const FollowSymbolMessage &message)
|
|||||||
result.endColumn = static_cast<int>(end.column);
|
result.endColumn = static_cast<int>(end.column);
|
||||||
result.fileName = start.filePath;
|
result.fileName = start.filePath;
|
||||||
|
|
||||||
|
result.isPureDeclarationForUsage = message.result.isPureDeclarationForUsage;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,7 +356,7 @@ void BackendReceiver::tooltip(const ToolTipMessage &message)
|
|||||||
void BackendReceiver::followSymbol(const ClangBackEnd::FollowSymbolMessage &message)
|
void BackendReceiver::followSymbol(const ClangBackEnd::FollowSymbolMessage &message)
|
||||||
{
|
{
|
||||||
qCDebugIpc() << "FollowSymbolMessage with"
|
qCDebugIpc() << "FollowSymbolMessage with"
|
||||||
<< message.sourceRange << "range";
|
<< message.result;
|
||||||
|
|
||||||
const quint64 ticket = message.ticketNumber;
|
const quint64 ticket = message.ticketNumber;
|
||||||
QFutureInterface<CppTools::SymbolInfo> futureInterface = m_followTable.take(ticket);
|
QFutureInterface<CppTools::SymbolInfo> futureInterface = m_followTable.take(ticket);
|
||||||
|
|||||||
@@ -140,6 +140,19 @@ static Utils::Link linkAtCursor(const QTextCursor &cursor,
|
|||||||
return Link();
|
return Link();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ::Utils::ProcessLinkCallback extendedCallback(::Utils::ProcessLinkCallback &&callback,
|
||||||
|
const CppTools::SymbolInfo &result)
|
||||||
|
{
|
||||||
|
// If globalFollowSymbol finds nothing follow to the declaration.
|
||||||
|
return [original_callback = std::move(callback), result](const ::Utils::Link &link) {
|
||||||
|
if (!link.hasValidTarget() && result.isPureDeclarationForUsage) {
|
||||||
|
return original_callback(::Utils::Link(result.fileName, result.startLine,
|
||||||
|
result.startColumn - 1));
|
||||||
|
}
|
||||||
|
return original_callback(link);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
void ClangFollowSymbol::findLink(const CppTools::CursorInEditor &data,
|
void ClangFollowSymbol::findLink(const CppTools::CursorInEditor &data,
|
||||||
::Utils::ProcessLinkCallback &&processLinkCallback,
|
::Utils::ProcessLinkCallback &&processLinkCallback,
|
||||||
bool resolveTarget,
|
bool resolveTarget,
|
||||||
@@ -185,11 +198,11 @@ void ClangFollowSymbol::findLink(const CppTools::CursorInEditor &data,
|
|||||||
return callback(Utils::Link());
|
return callback(Utils::Link());
|
||||||
CppTools::SymbolInfo result = m_watcher->result();
|
CppTools::SymbolInfo result = m_watcher->result();
|
||||||
// We did not fail but the result is empty
|
// We did not fail but the result is empty
|
||||||
if (result.fileName.isEmpty()) {
|
if (result.fileName.isEmpty() || result.isPureDeclarationForUsage) {
|
||||||
const CppTools::RefactoringEngineInterface &refactoringEngine
|
const CppTools::RefactoringEngineInterface &refactoringEngine
|
||||||
= *CppTools::CppModelManager::instance();
|
= *CppTools::CppModelManager::instance();
|
||||||
refactoringEngine.globalFollowSymbol(data,
|
refactoringEngine.globalFollowSymbol(data,
|
||||||
std::move(callback),
|
extendedCallback(std::move(callback), result),
|
||||||
snapshot,
|
snapshot,
|
||||||
documentFromSemanticInfo,
|
documentFromSemanticInfo,
|
||||||
symbolFinder,
|
symbolFinder,
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ public:
|
|||||||
int endLine = 0;
|
int endLine = 0;
|
||||||
int endColumn = 0;
|
int endColumn = 0;
|
||||||
QString fileName;
|
QString fileName;
|
||||||
|
bool isPureDeclarationForUsage = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CppTools
|
} // namespace CppTools
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ static int getTokenIndex(CXTranslationUnit tu, const Tokens &tokens, uint line,
|
|||||||
return tokenIndex;
|
return tokenIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceRangeContainer FollowSymbol::followSymbol(CXTranslationUnit tu,
|
FollowSymbolResult FollowSymbol::followSymbol(CXTranslationUnit tu,
|
||||||
const Cursor &fullCursor,
|
const Cursor &fullCursor,
|
||||||
uint line,
|
uint line,
|
||||||
uint column)
|
uint column)
|
||||||
@@ -175,7 +175,7 @@ SourceRangeContainer FollowSymbol::followSymbol(CXTranslationUnit tu,
|
|||||||
CXFile file = clang_getIncludedFile(cursors[tokenIndex]);
|
CXFile file = clang_getIncludedFile(cursors[tokenIndex]);
|
||||||
const ClangString filename(clang_getFileName(file));
|
const ClangString filename(clang_getFileName(file));
|
||||||
const SourceLocation loc(tu, filename, 1, 1);
|
const SourceLocation loc(tu, filename, 1, 1);
|
||||||
return SourceRange(loc, loc);
|
return SourceRangeContainer(SourceRange(loc, loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
// For definitions we can always find a declaration in current TU
|
// For definitions we can always find a declaration in current TU
|
||||||
@@ -185,12 +185,16 @@ SourceRangeContainer FollowSymbol::followSymbol(CXTranslationUnit tu,
|
|||||||
if (!cursor.isDeclaration()) {
|
if (!cursor.isDeclaration()) {
|
||||||
// This is the symbol usage
|
// This is the symbol usage
|
||||||
// We want to return definition
|
// We want to return definition
|
||||||
|
FollowSymbolResult result;
|
||||||
cursor = cursor.referenced();
|
cursor = cursor.referenced();
|
||||||
if (cursor.isNull() || !cursor.isDefinition()) {
|
if (cursor.isNull())
|
||||||
// We can't find definition in this TU
|
|
||||||
return SourceRangeContainer();
|
return SourceRangeContainer();
|
||||||
|
if (!cursor.isDefinition()) {
|
||||||
|
// We can't find definition in this TU
|
||||||
|
result.isPureDeclarationForUsage = true;
|
||||||
}
|
}
|
||||||
return extractMatchingTokenRange(cursor, tokenSpelling);
|
result.range = extractMatchingTokenRange(cursor, tokenSpelling);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor = cursor.definition();
|
cursor = cursor.definition();
|
||||||
|
|||||||
@@ -33,14 +33,15 @@ class Utf8String;
|
|||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
class Cursor;
|
|
||||||
class SourceRangeContainer;
|
|
||||||
class CommandLineArguments;
|
class CommandLineArguments;
|
||||||
|
class Cursor;
|
||||||
|
class FollowSymbolResult;
|
||||||
|
class SourceRangeContainer;
|
||||||
|
|
||||||
class FollowSymbol
|
class FollowSymbol
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static SourceRangeContainer followSymbol(CXTranslationUnit tu,
|
static FollowSymbolResult followSymbol(CXTranslationUnit tu,
|
||||||
const Cursor &fullCursor,
|
const Cursor &fullCursor,
|
||||||
uint line,
|
uint line,
|
||||||
uint column);
|
uint column);
|
||||||
|
|||||||
@@ -27,14 +27,15 @@
|
|||||||
|
|
||||||
#include "clangdocumentjob.h"
|
#include "clangdocumentjob.h"
|
||||||
|
|
||||||
|
#include <clangsupport/followsymbolmessage.h>
|
||||||
#include <clangsupport/sourcerangecontainer.h>
|
#include <clangsupport/sourcerangecontainer.h>
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
class FollowSymbolJob : public DocumentJob<SourceRangeContainer>
|
class FollowSymbolJob : public DocumentJob<FollowSymbolResult>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using AsyncResult = SourceRangeContainer;
|
using AsyncResult = FollowSymbolResult;
|
||||||
|
|
||||||
AsyncPrepareResult prepareAsyncRun() override;
|
AsyncPrepareResult prepareAsyncRun() override;
|
||||||
void finalizeAsyncRun() override;
|
void finalizeAsyncRun() override;
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ void TranslationUnit::extractDiagnostics(DiagnosticContainer &firstHeaderErrorDi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceRangeContainer TranslationUnit::followSymbol(uint line, uint column) const
|
FollowSymbolResult TranslationUnit::followSymbol(uint line, uint column) const
|
||||||
{
|
{
|
||||||
return FollowSymbol::followSymbol(m_cxTranslationUnit, cursorAt(line, column), line, column);
|
return FollowSymbol::followSymbol(m_cxTranslationUnit, cursorAt(line, column), line, column);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ namespace ClangBackEnd {
|
|||||||
class Cursor;
|
class Cursor;
|
||||||
class DiagnosticContainer;
|
class DiagnosticContainer;
|
||||||
class DiagnosticSet;
|
class DiagnosticSet;
|
||||||
|
class FollowSymbolResult;
|
||||||
class ReferencesResult;
|
class ReferencesResult;
|
||||||
class SkippedSourceRanges;
|
class SkippedSourceRanges;
|
||||||
class SourceLocation;
|
class SourceLocation;
|
||||||
@@ -108,7 +109,7 @@ public:
|
|||||||
TokenProcessor<FullTokenInfo> fullTokenInfosInRange(const SourceRange &range) const;
|
TokenProcessor<FullTokenInfo> fullTokenInfosInRange(const SourceRange &range) const;
|
||||||
|
|
||||||
SkippedSourceRanges skippedSourceRanges() const;
|
SkippedSourceRanges skippedSourceRanges() const;
|
||||||
SourceRangeContainer followSymbol(uint line, uint column) const;
|
FollowSymbolResult followSymbol(uint line, uint column) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Utf8String m_id;
|
const Utf8String m_id;
|
||||||
|
|||||||
@@ -630,14 +630,12 @@ void ClangCodeModelServer::expectReferences()
|
|||||||
|
|
||||||
void ClangCodeModelServer::expectFollowSymbol()
|
void ClangCodeModelServer::expectFollowSymbol()
|
||||||
{
|
{
|
||||||
const ClangBackEnd::SourceRangeContainer classDefinition{
|
const ClangBackEnd::FollowSymbolResult classDefinition
|
||||||
{filePathC, 40, 7},
|
= ClangBackEnd::SourceRangeContainer({filePathC, 40, 7}, {filePathC, 40, 10});
|
||||||
{filePathC, 40, 10}
|
|
||||||
};
|
|
||||||
|
|
||||||
EXPECT_CALL(mockClangCodeModelClient,
|
EXPECT_CALL(mockClangCodeModelClient,
|
||||||
followSymbol(
|
followSymbol(
|
||||||
Field(&FollowSymbolMessage::sourceRange,
|
Field(&FollowSymbolMessage::result,
|
||||||
Eq(classDefinition))))
|
Eq(classDefinition))))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include <clangdocuments.h>
|
#include <clangdocuments.h>
|
||||||
#include <clangtranslationunit.h>
|
#include <clangtranslationunit.h>
|
||||||
#include <fixitcontainer.h>
|
#include <fixitcontainer.h>
|
||||||
|
#include <followsymbolmessage.h>
|
||||||
#include <projectpart.h>
|
#include <projectpart.h>
|
||||||
#include <projects.h>
|
#include <projects.h>
|
||||||
#include <sourcelocationcontainer.h>
|
#include <sourcelocationcontainer.h>
|
||||||
@@ -55,6 +56,7 @@ using ::ClangBackEnd::Document;
|
|||||||
using ::ClangBackEnd::UnsavedFiles;
|
using ::ClangBackEnd::UnsavedFiles;
|
||||||
using ::ClangBackEnd::ReferencesResult;
|
using ::ClangBackEnd::ReferencesResult;
|
||||||
using ::ClangBackEnd::SourceRangeContainer;
|
using ::ClangBackEnd::SourceRangeContainer;
|
||||||
|
using ::ClangBackEnd::FollowSymbolResult;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const Utf8String sourceFilePath = Utf8StringLiteral(TESTDATA_DIR"/followsymbol_main.cpp");
|
const Utf8String sourceFilePath = Utf8StringLiteral(TESTDATA_DIR"/followsymbol_main.cpp");
|
||||||
@@ -131,12 +133,12 @@ public:
|
|||||||
class FollowSymbol : public ::testing::Test
|
class FollowSymbol : public ::testing::Test
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
SourceRangeContainer followSymbol(uint line, uint column)
|
FollowSymbolResult followSymbol(uint line, uint column)
|
||||||
{
|
{
|
||||||
return document.translationUnit().followSymbol(line, column);
|
return document.translationUnit().followSymbol(line, column);
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceRangeContainer followHeaderSymbol(uint line, uint column)
|
FollowSymbolResult followHeaderSymbol(uint line, uint column)
|
||||||
{
|
{
|
||||||
return headerDocument.translationUnit().followSymbol(line, column);
|
return headerDocument.translationUnit().followSymbol(line, column);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -237,12 +237,22 @@ std::ostream &operator<<(std::ostream &os, const RegisterProjectPartsForEditorMe
|
|||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, const FollowSymbolResult &result)
|
||||||
|
{
|
||||||
|
os << "("
|
||||||
|
<< result.range
|
||||||
|
<< ", " << result.isPureDeclarationForUsage
|
||||||
|
<< ")";
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, const FollowSymbolMessage &message)
|
std::ostream &operator<<(std::ostream &os, const FollowSymbolMessage &message)
|
||||||
{
|
{
|
||||||
os << "("
|
os << "("
|
||||||
<< message.fileContainer << ", "
|
<< message.fileContainer << ", "
|
||||||
<< message.ticketNumber << ", "
|
<< message.ticketNumber << ", "
|
||||||
<< message.sourceRange << ", "
|
<< message.result << ", "
|
||||||
<< ")";
|
<< ")";
|
||||||
|
|
||||||
return os;
|
return os;
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ class EchoMessage;
|
|||||||
class DocumentAnnotationsChangedMessage;
|
class DocumentAnnotationsChangedMessage;
|
||||||
class ReferencesMessage;
|
class ReferencesMessage;
|
||||||
class ToolTipMessage;
|
class ToolTipMessage;
|
||||||
|
class FollowSymbolResult;
|
||||||
class FollowSymbolMessage;
|
class FollowSymbolMessage;
|
||||||
class CompleteCodeMessage;
|
class CompleteCodeMessage;
|
||||||
class EndMessage;
|
class EndMessage;
|
||||||
@@ -177,6 +178,7 @@ std::ostream &operator<<(std::ostream &out, const EchoMessage &message);
|
|||||||
std::ostream &operator<<(std::ostream &out, const DocumentAnnotationsChangedMessage &message);
|
std::ostream &operator<<(std::ostream &out, const DocumentAnnotationsChangedMessage &message);
|
||||||
std::ostream &operator<<(std::ostream &out, const ReferencesMessage &message);
|
std::ostream &operator<<(std::ostream &out, const ReferencesMessage &message);
|
||||||
std::ostream &operator<<(std::ostream &out, const ToolTipMessage &message);
|
std::ostream &operator<<(std::ostream &out, const ToolTipMessage &message);
|
||||||
|
std::ostream &operator<<(std::ostream &out, const FollowSymbolResult &result);
|
||||||
std::ostream &operator<<(std::ostream &out, const FollowSymbolMessage &message);
|
std::ostream &operator<<(std::ostream &out, const FollowSymbolMessage &message);
|
||||||
std::ostream &operator<<(std::ostream &out, const CompleteCodeMessage &message);
|
std::ostream &operator<<(std::ostream &out, const CompleteCodeMessage &message);
|
||||||
std::ostream &operator<<(std::ostream &out, const EndMessage &message);
|
std::ostream &operator<<(std::ostream &out, const EndMessage &message);
|
||||||
|
|||||||
Reference in New Issue
Block a user