forked from qt-creator/qt-creator
ClangCodeModel: Do not ignore highlighting for raw string literals
Also add the special handling for prefix and suffix like in CppHighlighter, as not to re-introduce QTCREATORBUG-19119. Fixes: QTCREATORBUG-16183 Change-Id: Ie264946782220a8e5a862c1d4550bcd49bc2349f Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -197,13 +197,8 @@ void HighlightingResultReporter::run_internal()
|
||||
|
||||
using ClangBackEnd::HighlightingType;
|
||||
|
||||
for (const auto &tokenInfo : m_tokenInfos) {
|
||||
const HighlightingType mainType = tokenInfo.types.mainHighlightingType;
|
||||
if (mainType == HighlightingType::StringLiteral)
|
||||
continue;
|
||||
|
||||
for (const auto &tokenInfo : qAsConst(m_tokenInfos))
|
||||
reportChunkWise(toHighlightingResult(tokenInfo));
|
||||
}
|
||||
|
||||
if (isCanceled())
|
||||
return;
|
||||
|
@@ -44,6 +44,69 @@ static Q_LOGGING_CATEGORY(log, "qtc.cpptools.semantichighlighter", QtWarningMsg)
|
||||
|
||||
namespace CppTools {
|
||||
|
||||
static const QList<std::pair<HighlightingResult, QTextBlock>>
|
||||
splitRawStringLiteral(const HighlightingResult &result, const QTextBlock &startBlock)
|
||||
{
|
||||
if (result.textStyles.mainStyle != C_STRING)
|
||||
return {{result, startBlock}};
|
||||
|
||||
QTextCursor cursor(startBlock);
|
||||
cursor.setPosition(cursor.position() + result.column - 1);
|
||||
cursor.setPosition(cursor.position() + result.length, QTextCursor::KeepAnchor);
|
||||
const QString theString = cursor.selectedText();
|
||||
|
||||
// Find all the components of a raw string literal. If we don't succeed, then it's
|
||||
// something else.
|
||||
if (!theString.endsWith('"'))
|
||||
return {{result, startBlock}};
|
||||
int rOffset = -1;
|
||||
if (theString.startsWith("R\"")) {
|
||||
rOffset = 0;
|
||||
} else if (theString.startsWith("LR\"")
|
||||
|| theString.startsWith("uR\"")
|
||||
|| theString.startsWith("UR\"")) {
|
||||
rOffset = 1;
|
||||
} else if (theString.startsWith("u8R\"")) {
|
||||
rOffset = 2;
|
||||
}
|
||||
if (rOffset == -1)
|
||||
return {{result, startBlock}};
|
||||
const int delimiterOffset = rOffset + 2;
|
||||
const int openParenOffset = theString.indexOf('(', delimiterOffset);
|
||||
if (openParenOffset == -1)
|
||||
return {{result, startBlock}};
|
||||
const QStringView delimiter = theString.mid(delimiterOffset, openParenOffset - delimiterOffset);
|
||||
const int endDelimiterOffset = theString.length() - 1 - delimiter.length();
|
||||
if (theString.mid(endDelimiterOffset, delimiter.length()) != delimiter)
|
||||
return {{result, startBlock}};
|
||||
if (theString.at(endDelimiterOffset - 1) != ')')
|
||||
return {{result, startBlock}};
|
||||
|
||||
// Now split the result. For clarity, we display only the actual content as a string,
|
||||
// and the rest (including the delimiter) as a keyword.
|
||||
HighlightingResult prefix = result;
|
||||
prefix.textStyles.mainStyle = C_KEYWORD;
|
||||
prefix.textStyles.mixinStyles = {};
|
||||
prefix.length = delimiterOffset + delimiter.length() + 1;
|
||||
cursor.setPosition(startBlock.position() + result.column - 1 + prefix.length);
|
||||
QTextBlock stringBlock = cursor.block();
|
||||
HighlightingResult actualString = result;
|
||||
actualString.line = stringBlock.blockNumber() + 1;
|
||||
actualString.column = cursor.positionInBlock() + 1;
|
||||
actualString.length = endDelimiterOffset - openParenOffset - 2;
|
||||
cursor.setPosition(cursor.position() + actualString.length);
|
||||
QTextBlock suffixBlock = cursor.block();
|
||||
HighlightingResult suffix = result;
|
||||
suffix.textStyles.mainStyle = C_KEYWORD;
|
||||
suffix.textStyles.mixinStyles = {};
|
||||
suffix.line = suffixBlock.blockNumber() + 1;
|
||||
suffix.column = cursor.positionInBlock() + 1;
|
||||
suffix.length = delimiter.length() + 2;
|
||||
QTC_CHECK(prefix.length + actualString.length + suffix.length == result.length);
|
||||
|
||||
return {{prefix, startBlock}, {actualString, stringBlock}, {suffix, suffixBlock}};
|
||||
}
|
||||
|
||||
SemanticHighlighter::SemanticHighlighter(TextDocument *baseTextDocument)
|
||||
: QObject(baseTextDocument)
|
||||
, m_baseTextDocument(baseTextDocument)
|
||||
@@ -94,7 +157,8 @@ void SemanticHighlighter::onHighlighterResultAvailable(int from, int to)
|
||||
|
||||
SyntaxHighlighter *highlighter = m_baseTextDocument->syntaxHighlighter();
|
||||
QTC_ASSERT(highlighter, return);
|
||||
incrementalApplyExtraAdditionalFormats(highlighter, m_watcher->future(), from, to, m_formatMap);
|
||||
incrementalApplyExtraAdditionalFormats(highlighter, m_watcher->future(), from, to, m_formatMap,
|
||||
&splitRawStringLiteral);
|
||||
}
|
||||
|
||||
void SemanticHighlighter::onHighlighterFinished()
|
||||
|
@@ -47,9 +47,8 @@ public:
|
||||
};
|
||||
using Ranges = QVector<Range>;
|
||||
|
||||
Ranges rangesForResult(const HighlightingResult &result,
|
||||
QTextDocument *doc,
|
||||
const QHash<int, QTextCharFormat> &kindToFormat)
|
||||
const Ranges rangesForResult(const HighlightingResult &result, const QTextBlock &startBlock,
|
||||
const QHash<int, QTextCharFormat> &kindToFormat)
|
||||
{
|
||||
const QTextCharFormat format = result.useTextSyles
|
||||
? TextEditorSettings::fontSettings().toTextCharFormat(result.textStyles)
|
||||
@@ -58,7 +57,7 @@ Ranges rangesForResult(const HighlightingResult &result,
|
||||
return {};
|
||||
|
||||
HighlightingResult curResult = result;
|
||||
QTextBlock curBlock = doc->findBlockByNumber(curResult.line - 1);
|
||||
QTextBlock curBlock = startBlock;
|
||||
Ranges ranges;
|
||||
while (curBlock.isValid()) {
|
||||
Range range;
|
||||
@@ -78,13 +77,29 @@ Ranges rangesForResult(const HighlightingResult &result,
|
||||
return ranges;
|
||||
}
|
||||
|
||||
const Ranges rangesForResult(
|
||||
const HighlightingResult &result,
|
||||
QTextDocument *doc,
|
||||
const QHash<int, QTextCharFormat> &kindToFormat,
|
||||
const Splitter &splitter = {})
|
||||
{
|
||||
const QTextBlock startBlock = doc->findBlockByNumber(result.line - 1);
|
||||
if (splitter) {
|
||||
Ranges ranges;
|
||||
for (const auto &[newResult, newBlock] : splitter(result, startBlock))
|
||||
ranges << rangesForResult(newResult, newBlock, kindToFormat);
|
||||
return ranges;
|
||||
}
|
||||
return rangesForResult(result, startBlock, kindToFormat);
|
||||
}
|
||||
|
||||
void SemanticHighlighter::incrementalApplyExtraAdditionalFormats(
|
||||
SyntaxHighlighter *highlighter,
|
||||
}
|
||||
|
||||
void SemanticHighlighter::incrementalApplyExtraAdditionalFormats(SyntaxHighlighter *highlighter,
|
||||
const QFuture<HighlightingResult> &future,
|
||||
int from, int to,
|
||||
const QHash<int, QTextCharFormat> &kindToFormat)
|
||||
const QHash<int, QTextCharFormat> &kindToFormat,
|
||||
const Splitter &splitter)
|
||||
{
|
||||
if (to <= from)
|
||||
return;
|
||||
@@ -112,8 +127,7 @@ void SemanticHighlighter::incrementalApplyExtraAdditionalFormats(
|
||||
|
||||
std::map<QTextBlock, QVector<QTextLayout::FormatRange>> formatRanges;
|
||||
for (int i = from; i < to; ++i) {
|
||||
const Ranges ranges = rangesForResult(future.resultAt(i), doc, kindToFormat);
|
||||
for (const Range &range : ranges)
|
||||
for (const Range &range : rangesForResult(future.resultAt(i), doc, kindToFormat, splitter))
|
||||
formatRanges[range.block].append(range.formatRange);
|
||||
}
|
||||
|
||||
@@ -141,8 +155,7 @@ void SemanticHighlighter::setExtraAdditionalFormats(SyntaxHighlighter *highlight
|
||||
std::map<QTextBlock, QVector<QTextLayout::FormatRange>> formatRanges;
|
||||
|
||||
for (auto result : results) {
|
||||
const Ranges ranges = rangesForResult(result, doc, kindToFormat);
|
||||
for (const Range &range : ranges)
|
||||
for (const Range &range : rangesForResult(result, doc, kindToFormat))
|
||||
formatRanges[range.block].append(range.formatRange);
|
||||
}
|
||||
|
||||
|
@@ -33,6 +33,13 @@
|
||||
#include <QFuture>
|
||||
#include <QTextCharFormat>
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QTextBlock;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class SyntaxHighlighter;
|
||||
@@ -76,6 +83,9 @@ using HighlightingResults = QList<HighlightingResult>;
|
||||
|
||||
namespace SemanticHighlighter {
|
||||
|
||||
using Splitter = std::function<const QList<std::pair<HighlightingResult, QTextBlock>>
|
||||
(const HighlightingResult &, const QTextBlock &)>;
|
||||
|
||||
// Applies the future results [from, to) and applies the extra formats
|
||||
// indicated by Result::kind and kindToFormat to the correct location using
|
||||
// SyntaxHighlighter::setExtraAdditionalFormats.
|
||||
@@ -87,7 +97,8 @@ void TEXTEDITOR_EXPORT incrementalApplyExtraAdditionalFormats(
|
||||
SyntaxHighlighter *highlighter,
|
||||
const QFuture<HighlightingResult> &future,
|
||||
int from, int to,
|
||||
const QHash<int, QTextCharFormat> &kindToFormat);
|
||||
const QHash<int, QTextCharFormat> &kindToFormat,
|
||||
const Splitter &splitter = {});
|
||||
|
||||
// Clears all extra highlights and applies the extra formats
|
||||
// indicated by Result::kind and kindToFormat to the correct location using
|
||||
|
Reference in New Issue
Block a user