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)