From f130de2400b8fa6bc98110b721e12e9e02a5fc09 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Fri, 8 Sep 2017 09:33:35 +0200 Subject: [PATCH] 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 --- src/libs/clangsupport/followsymbolmessage.cpp | 4 +- src/libs/clangsupport/followsymbolmessage.h | 13 +-- .../highlightingmarkcontainer.cpp | 6 +- .../clangsupport/highlightingmarkcontainer.h | 32 +++++- .../requestfollowsymbolmessage.cpp | 2 - .../clangsupport/requestfollowsymbolmessage.h | 13 +-- .../clangbackendipcintegration.cpp | 7 +- .../clangbackendipcintegration.h | 3 +- .../clangeditordocumentprocessor.cpp | 12 ++- .../clangeditordocumentprocessor.h | 7 +- .../clangcodemodel/clangfollowsymbol.cpp | 97 +++++++++++++++---- .../clanghighlightingmarksreporter.cpp | 9 +- src/plugins/cppeditor/cppeditorwidget.cpp | 9 -- .../cpptools/baseeditordocumentprocessor.h | 2 +- .../cpptools/builtineditordocumentprocessor.h | 2 +- src/plugins/cpptools/cppsymbolinfo.h | 1 - .../ipcsource/clangcodemodelserver.cpp | 1 - .../ipcsource/clangfollowsymbol.cpp | 93 +++++++++--------- .../ipcsource/clangfollowsymbol.h | 15 +-- .../ipcsource/clangfollowsymboljob.cpp | 5 +- .../ipcsource/clangfollowsymboljob.h | 23 +---- .../ipcsource/clangjobrequest.cpp | 1 - .../clangbackend/ipcsource/clangjobrequest.h | 1 - .../ipcsource/clangtranslationunit.cpp | 12 +-- .../ipcsource/clangtranslationunit.h | 9 +- .../ipcsource/highlightingmark.cpp | 8 +- .../clangbackend/ipcsource/highlightingmark.h | 2 + .../ipcsource/highlightingmarks.cpp | 9 +- .../unit/unittest/clangfollowsymbol-test.cpp | 19 +--- .../unit/unittest/highlightingmarks-test.cpp | 36 +++++++ .../readandwritemessageblock-test.cpp | 3 +- 31 files changed, 265 insertions(+), 191 deletions(-) diff --git a/src/libs/clangsupport/followsymbolmessage.cpp b/src/libs/clangsupport/followsymbolmessage.cpp index 929199bef5b..cafd22aa4bc 100644 --- a/src/libs/clangsupport/followsymbolmessage.cpp +++ b/src/libs/clangsupport/followsymbolmessage.cpp @@ -36,8 +36,7 @@ QDebug operator<<(QDebug debug, const FollowSymbolMessage &message) debug.nospace() << "FollowSymbolMessage(" << message.m_fileContainer << ", " << message.m_ticketNumber - << ", " << message.m_sourceRange - << ", " << message.m_failedToFollow; + << ", " << message.m_sourceRange; debug.nospace() << ")"; @@ -50,7 +49,6 @@ std::ostream &operator<<(std::ostream &os, const FollowSymbolMessage &message) << message.m_fileContainer << ", " << message.m_ticketNumber << ", " << message.m_sourceRange << ", " - << message.m_failedToFollow << ", " << ")"; return os; diff --git a/src/libs/clangsupport/followsymbolmessage.h b/src/libs/clangsupport/followsymbolmessage.h index ad8f7348f39..3893a6e49c3 100644 --- a/src/libs/clangsupport/followsymbolmessage.h +++ b/src/libs/clangsupport/followsymbolmessage.h @@ -39,12 +39,10 @@ public: FollowSymbolMessage() = default; FollowSymbolMessage(const FileContainer &fileContainer, const SourceRangeContainer &range, - bool failedToFollow, quint64 ticketNumber) : m_fileContainer(fileContainer) , m_sourceRange(range) , m_ticketNumber(ticketNumber) - , m_failedToFollow(failedToFollow) { } const FileContainer &fileContainer() const @@ -57,11 +55,6 @@ public: return m_sourceRange; } - bool failedToFollow() const - { - return m_failedToFollow; - } - quint64 ticketNumber() const { return m_ticketNumber; @@ -72,7 +65,6 @@ public: out << message.m_fileContainer; out << message.m_sourceRange; out << message.m_ticketNumber; - out << message.m_failedToFollow; return out; } @@ -81,7 +73,6 @@ public: in >> message.m_fileContainer; in >> message.m_sourceRange; in >> message.m_ticketNumber; - in >> message.m_failedToFollow; return in; } @@ -89,8 +80,7 @@ public: { return first.m_ticketNumber == second.m_ticketNumber && first.m_fileContainer == second.m_fileContainer - && first.m_sourceRange == second.m_sourceRange - && first.m_failedToFollow == second.m_failedToFollow; + && first.m_sourceRange == second.m_sourceRange; } friend CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FollowSymbolMessage &message); @@ -99,7 +89,6 @@ private: FileContainer m_fileContainer; SourceRangeContainer m_sourceRange; quint64 m_ticketNumber = 0; - bool m_failedToFollow = false; }; DECLARE_MESSAGE(FollowSymbolMessage); diff --git a/src/libs/clangsupport/highlightingmarkcontainer.cpp b/src/libs/clangsupport/highlightingmarkcontainer.cpp index ab679c8d890..ec460a14a6f 100644 --- a/src/libs/clangsupport/highlightingmarkcontainer.cpp +++ b/src/libs/clangsupport/highlightingmarkcontainer.cpp @@ -65,6 +65,8 @@ QDebug operator<<(QDebug debug, const HighlightingMarkContainer &container) << container.column() << ", " << container.length() << ", " << highlightingTypeToCStringLiteral(container.types().mainHighlightingType) << ", " + << container.isIdentifier() << ", " + << container.isIncludeDirectivePath() << ")"; return debug; @@ -94,7 +96,9 @@ std::ostream &operator<<(std::ostream &os, const HighlightingMarkContainer &cont << container.line() << ", " << container.column() << ", " << container.length() << ", " - << container.types() + << container.types() << ", " + << container.isIdentifier() << ", " + << container.isIncludeDirectivePath() << ")"; return os; diff --git a/src/libs/clangsupport/highlightingmarkcontainer.h b/src/libs/clangsupport/highlightingmarkcontainer.h index 0bc3ab0b555..8b6e585e501 100644 --- a/src/libs/clangsupport/highlightingmarkcontainer.h +++ b/src/libs/clangsupport/highlightingmarkcontainer.h @@ -44,11 +44,14 @@ class HighlightingMarkContainer { public: 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), column_(column), length_(length), - types_(types) + types_(types), + isIdentifier_(isIdentifier), + isIncludeDirectivePath_(isIncludeDirectivePath) { } @@ -80,12 +83,29 @@ public: 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) { out << container.line_; out << container.column_; out << container.length_; out << container.types_; + out << container.isIdentifier_; + out << container.isIncludeDirectivePath_; return out; } @@ -96,6 +116,8 @@ public: in >> container.column_; in >> container.length_; in >> container.types_; + in >> container.isIdentifier_; + in >> container.isIncludeDirectivePath_; return in; } @@ -105,7 +127,9 @@ public: return first.line_ == second.line_ && first.column_ == second.column_ && first.length_ == second.length_ - && first.types_ == second.types_; + && first.types_ == second.types_ + && first.isIdentifier_ == second.isIdentifier_ + && first.isIncludeDirectivePath_ == second.isIncludeDirectivePath_; } private: @@ -113,6 +137,8 @@ private: uint column_ = 0; uint length_ = 0; HighlightingTypes types_; + bool isIdentifier_ = false; + bool isIncludeDirectivePath_ = false; }; inline QDataStream &operator<<(QDataStream &out, HighlightingType highlightingType) diff --git a/src/libs/clangsupport/requestfollowsymbolmessage.cpp b/src/libs/clangsupport/requestfollowsymbolmessage.cpp index 9d31139840a..dcb0b5cd2ef 100644 --- a/src/libs/clangsupport/requestfollowsymbolmessage.cpp +++ b/src/libs/clangsupport/requestfollowsymbolmessage.cpp @@ -42,7 +42,6 @@ QDebug operator<<(QDebug debug, const RequestFollowSymbolMessage &message) debug.nospace() << message.m_ticketNumber << ", "; debug.nospace() << message.m_line << ", "; debug.nospace() << message.m_column << ", "; - debug.nospace() << message.m_resolveTarget << ", "; debug.nospace() << ")"; @@ -57,7 +56,6 @@ std::ostream &operator<<(std::ostream &os, const RequestFollowSymbolMessage &mes << message.m_ticketNumber << ", " << message.m_line << ", " << message.m_column << ", " - << message.m_resolveTarget << ", " << ")"; return os; diff --git a/src/libs/clangsupport/requestfollowsymbolmessage.h b/src/libs/clangsupport/requestfollowsymbolmessage.h index a9c37e101a5..1305abfba81 100644 --- a/src/libs/clangsupport/requestfollowsymbolmessage.h +++ b/src/libs/clangsupport/requestfollowsymbolmessage.h @@ -40,14 +40,12 @@ public: RequestFollowSymbolMessage(const FileContainer &fileContainer, const QVector &dependentFiles, quint32 line, - quint32 column, - bool resolveTarget = true) + quint32 column) : m_fileContainer(fileContainer) , m_ticketNumber(++ticketCounter) , m_line(line) , m_column(column) , m_dependentFiles(dependentFiles) - , m_resolveTarget(resolveTarget) { } @@ -71,11 +69,6 @@ public: return m_column; } - bool resolveTarget() const - { - return m_resolveTarget; - } - quint64 ticketNumber() const { return m_ticketNumber; @@ -88,7 +81,6 @@ public: out << message.m_ticketNumber; out << message.m_line; out << message.m_column; - out << message.m_resolveTarget; return out; } @@ -100,7 +92,6 @@ public: in >> message.m_ticketNumber; in >> message.m_line; in >> message.m_column; - in >> message.m_resolveTarget; return in; } @@ -112,7 +103,6 @@ public: && first.m_line == second.m_line && first.m_column == second.m_column && first.m_fileContainer == second.m_fileContainer - && first.m_resolveTarget == second.m_resolveTarget && first.m_dependentFiles == second.m_dependentFiles; } @@ -124,7 +114,6 @@ private: quint32 m_line = 0; quint32 m_column = 0; QVector m_dependentFiles; - bool m_resolveTarget = true; static CMBIPC_EXPORT quint64 ticketCounter; }; diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp index 065ea0fe4b3..ff1cf8f0750 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp @@ -275,7 +275,6 @@ CppTools::SymbolInfo toSymbolInfo(const FollowSymbolMessage &message) result.endLine = static_cast(end.line()); result.endColumn = static_cast(end.column()); result.fileName = start.filePath(); - result.failedToFollow = message.failedToFollow(); return result; } @@ -748,14 +747,12 @@ QFuture IpcCommunicator::requestFollowSymbol( const FileContainer &curFileContainer, const QVector &dependentFiles, quint32 line, - quint32 column, - bool resolveTarget) + quint32 column) { const RequestFollowSymbolMessage message(curFileContainer, dependentFiles, line, - column, - resolveTarget); + column); m_ipcSender->requestFollowSymbol(message); return m_ipcReceiver.addExpectedRequestFollowSymbolMessage(message.ticketNumber()); diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.h b/src/plugins/clangcodemodel/clangbackendipcintegration.h index 94be668114e..63c9d768017 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.h +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.h @@ -169,8 +169,7 @@ public: QFuture requestFollowSymbol(const FileContainer &curFileContainer, const QVector &dependentFiles, quint32 line, - quint32 column, - bool resolveTarget); + quint32 column); void completeCode(ClangCompletionAssistProcessor *assistProcessor, const QString &filePath, quint32 line, quint32 column, diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index 593d3cb9c72..24d26adcfde 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -225,6 +225,12 @@ toTextEditorBlocks(QTextDocument *textDocument, } } +const QVector +&ClangEditorDocumentProcessor::highlightingMarks() const +{ + return m_highlightingMarks; +} + void ClangEditorDocumentProcessor::updateHighlighting( const QVector &highlightingMarks, const QVector &skippedPreprocessorRanges, @@ -234,6 +240,7 @@ void ClangEditorDocumentProcessor::updateHighlighting( const auto skippedPreprocessorBlocks = toTextEditorBlocks(textDocument(), skippedPreprocessorRanges); emit ifdefedOutBlocksUpdated(documentRevision, skippedPreprocessorBlocks); + m_highlightingMarks = highlightingMarks; m_semanticHighlighter.setHighlightingRunner( [highlightingMarks]() { auto *reporter = new HighlightingMarksReporter(highlightingMarks); @@ -376,7 +383,7 @@ static QVector prioritizeByBaseName(const QString &curPath, } QFuture -ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column, bool resolveTarget) +ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column) { QVector dependentFiles; CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); @@ -390,8 +397,7 @@ ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column, bool res return m_ipcCommunicator.requestFollowSymbol(simpleFileContainer(), dependentFiles, static_cast(line), - static_cast(column), - resolveTarget); + static_cast(column)); } ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithArguments() const diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h index 6255608dc23..d7f7f966f50 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h @@ -86,14 +86,14 @@ public: void setParserConfig(const CppTools::BaseEditorDocumentParser::Configuration config) override; QFuture cursorInfo(const CppTools::CursorInfoParams ¶ms) override; - QFuture requestFollowSymbol(int line, - int column, - bool resolveTarget) override; + QFuture requestFollowSymbol(int line, int column) override; ClangBackEnd::FileContainer fileContainerWithArguments() const; void clearDiagnosticsWithFixIts(); + const QVector &highlightingMarks() const; + public: static ClangEditorDocumentProcessor *get(const QString &filePath); @@ -122,6 +122,7 @@ private: QTimer m_updateTranslationUnitTimer; unsigned m_parserRevision; + QVector m_highlightingMarks; CppTools::SemanticHighlighter m_semanticHighlighter; CppTools::BuiltinEditorDocumentProcessor m_builtinProcessor; }; diff --git a/src/plugins/clangcodemodel/clangfollowsymbol.cpp b/src/plugins/clangcodemodel/clangfollowsymbol.cpp index ede9cac8245..bffa6fbcbfb 100644 --- a/src/plugins/clangcodemodel/clangfollowsymbol.cpp +++ b/src/plugins/clangcodemodel/clangfollowsymbol.cpp @@ -23,14 +23,78 @@ ** ****************************************************************************/ -#include "clangfollowsymbol.h" #include "clangeditordocumentprocessor.h" -#include "texteditor/texteditor.h" -#include "texteditor/convenience.h" +#include "clangfollowsymbol.h" + +#include +#include + +#include + +#include namespace ClangCodeModel { namespace Internal { +// Returns invalid Mark if it is not found at (line, column) +static bool findMark(const QVector &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 &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( const CppTools::CursorInEditor &data, bool resolveTarget, @@ -39,42 +103,39 @@ TextEditor::TextEditorWidget::Link ClangFollowSymbol::findLink( CppTools::SymbolFinder *, bool) { - Link link; - int lineNumber = 0, positionInBlock = 0; QTextCursor cursor = TextEditor::Convenience::wordStartCursor(data.cursor()); TextEditor::Convenience::convertPosition(cursor.document(), cursor.position(), &lineNumber, &positionInBlock); - const unsigned line = lineNumber; - const unsigned column = positionInBlock + 1; - if (!resolveTarget) - return link; + const uint line = lineNumber; + const uint column = positionInBlock + 1; + ClangEditorDocumentProcessor *processor = ClangEditorDocumentProcessor::get( data.filePath().toString()); if (!processor) - return link; + return Link(); + + if (!resolveTarget) + return linkAtCursor(cursor, data.filePath().toString(), line, column, processor); QFuture info = processor->requestFollowSymbol(static_cast(line), - static_cast(column), - resolveTarget); + static_cast(column)); + if (info.isCanceled()) - return link; + return Link(); while (!info.isFinished()) { if (info.isCanceled()) - return link; + return Link(); QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); } CppTools::SymbolInfo result = info.result(); - if (result.failedToFollow) - return link; - // We did not fail but the result is empty if (result.fileName.isEmpty()) - return link; + return Link(); return Link(result.fileName, result.startLine, result.startColumn - 1); } diff --git a/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp b/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp index 6090b73f415..747070a317a 100644 --- a/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp +++ b/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp @@ -158,8 +158,15 @@ void HighlightingMarksReporter::run_internal() if (isCanceled()) 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)); + } if (isCanceled()) return; diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp index 28f49380244..75938351712 100644 --- a/src/plugins/cppeditor/cppeditorwidget.cpp +++ b/src/plugins/cppeditor/cppeditorwidget.cpp @@ -649,15 +649,6 @@ CppEditorWidget::Link CppEditorWidget::findLinkAt(const QTextCursor &cursor, return Link(); 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}, resolveTarget, diff --git a/src/plugins/cpptools/baseeditordocumentprocessor.h b/src/plugins/cpptools/baseeditordocumentprocessor.h index 342979dae35..1ac31a6ebc8 100644 --- a/src/plugins/cpptools/baseeditordocumentprocessor.h +++ b/src/plugins/cpptools/baseeditordocumentprocessor.h @@ -76,7 +76,7 @@ public: virtual void setParserConfig(const BaseEditorDocumentParser::Configuration config); virtual QFuture cursorInfo(const CursorInfoParams ¶ms) = 0; - virtual QFuture requestFollowSymbol(int line, int column, bool resolveTarget) = 0; + virtual QFuture requestFollowSymbol(int line, int column) = 0; public: using HeaderErrorDiagnosticWidgetCreator = std::function; diff --git a/src/plugins/cpptools/builtineditordocumentprocessor.h b/src/plugins/cpptools/builtineditordocumentprocessor.h index 7d3d96f992f..800bff085a6 100644 --- a/src/plugins/cpptools/builtineditordocumentprocessor.h +++ b/src/plugins/cpptools/builtineditordocumentprocessor.h @@ -52,7 +52,7 @@ public: bool isParserRunning() const override; QFuture cursorInfo(const CursorInfoParams ¶ms) override; - QFuture requestFollowSymbol(int, int, bool) override + QFuture requestFollowSymbol(int, int) override { return QFuture(); } private: diff --git a/src/plugins/cpptools/cppsymbolinfo.h b/src/plugins/cpptools/cppsymbolinfo.h index 17d2713bc37..dcd00dd3c21 100644 --- a/src/plugins/cpptools/cppsymbolinfo.h +++ b/src/plugins/cpptools/cppsymbolinfo.h @@ -39,7 +39,6 @@ public: int endLine = 0; int endColumn = 0; QString fileName; - bool failedToFollow = false; }; } // namespace CppTools diff --git a/src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp b/src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp index d3f0726aff2..9def46b2dba 100644 --- a/src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp +++ b/src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp @@ -281,7 +281,6 @@ void ClangCodeModelServer::requestFollowSymbol(const RequestFollowSymbolMessage JobRequest jobRequest = processor.createJobRequest(JobRequest::Type::FollowSymbol); fillJobRequest(jobRequest, message); jobRequest.dependentFiles = message.dependentFiles(); - jobRequest.resolveTarget = message.resolveTarget(); processor.addJob(jobRequest); processor.process(); } catch (const std::exception &exception) { diff --git a/src/tools/clangbackend/ipcsource/clangfollowsymbol.cpp b/src/tools/clangbackend/ipcsource/clangfollowsymbol.cpp index ab6bd824bb6..bc151bc93c4 100644 --- a/src/tools/clangbackend/ipcsource/clangfollowsymbol.cpp +++ b/src/tools/clangbackend/ipcsource/clangfollowsymbol.cpp @@ -41,10 +41,16 @@ namespace { struct Tokens { + Tokens(const Tokens &) = delete; Tokens(const Cursor &cursor) { tu = cursor.cxTranslationUnit(); 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() { clang_disposeTokens(tu, data, tokenCount); } @@ -198,11 +204,11 @@ static IndexerCallbacks createIndexerCallbacks() }; } -static FollowSymbolResult followSymbolInDependentFiles(CXIndex index, - const Cursor &cursor, - const Utf8String &tokenSpelling, - const QVector &dependentFiles, - const CommandLineArguments ¤tArgs) +static SourceRangeContainer followSymbolInDependentFiles(CXIndex index, + const Cursor &cursor, + const Utf8String &tokenSpelling, + const QVector &dependentFiles, + const CommandLineArguments ¤tArgs) { int argsCount = 0; if (currentArgs.data()) @@ -250,63 +256,61 @@ static FollowSymbolResult followSymbolInDependentFiles(CXIndex index, for (const std::future &future: indexFutures) future.wait(); - FollowSymbolResult result; for (const FollowSymbolData &data: dataVector) { if (!data.result().start().filePath().isEmpty()) { - result.range = data.result(); - break; + return data.result(); } } - return result; + return SourceRangeContainer(); } -FollowSymbolResult FollowSymbol::followSymbol(CXIndex index, - const Cursor &fullCursor, - uint line, - uint column, - const QVector &dependentFiles, - const CommandLineArguments ¤tArgs) +SourceRangeContainer FollowSymbol::followSymbol(CXTranslationUnit tu, + CXIndex index, + const Cursor &fullCursor, + uint line, + uint column, + const QVector &dependentFiles, + const CommandLineArguments ¤tArgs) { - FollowSymbolResult result; - Tokens tokens(fullCursor); - if (!tokens.tokenCount) { - result.failedToFollow = true; - return result; - } + std::unique_ptr tokens(new Tokens(fullCursor)); - const CXTranslationUnit tu = fullCursor.cxTranslationUnit(); + if (!tokens->tokenCount) + tokens.reset(new Tokens(tu)); - QVector cursors(static_cast(tokens.tokenCount)); - clang_annotateTokens(tu, tokens.data, tokens.tokenCount, cursors.data()); - int tokenIndex = getTokenIndex(tu, tokens, line, column); - QTC_ASSERT(tokenIndex >= 0, return result); + if (!tokens->tokenCount) + return SourceRangeContainer(); - const Utf8String tokenSpelling = ClangString(clang_getTokenSpelling(tu, tokens.data[tokenIndex])); + QVector cursors(static_cast(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()) - return result; + return SourceRangeContainer(); Cursor cursor{cursors[tokenIndex]}; + if (cursor.kind() == CXCursor_InclusionDirective) { CXFile file = clang_getIncludedFile(cursors[tokenIndex]); const ClangString filename(clang_getFileName(file)); const SourceLocation loc(tu, filename, 1, 1); - result.range = SourceRange(loc, loc); - return result; + return SourceRange(loc, loc); } - if (cursor.isDefinition()) { - // For definitions we can always find a declaration in current TU - result.range = extractMatchingTokenRange(cursor.canonical(), tokenSpelling); - return result; - } + // For definitions we can always find a declaration in current TU + if (cursor.isDefinition()) + return extractMatchingTokenRange(cursor.canonical(), tokenSpelling); + SourceRangeContainer result; if (!cursor.isDeclaration()) { // This is the symbol usage // We want to return definition or at least declaration of this symbol const Cursor referencedCursor = cursor.referenced(); if (referencedCursor.isNull() || referencedCursor == cursor) - return result; - result.range = extractMatchingTokenRange(referencedCursor, tokenSpelling); + return SourceRangeContainer(); + result = extractMatchingTokenRange(referencedCursor, tokenSpelling); // We've already found what we need if (referencedCursor.isDefinition()) @@ -317,17 +321,16 @@ FollowSymbolResult FollowSymbol::followSymbol(CXIndex index, const Cursor definitionCursor = cursor.definition(); if (!definitionCursor.isNull() && definitionCursor != cursor) { // If we are able to find a definition in current TU - result.range = extractMatchingTokenRange(definitionCursor, tokenSpelling); - return result; + return extractMatchingTokenRange(definitionCursor, tokenSpelling); } // Search for the definition in the dependent files - FollowSymbolResult dependentFilesResult = followSymbolInDependentFiles(index, - cursor, - tokenSpelling, - dependentFiles, - currentArgs); - return dependentFilesResult.range.start().filePath().isEmpty() ? + SourceRangeContainer dependentFilesResult = followSymbolInDependentFiles(index, + cursor, + tokenSpelling, + dependentFiles, + currentArgs); + return dependentFilesResult.start().filePath().isEmpty() ? result : dependentFilesResult; } diff --git a/src/tools/clangbackend/ipcsource/clangfollowsymbol.h b/src/tools/clangbackend/ipcsource/clangfollowsymbol.h index c3c0c5c2092..a881bd9631d 100644 --- a/src/tools/clangbackend/ipcsource/clangfollowsymbol.h +++ b/src/tools/clangbackend/ipcsource/clangfollowsymbol.h @@ -34,18 +34,19 @@ class Utf8String; namespace ClangBackEnd { class Cursor; -class FollowSymbolResult; +class SourceRangeContainer; class CommandLineArguments; class FollowSymbol { public: - static FollowSymbolResult followSymbol(CXIndex index, - const Cursor &fullCursor, - uint line, - uint column, - const QVector &dependentFiles, - const CommandLineArguments ¤tArgs); + static SourceRangeContainer followSymbol(CXTranslationUnit tu, + CXIndex index, + const Cursor &fullCursor, + uint line, + uint column, + const QVector &dependentFiles, + const CommandLineArguments ¤tArgs); }; } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangfollowsymboljob.cpp b/src/tools/clangbackend/ipcsource/clangfollowsymboljob.cpp index 83f67158756..7136db34326 100644 --- a/src/tools/clangbackend/ipcsource/clangfollowsymboljob.cpp +++ b/src/tools/clangbackend/ipcsource/clangfollowsymboljob.cpp @@ -38,8 +38,6 @@ IAsyncJob::AsyncPrepareResult FollowSymbolJob::prepareAsyncRun() const JobRequest jobRequest = context().jobRequest; QTC_ASSERT(jobRequest.type == JobRequest::Type::FollowSymbol, return AsyncPrepareResult()); - // Is too slow because of IPC timings, no implementation for now - QTC_ASSERT(jobRequest.resolveTarget, return AsyncPrepareResult()); QTC_ASSERT(acquireDocument(), return AsyncPrepareResult()); const TranslationUnit translationUnit = *m_translationUnit; @@ -66,8 +64,7 @@ void FollowSymbolJob::finalizeAsyncRun() const AsyncResult result = asyncResult(); const FollowSymbolMessage message(m_pinnedFileContainer, - result.range, - result.failedToFollow, + result, context().jobRequest.ticketNumber); context().client->followSymbol(message); } diff --git a/src/tools/clangbackend/ipcsource/clangfollowsymboljob.h b/src/tools/clangbackend/ipcsource/clangfollowsymboljob.h index 7c8391fb9b2..3a8741db1c6 100644 --- a/src/tools/clangbackend/ipcsource/clangfollowsymboljob.h +++ b/src/tools/clangbackend/ipcsource/clangfollowsymboljob.h @@ -31,29 +31,10 @@ namespace ClangBackEnd { -class FollowSymbolResult +class FollowSymbolJob : public DocumentJob { public: - FollowSymbolResult() = default; - 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 -{ -public: - using AsyncResult = FollowSymbolResult; + using AsyncResult = SourceRangeContainer; AsyncPrepareResult prepareAsyncRun() override; void finalizeAsyncRun() override; diff --git a/src/tools/clangbackend/ipcsource/clangjobrequest.cpp b/src/tools/clangbackend/ipcsource/clangjobrequest.cpp index 4130557ee67..9f8eb55f77f 100644 --- a/src/tools/clangbackend/ipcsource/clangjobrequest.cpp +++ b/src/tools/clangbackend/ipcsource/clangjobrequest.cpp @@ -229,7 +229,6 @@ void JobRequest::cancelJob(ClangCodeModelClientInterface &client) const case JobRequest::Type::FollowSymbol: client.followSymbol(FollowSymbolMessage(FileContainer(), SourceRangeContainer(), - true, ticketNumber)); break; } diff --git a/src/tools/clangbackend/ipcsource/clangjobrequest.h b/src/tools/clangbackend/ipcsource/clangjobrequest.h index a73eda7beeb..78aaed6618a 100644 --- a/src/tools/clangbackend/ipcsource/clangjobrequest.h +++ b/src/tools/clangbackend/ipcsource/clangjobrequest.h @@ -118,7 +118,6 @@ public: qint32 funcNameStartColumn = -1; quint64 ticketNumber = 0; Utf8StringVector dependentFiles; - bool resolveTarget = true; }; using JobRequests = QVector; diff --git a/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp b/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp index adc732118eb..720bfb92555 100644 --- a/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp +++ b/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp @@ -243,13 +243,13 @@ void TranslationUnit::extractDiagnostics(DiagnosticContainer &firstHeaderErrorDi } } -FollowSymbolResult TranslationUnit::followSymbol(uint line, - uint column, - const QVector &dependentFiles, - const CommandLineArguments ¤tArgs) const +SourceRangeContainer TranslationUnit::followSymbol(uint line, + uint column, + const QVector &dependentFiles, + const CommandLineArguments ¤tArgs) const { - return FollowSymbol::followSymbol(m_cxIndex, cursorAt(line, column), line, column, - dependentFiles, currentArgs); + return FollowSymbol::followSymbol(m_cxTranslationUnit, m_cxIndex, cursorAt(line, column), line, + column, dependentFiles, currentArgs); } } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangtranslationunit.h b/src/tools/clangbackend/ipcsource/clangtranslationunit.h index 3ae020478ee..9634c8cb510 100644 --- a/src/tools/clangbackend/ipcsource/clangtranslationunit.h +++ b/src/tools/clangbackend/ipcsource/clangtranslationunit.h @@ -37,7 +37,6 @@ class DiagnosticSet; class HighlightingMarkContainer; class HighlightingMarks; class ReferencesResult; -class FollowSymbolResult; class SkippedSourceRanges; class SourceLocation; class SourceRange; @@ -101,10 +100,10 @@ public: HighlightingMarks highlightingMarksInRange(const SourceRange &range) const; SkippedSourceRanges skippedSourceRanges() const; - FollowSymbolResult followSymbol(uint line, - uint column, - const QVector &dependentFiles, - const CommandLineArguments ¤tArgs) const; + SourceRangeContainer followSymbol(uint line, + uint column, + const QVector &dependentFiles, + const CommandLineArguments ¤tArgs) const; private: const Utf8String m_id; diff --git a/src/tools/clangbackend/ipcsource/highlightingmark.cpp b/src/tools/clangbackend/ipcsource/highlightingmark.cpp index 510192b6e70..9339d4ba9e7 100644 --- a/src/tools/clangbackend/ipcsource/highlightingmark.cpp +++ b/src/tools/clangbackend/ipcsource/highlightingmark.cpp @@ -105,7 +105,8 @@ bool HighlightingMark::hasFunctionArguments() 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 { @@ -288,6 +289,8 @@ void HighlightingMark::functionKind(const Cursor &cursor, Recursion recursion) void HighlightingMark::identifierKind(const Cursor &cursor, Recursion recursion) { + m_isIdentifier = (cursor.kind() != CXCursor_PreprocessingDirective); + switch (cursor.kind()) { case CXCursor_Destructor: case CXCursor_Constructor: @@ -352,6 +355,7 @@ HighlightingType literalKind(const Cursor &cursor) switch (cursor.kind()) { case CXCursor_CharacterLiteral: case CXCursor_StringLiteral: + case CXCursor_InclusionDirective: case CXCursor_ObjCStringLiteral: return HighlightingType::StringLiteral; case CXCursor_IntegerLiteral: case CXCursor_ImaginaryLiteral: @@ -438,6 +442,8 @@ void HighlightingMark::collectKinds(CXTranslationUnit cxTranslationUnit, case CXToken_Comment: m_types.mainHighlightingType = HighlightingType::Comment; 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) diff --git a/src/tools/clangbackend/ipcsource/highlightingmark.h b/src/tools/clangbackend/ipcsource/highlightingmark.h index 151bd263d25..b322391c49d 100644 --- a/src/tools/clangbackend/ipcsource/highlightingmark.h +++ b/src/tools/clangbackend/ipcsource/highlightingmark.h @@ -87,6 +87,8 @@ private: uint m_length; uint m_offset = 0; HighlightingTypes m_types; + bool m_isIdentifier = false; + bool m_isInclusion = false; }; diff --git a/src/tools/clangbackend/ipcsource/highlightingmarks.cpp b/src/tools/clangbackend/ipcsource/highlightingmarks.cpp index 2e157ff835e..ed8ddfdd656 100644 --- a/src/tools/clangbackend/ipcsource/highlightingmarks.cpp +++ b/src/tools/clangbackend/ipcsource/highlightingmarks.cpp @@ -68,15 +68,12 @@ QVector HighlightingMarks::toHighlightingMarksContain const auto isValidHighlightMark = [] (const HighlightingMark &highlightMark) { return !highlightMark.hasInvalidMainType() - && !highlightMark.hasMainType(HighlightingType::StringLiteral) - && !highlightMark.hasMainType(HighlightingType::NumberLiteral) - && !highlightMark.hasMainType(HighlightingType::Comment); + && !highlightMark.hasMainType(HighlightingType::NumberLiteral) + && !highlightMark.hasMainType(HighlightingType::Comment); }; - - for (const HighlightingMark &highlightMark : *this) { + for (const HighlightingMark &highlightMark : *this) if (isValidHighlightMark(highlightMark)) containers.push_back(highlightMark); - } return containers; } diff --git a/tests/unit/unittest/clangfollowsymbol-test.cpp b/tests/unit/unittest/clangfollowsymbol-test.cpp index 046932034f0..566c02b0e5d 100644 --- a/tests/unit/unittest/clangfollowsymbol-test.cpp +++ b/tests/unit/unittest/clangfollowsymbol-test.cpp @@ -56,20 +56,11 @@ using ::ClangBackEnd::UnsavedFiles; using ::ClangBackEnd::ReferencesResult; using ::ClangBackEnd::SourceRangeContainer; -using ClangBackEnd::FollowSymbolResult; - namespace { const Utf8String sourceFilePath = Utf8StringLiteral(TESTDATA_DIR"/followsymbol_main.cpp"); const Utf8String headerFilePath = Utf8StringLiteral(TESTDATA_DIR"/followsymbol_header.h"); 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, std::string(negation ? "isn't " : "is ") + PrintToString(SourceRangeContainer { @@ -83,7 +74,7 @@ MATCHER_P3(MatchesHeaderSourceRange, line, column, length, SourceLocationContainer(headerFilePath, line, column + length) }; - return arg == FollowSymbolResult {expected, false}; + return arg == expected; } MATCHER_P3(MatchesSourceRange, line, column, length, @@ -99,7 +90,7 @@ MATCHER_P3(MatchesSourceRange, line, column, length, SourceLocationContainer(sourceFilePath, line, column + length) }; - return arg == FollowSymbolResult {expected, false}; + return arg == expected; } MATCHER_P4(MatchesFileSourceRange, filename, line, column, length, @@ -115,7 +106,7 @@ MATCHER_P4(MatchesFileSourceRange, filename, line, column, length, SourceLocationContainer(filename, line, column + length) }; - return arg == FollowSymbolResult {expected, false}; + return arg == expected; } class Data { @@ -150,7 +141,7 @@ private: class FollowSymbol : public ::testing::Test { protected: - FollowSymbolResult followSymbol(uint line, uint column) + SourceRangeContainer followSymbol(uint line, uint column) { ClangBackEnd::TranslationUnitUpdateInput updateInput = d->document().createUpdateInput(); const ClangBackEnd::CommandLineArguments currentArgs(updateInput.filePath.constData(), @@ -162,7 +153,7 @@ protected: currentArgs); } - FollowSymbolResult followHeaderSymbol(uint line, uint column) + SourceRangeContainer followHeaderSymbol(uint line, uint column) { ClangBackEnd::TranslationUnitUpdateInput updateInput = d->headerDocument().createUpdateInput(); diff --git a/tests/unit/unittest/highlightingmarks-test.cpp b/tests/unit/unittest/highlightingmarks-test.cpp index 16c7bc59e60..1aeeb734feb 100644 --- a/tests/unit/unittest/highlightingmarks-test.cpp +++ b/tests/unit/unittest/highlightingmarks-test.cpp @@ -1184,6 +1184,42 @@ TEST_F(HighlightingMarks, UsingTemplateFunction) 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; void HighlightingMarks::SetUpTestCase() diff --git a/tests/unit/unittest/readandwritemessageblock-test.cpp b/tests/unit/unittest/readandwritemessageblock-test.cpp index ac57f833986..445743543a7 100644 --- a/tests/unit/unittest/readandwritemessageblock-test.cpp +++ b/tests/unit/unittest/readandwritemessageblock-test.cpp @@ -208,8 +208,7 @@ TEST_F(ReadAndWriteMessageBlock, CompareRequestFollowSymbol) QVector dependentFiles; dependentFiles.push_back(QString("somefile.cpp")); dependentFiles.push_back(QString("otherfile.cpp")); - CompareMessage(ClangBackEnd::RequestFollowSymbolMessage{fileContainer, dependentFiles, 13, 37, - false}); + CompareMessage(ClangBackEnd::RequestFollowSymbolMessage{fileContainer, dependentFiles, 13, 37}); } TEST_F(ReadAndWriteMessageBlock, CompareReferences)