diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index fd1b9b87472..f7a55a099a5 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -2404,16 +2404,37 @@ static void semanticHighlighter(QFutureInterface &future, return true; if (token.type != "variable" && token.type != "property" && token.type != "parameter") return false; - const QList path = getAstPath(ast, tokenRange(token)); + const Range range = tokenRange(token); + const QList path = getAstPath(ast, range); if (path.size() < 2) return false; if (path.last().hasConstType()) return false; for (auto it = path.rbegin() + 1; it != path.rend(); ++it) { if (it->kind() == "Call" || it->kind() == "CXXConstruct" - || it->kind() == "MemberInitializer" || it->kind() == "CXXOperatorCall") { + || it->kind() == "MemberInitializer") { return true; } + + // The token should get marked for e.g. lambdas, but not for assignment operators, + // where the user sees that it's being written. + if (it->kind() == "CXXOperatorCall") { + const QList children = it->children().value_or(QList()); + if (children.size() < 2) + return false; + if (!children.last().range().contains(range)) + return false; + QList firstChildTree{children.first()}; + while (!firstChildTree.isEmpty()) { + const AstNode n = firstChildTree.takeFirst(); + const QString detail = n.detail().value_or(QString()); + if (detail.startsWith("operator")) + return !detail.contains('='); + firstChildTree << n.children().value_or(QList()); + } + return true; + } + if (it->kind().endsWith("Cast") && it->hasConstType()) return false; if (it->kind() == "Member" && it->arcanaContains("(") diff --git a/src/plugins/clangcodemodel/test/clangdtests.cpp b/src/plugins/clangcodemodel/test/clangdtests.cpp index 22fd7a20c66..927728d8754 100644 --- a/src/plugins/clangcodemodel/test/clangdtests.cpp +++ b/src/plugins/clangcodemodel/test/clangdtests.cpp @@ -1040,7 +1040,9 @@ void ClangdTestHighlighting::test_data() << QList{C_PARAMETER, C_OUTPUT_ARGUMENT} << 0; QTest::newRow("typedef as underlying type in enum declaration") << 424 << 21 << 424 << 39 << QList{C_TYPE} << 0; - QTest::newRow("argument to user-defined subscript operator") << 434 << 12 << 434 << 17 + QTest::newRow("argument 1 to user-defined subscript operator") << 434 << 5 << 434 << 11 + << QList{C_PARAMETER} << 0; + QTest::newRow("argument 2 to user-defined subscript operator") << 434 << 12 << 434 << 17 << QList{C_PARAMETER, C_OUTPUT_ARGUMENT} << 0; QTest::newRow("partial class template specialization") << 553 << 25 << 553 << 28 << QList{C_TYPE, C_DECLARATION} << 0; @@ -1246,6 +1248,7 @@ void ClangdTestHighlighting::test_data() << QList{C_LOCAL, C_OUTPUT_ARGUMENT} << 0; QTest::newRow("const argument to unnamed lambda") << 830 << 16 << 830 << 19 << QList{C_LOCAL} << 0; + QTest::newRow("simple assignment") << 835 << 5 << 835 << 6 << QList{C_LOCAL} << 0; } void ClangdTestHighlighting::test() diff --git a/src/plugins/clangcodemodel/test/data/highlighting/highlighting.cpp b/src/plugins/clangcodemodel/test/data/highlighting/highlighting.cpp index 6e0ed1c8ec8..652d9540c80 100644 --- a/src/plugins/clangcodemodel/test/data/highlighting/highlighting.cpp +++ b/src/plugins/clangcodemodel/test/data/highlighting/highlighting.cpp @@ -829,3 +829,8 @@ void lambdaArgTest() [](int &) {}(val); [](int) {}(val); } + +void assignmentTest() { + struct S {} s; + s = {}; +}