forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/7.0'
Change-Id: Iab67dffe64bee391bd921ed8832bb17b36ec861b
This commit is contained in:
@@ -2649,7 +2649,8 @@ static QList<BlockRange> cleanupDisabledCode(HighlightingResults &results, const
|
||||
int rangeStartPos = -1;
|
||||
for (auto it = results.begin(); it != results.end();) {
|
||||
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) {
|
||||
const QTextBlock block = doc->findBlockByNumber(it->line - 1);
|
||||
ifdefedOutRanges << BlockRange(rangeStartPos, block.position());
|
||||
@@ -2661,19 +2662,28 @@ static QList<BlockRange> cleanupDisabledCode(HighlightingResults &results, const
|
||||
|
||||
if (!wasIfdefedOut)
|
||||
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();
|
||||
if (!content.startsWith(QLatin1String("#if"))
|
||||
&& !content.startsWith(QLatin1String("#elif"))
|
||||
&& !content.startsWith(QLatin1String("#else"))
|
||||
&& !content.startsWith(QLatin1String("#endif"))) {
|
||||
static const QStringList ppSuffixes{"if", "ifdef", "elif", "else", "endif"};
|
||||
const QList<QStringView> contentList = content.split(' ', Qt::SkipEmptyParts);
|
||||
if (contentList.size() < 2 || contentList.first() != QLatin1String("#")
|
||||
|| !ppSuffixes.contains(contentList.at(1))) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Does the current line contain a potential "ifdefed-out switcher"?
|
||||
// If not, no state change is possible and we continue with the next line.
|
||||
const auto isPreprocessorControlStatement = [&] {
|
||||
const int pos = Utils::Text::positionInText(doc, it->line, it->column);
|
||||
const QStringView content = subViewLen(docContent, pos, it->length).trimmed();
|
||||
if (content.isEmpty() || content.first() != '#')
|
||||
return false;
|
||||
int offset = 1;
|
||||
while (offset < content.size() && content.at(offset).isSpace())
|
||||
++offset;
|
||||
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) {
|
||||
@@ -2700,6 +2710,12 @@ static QList<BlockRange> cleanupDisabledCode(HighlightingResults &results, const
|
||||
if (rangeStartPos != -1)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -2741,10 +2757,22 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
|
||||
// where the user sees that it's being written.
|
||||
if (it->kind() == "CXXOperatorCall") {
|
||||
const QList<AstNode> children = it->children().value_or(QList<AstNode>());
|
||||
|
||||
// Child 1 is the call itself, Child 2 is the named entity on which the call happens
|
||||
// (a lambda or a class instance), after that follow the actual call arguments.
|
||||
if (children.size() < 2)
|
||||
return false;
|
||||
if (!children.last().range().contains(range))
|
||||
|
||||
// The call itself is never modifiable.
|
||||
if (children.first().range() == range)
|
||||
return false;
|
||||
|
||||
// The callable is never displayed as an output parameter.
|
||||
// TODO: A good argument can be made to display objects on which a non-const
|
||||
// operator or function is called as output parameters.
|
||||
if (children.at(1).range() == range)
|
||||
return false;
|
||||
|
||||
QList<AstNode> firstChildTree{children.first()};
|
||||
while (!firstChildTree.isEmpty()) {
|
||||
const AstNode n = firstChildTree.takeFirst();
|
||||
@@ -2859,13 +2887,13 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
|
||||
|
||||
auto results = QtConcurrent::blockingMapped<HighlightingResults>(tokens, toResult);
|
||||
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();
|
||||
if (!future.isCanceled()) {
|
||||
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;
|
||||
for (const HighlightingResult &r : results) {
|
||||
if (r.textStyles.mainStyle != C_VIRTUAL_METHOD)
|
||||
@@ -2880,8 +2908,7 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
|
||||
client->setVirtualRanges(filePath, virtualRanges, docRevision);
|
||||
}
|
||||
}, Qt::QueuedConnection);
|
||||
future.reportResults(QVector<HighlightingResult>(results.cbegin(),
|
||||
results.cend()));
|
||||
future.reportResults(QVector<HighlightingResult>(results.cbegin(), results.cend()));
|
||||
}
|
||||
future.reportFinished();
|
||||
}
|
||||
|
||||
@@ -1285,6 +1285,14 @@ void ClangdTestHighlighting::test_data()
|
||||
<< QList<int>{C_LOCAL} << 0;
|
||||
QTest::newRow("const member as function argument") << 868 << 32 << 868 << 43
|
||||
<< QList<int>{C_FIELD} << 0;
|
||||
QTest::newRow("lambda call without arguments (const var)") << 887 << 5 << 887 << 12
|
||||
<< QList<int>{C_LOCAL} << 0;
|
||||
QTest::newRow("lambda call without arguments (non-const var)") << 889 << 5 << 889 << 12
|
||||
<< QList<int>{C_LOCAL} << 0;
|
||||
QTest::newRow("non-const operator()") << 898 << 5 << 898 << 7
|
||||
<< QList<int>{C_LOCAL} << 0;
|
||||
QTest::newRow("const operator()") << 903 << 5 << 903 << 7
|
||||
<< QList<int>{C_LOCAL} << 0;
|
||||
}
|
||||
|
||||
void ClangdTestHighlighting::test()
|
||||
|
||||
@@ -880,3 +880,25 @@ void constMemberAsFunctionArg()
|
||||
#if 0
|
||||
#define BAR
|
||||
# endif
|
||||
|
||||
void lambdaCall()
|
||||
{
|
||||
const auto lambda1 = [] {};
|
||||
lambda1();
|
||||
auto lambda2 = [] {};
|
||||
lambda2();
|
||||
}
|
||||
|
||||
void callOperators()
|
||||
{
|
||||
struct Callable1 {
|
||||
void operator()() {};
|
||||
};
|
||||
Callable1 c1;
|
||||
c1();
|
||||
struct Callable2 {
|
||||
void operator()() const {};
|
||||
};
|
||||
Callable2 c2;
|
||||
c2();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user