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 <nikolai.kosjar@qt.io>
This commit is contained in:
Ivan Donchevskii
2017-11-29 16:08:06 +01:00
parent 6deec195f1
commit 09310bcdc6
26 changed files with 106 additions and 111 deletions

View File

@@ -368,26 +368,23 @@ QFuture<CppTools::CursorInfo> 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<CppTools::CursorInfo> 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<CppTools::ToolTipInfo> BackendCommunicator::requestToolTip(

View File

@@ -75,13 +75,11 @@ public:
const FileContainer &fileContainer,
quint32 line,
quint32 column,
QTextDocument *textDocument,
const LocalUseMap &localUses);
QFuture<CppTools::CursorInfo> requestLocalReferences(
const FileContainer &fileContainer,
quint32 line,
quint32 column,
QTextDocument *textDocument);
quint32 column);
QFuture<CppTools::ToolTipInfo> requestToolTip(const FileContainer &fileContainer,
quint32 line,
quint32 column);

View File

@@ -101,16 +101,14 @@ void BackendReceiver::deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidge
QFuture<CppTools::CursorInfo> BackendReceiver::addExpectedReferencesMessage(
quint64 ticket,
QTextDocument *textDocument,
const CppTools::SemanticInfo::LocalUseMap &localUses)
{
QTC_CHECK(textDocument);
QTC_CHECK(!m_referencesTable.contains(ticket));
QFutureInterface<CppTools::CursorInfo> 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<int>(start.line()) - 1);
const int shift = ClangCodeModel::Utils::extraUtf8CharsShift(block.text(),
static_cast<int>(start.column()));
const uint column = start.column() - static_cast<uint>(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();
}

View File

@@ -56,7 +56,6 @@ public:
QFuture<CppTools::CursorInfo>
addExpectedReferencesMessage(quint64 ticket,
QTextDocument *textDocument,
const CppTools::SemanticInfo::LocalUseMap &localUses
= CppTools::SemanticInfo::LocalUseMap());
QFuture<CppTools::SymbolInfo> addExpectedRequestFollowSymbolMessage(quint64 ticket);
@@ -82,13 +81,10 @@ private:
struct ReferencesEntry {
ReferencesEntry() = default;
ReferencesEntry(QFutureInterface<CppTools::CursorInfo> futureInterface,
QTextDocument *textDocument,
const CppTools::SemanticInfo::LocalUseMap &localUses)
: futureInterface(futureInterface)
, textDocument(textDocument)
, localUses(localUses) {}
QFutureInterface<CppTools::CursorInfo> futureInterface;
QPointer<QTextDocument> textDocument;
CppTools::SemanticInfo::LocalUseMap localUses;
};
QHash<quint64, ReferencesEntry> m_referencesTable;

View File

@@ -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};
}

View File

@@ -64,8 +64,7 @@ int positionInText(QTextDocument *textDocument,
{
auto textBlock = textDocument->findBlockByNumber(
static_cast<int>(sourceLocationContainer.line()) - 1);
int column = static_cast<int>(sourceLocationContainer.column()) - 1;
column -= ClangCodeModel::Utils::extraUtf8CharsShift(textBlock.text(), column);
const int column = static_cast<int>(sourceLocationContainer.column()) - 1;
return textBlock.position() + column;
}

View File

@@ -331,20 +331,19 @@ ClangEditorDocumentProcessor::cursorInfo(const CppTools::CursorInfoParams &param
{
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<quint32>(line),
static_cast<quint32>(column),
textDocument(),
localUses);
}
@@ -361,8 +360,7 @@ QFuture<CppTools::CursorInfo> ClangEditorDocumentProcessor::requestLocalReferenc
return m_communicator.requestLocalReferences(simpleFileContainer(),
static_cast<quint32>(line),
static_cast<quint32>(column),
textDocument());
static_cast<quint32>(column));
}
QFuture<CppTools::SymbolInfo>

View File

@@ -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<uchar>(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

View File

@@ -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