forked from qt-creator/qt-creator
Clang: use HighlightingMarks for hover with Ctrl highlighting
Make this highlighting work without builtin code model but based on the HighlightingMarks that we already have from ClangCodeModel. Redundant parameters are removed by this change. Change-Id: I73b5dab46ba59d2f813236831818f0a9bc94c5bc Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
@@ -36,8 +36,7 @@ QDebug operator<<(QDebug debug, const FollowSymbolMessage &message)
|
|||||||
debug.nospace() << "FollowSymbolMessage("
|
debug.nospace() << "FollowSymbolMessage("
|
||||||
<< message.m_fileContainer
|
<< message.m_fileContainer
|
||||||
<< ", " << message.m_ticketNumber
|
<< ", " << message.m_ticketNumber
|
||||||
<< ", " << message.m_sourceRange
|
<< ", " << message.m_sourceRange;
|
||||||
<< ", " << message.m_failedToFollow;
|
|
||||||
|
|
||||||
debug.nospace() << ")";
|
debug.nospace() << ")";
|
||||||
|
|
||||||
@@ -50,7 +49,6 @@ std::ostream &operator<<(std::ostream &os, const FollowSymbolMessage &message)
|
|||||||
<< message.m_fileContainer << ", "
|
<< message.m_fileContainer << ", "
|
||||||
<< message.m_ticketNumber << ", "
|
<< message.m_ticketNumber << ", "
|
||||||
<< message.m_sourceRange << ", "
|
<< message.m_sourceRange << ", "
|
||||||
<< message.m_failedToFollow << ", "
|
|
||||||
<< ")";
|
<< ")";
|
||||||
|
|
||||||
return os;
|
return os;
|
||||||
|
|||||||
@@ -39,12 +39,10 @@ public:
|
|||||||
FollowSymbolMessage() = default;
|
FollowSymbolMessage() = default;
|
||||||
FollowSymbolMessage(const FileContainer &fileContainer,
|
FollowSymbolMessage(const FileContainer &fileContainer,
|
||||||
const SourceRangeContainer &range,
|
const SourceRangeContainer &range,
|
||||||
bool failedToFollow,
|
|
||||||
quint64 ticketNumber)
|
quint64 ticketNumber)
|
||||||
: m_fileContainer(fileContainer)
|
: m_fileContainer(fileContainer)
|
||||||
, m_sourceRange(range)
|
, m_sourceRange(range)
|
||||||
, m_ticketNumber(ticketNumber)
|
, m_ticketNumber(ticketNumber)
|
||||||
, m_failedToFollow(failedToFollow)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
const FileContainer &fileContainer() const
|
const FileContainer &fileContainer() const
|
||||||
@@ -57,11 +55,6 @@ public:
|
|||||||
return m_sourceRange;
|
return m_sourceRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool failedToFollow() const
|
|
||||||
{
|
|
||||||
return m_failedToFollow;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint64 ticketNumber() const
|
quint64 ticketNumber() const
|
||||||
{
|
{
|
||||||
return m_ticketNumber;
|
return m_ticketNumber;
|
||||||
@@ -72,7 +65,6 @@ public:
|
|||||||
out << message.m_fileContainer;
|
out << message.m_fileContainer;
|
||||||
out << message.m_sourceRange;
|
out << message.m_sourceRange;
|
||||||
out << message.m_ticketNumber;
|
out << message.m_ticketNumber;
|
||||||
out << message.m_failedToFollow;
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +73,6 @@ public:
|
|||||||
in >> message.m_fileContainer;
|
in >> message.m_fileContainer;
|
||||||
in >> message.m_sourceRange;
|
in >> message.m_sourceRange;
|
||||||
in >> message.m_ticketNumber;
|
in >> message.m_ticketNumber;
|
||||||
in >> message.m_failedToFollow;
|
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,8 +80,7 @@ public:
|
|||||||
{
|
{
|
||||||
return first.m_ticketNumber == second.m_ticketNumber
|
return first.m_ticketNumber == second.m_ticketNumber
|
||||||
&& first.m_fileContainer == second.m_fileContainer
|
&& first.m_fileContainer == second.m_fileContainer
|
||||||
&& first.m_sourceRange == second.m_sourceRange
|
&& first.m_sourceRange == second.m_sourceRange;
|
||||||
&& first.m_failedToFollow == second.m_failedToFollow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
friend CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FollowSymbolMessage &message);
|
friend CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FollowSymbolMessage &message);
|
||||||
@@ -99,7 +89,6 @@ private:
|
|||||||
FileContainer m_fileContainer;
|
FileContainer m_fileContainer;
|
||||||
SourceRangeContainer m_sourceRange;
|
SourceRangeContainer m_sourceRange;
|
||||||
quint64 m_ticketNumber = 0;
|
quint64 m_ticketNumber = 0;
|
||||||
bool m_failedToFollow = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_MESSAGE(FollowSymbolMessage);
|
DECLARE_MESSAGE(FollowSymbolMessage);
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ QDebug operator<<(QDebug debug, const HighlightingMarkContainer &container)
|
|||||||
<< container.column() << ", "
|
<< container.column() << ", "
|
||||||
<< container.length() << ", "
|
<< container.length() << ", "
|
||||||
<< highlightingTypeToCStringLiteral(container.types().mainHighlightingType) << ", "
|
<< highlightingTypeToCStringLiteral(container.types().mainHighlightingType) << ", "
|
||||||
|
<< container.isIdentifier() << ", "
|
||||||
|
<< container.isIncludeDirectivePath()
|
||||||
<< ")";
|
<< ")";
|
||||||
|
|
||||||
return debug;
|
return debug;
|
||||||
@@ -94,7 +96,9 @@ std::ostream &operator<<(std::ostream &os, const HighlightingMarkContainer &cont
|
|||||||
<< container.line() << ", "
|
<< container.line() << ", "
|
||||||
<< container.column() << ", "
|
<< container.column() << ", "
|
||||||
<< container.length() << ", "
|
<< container.length() << ", "
|
||||||
<< container.types()
|
<< container.types() << ", "
|
||||||
|
<< container.isIdentifier() << ", "
|
||||||
|
<< container.isIncludeDirectivePath()
|
||||||
<< ")";
|
<< ")";
|
||||||
|
|
||||||
return os;
|
return os;
|
||||||
|
|||||||
@@ -44,11 +44,14 @@ class HighlightingMarkContainer
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HighlightingMarkContainer() = default;
|
HighlightingMarkContainer() = default;
|
||||||
HighlightingMarkContainer(uint line, uint column, uint length, HighlightingTypes types)
|
HighlightingMarkContainer(uint line, uint column, uint length, HighlightingTypes types,
|
||||||
|
bool isIdentifier = false, bool isIncludeDirectivePath = false)
|
||||||
: line_(line),
|
: line_(line),
|
||||||
column_(column),
|
column_(column),
|
||||||
length_(length),
|
length_(length),
|
||||||
types_(types)
|
types_(types),
|
||||||
|
isIdentifier_(isIdentifier),
|
||||||
|
isIncludeDirectivePath_(isIncludeDirectivePath)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,12 +83,29 @@ public:
|
|||||||
return types_;
|
return types_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isInvalid() const
|
||||||
|
{
|
||||||
|
return line_ == 0 && column_ == 0 && length_ == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isIdentifier() const
|
||||||
|
{
|
||||||
|
return isIdentifier_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isIncludeDirectivePath() const
|
||||||
|
{
|
||||||
|
return isIncludeDirectivePath_;
|
||||||
|
}
|
||||||
|
|
||||||
friend QDataStream &operator<<(QDataStream &out, const HighlightingMarkContainer &container)
|
friend QDataStream &operator<<(QDataStream &out, const HighlightingMarkContainer &container)
|
||||||
{
|
{
|
||||||
out << container.line_;
|
out << container.line_;
|
||||||
out << container.column_;
|
out << container.column_;
|
||||||
out << container.length_;
|
out << container.length_;
|
||||||
out << container.types_;
|
out << container.types_;
|
||||||
|
out << container.isIdentifier_;
|
||||||
|
out << container.isIncludeDirectivePath_;
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -96,6 +116,8 @@ public:
|
|||||||
in >> container.column_;
|
in >> container.column_;
|
||||||
in >> container.length_;
|
in >> container.length_;
|
||||||
in >> container.types_;
|
in >> container.types_;
|
||||||
|
in >> container.isIdentifier_;
|
||||||
|
in >> container.isIncludeDirectivePath_;
|
||||||
|
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
@@ -105,7 +127,9 @@ public:
|
|||||||
return first.line_ == second.line_
|
return first.line_ == second.line_
|
||||||
&& first.column_ == second.column_
|
&& first.column_ == second.column_
|
||||||
&& first.length_ == second.length_
|
&& first.length_ == second.length_
|
||||||
&& first.types_ == second.types_;
|
&& first.types_ == second.types_
|
||||||
|
&& first.isIdentifier_ == second.isIdentifier_
|
||||||
|
&& first.isIncludeDirectivePath_ == second.isIncludeDirectivePath_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -113,6 +137,8 @@ private:
|
|||||||
uint column_ = 0;
|
uint column_ = 0;
|
||||||
uint length_ = 0;
|
uint length_ = 0;
|
||||||
HighlightingTypes types_;
|
HighlightingTypes types_;
|
||||||
|
bool isIdentifier_ = false;
|
||||||
|
bool isIncludeDirectivePath_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline QDataStream &operator<<(QDataStream &out, HighlightingType highlightingType)
|
inline QDataStream &operator<<(QDataStream &out, HighlightingType highlightingType)
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ QDebug operator<<(QDebug debug, const RequestFollowSymbolMessage &message)
|
|||||||
debug.nospace() << message.m_ticketNumber << ", ";
|
debug.nospace() << message.m_ticketNumber << ", ";
|
||||||
debug.nospace() << message.m_line << ", ";
|
debug.nospace() << message.m_line << ", ";
|
||||||
debug.nospace() << message.m_column << ", ";
|
debug.nospace() << message.m_column << ", ";
|
||||||
debug.nospace() << message.m_resolveTarget << ", ";
|
|
||||||
|
|
||||||
debug.nospace() << ")";
|
debug.nospace() << ")";
|
||||||
|
|
||||||
@@ -57,7 +56,6 @@ std::ostream &operator<<(std::ostream &os, const RequestFollowSymbolMessage &mes
|
|||||||
<< message.m_ticketNumber << ", "
|
<< message.m_ticketNumber << ", "
|
||||||
<< message.m_line << ", "
|
<< message.m_line << ", "
|
||||||
<< message.m_column << ", "
|
<< message.m_column << ", "
|
||||||
<< message.m_resolveTarget << ", "
|
|
||||||
<< ")";
|
<< ")";
|
||||||
|
|
||||||
return os;
|
return os;
|
||||||
|
|||||||
@@ -40,14 +40,12 @@ public:
|
|||||||
RequestFollowSymbolMessage(const FileContainer &fileContainer,
|
RequestFollowSymbolMessage(const FileContainer &fileContainer,
|
||||||
const QVector<Utf8String> &dependentFiles,
|
const QVector<Utf8String> &dependentFiles,
|
||||||
quint32 line,
|
quint32 line,
|
||||||
quint32 column,
|
quint32 column)
|
||||||
bool resolveTarget = true)
|
|
||||||
: m_fileContainer(fileContainer)
|
: m_fileContainer(fileContainer)
|
||||||
, m_ticketNumber(++ticketCounter)
|
, m_ticketNumber(++ticketCounter)
|
||||||
, m_line(line)
|
, m_line(line)
|
||||||
, m_column(column)
|
, m_column(column)
|
||||||
, m_dependentFiles(dependentFiles)
|
, m_dependentFiles(dependentFiles)
|
||||||
, m_resolveTarget(resolveTarget)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,11 +69,6 @@ public:
|
|||||||
return m_column;
|
return m_column;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool resolveTarget() const
|
|
||||||
{
|
|
||||||
return m_resolveTarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint64 ticketNumber() const
|
quint64 ticketNumber() const
|
||||||
{
|
{
|
||||||
return m_ticketNumber;
|
return m_ticketNumber;
|
||||||
@@ -88,7 +81,6 @@ public:
|
|||||||
out << message.m_ticketNumber;
|
out << message.m_ticketNumber;
|
||||||
out << message.m_line;
|
out << message.m_line;
|
||||||
out << message.m_column;
|
out << message.m_column;
|
||||||
out << message.m_resolveTarget;
|
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -100,7 +92,6 @@ public:
|
|||||||
in >> message.m_ticketNumber;
|
in >> message.m_ticketNumber;
|
||||||
in >> message.m_line;
|
in >> message.m_line;
|
||||||
in >> message.m_column;
|
in >> message.m_column;
|
||||||
in >> message.m_resolveTarget;
|
|
||||||
|
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
@@ -112,7 +103,6 @@ public:
|
|||||||
&& first.m_line == second.m_line
|
&& first.m_line == second.m_line
|
||||||
&& first.m_column == second.m_column
|
&& first.m_column == second.m_column
|
||||||
&& first.m_fileContainer == second.m_fileContainer
|
&& first.m_fileContainer == second.m_fileContainer
|
||||||
&& first.m_resolveTarget == second.m_resolveTarget
|
|
||||||
&& first.m_dependentFiles == second.m_dependentFiles;
|
&& first.m_dependentFiles == second.m_dependentFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +114,6 @@ private:
|
|||||||
quint32 m_line = 0;
|
quint32 m_line = 0;
|
||||||
quint32 m_column = 0;
|
quint32 m_column = 0;
|
||||||
QVector<Utf8String> m_dependentFiles;
|
QVector<Utf8String> m_dependentFiles;
|
||||||
bool m_resolveTarget = true;
|
|
||||||
static CMBIPC_EXPORT quint64 ticketCounter;
|
static CMBIPC_EXPORT quint64 ticketCounter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -275,7 +275,6 @@ CppTools::SymbolInfo toSymbolInfo(const FollowSymbolMessage &message)
|
|||||||
result.endLine = static_cast<int>(end.line());
|
result.endLine = static_cast<int>(end.line());
|
||||||
result.endColumn = static_cast<int>(end.column());
|
result.endColumn = static_cast<int>(end.column());
|
||||||
result.fileName = start.filePath();
|
result.fileName = start.filePath();
|
||||||
result.failedToFollow = message.failedToFollow();
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -748,14 +747,12 @@ QFuture<CppTools::SymbolInfo> IpcCommunicator::requestFollowSymbol(
|
|||||||
const FileContainer &curFileContainer,
|
const FileContainer &curFileContainer,
|
||||||
const QVector<Utf8String> &dependentFiles,
|
const QVector<Utf8String> &dependentFiles,
|
||||||
quint32 line,
|
quint32 line,
|
||||||
quint32 column,
|
quint32 column)
|
||||||
bool resolveTarget)
|
|
||||||
{
|
{
|
||||||
const RequestFollowSymbolMessage message(curFileContainer,
|
const RequestFollowSymbolMessage message(curFileContainer,
|
||||||
dependentFiles,
|
dependentFiles,
|
||||||
line,
|
line,
|
||||||
column,
|
column);
|
||||||
resolveTarget);
|
|
||||||
m_ipcSender->requestFollowSymbol(message);
|
m_ipcSender->requestFollowSymbol(message);
|
||||||
|
|
||||||
return m_ipcReceiver.addExpectedRequestFollowSymbolMessage(message.ticketNumber());
|
return m_ipcReceiver.addExpectedRequestFollowSymbolMessage(message.ticketNumber());
|
||||||
|
|||||||
@@ -169,8 +169,7 @@ public:
|
|||||||
QFuture<CppTools::SymbolInfo> requestFollowSymbol(const FileContainer &curFileContainer,
|
QFuture<CppTools::SymbolInfo> requestFollowSymbol(const FileContainer &curFileContainer,
|
||||||
const QVector<Utf8String> &dependentFiles,
|
const QVector<Utf8String> &dependentFiles,
|
||||||
quint32 line,
|
quint32 line,
|
||||||
quint32 column,
|
quint32 column);
|
||||||
bool resolveTarget);
|
|
||||||
void completeCode(ClangCompletionAssistProcessor *assistProcessor, const QString &filePath,
|
void completeCode(ClangCompletionAssistProcessor *assistProcessor, const QString &filePath,
|
||||||
quint32 line,
|
quint32 line,
|
||||||
quint32 column,
|
quint32 column,
|
||||||
|
|||||||
@@ -225,6 +225,12 @@ toTextEditorBlocks(QTextDocument *textDocument,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QVector<ClangBackEnd::HighlightingMarkContainer>
|
||||||
|
&ClangEditorDocumentProcessor::highlightingMarks() const
|
||||||
|
{
|
||||||
|
return m_highlightingMarks;
|
||||||
|
}
|
||||||
|
|
||||||
void ClangEditorDocumentProcessor::updateHighlighting(
|
void ClangEditorDocumentProcessor::updateHighlighting(
|
||||||
const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks,
|
const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks,
|
||||||
const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges,
|
const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges,
|
||||||
@@ -234,6 +240,7 @@ void ClangEditorDocumentProcessor::updateHighlighting(
|
|||||||
const auto skippedPreprocessorBlocks = toTextEditorBlocks(textDocument(), skippedPreprocessorRanges);
|
const auto skippedPreprocessorBlocks = toTextEditorBlocks(textDocument(), skippedPreprocessorRanges);
|
||||||
emit ifdefedOutBlocksUpdated(documentRevision, skippedPreprocessorBlocks);
|
emit ifdefedOutBlocksUpdated(documentRevision, skippedPreprocessorBlocks);
|
||||||
|
|
||||||
|
m_highlightingMarks = highlightingMarks;
|
||||||
m_semanticHighlighter.setHighlightingRunner(
|
m_semanticHighlighter.setHighlightingRunner(
|
||||||
[highlightingMarks]() {
|
[highlightingMarks]() {
|
||||||
auto *reporter = new HighlightingMarksReporter(highlightingMarks);
|
auto *reporter = new HighlightingMarksReporter(highlightingMarks);
|
||||||
@@ -376,7 +383,7 @@ static QVector<Utf8String> prioritizeByBaseName(const QString &curPath,
|
|||||||
}
|
}
|
||||||
|
|
||||||
QFuture<CppTools::SymbolInfo>
|
QFuture<CppTools::SymbolInfo>
|
||||||
ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column, bool resolveTarget)
|
ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column)
|
||||||
{
|
{
|
||||||
QVector<Utf8String> dependentFiles;
|
QVector<Utf8String> dependentFiles;
|
||||||
CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
|
CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
|
||||||
@@ -390,8 +397,7 @@ ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column, bool res
|
|||||||
return m_ipcCommunicator.requestFollowSymbol(simpleFileContainer(),
|
return m_ipcCommunicator.requestFollowSymbol(simpleFileContainer(),
|
||||||
dependentFiles,
|
dependentFiles,
|
||||||
static_cast<quint32>(line),
|
static_cast<quint32>(line),
|
||||||
static_cast<quint32>(column),
|
static_cast<quint32>(column));
|
||||||
resolveTarget);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithArguments() const
|
ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithArguments() const
|
||||||
|
|||||||
@@ -86,14 +86,14 @@ public:
|
|||||||
void setParserConfig(const CppTools::BaseEditorDocumentParser::Configuration config) override;
|
void setParserConfig(const CppTools::BaseEditorDocumentParser::Configuration config) override;
|
||||||
|
|
||||||
QFuture<CppTools::CursorInfo> cursorInfo(const CppTools::CursorInfoParams ¶ms) override;
|
QFuture<CppTools::CursorInfo> cursorInfo(const CppTools::CursorInfoParams ¶ms) override;
|
||||||
QFuture<CppTools::SymbolInfo> requestFollowSymbol(int line,
|
QFuture<CppTools::SymbolInfo> requestFollowSymbol(int line, int column) override;
|
||||||
int column,
|
|
||||||
bool resolveTarget) override;
|
|
||||||
|
|
||||||
ClangBackEnd::FileContainer fileContainerWithArguments() const;
|
ClangBackEnd::FileContainer fileContainerWithArguments() const;
|
||||||
|
|
||||||
void clearDiagnosticsWithFixIts();
|
void clearDiagnosticsWithFixIts();
|
||||||
|
|
||||||
|
const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static ClangEditorDocumentProcessor *get(const QString &filePath);
|
static ClangEditorDocumentProcessor *get(const QString &filePath);
|
||||||
|
|
||||||
@@ -122,6 +122,7 @@ private:
|
|||||||
QTimer m_updateTranslationUnitTimer;
|
QTimer m_updateTranslationUnitTimer;
|
||||||
unsigned m_parserRevision;
|
unsigned m_parserRevision;
|
||||||
|
|
||||||
|
QVector<ClangBackEnd::HighlightingMarkContainer> m_highlightingMarks;
|
||||||
CppTools::SemanticHighlighter m_semanticHighlighter;
|
CppTools::SemanticHighlighter m_semanticHighlighter;
|
||||||
CppTools::BuiltinEditorDocumentProcessor m_builtinProcessor;
|
CppTools::BuiltinEditorDocumentProcessor m_builtinProcessor;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,14 +23,78 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "clangfollowsymbol.h"
|
|
||||||
#include "clangeditordocumentprocessor.h"
|
#include "clangeditordocumentprocessor.h"
|
||||||
#include "texteditor/texteditor.h"
|
#include "clangfollowsymbol.h"
|
||||||
#include "texteditor/convenience.h"
|
|
||||||
|
#include <texteditor/convenience.h>
|
||||||
|
#include <texteditor/texteditor.h>
|
||||||
|
|
||||||
|
#include <clangsupport/highlightingmarkcontainer.h>
|
||||||
|
|
||||||
|
#include <utils/algorithm.h>
|
||||||
|
|
||||||
namespace ClangCodeModel {
|
namespace ClangCodeModel {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
// Returns invalid Mark if it is not found at (line, column)
|
||||||
|
static bool findMark(const QVector<ClangBackEnd::HighlightingMarkContainer> &marks,
|
||||||
|
uint line,
|
||||||
|
uint column,
|
||||||
|
ClangBackEnd::HighlightingMarkContainer &mark)
|
||||||
|
{
|
||||||
|
mark = Utils::findOrDefault(marks,
|
||||||
|
[line, column](const ClangBackEnd::HighlightingMarkContainer &curMark) {
|
||||||
|
if (curMark.line() != line)
|
||||||
|
return false;
|
||||||
|
if (curMark.column() == column)
|
||||||
|
return true;
|
||||||
|
if (curMark.column() < column && curMark.column() + curMark.length() >= column)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
if (mark.isInvalid())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getMarkPos(QTextCursor cursor, const ClangBackEnd::HighlightingMarkContainer &mark)
|
||||||
|
{
|
||||||
|
cursor.setPosition(0);
|
||||||
|
cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, mark.line() - 1);
|
||||||
|
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, mark.column() - 1);
|
||||||
|
return cursor.position();
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextEditor::TextEditorWidget::Link linkAtCursor(QTextCursor cursor,
|
||||||
|
const QString &filePath,
|
||||||
|
uint line,
|
||||||
|
uint column,
|
||||||
|
ClangEditorDocumentProcessor *processor)
|
||||||
|
{
|
||||||
|
using Link = TextEditor::TextEditorWidget::Link;
|
||||||
|
|
||||||
|
const QVector<ClangBackEnd::HighlightingMarkContainer> &marks
|
||||||
|
= processor->highlightingMarks();
|
||||||
|
ClangBackEnd::HighlightingMarkContainer mark;
|
||||||
|
if (!findMark(marks, line, column, mark))
|
||||||
|
return Link();
|
||||||
|
|
||||||
|
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
|
||||||
|
const QString tokenStr = cursor.selectedText();
|
||||||
|
|
||||||
|
Link token(filePath, mark.line(), mark.column());
|
||||||
|
token.linkTextStart = getMarkPos(cursor, mark);
|
||||||
|
token.linkTextEnd = token.linkTextStart + mark.length();
|
||||||
|
if (mark.isIncludeDirectivePath()) {
|
||||||
|
if (tokenStr != "include" && tokenStr != "#" && tokenStr != "<")
|
||||||
|
return token;
|
||||||
|
return Link();
|
||||||
|
}
|
||||||
|
if (mark.isIdentifier() || tokenStr == "operator")
|
||||||
|
return token;
|
||||||
|
return Link();
|
||||||
|
}
|
||||||
|
|
||||||
TextEditor::TextEditorWidget::Link ClangFollowSymbol::findLink(
|
TextEditor::TextEditorWidget::Link ClangFollowSymbol::findLink(
|
||||||
const CppTools::CursorInEditor &data,
|
const CppTools::CursorInEditor &data,
|
||||||
bool resolveTarget,
|
bool resolveTarget,
|
||||||
@@ -39,42 +103,39 @@ TextEditor::TextEditorWidget::Link ClangFollowSymbol::findLink(
|
|||||||
CppTools::SymbolFinder *,
|
CppTools::SymbolFinder *,
|
||||||
bool)
|
bool)
|
||||||
{
|
{
|
||||||
Link link;
|
|
||||||
|
|
||||||
int lineNumber = 0, positionInBlock = 0;
|
int lineNumber = 0, positionInBlock = 0;
|
||||||
QTextCursor cursor = TextEditor::Convenience::wordStartCursor(data.cursor());
|
QTextCursor cursor = TextEditor::Convenience::wordStartCursor(data.cursor());
|
||||||
TextEditor::Convenience::convertPosition(cursor.document(), cursor.position(), &lineNumber,
|
TextEditor::Convenience::convertPosition(cursor.document(), cursor.position(), &lineNumber,
|
||||||
&positionInBlock);
|
&positionInBlock);
|
||||||
const unsigned line = lineNumber;
|
|
||||||
const unsigned column = positionInBlock + 1;
|
|
||||||
|
|
||||||
if (!resolveTarget)
|
const uint line = lineNumber;
|
||||||
return link;
|
const uint column = positionInBlock + 1;
|
||||||
|
|
||||||
ClangEditorDocumentProcessor *processor = ClangEditorDocumentProcessor::get(
|
ClangEditorDocumentProcessor *processor = ClangEditorDocumentProcessor::get(
|
||||||
data.filePath().toString());
|
data.filePath().toString());
|
||||||
if (!processor)
|
if (!processor)
|
||||||
return link;
|
return Link();
|
||||||
|
|
||||||
|
if (!resolveTarget)
|
||||||
|
return linkAtCursor(cursor, data.filePath().toString(), line, column, processor);
|
||||||
|
|
||||||
QFuture<CppTools::SymbolInfo> info
|
QFuture<CppTools::SymbolInfo> info
|
||||||
= processor->requestFollowSymbol(static_cast<int>(line),
|
= processor->requestFollowSymbol(static_cast<int>(line),
|
||||||
static_cast<int>(column),
|
static_cast<int>(column));
|
||||||
resolveTarget);
|
|
||||||
if (info.isCanceled())
|
if (info.isCanceled())
|
||||||
return link;
|
return Link();
|
||||||
|
|
||||||
while (!info.isFinished()) {
|
while (!info.isFinished()) {
|
||||||
if (info.isCanceled())
|
if (info.isCanceled())
|
||||||
return link;
|
return Link();
|
||||||
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||||
}
|
}
|
||||||
CppTools::SymbolInfo result = info.result();
|
CppTools::SymbolInfo result = info.result();
|
||||||
|
|
||||||
if (result.failedToFollow)
|
|
||||||
return link;
|
|
||||||
|
|
||||||
// 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())
|
||||||
return link;
|
return Link();
|
||||||
|
|
||||||
return Link(result.fileName, result.startLine, result.startColumn - 1);
|
return Link(result.fileName, result.startLine, result.startColumn - 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,8 +158,15 @@ void HighlightingMarksReporter::run_internal()
|
|||||||
if (isCanceled())
|
if (isCanceled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (const auto &highlightingMark : m_highlightingMarks)
|
using ClangBackEnd::HighlightingType;
|
||||||
|
|
||||||
|
for (const auto &highlightingMark : m_highlightingMarks) {
|
||||||
|
const HighlightingType mainType = highlightingMark.types().mainHighlightingType;
|
||||||
|
if (mainType == HighlightingType::StringLiteral)
|
||||||
|
continue;
|
||||||
|
|
||||||
reportChunkWise(toHighlightingResult(highlightingMark));
|
reportChunkWise(toHighlightingResult(highlightingMark));
|
||||||
|
}
|
||||||
|
|
||||||
if (isCanceled())
|
if (isCanceled())
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -649,15 +649,6 @@ CppEditorWidget::Link CppEditorWidget::findLinkAt(const QTextCursor &cursor,
|
|||||||
return Link();
|
return Link();
|
||||||
|
|
||||||
const Utils::FileName &filePath = textDocument()->filePath();
|
const Utils::FileName &filePath = textDocument()->filePath();
|
||||||
if (!resolveTarget) {
|
|
||||||
// TODO: get that part also from clang
|
|
||||||
return d->m_builtinFollowSymbol.findLink(CppTools::CursorInEditor{cursor, filePath, this},
|
|
||||||
resolveTarget,
|
|
||||||
d->m_modelManager->snapshot(),
|
|
||||||
d->m_lastSemanticInfo.doc,
|
|
||||||
d->m_modelManager->symbolFinder(),
|
|
||||||
inNextSplit);
|
|
||||||
}
|
|
||||||
|
|
||||||
return followSymbolInterface()->findLink(CppTools::CursorInEditor{cursor, filePath, this},
|
return followSymbolInterface()->findLink(CppTools::CursorInEditor{cursor, filePath, this},
|
||||||
resolveTarget,
|
resolveTarget,
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ public:
|
|||||||
virtual void setParserConfig(const BaseEditorDocumentParser::Configuration config);
|
virtual void setParserConfig(const BaseEditorDocumentParser::Configuration config);
|
||||||
|
|
||||||
virtual QFuture<CursorInfo> cursorInfo(const CursorInfoParams ¶ms) = 0;
|
virtual QFuture<CursorInfo> cursorInfo(const CursorInfoParams ¶ms) = 0;
|
||||||
virtual QFuture<SymbolInfo> requestFollowSymbol(int line, int column, bool resolveTarget) = 0;
|
virtual QFuture<SymbolInfo> requestFollowSymbol(int line, int column) = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using HeaderErrorDiagnosticWidgetCreator = std::function<QWidget*()>;
|
using HeaderErrorDiagnosticWidgetCreator = std::function<QWidget*()>;
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public:
|
|||||||
bool isParserRunning() const override;
|
bool isParserRunning() const override;
|
||||||
|
|
||||||
QFuture<CursorInfo> cursorInfo(const CursorInfoParams ¶ms) override;
|
QFuture<CursorInfo> cursorInfo(const CursorInfoParams ¶ms) override;
|
||||||
QFuture<SymbolInfo> requestFollowSymbol(int, int, bool) override
|
QFuture<SymbolInfo> requestFollowSymbol(int, int) override
|
||||||
{ return QFuture<SymbolInfo>(); }
|
{ return QFuture<SymbolInfo>(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ public:
|
|||||||
int endLine = 0;
|
int endLine = 0;
|
||||||
int endColumn = 0;
|
int endColumn = 0;
|
||||||
QString fileName;
|
QString fileName;
|
||||||
bool failedToFollow = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CppTools
|
} // namespace CppTools
|
||||||
|
|||||||
@@ -281,7 +281,6 @@ void ClangCodeModelServer::requestFollowSymbol(const RequestFollowSymbolMessage
|
|||||||
JobRequest jobRequest = processor.createJobRequest(JobRequest::Type::FollowSymbol);
|
JobRequest jobRequest = processor.createJobRequest(JobRequest::Type::FollowSymbol);
|
||||||
fillJobRequest(jobRequest, message);
|
fillJobRequest(jobRequest, message);
|
||||||
jobRequest.dependentFiles = message.dependentFiles();
|
jobRequest.dependentFiles = message.dependentFiles();
|
||||||
jobRequest.resolveTarget = message.resolveTarget();
|
|
||||||
processor.addJob(jobRequest);
|
processor.addJob(jobRequest);
|
||||||
processor.process();
|
processor.process();
|
||||||
} catch (const std::exception &exception) {
|
} catch (const std::exception &exception) {
|
||||||
|
|||||||
@@ -41,10 +41,16 @@ namespace {
|
|||||||
|
|
||||||
struct Tokens
|
struct Tokens
|
||||||
{
|
{
|
||||||
|
Tokens(const Tokens &) = delete;
|
||||||
Tokens(const Cursor &cursor) {
|
Tokens(const Cursor &cursor) {
|
||||||
tu = cursor.cxTranslationUnit();
|
tu = cursor.cxTranslationUnit();
|
||||||
clang_tokenize(tu, cursor.cxSourceRange(), &data, &tokenCount);
|
clang_tokenize(tu, cursor.cxSourceRange(), &data, &tokenCount);
|
||||||
}
|
}
|
||||||
|
Tokens(const CXTranslationUnit &tu) {
|
||||||
|
const CXSourceRange range
|
||||||
|
= clang_getCursorExtent(clang_getTranslationUnitCursor(tu));
|
||||||
|
clang_tokenize(tu, range, &data, &tokenCount);
|
||||||
|
}
|
||||||
~Tokens() {
|
~Tokens() {
|
||||||
clang_disposeTokens(tu, data, tokenCount);
|
clang_disposeTokens(tu, data, tokenCount);
|
||||||
}
|
}
|
||||||
@@ -198,7 +204,7 @@ static IndexerCallbacks createIndexerCallbacks()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static FollowSymbolResult followSymbolInDependentFiles(CXIndex index,
|
static SourceRangeContainer followSymbolInDependentFiles(CXIndex index,
|
||||||
const Cursor &cursor,
|
const Cursor &cursor,
|
||||||
const Utf8String &tokenSpelling,
|
const Utf8String &tokenSpelling,
|
||||||
const QVector<Utf8String> &dependentFiles,
|
const QVector<Utf8String> &dependentFiles,
|
||||||
@@ -250,63 +256,61 @@ static FollowSymbolResult followSymbolInDependentFiles(CXIndex index,
|
|||||||
for (const std::future<void> &future: indexFutures)
|
for (const std::future<void> &future: indexFutures)
|
||||||
future.wait();
|
future.wait();
|
||||||
|
|
||||||
FollowSymbolResult result;
|
|
||||||
for (const FollowSymbolData &data: dataVector) {
|
for (const FollowSymbolData &data: dataVector) {
|
||||||
if (!data.result().start().filePath().isEmpty()) {
|
if (!data.result().start().filePath().isEmpty()) {
|
||||||
result.range = data.result();
|
return data.result();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return SourceRangeContainer();
|
||||||
}
|
}
|
||||||
|
|
||||||
FollowSymbolResult FollowSymbol::followSymbol(CXIndex index,
|
SourceRangeContainer FollowSymbol::followSymbol(CXTranslationUnit tu,
|
||||||
|
CXIndex index,
|
||||||
const Cursor &fullCursor,
|
const Cursor &fullCursor,
|
||||||
uint line,
|
uint line,
|
||||||
uint column,
|
uint column,
|
||||||
const QVector<Utf8String> &dependentFiles,
|
const QVector<Utf8String> &dependentFiles,
|
||||||
const CommandLineArguments ¤tArgs)
|
const CommandLineArguments ¤tArgs)
|
||||||
{
|
{
|
||||||
FollowSymbolResult result;
|
std::unique_ptr<Tokens> tokens(new Tokens(fullCursor));
|
||||||
Tokens tokens(fullCursor);
|
|
||||||
if (!tokens.tokenCount) {
|
|
||||||
result.failedToFollow = true;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CXTranslationUnit tu = fullCursor.cxTranslationUnit();
|
if (!tokens->tokenCount)
|
||||||
|
tokens.reset(new Tokens(tu));
|
||||||
|
|
||||||
QVector<CXCursor> cursors(static_cast<int>(tokens.tokenCount));
|
if (!tokens->tokenCount)
|
||||||
clang_annotateTokens(tu, tokens.data, tokens.tokenCount, cursors.data());
|
return SourceRangeContainer();
|
||||||
int tokenIndex = getTokenIndex(tu, tokens, line, column);
|
|
||||||
QTC_ASSERT(tokenIndex >= 0, return result);
|
|
||||||
|
|
||||||
const Utf8String tokenSpelling = ClangString(clang_getTokenSpelling(tu, tokens.data[tokenIndex]));
|
QVector<CXCursor> cursors(static_cast<int>(tokens->tokenCount));
|
||||||
|
clang_annotateTokens(tu, tokens->data, tokens->tokenCount, cursors.data());
|
||||||
|
int tokenIndex = getTokenIndex(tu, *tokens, line, column);
|
||||||
|
QTC_ASSERT(tokenIndex >= 0, return SourceRangeContainer());
|
||||||
|
|
||||||
|
const Utf8String tokenSpelling = ClangString(
|
||||||
|
clang_getTokenSpelling(tu, tokens->data[tokenIndex]));
|
||||||
if (tokenSpelling.isEmpty())
|
if (tokenSpelling.isEmpty())
|
||||||
return result;
|
return SourceRangeContainer();
|
||||||
|
|
||||||
Cursor cursor{cursors[tokenIndex]};
|
Cursor cursor{cursors[tokenIndex]};
|
||||||
|
|
||||||
if (cursor.kind() == CXCursor_InclusionDirective) {
|
if (cursor.kind() == CXCursor_InclusionDirective) {
|
||||||
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);
|
||||||
result.range = SourceRange(loc, loc);
|
return SourceRange(loc, loc);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cursor.isDefinition()) {
|
|
||||||
// For definitions we can always find a declaration in current TU
|
// For definitions we can always find a declaration in current TU
|
||||||
result.range = extractMatchingTokenRange(cursor.canonical(), tokenSpelling);
|
if (cursor.isDefinition())
|
||||||
return result;
|
return extractMatchingTokenRange(cursor.canonical(), tokenSpelling);
|
||||||
}
|
|
||||||
|
|
||||||
|
SourceRangeContainer result;
|
||||||
if (!cursor.isDeclaration()) {
|
if (!cursor.isDeclaration()) {
|
||||||
// This is the symbol usage
|
// This is the symbol usage
|
||||||
// We want to return definition or at least declaration of this symbol
|
// We want to return definition or at least declaration of this symbol
|
||||||
const Cursor referencedCursor = cursor.referenced();
|
const Cursor referencedCursor = cursor.referenced();
|
||||||
if (referencedCursor.isNull() || referencedCursor == cursor)
|
if (referencedCursor.isNull() || referencedCursor == cursor)
|
||||||
return result;
|
return SourceRangeContainer();
|
||||||
result.range = extractMatchingTokenRange(referencedCursor, tokenSpelling);
|
result = extractMatchingTokenRange(referencedCursor, tokenSpelling);
|
||||||
|
|
||||||
// We've already found what we need
|
// We've already found what we need
|
||||||
if (referencedCursor.isDefinition())
|
if (referencedCursor.isDefinition())
|
||||||
@@ -317,17 +321,16 @@ FollowSymbolResult FollowSymbol::followSymbol(CXIndex index,
|
|||||||
const Cursor definitionCursor = cursor.definition();
|
const Cursor definitionCursor = cursor.definition();
|
||||||
if (!definitionCursor.isNull() && definitionCursor != cursor) {
|
if (!definitionCursor.isNull() && definitionCursor != cursor) {
|
||||||
// If we are able to find a definition in current TU
|
// If we are able to find a definition in current TU
|
||||||
result.range = extractMatchingTokenRange(definitionCursor, tokenSpelling);
|
return extractMatchingTokenRange(definitionCursor, tokenSpelling);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for the definition in the dependent files
|
// Search for the definition in the dependent files
|
||||||
FollowSymbolResult dependentFilesResult = followSymbolInDependentFiles(index,
|
SourceRangeContainer dependentFilesResult = followSymbolInDependentFiles(index,
|
||||||
cursor,
|
cursor,
|
||||||
tokenSpelling,
|
tokenSpelling,
|
||||||
dependentFiles,
|
dependentFiles,
|
||||||
currentArgs);
|
currentArgs);
|
||||||
return dependentFilesResult.range.start().filePath().isEmpty() ?
|
return dependentFilesResult.start().filePath().isEmpty() ?
|
||||||
result : dependentFilesResult;
|
result : dependentFilesResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,13 +34,14 @@ class Utf8String;
|
|||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
class Cursor;
|
class Cursor;
|
||||||
class FollowSymbolResult;
|
class SourceRangeContainer;
|
||||||
class CommandLineArguments;
|
class CommandLineArguments;
|
||||||
|
|
||||||
class FollowSymbol
|
class FollowSymbol
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static FollowSymbolResult followSymbol(CXIndex index,
|
static SourceRangeContainer followSymbol(CXTranslationUnit tu,
|
||||||
|
CXIndex index,
|
||||||
const Cursor &fullCursor,
|
const Cursor &fullCursor,
|
||||||
uint line,
|
uint line,
|
||||||
uint column,
|
uint column,
|
||||||
|
|||||||
@@ -38,8 +38,6 @@ IAsyncJob::AsyncPrepareResult FollowSymbolJob::prepareAsyncRun()
|
|||||||
const JobRequest jobRequest = context().jobRequest;
|
const JobRequest jobRequest = context().jobRequest;
|
||||||
QTC_ASSERT(jobRequest.type == JobRequest::Type::FollowSymbol,
|
QTC_ASSERT(jobRequest.type == JobRequest::Type::FollowSymbol,
|
||||||
return AsyncPrepareResult());
|
return AsyncPrepareResult());
|
||||||
// Is too slow because of IPC timings, no implementation for now
|
|
||||||
QTC_ASSERT(jobRequest.resolveTarget, return AsyncPrepareResult());
|
|
||||||
QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
|
QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
|
||||||
|
|
||||||
const TranslationUnit translationUnit = *m_translationUnit;
|
const TranslationUnit translationUnit = *m_translationUnit;
|
||||||
@@ -66,8 +64,7 @@ void FollowSymbolJob::finalizeAsyncRun()
|
|||||||
const AsyncResult result = asyncResult();
|
const AsyncResult result = asyncResult();
|
||||||
|
|
||||||
const FollowSymbolMessage message(m_pinnedFileContainer,
|
const FollowSymbolMessage message(m_pinnedFileContainer,
|
||||||
result.range,
|
result,
|
||||||
result.failedToFollow,
|
|
||||||
context().jobRequest.ticketNumber);
|
context().jobRequest.ticketNumber);
|
||||||
context().client->followSymbol(message);
|
context().client->followSymbol(message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,29 +31,10 @@
|
|||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
class FollowSymbolResult
|
class FollowSymbolJob : public DocumentJob<SourceRangeContainer>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FollowSymbolResult() = default;
|
using AsyncResult = SourceRangeContainer;
|
||||||
FollowSymbolResult(const SourceRangeContainer &range, bool failedToFollow = false)
|
|
||||||
: range(range)
|
|
||||||
, failedToFollow(failedToFollow)
|
|
||||||
{}
|
|
||||||
|
|
||||||
friend bool operator==(const FollowSymbolResult &first, const FollowSymbolResult &second)
|
|
||||||
{
|
|
||||||
return first.range == second.range
|
|
||||||
&& first.failedToFollow == second.failedToFollow;
|
|
||||||
}
|
|
||||||
|
|
||||||
SourceRangeContainer range;
|
|
||||||
bool failedToFollow = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FollowSymbolJob : public DocumentJob<FollowSymbolResult>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using AsyncResult = FollowSymbolResult;
|
|
||||||
|
|
||||||
AsyncPrepareResult prepareAsyncRun() override;
|
AsyncPrepareResult prepareAsyncRun() override;
|
||||||
void finalizeAsyncRun() override;
|
void finalizeAsyncRun() override;
|
||||||
|
|||||||
@@ -229,7 +229,6 @@ void JobRequest::cancelJob(ClangCodeModelClientInterface &client) const
|
|||||||
case JobRequest::Type::FollowSymbol:
|
case JobRequest::Type::FollowSymbol:
|
||||||
client.followSymbol(FollowSymbolMessage(FileContainer(),
|
client.followSymbol(FollowSymbolMessage(FileContainer(),
|
||||||
SourceRangeContainer(),
|
SourceRangeContainer(),
|
||||||
true,
|
|
||||||
ticketNumber));
|
ticketNumber));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,7 +118,6 @@ public:
|
|||||||
qint32 funcNameStartColumn = -1;
|
qint32 funcNameStartColumn = -1;
|
||||||
quint64 ticketNumber = 0;
|
quint64 ticketNumber = 0;
|
||||||
Utf8StringVector dependentFiles;
|
Utf8StringVector dependentFiles;
|
||||||
bool resolveTarget = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using JobRequests = QVector<JobRequest>;
|
using JobRequests = QVector<JobRequest>;
|
||||||
|
|||||||
@@ -243,13 +243,13 @@ void TranslationUnit::extractDiagnostics(DiagnosticContainer &firstHeaderErrorDi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FollowSymbolResult TranslationUnit::followSymbol(uint line,
|
SourceRangeContainer TranslationUnit::followSymbol(uint line,
|
||||||
uint column,
|
uint column,
|
||||||
const QVector<Utf8String> &dependentFiles,
|
const QVector<Utf8String> &dependentFiles,
|
||||||
const CommandLineArguments ¤tArgs) const
|
const CommandLineArguments ¤tArgs) const
|
||||||
{
|
{
|
||||||
return FollowSymbol::followSymbol(m_cxIndex, cursorAt(line, column), line, column,
|
return FollowSymbol::followSymbol(m_cxTranslationUnit, m_cxIndex, cursorAt(line, column), line,
|
||||||
dependentFiles, currentArgs);
|
column, dependentFiles, currentArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ class DiagnosticSet;
|
|||||||
class HighlightingMarkContainer;
|
class HighlightingMarkContainer;
|
||||||
class HighlightingMarks;
|
class HighlightingMarks;
|
||||||
class ReferencesResult;
|
class ReferencesResult;
|
||||||
class FollowSymbolResult;
|
|
||||||
class SkippedSourceRanges;
|
class SkippedSourceRanges;
|
||||||
class SourceLocation;
|
class SourceLocation;
|
||||||
class SourceRange;
|
class SourceRange;
|
||||||
@@ -101,7 +100,7 @@ public:
|
|||||||
HighlightingMarks highlightingMarksInRange(const SourceRange &range) const;
|
HighlightingMarks highlightingMarksInRange(const SourceRange &range) const;
|
||||||
|
|
||||||
SkippedSourceRanges skippedSourceRanges() const;
|
SkippedSourceRanges skippedSourceRanges() const;
|
||||||
FollowSymbolResult followSymbol(uint line,
|
SourceRangeContainer followSymbol(uint line,
|
||||||
uint column,
|
uint column,
|
||||||
const QVector<Utf8String> &dependentFiles,
|
const QVector<Utf8String> &dependentFiles,
|
||||||
const CommandLineArguments ¤tArgs) const;
|
const CommandLineArguments ¤tArgs) const;
|
||||||
|
|||||||
@@ -105,7 +105,8 @@ bool HighlightingMark::hasFunctionArguments() const
|
|||||||
|
|
||||||
HighlightingMark::operator HighlightingMarkContainer() const
|
HighlightingMark::operator HighlightingMarkContainer() const
|
||||||
{
|
{
|
||||||
return HighlightingMarkContainer(m_line, m_column, m_length, m_types);
|
return HighlightingMarkContainer(m_line, m_column, m_length, m_types, m_isIdentifier,
|
||||||
|
m_isInclusion);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -288,6 +289,8 @@ void HighlightingMark::functionKind(const Cursor &cursor, Recursion recursion)
|
|||||||
|
|
||||||
void HighlightingMark::identifierKind(const Cursor &cursor, Recursion recursion)
|
void HighlightingMark::identifierKind(const Cursor &cursor, Recursion recursion)
|
||||||
{
|
{
|
||||||
|
m_isIdentifier = (cursor.kind() != CXCursor_PreprocessingDirective);
|
||||||
|
|
||||||
switch (cursor.kind()) {
|
switch (cursor.kind()) {
|
||||||
case CXCursor_Destructor:
|
case CXCursor_Destructor:
|
||||||
case CXCursor_Constructor:
|
case CXCursor_Constructor:
|
||||||
@@ -352,6 +355,7 @@ HighlightingType literalKind(const Cursor &cursor)
|
|||||||
switch (cursor.kind()) {
|
switch (cursor.kind()) {
|
||||||
case CXCursor_CharacterLiteral:
|
case CXCursor_CharacterLiteral:
|
||||||
case CXCursor_StringLiteral:
|
case CXCursor_StringLiteral:
|
||||||
|
case CXCursor_InclusionDirective:
|
||||||
case CXCursor_ObjCStringLiteral: return HighlightingType::StringLiteral;
|
case CXCursor_ObjCStringLiteral: return HighlightingType::StringLiteral;
|
||||||
case CXCursor_IntegerLiteral:
|
case CXCursor_IntegerLiteral:
|
||||||
case CXCursor_ImaginaryLiteral:
|
case CXCursor_ImaginaryLiteral:
|
||||||
@@ -438,6 +442,8 @@ void HighlightingMark::collectKinds(CXTranslationUnit cxTranslationUnit,
|
|||||||
case CXToken_Comment: m_types.mainHighlightingType = HighlightingType::Comment; break;
|
case CXToken_Comment: m_types.mainHighlightingType = HighlightingType::Comment; break;
|
||||||
case CXToken_Literal: m_types.mainHighlightingType = literalKind(cursor); break;
|
case CXToken_Literal: m_types.mainHighlightingType = literalKind(cursor); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_isInclusion = (cursor.kind() == CXCursor_InclusionDirective);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, const HighlightingMark& highlightingMark)
|
std::ostream &operator<<(std::ostream &os, const HighlightingMark& highlightingMark)
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ private:
|
|||||||
uint m_length;
|
uint m_length;
|
||||||
uint m_offset = 0;
|
uint m_offset = 0;
|
||||||
HighlightingTypes m_types;
|
HighlightingTypes m_types;
|
||||||
|
bool m_isIdentifier = false;
|
||||||
|
bool m_isInclusion = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -68,15 +68,12 @@ QVector<HighlightingMarkContainer> HighlightingMarks::toHighlightingMarksContain
|
|||||||
|
|
||||||
const auto isValidHighlightMark = [] (const HighlightingMark &highlightMark) {
|
const auto isValidHighlightMark = [] (const HighlightingMark &highlightMark) {
|
||||||
return !highlightMark.hasInvalidMainType()
|
return !highlightMark.hasInvalidMainType()
|
||||||
&& !highlightMark.hasMainType(HighlightingType::StringLiteral)
|
|
||||||
&& !highlightMark.hasMainType(HighlightingType::NumberLiteral)
|
&& !highlightMark.hasMainType(HighlightingType::NumberLiteral)
|
||||||
&& !highlightMark.hasMainType(HighlightingType::Comment);
|
&& !highlightMark.hasMainType(HighlightingType::Comment);
|
||||||
};
|
};
|
||||||
|
for (const HighlightingMark &highlightMark : *this)
|
||||||
for (const HighlightingMark &highlightMark : *this) {
|
|
||||||
if (isValidHighlightMark(highlightMark))
|
if (isValidHighlightMark(highlightMark))
|
||||||
containers.push_back(highlightMark);
|
containers.push_back(highlightMark);
|
||||||
}
|
|
||||||
|
|
||||||
return containers;
|
return containers;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,20 +56,11 @@ 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");
|
||||||
const Utf8String headerFilePath = Utf8StringLiteral(TESTDATA_DIR"/followsymbol_header.h");
|
const Utf8String headerFilePath = Utf8StringLiteral(TESTDATA_DIR"/followsymbol_header.h");
|
||||||
const Utf8String cursorPath = Utf8StringLiteral(TESTDATA_DIR"/cursor.cpp");
|
const Utf8String cursorPath = Utf8StringLiteral(TESTDATA_DIR"/cursor.cpp");
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, const FollowSymbolResult &result)
|
|
||||||
{
|
|
||||||
os << result.range;
|
|
||||||
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
MATCHER_P3(MatchesHeaderSourceRange, line, column, length,
|
MATCHER_P3(MatchesHeaderSourceRange, line, column, length,
|
||||||
std::string(negation ? "isn't " : "is ")
|
std::string(negation ? "isn't " : "is ")
|
||||||
+ PrintToString(SourceRangeContainer {
|
+ PrintToString(SourceRangeContainer {
|
||||||
@@ -83,7 +74,7 @@ MATCHER_P3(MatchesHeaderSourceRange, line, column, length,
|
|||||||
SourceLocationContainer(headerFilePath, line, column + length)
|
SourceLocationContainer(headerFilePath, line, column + length)
|
||||||
};
|
};
|
||||||
|
|
||||||
return arg == FollowSymbolResult {expected, false};
|
return arg == expected;
|
||||||
}
|
}
|
||||||
|
|
||||||
MATCHER_P3(MatchesSourceRange, line, column, length,
|
MATCHER_P3(MatchesSourceRange, line, column, length,
|
||||||
@@ -99,7 +90,7 @@ MATCHER_P3(MatchesSourceRange, line, column, length,
|
|||||||
SourceLocationContainer(sourceFilePath, line, column + length)
|
SourceLocationContainer(sourceFilePath, line, column + length)
|
||||||
};
|
};
|
||||||
|
|
||||||
return arg == FollowSymbolResult {expected, false};
|
return arg == expected;
|
||||||
}
|
}
|
||||||
|
|
||||||
MATCHER_P4(MatchesFileSourceRange, filename, line, column, length,
|
MATCHER_P4(MatchesFileSourceRange, filename, line, column, length,
|
||||||
@@ -115,7 +106,7 @@ MATCHER_P4(MatchesFileSourceRange, filename, line, column, length,
|
|||||||
SourceLocationContainer(filename, line, column + length)
|
SourceLocationContainer(filename, line, column + length)
|
||||||
};
|
};
|
||||||
|
|
||||||
return arg == FollowSymbolResult {expected, false};
|
return arg == expected;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Data {
|
class Data {
|
||||||
@@ -150,7 +141,7 @@ private:
|
|||||||
class FollowSymbol : public ::testing::Test
|
class FollowSymbol : public ::testing::Test
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
FollowSymbolResult followSymbol(uint line, uint column)
|
SourceRangeContainer followSymbol(uint line, uint column)
|
||||||
{
|
{
|
||||||
ClangBackEnd::TranslationUnitUpdateInput updateInput = d->document().createUpdateInput();
|
ClangBackEnd::TranslationUnitUpdateInput updateInput = d->document().createUpdateInput();
|
||||||
const ClangBackEnd::CommandLineArguments currentArgs(updateInput.filePath.constData(),
|
const ClangBackEnd::CommandLineArguments currentArgs(updateInput.filePath.constData(),
|
||||||
@@ -162,7 +153,7 @@ protected:
|
|||||||
currentArgs);
|
currentArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
FollowSymbolResult followHeaderSymbol(uint line, uint column)
|
SourceRangeContainer followHeaderSymbol(uint line, uint column)
|
||||||
{
|
{
|
||||||
ClangBackEnd::TranslationUnitUpdateInput updateInput
|
ClangBackEnd::TranslationUnitUpdateInput updateInput
|
||||||
= d->headerDocument().createUpdateInput();
|
= d->headerDocument().createUpdateInput();
|
||||||
|
|||||||
@@ -1184,6 +1184,42 @@ TEST_F(HighlightingMarks, UsingTemplateFunction)
|
|||||||
ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Function));
|
ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Function));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(HighlightingMarks, HeaderNameIsInclusion)
|
||||||
|
{
|
||||||
|
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(239, 31));
|
||||||
|
ClangBackEnd::HighlightingMarkContainer container(infos[2]);
|
||||||
|
ASSERT_THAT(container.isIncludeDirectivePath(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(HighlightingMarks, HeaderNameIsInclusionWithAngleBrackets)
|
||||||
|
{
|
||||||
|
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(289, 31));
|
||||||
|
ClangBackEnd::HighlightingMarkContainer container(infos[2]);
|
||||||
|
ASSERT_THAT(container.isIncludeDirectivePath(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(HighlightingMarks, NotInclusion)
|
||||||
|
{
|
||||||
|
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(241, 13));
|
||||||
|
ClangBackEnd::HighlightingMarkContainer container(infos[1]);
|
||||||
|
ASSERT_THAT(container.isIncludeDirectivePath(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(HighlightingMarks, MacroIsIdentifier)
|
||||||
|
{
|
||||||
|
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(232, 30));
|
||||||
|
ClangBackEnd::HighlightingMarkContainer container(infos[2]);
|
||||||
|
ASSERT_THAT(container.isIdentifier(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(HighlightingMarks, DefineIsNotIdentifier)
|
||||||
|
{
|
||||||
|
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(232, 30));
|
||||||
|
ClangBackEnd::HighlightingMarkContainer container(infos[1]);
|
||||||
|
ASSERT_THAT(container.isIncludeDirectivePath(), false);
|
||||||
|
}
|
||||||
|
|
||||||
Data *HighlightingMarks::d;
|
Data *HighlightingMarks::d;
|
||||||
|
|
||||||
void HighlightingMarks::SetUpTestCase()
|
void HighlightingMarks::SetUpTestCase()
|
||||||
|
|||||||
@@ -208,8 +208,7 @@ TEST_F(ReadAndWriteMessageBlock, CompareRequestFollowSymbol)
|
|||||||
QVector<Utf8String> dependentFiles;
|
QVector<Utf8String> dependentFiles;
|
||||||
dependentFiles.push_back(QString("somefile.cpp"));
|
dependentFiles.push_back(QString("somefile.cpp"));
|
||||||
dependentFiles.push_back(QString("otherfile.cpp"));
|
dependentFiles.push_back(QString("otherfile.cpp"));
|
||||||
CompareMessage(ClangBackEnd::RequestFollowSymbolMessage{fileContainer, dependentFiles, 13, 37,
|
CompareMessage(ClangBackEnd::RequestFollowSymbolMessage{fileContainer, dependentFiles, 13, 37});
|
||||||
false});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ReadAndWriteMessageBlock, CompareReferences)
|
TEST_F(ReadAndWriteMessageBlock, CompareReferences)
|
||||||
|
|||||||
Reference in New Issue
Block a user