forked from qt-creator/qt-creator
ClangCodeModel: Improve ifdef'ed out code handling with clangd
- Made code more self-documenting. - Added more comments. - Added debug output. - Rewrote ugly redundant code checking for #ifdef & friends. - For consistency, emit update about ifdef'ed code only if we also report the other highlighting results. Change-Id: Idd3cbd3c169343bcaf6b6b19330130378ac6c5d0 Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -2575,7 +2575,8 @@ static QList<BlockRange> cleanupDisabledCode(HighlightingResults &results, const
|
|||||||
int rangeStartPos = -1;
|
int rangeStartPos = -1;
|
||||||
for (auto it = results.begin(); it != results.end();) {
|
for (auto it = results.begin(); it != results.end();) {
|
||||||
const bool wasIfdefedOut = rangeStartPos != -1;
|
const bool wasIfdefedOut = rangeStartPos != -1;
|
||||||
if (it->textStyles.mainStyle != C_DISABLED_CODE) {
|
const bool isIfDefedOut = it->textStyles.mainStyle == C_DISABLED_CODE;
|
||||||
|
if (!isIfDefedOut) {
|
||||||
if (wasIfdefedOut) {
|
if (wasIfdefedOut) {
|
||||||
const QTextBlock block = doc->findBlockByNumber(it->line - 1);
|
const QTextBlock block = doc->findBlockByNumber(it->line - 1);
|
||||||
ifdefedOutRanges << BlockRange(rangeStartPos, block.position());
|
ifdefedOutRanges << BlockRange(rangeStartPos, block.position());
|
||||||
@@ -2587,19 +2588,28 @@ static QList<BlockRange> cleanupDisabledCode(HighlightingResults &results, const
|
|||||||
|
|
||||||
if (!wasIfdefedOut)
|
if (!wasIfdefedOut)
|
||||||
rangeStartPos = doc->findBlockByNumber(it->line - 1).position();
|
rangeStartPos = doc->findBlockByNumber(it->line - 1).position();
|
||||||
const int pos = Utils::Text::positionInText(doc, it->line, it->column);
|
|
||||||
const QStringView content = subViewLen(docContent, pos, it->length).trimmed();
|
// Does the current line contain a potential "ifdefed-out switcher"?
|
||||||
if (!content.startsWith(QLatin1String("#if"))
|
// If not, no state change is possible and we continue with the next line.
|
||||||
&& !content.startsWith(QLatin1String("#elif"))
|
const auto isPreprocessorControlStatement = [&] {
|
||||||
&& !content.startsWith(QLatin1String("#else"))
|
const int pos = Utils::Text::positionInText(doc, it->line, it->column);
|
||||||
&& !content.startsWith(QLatin1String("#endif"))) {
|
const QStringView content = subViewLen(docContent, pos, it->length).trimmed();
|
||||||
static const QStringList ppSuffixes{"if", "ifdef", "elif", "else", "endif"};
|
if (content.isEmpty() || content.first() != '#')
|
||||||
const QList<QStringView> contentList = content.split(' ', Qt::SkipEmptyParts);
|
return false;
|
||||||
if (contentList.size() < 2 || contentList.first() != QLatin1String("#")
|
int offset = 1;
|
||||||
|| !ppSuffixes.contains(contentList.at(1))) {
|
while (offset < content.size() && content.at(offset).isSpace())
|
||||||
++it;
|
++offset;
|
||||||
continue;
|
if (offset == content.size())
|
||||||
}
|
return false;
|
||||||
|
const QStringView ppDirective = content.mid(offset);
|
||||||
|
return ppDirective.startsWith(QLatin1String("if"))
|
||||||
|
|| ppDirective.startsWith(QLatin1String("elif"))
|
||||||
|
|| ppDirective.startsWith(QLatin1String("else"))
|
||||||
|
|| ppDirective.startsWith(QLatin1String("endif"));
|
||||||
|
};
|
||||||
|
if (!isPreprocessorControlStatement()) {
|
||||||
|
++it;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wasIfdefedOut) {
|
if (!wasIfdefedOut) {
|
||||||
@@ -2626,6 +2636,12 @@ static QList<BlockRange> cleanupDisabledCode(HighlightingResults &results, const
|
|||||||
if (rangeStartPos != -1)
|
if (rangeStartPos != -1)
|
||||||
ifdefedOutRanges << BlockRange(rangeStartPos, doc->characterCount());
|
ifdefedOutRanges << BlockRange(rangeStartPos, doc->characterCount());
|
||||||
|
|
||||||
|
qCDebug(clangdLogHighlight) << "found" << ifdefedOutRanges.size() << "ifdefed-out ranges";
|
||||||
|
if (clangdLogHighlight().isDebugEnabled()) {
|
||||||
|
for (const BlockRange &r : qAsConst(ifdefedOutRanges))
|
||||||
|
qCDebug(clangdLogHighlight) << r.first() << r.last();
|
||||||
|
}
|
||||||
|
|
||||||
return ifdefedOutRanges;
|
return ifdefedOutRanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2785,13 +2801,13 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
|
|||||||
|
|
||||||
auto results = QtConcurrent::blockingMapped<HighlightingResults>(tokens, toResult);
|
auto results = QtConcurrent::blockingMapped<HighlightingResults>(tokens, toResult);
|
||||||
const QList<BlockRange> ifdefedOutBlocks = cleanupDisabledCode(results, &doc, docContents);
|
const QList<BlockRange> ifdefedOutBlocks = cleanupDisabledCode(results, &doc, docContents);
|
||||||
QMetaObject::invokeMethod(textDocument, [textDocument, ifdefedOutBlocks, docRevision] {
|
|
||||||
if (textDocument && textDocument->document()->revision() == docRevision)
|
|
||||||
textDocument->setIfdefedOutBlocks(ifdefedOutBlocks);
|
|
||||||
}, Qt::QueuedConnection);
|
|
||||||
ExtraHighlightingResultsCollector(future, results, filePath, ast, &doc, docContents).collect();
|
ExtraHighlightingResultsCollector(future, results, filePath, ast, &doc, docContents).collect();
|
||||||
if (!future.isCanceled()) {
|
if (!future.isCanceled()) {
|
||||||
qCDebug(clangdLog) << "reporting" << results.size() << "highlighting results";
|
qCDebug(clangdLog) << "reporting" << results.size() << "highlighting results";
|
||||||
|
QMetaObject::invokeMethod(textDocument, [textDocument, ifdefedOutBlocks, docRevision] {
|
||||||
|
if (textDocument && textDocument->document()->revision() == docRevision)
|
||||||
|
textDocument->setIfdefedOutBlocks(ifdefedOutBlocks);
|
||||||
|
}, Qt::QueuedConnection);
|
||||||
QList<Range> virtualRanges;
|
QList<Range> virtualRanges;
|
||||||
for (const HighlightingResult &r : results) {
|
for (const HighlightingResult &r : results) {
|
||||||
if (r.textStyles.mainStyle != C_VIRTUAL_METHOD)
|
if (r.textStyles.mainStyle != C_VIRTUAL_METHOD)
|
||||||
@@ -2806,8 +2822,7 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
|
|||||||
client->setVirtualRanges(filePath, virtualRanges, docRevision);
|
client->setVirtualRanges(filePath, virtualRanges, docRevision);
|
||||||
}
|
}
|
||||||
}, Qt::QueuedConnection);
|
}, Qt::QueuedConnection);
|
||||||
future.reportResults(QVector<HighlightingResult>(results.cbegin(),
|
future.reportResults(QVector<HighlightingResult>(results.cbegin(), results.cend()));
|
||||||
results.cend()));
|
|
||||||
}
|
}
|
||||||
future.reportFinished();
|
future.reportFinished();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user