forked from qt-creator/qt-creator
ClangCodeModel: Properly mark "#ifdefed-out" blocks with clangd
The behavior is now the same as when using libclang. Namely: - The whole block is grayed out, rather than just symbols having a gray background. - Ifdefed-out blocks no longer mess with the brace depth. Change-Id: I8b5f3a788430edcd9dd79249323c26a5ee5d68ed Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -2386,20 +2386,28 @@ static void collectExtraResults(QFutureInterface<TextEditor::HighlightingResult>
|
|||||||
|
|
||||||
// clangd reports also the #ifs, #elses and #endifs around the disabled code as disabled,
|
// clangd reports also the #ifs, #elses and #endifs around the disabled code as disabled,
|
||||||
// and not even in a consistent manner. We don't want this, so we have to clean up here.
|
// and not even in a consistent manner. We don't want this, so we have to clean up here.
|
||||||
// TODO: Fix in clangd?
|
// But note that we require this behavior, as otherwise we would not be able to grey out
|
||||||
static void cleanupDisabledCode(TextEditor::HighlightingResults &results, QTextDocument *doc,
|
// e.g. empty lines after an #fdef, due to the lack of symbols.
|
||||||
|
static QList<TextEditor::BlockRange>
|
||||||
|
cleanupDisabledCode(TextEditor::HighlightingResults &results, QTextDocument *doc,
|
||||||
const QString &docContent)
|
const QString &docContent)
|
||||||
{
|
{
|
||||||
bool inDisabled = false;
|
QList<TextEditor::BlockRange> ifdefedOutRanges;
|
||||||
|
int rangeStartPos = -1;
|
||||||
for (auto it = results.begin(); it != results.end();) {
|
for (auto it = results.begin(); it != results.end();) {
|
||||||
const bool wasInDisabled = inDisabled;
|
const bool wasIfdefedOut = rangeStartPos != -1;
|
||||||
if (it->textStyles.mainStyle != TextEditor::C_DISABLED_CODE) {
|
if (it->textStyles.mainStyle != TextEditor::C_DISABLED_CODE) {
|
||||||
inDisabled = false;
|
if (wasIfdefedOut) {
|
||||||
|
const QTextBlock block = doc->findBlockByNumber(it->line - 1);
|
||||||
|
ifdefedOutRanges << TextEditor::BlockRange(rangeStartPos, block.position());
|
||||||
|
rangeStartPos = -1;
|
||||||
|
}
|
||||||
++it;
|
++it;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
inDisabled = true;
|
if (!wasIfdefedOut)
|
||||||
|
rangeStartPos = doc->findBlockByNumber(it->line - 1).position();
|
||||||
const int pos = Utils::Text::positionInText(doc, it->line, it->column);
|
const int pos = Utils::Text::positionInText(doc, it->line, it->column);
|
||||||
const QStringView content(QStringView(docContent).mid(pos, it->length).trimmed());
|
const QStringView content(QStringView(docContent).mid(pos, it->length).trimmed());
|
||||||
if (!content.startsWith(QLatin1String("#if"))
|
if (!content.startsWith(QLatin1String("#if"))
|
||||||
@@ -2410,25 +2418,37 @@ static void cleanupDisabledCode(TextEditor::HighlightingResults &results, QTextD
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wasInDisabled) {
|
if (!wasIfdefedOut) {
|
||||||
// The #if or #else that starts disabled code should not be disabled.
|
// The #if or #else that starts disabled code should not be disabled.
|
||||||
|
const QTextBlock nextBlock = doc->findBlockByNumber(it->line);
|
||||||
|
rangeStartPos = nextBlock.isValid() ? nextBlock.position() : -1;
|
||||||
it = results.erase(it);
|
it = results.erase(it);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wasInDisabled && (it + 1 == results.end()
|
if (wasIfdefedOut && (it + 1 == results.end()
|
||||||
|| (it + 1)->textStyles.mainStyle != TextEditor::C_DISABLED_CODE)) {
|
|| (it + 1)->textStyles.mainStyle != TextEditor::C_DISABLED_CODE)) {
|
||||||
// The #else or #endif that ends disabled code should not be disabled.
|
// The #else or #endif that ends disabled code should not be disabled.
|
||||||
|
const QTextBlock block = doc->findBlockByNumber(it->line - 1);
|
||||||
|
ifdefedOutRanges << TextEditor::BlockRange(rangeStartPos, block.position());
|
||||||
|
rangeStartPos = -1;
|
||||||
it = results.erase(it);
|
it = results.erase(it);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rangeStartPos != -1)
|
||||||
|
ifdefedOutRanges << TextEditor::BlockRange(rangeStartPos, doc->characterCount());
|
||||||
|
|
||||||
|
return ifdefedOutRanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void semanticHighlighter(QFutureInterface<TextEditor::HighlightingResult> &future,
|
static void semanticHighlighter(QFutureInterface<TextEditor::HighlightingResult> &future,
|
||||||
const QList<ExpandedSemanticToken> &tokens,
|
const QList<ExpandedSemanticToken> &tokens,
|
||||||
const QString &docContents, const AstNode &ast)
|
const QString &docContents, const AstNode &ast,
|
||||||
|
const QPointer<TextEditor::TextEditorWidget> &widget,
|
||||||
|
int docRevision)
|
||||||
{
|
{
|
||||||
if (future.isCanceled()) {
|
if (future.isCanceled()) {
|
||||||
future.reportFinished();
|
future.reportFinished();
|
||||||
@@ -2548,7 +2568,12 @@ static void semanticHighlighter(QFutureInterface<TextEditor::HighlightingResult>
|
|||||||
};
|
};
|
||||||
|
|
||||||
TextEditor::HighlightingResults results = Utils::transform(tokens, toResult);
|
TextEditor::HighlightingResults results = Utils::transform(tokens, toResult);
|
||||||
cleanupDisabledCode(results, &doc, docContents);
|
const QList<TextEditor::BlockRange> ifdefedOutBlocks
|
||||||
|
= cleanupDisabledCode(results, &doc, docContents);
|
||||||
|
QMetaObject::invokeMethod(widget, [widget, ifdefedOutBlocks, docRevision] {
|
||||||
|
if (widget && widget->textDocument()->document()->revision() == docRevision)
|
||||||
|
widget->setIfdefedOutBlocks(ifdefedOutBlocks);
|
||||||
|
}, Qt::QueuedConnection);
|
||||||
collectExtraResults(future, results, ast, &doc, docContents);
|
collectExtraResults(future, results, ast, &doc, docContents);
|
||||||
if (!future.isCanceled()) {
|
if (!future.isCanceled()) {
|
||||||
qCDebug(clangdLog) << "reporting" << results.size() << "highlighting results";
|
qCDebug(clangdLog) << "reporting" << results.size() << "highlighting results";
|
||||||
@@ -2588,9 +2613,13 @@ void ClangdClient::Private::handleSemanticTokens(TextEditor::TextDocument *doc,
|
|||||||
if (ast && clangdLogAst().isDebugEnabled())
|
if (ast && clangdLogAst().isDebugEnabled())
|
||||||
ast->print();
|
ast->print();
|
||||||
|
|
||||||
|
IEditor * const editor = Utils::findOrDefault(EditorManager::visibleEditors(),
|
||||||
|
[doc](const IEditor *editor) { return editor->document() == doc; });
|
||||||
|
const auto editorWidget = TextEditor::TextEditorWidget::fromEditor(editor);
|
||||||
const auto runner = [tokens, text = doc->document()->toPlainText(),
|
const auto runner = [tokens, text = doc->document()->toPlainText(),
|
||||||
theAst = ast ? *ast : AstNode()] {
|
theAst = ast ? *ast : AstNode(), w = QPointer(editorWidget),
|
||||||
return Utils::runAsync(semanticHighlighter, tokens, text, theAst);
|
rev = doc->document()->revision()] {
|
||||||
|
return Utils::runAsync(semanticHighlighter, tokens, text, theAst, w, rev);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isTesting) {
|
if (isTesting) {
|
||||||
|
Reference in New Issue
Block a user