From 09310bcdc68e4242106e3f15761116797f8f0d78 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Wed, 29 Nov 2017 16:08:06 +0100 Subject: [PATCH] Clang: fix utf8 related column numbers Use new clang_getFileContents to efficiently convert utf8 byte offsets from line start to column numbers. Also provide simplier backwards convertion to pass resulting utf8 offset to clang. Task-number: QTCREATORBUG-16941 Change-Id: If0e58fe01ad3e281b7e952e972b9e86f6e75aadb Reviewed-by: Nikolai Kosjar --- .../clangbackendcommunicator.cpp | 9 ++---- .../clangcodemodel/clangbackendcommunicator.h | 4 +-- .../clangcodemodel/clangbackendreceiver.cpp | 22 ++++----------- .../clangcodemodel/clangbackendreceiver.h | 4 --- .../clangcompletionassistprocessor.cpp | 3 +- .../clangcodemodel/clangdiagnosticmanager.cpp | 3 +- .../clangeditordocumentprocessor.cpp | 8 ++---- src/plugins/clangcodemodel/clangutils.cpp | 26 ----------------- src/plugins/clangcodemodel/clangutils.h | 2 -- .../clangbackend/source/clangfollowsymbol.cpp | 6 ++-- .../source/clangreferencescollector.cpp | 5 ++-- .../source/clangtranslationunit.cpp | 2 +- src/tools/clangbackend/source/cursor.cpp | 6 ++-- src/tools/clangbackend/source/diagnostic.cpp | 20 ++++++++----- src/tools/clangbackend/source/diagnostic.h | 3 +- .../clangbackend/source/diagnosticset.cpp | 20 +++++++------ src/tools/clangbackend/source/diagnosticset.h | 3 +- .../source/diagnosticsetiterator.h | 13 ++++++--- src/tools/clangbackend/source/fixit.cpp | 4 +-- src/tools/clangbackend/source/fixit.h | 2 +- .../source/skippedsourceranges.cpp | 2 +- .../clangbackend/source/sourcelocation.cpp | 28 ++++++++++++++++--- .../clangbackend/source/sourcelocation.h | 4 ++- src/tools/clangbackend/source/sourcerange.cpp | 12 ++++---- src/tools/clangbackend/source/sourcerange.h | 3 +- src/tools/clangbackend/source/tokeninfo.cpp | 3 +- 26 files changed, 106 insertions(+), 111 deletions(-) diff --git a/src/plugins/clangcodemodel/clangbackendcommunicator.cpp b/src/plugins/clangcodemodel/clangbackendcommunicator.cpp index 193e6dfbff3..9e59ab98a8b 100644 --- a/src/plugins/clangcodemodel/clangbackendcommunicator.cpp +++ b/src/plugins/clangcodemodel/clangbackendcommunicator.cpp @@ -368,26 +368,23 @@ QFuture BackendCommunicator::requestReferences( const FileContainer &fileContainer, quint32 line, quint32 column, - QTextDocument *textDocument, const CppTools::SemanticInfo::LocalUseMap &localUses) { const RequestReferencesMessage message(fileContainer, line, column); m_sender->requestReferences(message); - return m_receiver.addExpectedReferencesMessage(message.ticketNumber(), textDocument, - localUses); + return m_receiver.addExpectedReferencesMessage(message.ticketNumber(), localUses); } QFuture BackendCommunicator::requestLocalReferences( const FileContainer &fileContainer, quint32 line, - quint32 column, - QTextDocument *textDocument) + quint32 column) { const RequestReferencesMessage message(fileContainer, line, column, true); m_sender->requestReferences(message); - return m_receiver.addExpectedReferencesMessage(message.ticketNumber(), textDocument); + return m_receiver.addExpectedReferencesMessage(message.ticketNumber()); } QFuture BackendCommunicator::requestToolTip( diff --git a/src/plugins/clangcodemodel/clangbackendcommunicator.h b/src/plugins/clangcodemodel/clangbackendcommunicator.h index 748f2a00658..941126c7c71 100644 --- a/src/plugins/clangcodemodel/clangbackendcommunicator.h +++ b/src/plugins/clangcodemodel/clangbackendcommunicator.h @@ -75,13 +75,11 @@ public: const FileContainer &fileContainer, quint32 line, quint32 column, - QTextDocument *textDocument, const LocalUseMap &localUses); QFuture requestLocalReferences( const FileContainer &fileContainer, quint32 line, - quint32 column, - QTextDocument *textDocument); + quint32 column); QFuture requestToolTip(const FileContainer &fileContainer, quint32 line, quint32 column); diff --git a/src/plugins/clangcodemodel/clangbackendreceiver.cpp b/src/plugins/clangcodemodel/clangbackendreceiver.cpp index 3794eb0b6ba..306dfb05f1a 100644 --- a/src/plugins/clangcodemodel/clangbackendreceiver.cpp +++ b/src/plugins/clangcodemodel/clangbackendreceiver.cpp @@ -101,16 +101,14 @@ void BackendReceiver::deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidge QFuture BackendReceiver::addExpectedReferencesMessage( quint64 ticket, - QTextDocument *textDocument, const CppTools::SemanticInfo::LocalUseMap &localUses) { - QTC_CHECK(textDocument); QTC_CHECK(!m_referencesTable.contains(ticket)); QFutureInterface futureInterface; futureInterface.reportStarted(); - const ReferencesEntry entry{futureInterface, textDocument, localUses}; + const ReferencesEntry entry{futureInterface, localUses}; m_referencesTable.insert(ticket, entry); return futureInterface.future(); @@ -221,24 +219,17 @@ void BackendReceiver::documentAnnotationsChanged(const DocumentAnnotationsChange } static -CppTools::CursorInfo::Range toCursorInfoRange(const QTextDocument &textDocument, - const SourceRangeContainer &sourceRange) +CppTools::CursorInfo::Range toCursorInfoRange(const SourceRangeContainer &sourceRange) { const SourceLocationContainer start = sourceRange.start(); const SourceLocationContainer end = sourceRange.end(); const unsigned length = end.column() - start.column(); - const QTextBlock block = textDocument.findBlockByNumber(static_cast(start.line()) - 1); - const int shift = ClangCodeModel::Utils::extraUtf8CharsShift(block.text(), - static_cast(start.column())); - const uint column = start.column() - static_cast(shift); - - return CppTools::CursorInfo::Range(start.line(), column, length); + return CppTools::CursorInfo::Range(start.line(), start.column(), length); } static -CppTools::CursorInfo toCursorInfo(const QTextDocument &textDocument, - const CppTools::SemanticInfo::LocalUseMap &localUses, +CppTools::CursorInfo toCursorInfo(const CppTools::SemanticInfo::LocalUseMap &localUses, const ReferencesMessage &message) { CppTools::CursorInfo result; @@ -246,7 +237,7 @@ CppTools::CursorInfo toCursorInfo(const QTextDocument &textDocument, result.areUseRangesForLocalVariable = message.isLocalVariable(); for (const SourceRangeContainer &reference : references) - result.useRanges.append(toCursorInfoRange(textDocument, reference)); + result.useRanges.append(toCursorInfoRange(reference)); result.useRanges.reserve(references.size()); result.localUses = localUses; @@ -284,8 +275,7 @@ void BackendReceiver::references(const ReferencesMessage &message) if (futureInterface.isCanceled()) return; // Editor document closed or a new request was issued making this result outdated. - QTC_ASSERT(entry.textDocument, return); - futureInterface.reportResult(toCursorInfo(*entry.textDocument, entry.localUses, message)); + futureInterface.reportResult(toCursorInfo(entry.localUses, message)); futureInterface.reportFinished(); } diff --git a/src/plugins/clangcodemodel/clangbackendreceiver.h b/src/plugins/clangcodemodel/clangbackendreceiver.h index 921150a52dc..19eeb3ce5bb 100644 --- a/src/plugins/clangcodemodel/clangbackendreceiver.h +++ b/src/plugins/clangcodemodel/clangbackendreceiver.h @@ -56,7 +56,6 @@ public: QFuture addExpectedReferencesMessage(quint64 ticket, - QTextDocument *textDocument, const CppTools::SemanticInfo::LocalUseMap &localUses = CppTools::SemanticInfo::LocalUseMap()); QFuture addExpectedRequestFollowSymbolMessage(quint64 ticket); @@ -82,13 +81,10 @@ private: struct ReferencesEntry { ReferencesEntry() = default; ReferencesEntry(QFutureInterface futureInterface, - QTextDocument *textDocument, const CppTools::SemanticInfo::LocalUseMap &localUses) : futureInterface(futureInterface) - , textDocument(textDocument) , localUses(localUses) {} QFutureInterface futureInterface; - QPointer textDocument; CppTools::SemanticInfo::LocalUseMap localUses; }; QHash m_referencesTable; diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp index 644c5d778c9..2a4673f2133 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp +++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp @@ -559,7 +559,8 @@ ClangCompletionAssistProcessor::extractLineColumn(int position) int line = -1, column = -1; ::Utils::Text::convertPosition(m_interface->textDocument(), position, &line, &column); const QTextBlock block = m_interface->textDocument()->findBlock(position); - column += ClangCodeModel::Utils::extraUtf8CharsShift(block.text(), column) + 1; + const QString stringOnTheLeft = block.text().left(column); + column = stringOnTheLeft.toUtf8().size() + 1; // '+ 1' is for 1-based columns return {line, column}; } diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp index eb43f6556ee..261d196b0b4 100644 --- a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp +++ b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp @@ -64,8 +64,7 @@ int positionInText(QTextDocument *textDocument, { auto textBlock = textDocument->findBlockByNumber( static_cast(sourceLocationContainer.line()) - 1); - int column = static_cast(sourceLocationContainer.column()) - 1; - column -= ClangCodeModel::Utils::extraUtf8CharsShift(textBlock.text(), column); + const int column = static_cast(sourceLocationContainer.column()) - 1; return textBlock.position() + column; } diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index b0c1959dbb0..e1a02f453d9 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -331,20 +331,19 @@ ClangEditorDocumentProcessor::cursorInfo(const CppTools::CursorInfoParams ¶m { int line, column; convertPosition(params.textCursor, &line, &column); - ++column; // for 1-based columns if (!isCursorOnIdentifier(params.textCursor)) return defaultCursorInfoFuture(); const QTextBlock block = params.textCursor.document()->findBlockByNumber(line - 1); - column += ClangCodeModel::Utils::extraUtf8CharsShift(block.text(), column); + const QString stringOnTheLeft = block.text().left(column); + column = stringOnTheLeft.toUtf8().size() + 1; // '+ 1' is for 1-based columns const CppTools::SemanticInfo::LocalUseMap localUses = CppTools::BuiltinCursorInfo::findLocalUses(params.semanticInfo.doc, line, column); return m_communicator.requestReferences(simpleFileContainer(), static_cast(line), static_cast(column), - textDocument(), localUses); } @@ -361,8 +360,7 @@ QFuture ClangEditorDocumentProcessor::requestLocalReferenc return m_communicator.requestLocalReferences(simpleFileContainer(), static_cast(line), - static_cast(column), - textDocument()); + static_cast(column)); } QFuture diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp index dea79f66250..cf659ff4046 100644 --- a/src/plugins/clangcodemodel/clangutils.cpp +++ b/src/plugins/clangcodemodel/clangutils.cpp @@ -190,31 +190,5 @@ void setLastSentDocumentRevision(const QString &filePath, uint revision) document->sendTracker().setLastSentRevision(int(revision)); } -// CLANG-UPGRADE-CHECK: Workaround still needed? -// Remove once clang reports correct columns for lines with multi-byte utf8. -int extraUtf8CharsShift(const QString &str, int column) -{ - int shift = 0; - const QByteArray byteArray = str.toUtf8(); - for (int i = 0; i < qMin(str.length(), column); ++i) { - const uchar firstByte = static_cast(byteArray.at(i)); - // Skip different amount of bytes depending on value - if (firstByte < 0xC0) { - continue; - } else if (firstByte < 0xE0) { - ++shift; - ++i; - } else if (firstByte < 0xF0) { - shift += 2; - i += 2; - } else { - shift += 3; - i += 3; - } - } - return shift; -} - - } // namespace Utils } // namespace Clang diff --git a/src/plugins/clangcodemodel/clangutils.h b/src/plugins/clangcodemodel/clangutils.h index 6529af2b2c3..edd26ba7552 100644 --- a/src/plugins/clangcodemodel/clangutils.h +++ b/src/plugins/clangcodemodel/clangutils.h @@ -47,7 +47,5 @@ CppTools::ProjectPart::Ptr projectPartForFileBasedOnProcessor(const QString &fil bool isProjectPartLoaded(const CppTools::ProjectPart::Ptr projectPart); QString projectPartIdForFile(const QString &filePath); -int extraUtf8CharsShift(const QString &str, int column); - } // namespace Utils } // namespace Clang diff --git a/src/tools/clangbackend/source/clangfollowsymbol.cpp b/src/tools/clangbackend/source/clangfollowsymbol.cpp index 26de30ed347..2d8b7004ebe 100644 --- a/src/tools/clangbackend/source/clangfollowsymbol.cpp +++ b/src/tools/clangbackend/source/clangfollowsymbol.cpp @@ -107,7 +107,7 @@ static SourceRange getOperatorRange(const CXTranslationUnit tu, ++operatorIndex; } const CXSourceLocation end = clang_getTokenLocation(tu, tokens.data[operatorIndex]); - return SourceRange(clang_getRange(start, end)); + return SourceRange(tu, clang_getRange(start, end)); } static SourceRangeContainer extractMatchingTokenRange(const Cursor &cursor, @@ -128,7 +128,7 @@ static SourceRangeContainer extractMatchingTokenRange(const Cursor &cursor, continue; } } - return SourceRange(clang_getTokenExtent(tu, tokens.data[i])); + return SourceRange(tu, clang_getTokenExtent(tu, tokens.data[i])); } return SourceRangeContainer(); } @@ -137,7 +137,7 @@ static int getTokenIndex(CXTranslationUnit tu, const Tokens &tokens, uint line, { int tokenIndex = -1; for (int i = static_cast(tokens.tokenCount - 1); i >= 0; --i) { - const SourceRange range = clang_getTokenExtent(tu, tokens.data[i]); + const SourceRange range(tu, clang_getTokenExtent(tu, tokens.data[i])); if (range.contains(line, column)) { tokenIndex = i; break; diff --git a/src/tools/clangbackend/source/clangreferencescollector.cpp b/src/tools/clangbackend/source/clangreferencescollector.cpp index 64d9b61392b..ff8465c53f4 100644 --- a/src/tools/clangbackend/source/clangreferencescollector.cpp +++ b/src/tools/clangbackend/source/clangreferencescollector.cpp @@ -155,7 +155,7 @@ ReferencesCollector::~ReferencesCollector() bool ReferencesCollector::isWithinTokenRange(CXToken token, uint line, uint column) const { - const SourceRange range = clang_getTokenExtent(m_cxTranslationUnit, token); + const SourceRange range {m_cxTranslationUnit, clang_getTokenExtent(m_cxTranslationUnit, token)}; return range.contains(line, column); } @@ -229,7 +229,8 @@ ReferencesResult ReferencesCollector::collect(uint line, uint column, bool local const Utf8String identifier = ClangString(clang_getTokenSpelling(m_cxTranslationUnit, token)); for (uint i = 0; i < m_cxTokenCount; ++i) { if (checkToken(i, identifier, usr)) { - const SourceRange range = clang_getTokenExtent(m_cxTranslationUnit, m_cxTokens[i]); + const SourceRange range {m_cxTranslationUnit, + clang_getTokenExtent(m_cxTranslationUnit, m_cxTokens[i])}; result.references.append(range); } } diff --git a/src/tools/clangbackend/source/clangtranslationunit.cpp b/src/tools/clangbackend/source/clangtranslationunit.cpp index da06999b614..cce7548b3c2 100644 --- a/src/tools/clangbackend/source/clangtranslationunit.cpp +++ b/src/tools/clangbackend/source/clangtranslationunit.cpp @@ -161,7 +161,7 @@ ReferencesResult TranslationUnit::references(uint line, uint column, bool localR DiagnosticSet TranslationUnit::diagnostics() const { - return DiagnosticSet(clang_getDiagnosticSetFromTU(m_cxTranslationUnit)); + return DiagnosticSet(m_cxTranslationUnit, clang_getDiagnosticSetFromTU(m_cxTranslationUnit)); } SourceLocation TranslationUnit::sourceLocationAt(uint line,uint column) const diff --git a/src/tools/clangbackend/source/cursor.cpp b/src/tools/clangbackend/source/cursor.cpp index 41a0465e7a0..8b9b22f7cc5 100644 --- a/src/tools/clangbackend/source/cursor.cpp +++ b/src/tools/clangbackend/source/cursor.cpp @@ -283,7 +283,7 @@ CXFile Cursor::includedFile() const SourceLocation Cursor::sourceLocation() const { - return clang_getCursorLocation(cxCursor); + return {cxTranslationUnit(), clang_getCursorLocation(cxCursor)}; } CXSourceLocation Cursor::cxSourceLocation() const @@ -293,7 +293,7 @@ CXSourceLocation Cursor::cxSourceLocation() const SourceRange Cursor::sourceRange() const { - return clang_getCursorExtent(cxCursor); + return {cxTranslationUnit(), clang_getCursorExtent(cxCursor)}; } CXSourceRange Cursor::cxSourceRange() const @@ -308,7 +308,7 @@ CXTranslationUnit Cursor::cxTranslationUnit() const SourceRange Cursor::commentRange() const { - return clang_Cursor_getCommentRange(cxCursor); + return {cxTranslationUnit(), clang_Cursor_getCommentRange(cxCursor)}; } bool Cursor::hasSameSourceLocationAs(const Cursor &other) const diff --git a/src/tools/clangbackend/source/diagnostic.cpp b/src/tools/clangbackend/source/diagnostic.cpp index 5e74970ac24..b7bcf5b02f6 100644 --- a/src/tools/clangbackend/source/diagnostic.cpp +++ b/src/tools/clangbackend/source/diagnostic.cpp @@ -36,8 +36,9 @@ namespace ClangBackEnd { -Diagnostic::Diagnostic(CXDiagnostic cxDiagnostic) - : cxDiagnostic(cxDiagnostic) +Diagnostic::Diagnostic(CXTranslationUnit translationUnit, CXDiagnostic cxDiagnostic) + : cxDiagnostic(cxDiagnostic), + cxTranslationUnit(translationUnit) { } @@ -47,9 +48,11 @@ Diagnostic::~Diagnostic() } Diagnostic::Diagnostic(Diagnostic &&other) - : cxDiagnostic(std::move(other.cxDiagnostic)) + : cxDiagnostic(std::move(other.cxDiagnostic)), + cxTranslationUnit(std::move(other.cxTranslationUnit)) { other.cxDiagnostic = nullptr; + other.cxTranslationUnit = nullptr; } Diagnostic &Diagnostic::operator=(Diagnostic &&other) @@ -57,7 +60,9 @@ Diagnostic &Diagnostic::operator=(Diagnostic &&other) if (this != &other) { clang_disposeDiagnostic(cxDiagnostic); cxDiagnostic = std::move(other.cxDiagnostic); + cxTranslationUnit = std::move(other.cxTranslationUnit); other.cxDiagnostic = nullptr; + other.cxTranslationUnit = nullptr; } return *this; @@ -90,7 +95,7 @@ std::pair Diagnostic::options() const SourceLocation Diagnostic::location() const { - return SourceLocation(clang_getDiagnosticLocation(cxDiagnostic)); + return {cxTranslationUnit, clang_getDiagnosticLocation(cxDiagnostic)}; } DiagnosticSeverity Diagnostic::severity() const @@ -105,7 +110,8 @@ std::vector Diagnostic::ranges() const ranges.reserve(rangesCount); for (uint index = 0; index < rangesCount; ++index) { - const SourceRange sourceRange(clang_getDiagnosticRange(cxDiagnostic, index)); + const SourceRange sourceRange {cxTranslationUnit, + clang_getDiagnosticRange(cxDiagnostic, index)}; if (sourceRange.isValid()) ranges.push_back(std::move(sourceRange)); @@ -123,14 +129,14 @@ std::vector Diagnostic::fixIts() const fixIts.reserve(fixItsCount); for (uint index = 0; index < fixItsCount; ++index) - fixIts.push_back(FixIt(cxDiagnostic, index)); + fixIts.push_back(FixIt(cxTranslationUnit, cxDiagnostic, index)); return fixIts; } DiagnosticSet Diagnostic::childDiagnostics() const { - return DiagnosticSet(clang_getChildDiagnostics(cxDiagnostic)); + return DiagnosticSet(cxTranslationUnit, clang_getChildDiagnostics(cxDiagnostic)); } DiagnosticContainer Diagnostic::toDiagnosticContainer() const diff --git a/src/tools/clangbackend/source/diagnostic.h b/src/tools/clangbackend/source/diagnostic.h index 140322931fb..49161fe40e1 100644 --- a/src/tools/clangbackend/source/diagnostic.h +++ b/src/tools/clangbackend/source/diagnostic.h @@ -73,12 +73,13 @@ public: DiagnosticContainer toDiagnosticContainer() const; private: - Diagnostic(CXDiagnostic cxDiagnostic); + Diagnostic(CXTranslationUnit translationUnit, CXDiagnostic cxDiagnostic); QVector getSourceRangeContainers() const; QVector getFixItContainers() const; private: CXDiagnostic cxDiagnostic; + CXTranslationUnit cxTranslationUnit; }; inline bool operator==(Diagnostic first, Diagnostic second) diff --git a/src/tools/clangbackend/source/diagnosticset.cpp b/src/tools/clangbackend/source/diagnosticset.cpp index ce3504a114a..39c82551371 100644 --- a/src/tools/clangbackend/source/diagnosticset.cpp +++ b/src/tools/clangbackend/source/diagnosticset.cpp @@ -33,8 +33,9 @@ namespace ClangBackEnd { -DiagnosticSet::DiagnosticSet(CXDiagnosticSet cxDiagnosticSet) - : cxDiagnosticSet(cxDiagnosticSet) +DiagnosticSet::DiagnosticSet(CXTranslationUnit translationUnit, CXDiagnosticSet cxDiagnosticSet) + : cxDiagnosticSet(cxDiagnosticSet), + cxTranslationUnit(translationUnit) { } @@ -44,7 +45,8 @@ DiagnosticSet::~DiagnosticSet() } DiagnosticSet::DiagnosticSet(DiagnosticSet &&other) - : cxDiagnosticSet(std::move(other.cxDiagnosticSet)) + : cxDiagnosticSet(std::move(other.cxDiagnosticSet)), + cxTranslationUnit(std::move(other.cxTranslationUnit)) { other.cxDiagnosticSet = nullptr; } @@ -54,7 +56,9 @@ DiagnosticSet &DiagnosticSet::operator=(DiagnosticSet &&other) if (this != &other) { clang_disposeDiagnosticSet(cxDiagnosticSet); cxDiagnosticSet = std::move(other.cxDiagnosticSet); + cxTranslationUnit = std::move(other.cxTranslationUnit); other.cxDiagnosticSet = nullptr; + other.cxTranslationUnit = nullptr; } return *this; @@ -62,22 +66,22 @@ DiagnosticSet &DiagnosticSet::operator=(DiagnosticSet &&other) Diagnostic DiagnosticSet::front() const { - return Diagnostic(clang_getDiagnosticInSet(cxDiagnosticSet, 0)); + return Diagnostic(cxTranslationUnit, clang_getDiagnosticInSet(cxDiagnosticSet, 0)); } Diagnostic DiagnosticSet::back() const { - return Diagnostic(clang_getDiagnosticInSet(cxDiagnosticSet, size() - 1)); + return Diagnostic(cxTranslationUnit, clang_getDiagnosticInSet(cxDiagnosticSet, size() - 1)); } DiagnosticSet::ConstIterator DiagnosticSet::begin() const { - return DiagnosticSetIterator(cxDiagnosticSet, 0); + return DiagnosticSetIterator(cxTranslationUnit, cxDiagnosticSet, 0); } DiagnosticSet::ConstIterator DiagnosticSet::end() const { - return DiagnosticSetIterator(cxDiagnosticSet, size()); + return DiagnosticSetIterator(cxTranslationUnit, cxDiagnosticSet, size()); } QVector DiagnosticSet::toDiagnosticContainers() const @@ -113,7 +117,7 @@ bool DiagnosticSet::isNull() const Diagnostic DiagnosticSet::at(uint index) const { - return Diagnostic(clang_getDiagnosticInSet(cxDiagnosticSet, index)); + return Diagnostic(cxTranslationUnit, clang_getDiagnosticInSet(cxDiagnosticSet, index)); } } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/source/diagnosticset.h b/src/tools/clangbackend/source/diagnosticset.h index e715ad2627b..63f672de419 100644 --- a/src/tools/clangbackend/source/diagnosticset.h +++ b/src/tools/clangbackend/source/diagnosticset.h @@ -72,10 +72,11 @@ public: const IsAcceptedDiagnostic &isAcceptedDiagnostic) const; private: - DiagnosticSet(CXDiagnosticSet cxDiagnosticSet); + DiagnosticSet(CXTranslationUnit translationUnit, CXDiagnosticSet cxDiagnosticSet); private: CXDiagnosticSet cxDiagnosticSet; + CXTranslationUnit cxTranslationUnit; }; } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/source/diagnosticsetiterator.h b/src/tools/clangbackend/source/diagnosticsetiterator.h index 7739dfd3654..72a98319550 100644 --- a/src/tools/clangbackend/source/diagnosticsetiterator.h +++ b/src/tools/clangbackend/source/diagnosticsetiterator.h @@ -25,6 +25,8 @@ #pragma once +#include "diagnostic.h" + #include #include @@ -34,13 +36,15 @@ namespace ClangBackEnd { using uint = unsigned int; class DiagnosticSet; -class Diagnostic; class DiagnosticSetIterator : public std::iterator { public: - DiagnosticSetIterator(CXDiagnosticSet cxDiagnosticSet, uint index) + DiagnosticSetIterator(CXTranslationUnit translationUnit, + CXDiagnosticSet cxDiagnosticSet, + uint index) : cxDiagnosticSet(cxDiagnosticSet), + cxTranslationUnit(translationUnit), index(index) {} @@ -58,7 +62,7 @@ public: DiagnosticSetIterator operator++(int) { uint oldIndex = index++; - return DiagnosticSetIterator(cxDiagnosticSet, oldIndex); + return DiagnosticSetIterator(cxTranslationUnit, cxDiagnosticSet, oldIndex); } bool operator==(const DiagnosticSetIterator &other) @@ -73,11 +77,12 @@ public: Diagnostic operator*() { - return Diagnostic(clang_getDiagnosticInSet(cxDiagnosticSet, index)); + return Diagnostic(cxTranslationUnit, clang_getDiagnosticInSet(cxDiagnosticSet, index)); } private: CXDiagnosticSet cxDiagnosticSet; + CXTranslationUnit cxTranslationUnit; uint index; }; diff --git a/src/tools/clangbackend/source/fixit.cpp b/src/tools/clangbackend/source/fixit.cpp index c2de39c9224..8626602d456 100644 --- a/src/tools/clangbackend/source/fixit.cpp +++ b/src/tools/clangbackend/source/fixit.cpp @@ -46,12 +46,12 @@ FixItContainer FixIt::toFixItContainer() const return FixItContainer(text_, sourceRange.toSourceRangeContainer()); } -FixIt::FixIt(CXDiagnostic cxDiagnostic, uint index) +FixIt::FixIt(CXTranslationUnit translationUnit, CXDiagnostic cxDiagnostic, uint index) { CXSourceRange cxSourceRange; text_ = ClangString(clang_getDiagnosticFixIt(cxDiagnostic, index, &cxSourceRange)); - sourceRange = SourceRange(cxSourceRange); + sourceRange = SourceRange(translationUnit, cxSourceRange); } } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/source/fixit.h b/src/tools/clangbackend/source/fixit.h index f866bc8c18c..b0c1f139aee 100644 --- a/src/tools/clangbackend/source/fixit.h +++ b/src/tools/clangbackend/source/fixit.h @@ -47,7 +47,7 @@ public: FixItContainer toFixItContainer() const; private: - FixIt(CXDiagnostic cxDiagnostic, uint index); + FixIt(CXTranslationUnit translationUnit, CXDiagnostic cxDiagnostic, uint index); private: SourceRange sourceRange; diff --git a/src/tools/clangbackend/source/skippedsourceranges.cpp b/src/tools/clangbackend/source/skippedsourceranges.cpp index ca38510cf2c..f15bd446682 100644 --- a/src/tools/clangbackend/source/skippedsourceranges.cpp +++ b/src/tools/clangbackend/source/skippedsourceranges.cpp @@ -79,7 +79,7 @@ std::vector SkippedSourceRanges::sourceRanges() const sourceRanges.reserve(sourceRangeCount); for (uint i = 0; i < cxSkippedSourceRanges->count; ++i) { - const SourceRange range = cxSkippedSourceRanges->ranges[i]; + const SourceRange range {cxTranslationUnit, cxSkippedSourceRanges->ranges[i]}; const SourceRange adaptedRange = adaptedSourceRange(cxTranslationUnit, range); sourceRanges.push_back(adaptedRange); diff --git a/src/tools/clangbackend/source/sourcelocation.cpp b/src/tools/clangbackend/source/sourcelocation.cpp index 161ed5b0a50..d015cad4eef 100644 --- a/src/tools/clangbackend/source/sourcelocation.cpp +++ b/src/tools/clangbackend/source/sourcelocation.cpp @@ -29,10 +29,13 @@ #include "clangfilepath.h" #include "clangstring.h" -#include +#include + +#include + +#include #include -#include namespace ClangBackEnd { @@ -72,8 +75,10 @@ SourceLocationContainer SourceLocation::toSourceLocationContainer() const return SourceLocationContainer(filePath(), line_, column_); } -SourceLocation::SourceLocation(CXSourceLocation cxSourceLocation) +SourceLocation::SourceLocation(CXTranslationUnit cxTranslationUnit, + CXSourceLocation cxSourceLocation) : cxSourceLocation(cxSourceLocation) + , cxTranslationUnit(cxTranslationUnit) { CXFile cxFile; @@ -83,8 +88,22 @@ SourceLocation::SourceLocation(CXSourceLocation cxSourceLocation) &column_, &offset_); - filePath_ = ClangString(clang_getFileName(cxFile)); isFilePathNormalized_ = false; + if (!cxFile) + return; + + filePath_ = ClangString(clang_getFileName(cxFile)); +// CLANG-UPGRADE-CHECK: Remove HAS_GETFILECONTENTS_BACKPORTED check once we require clang >= 6.0 +#if defined(CINDEX_VERSION_HAS_GETFILECONTENTS_BACKPORTED) || CINDEX_VERSION_MINOR >= 44 + if (column_ > 1) { + const uint lineStart = offset_ + 1 - column_; + const char *contents = clang_getFileContents(cxTranslationUnit, cxFile, nullptr); + if (!contents) + return; + column_ = static_cast(QString::fromUtf8(&contents[lineStart], + static_cast(column_)).size()); + } +#endif } SourceLocation::SourceLocation(CXTranslationUnit cxTranslationUnit, @@ -96,6 +115,7 @@ SourceLocation::SourceLocation(CXTranslationUnit cxTranslationUnit, filePath.constData()), line, column)), + cxTranslationUnit(cxTranslationUnit), filePath_(filePath), line_(line), column_(column), diff --git a/src/tools/clangbackend/source/sourcelocation.h b/src/tools/clangbackend/source/sourcelocation.h index 65c3ec69ad6..bf8962161f0 100644 --- a/src/tools/clangbackend/source/sourcelocation.h +++ b/src/tools/clangbackend/source/sourcelocation.h @@ -57,12 +57,14 @@ public: SourceLocationContainer toSourceLocationContainer() const; private: - SourceLocation(CXSourceLocation cxSourceLocation); + SourceLocation(CXTranslationUnit cxTranslationUnit, + CXSourceLocation cxSourceLocation); operator CXSourceLocation() const; private: CXSourceLocation cxSourceLocation; + CXTranslationUnit cxTranslationUnit; mutable Utf8String filePath_; uint line_ = 0; uint column_ = 0; diff --git a/src/tools/clangbackend/source/sourcerange.cpp b/src/tools/clangbackend/source/sourcerange.cpp index 20c6efb5e65..ff1a4753918 100644 --- a/src/tools/clangbackend/source/sourcerange.cpp +++ b/src/tools/clangbackend/source/sourcerange.cpp @@ -39,7 +39,8 @@ SourceRange::SourceRange() } SourceRange::SourceRange(const SourceLocation &start, const SourceLocation &end) - : cxSourceRange(clang_getRange(start, end)) + : cxSourceRange(clang_getRange(start, end)), + cxTranslationUnit(start.cxTranslationUnit) { } @@ -55,12 +56,12 @@ bool SourceRange::isValid() const SourceLocation SourceRange::start() const { - return SourceLocation(clang_getRangeStart(cxSourceRange)); + return {cxTranslationUnit, clang_getRangeStart(cxSourceRange)}; } SourceLocation SourceRange::end() const { - return SourceLocation(clang_getRangeEnd(cxSourceRange)); + return {cxTranslationUnit, clang_getRangeEnd(cxSourceRange)}; } bool SourceRange::contains(unsigned line, unsigned column) const @@ -90,8 +91,9 @@ ClangBackEnd::SourceRange::operator CXSourceRange() const return cxSourceRange; } -SourceRange::SourceRange(CXSourceRange cxSourceRange) - : cxSourceRange(cxSourceRange) +SourceRange::SourceRange(CXTranslationUnit translationUnit, CXSourceRange cxSourceRange) + : cxSourceRange(cxSourceRange), + cxTranslationUnit(translationUnit) { } diff --git a/src/tools/clangbackend/source/sourcerange.h b/src/tools/clangbackend/source/sourcerange.h index b8083e86955..4c30ad43f8e 100644 --- a/src/tools/clangbackend/source/sourcerange.h +++ b/src/tools/clangbackend/source/sourcerange.h @@ -40,7 +40,7 @@ class SourceRange public: SourceRange(); - SourceRange(CXSourceRange cxSourceRange); + SourceRange(CXTranslationUnit cxTranslationUnit, CXSourceRange cxSourceRange); SourceRange(const SourceLocation &start, const SourceLocation &end); bool isNull() const; @@ -58,6 +58,7 @@ public: private: CXSourceRange cxSourceRange; + CXTranslationUnit cxTranslationUnit = nullptr; }; bool operator==(const SourceRange &first, const SourceRange &second); diff --git a/src/tools/clangbackend/source/tokeninfo.cpp b/src/tools/clangbackend/source/tokeninfo.cpp index 703b0f78085..a9c84312861 100644 --- a/src/tools/clangbackend/source/tokeninfo.cpp +++ b/src/tools/clangbackend/source/tokeninfo.cpp @@ -43,7 +43,8 @@ TokenInfo::TokenInfo(const CXCursor &cxCursor, : m_currentOutputArgumentRanges(¤tOutputArgumentRanges), m_originalCursor(cxCursor) { - const SourceRange sourceRange = clang_getTokenExtent(cxTranslationUnit, *cxToken); + const SourceRange sourceRange {cxTranslationUnit, + clang_getTokenExtent(cxTranslationUnit, *cxToken)}; const auto start = sourceRange.start(); const auto end = sourceRange.end();