diff --git a/clang-tools-extra/clangd/SemanticHighlighting.h b/clang-tools-extra/clangd/SemanticHighlighting.h --- a/clang-tools-extra/clangd/SemanticHighlighting.h +++ b/clang-tools-extra/clangd/SemanticHighlighting.h @@ -50,6 +50,7 @@ Primitive, Macro, Modifier, + Operator, // This one is different from the other kinds as it's a line style // rather than a token style. @@ -74,6 +75,7 @@ UsedAsMutableReference, UsedAsMutablePointer, ConstructorOrDestructor, + UserDefined, FunctionScope, ClassScope, diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -566,6 +566,71 @@ return true; } + bool VisitFunctionDecl(FunctionDecl *D) { + if (D->isOverloadedOperator()) { + const auto addOpDeclToken = [&](SourceLocation Loc) { + auto &Token = H.addToken(Loc, HighlightingKind::Operator) + .addModifier(HighlightingModifier::Declaration); + if (D->isThisDeclarationADefinition()) + Token.addModifier(HighlightingModifier::Definition); + }; + const auto Range = D->getNameInfo().getCXXOperatorNameRange(); + addOpDeclToken(Range.getBegin()); + const auto Kind = D->getOverloadedOperator(); + if (Kind == OO_Call || Kind == OO_Subscript) + addOpDeclToken(Range.getEnd()); + } + return true; + } + + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { + const auto addOpToken = [&](SourceLocation Loc) { + H.addToken(Loc, HighlightingKind::Operator) + .addModifier(HighlightingModifier::UserDefined); + }; + addOpToken(E->getOperatorLoc()); + const auto Kind = E->getOperator(); + if (Kind == OO_Call || Kind == OO_Subscript) { + if (auto *Callee = E->getCallee()) + addOpToken(Callee->getBeginLoc()); + } + return true; + } + + bool VisitUnaryOperator(UnaryOperator *Op) { + auto &Token = H.addToken(Op->getOperatorLoc(), HighlightingKind::Operator); + if (Op->getSubExpr()->isTypeDependent()) + Token.addModifier(HighlightingModifier::UserDefined); + return true; + } + + bool VisitBinaryOperator(BinaryOperator *Op) { + auto &Token = H.addToken(Op->getOperatorLoc(), HighlightingKind::Operator); + if (Op->getLHS()->isTypeDependent() || Op->getRHS()->isTypeDependent()) + Token.addModifier(HighlightingModifier::UserDefined); + return true; + } + + bool VisitConditionalOperator(ConditionalOperator *Op) { + H.addToken(Op->getQuestionLoc(), HighlightingKind::Operator); + H.addToken(Op->getColonLoc(), HighlightingKind::Operator); + return true; + } + + bool VisitCXXNewExpr(CXXNewExpr *E) { + auto &Token = H.addToken(E->getBeginLoc(), HighlightingKind::Operator); + if (isa(E->getOperatorNew())) + Token.addModifier(HighlightingModifier::UserDefined); + return true; + } + + bool VisitCXXDeleteExpr(CXXDeleteExpr *E) { + auto &Token = H.addToken(E->getBeginLoc(), HighlightingKind::Operator); + if (isa(E->getOperatorDelete())) + Token.addModifier(HighlightingModifier::UserDefined); + return true; + } + bool VisitCallExpr(CallExpr *E) { // Highlighting parameters passed by non-const reference does not really // make sense for literals... @@ -671,12 +736,20 @@ bool VisitCXXMemberCallExpr(CXXMemberCallExpr *CE) { // getMethodDecl can return nullptr with member pointers, e.g. // `(foo.*pointer_to_member_fun)(arg);` - if (isa_and_present(CE->getMethodDecl())) { - if (auto *ME = dyn_cast(CE->getCallee())) { - if (auto *TI = ME->getMemberNameInfo().getNamedTypeInfo()) { - H.addExtraModifier(TI->getTypeLoc().getBeginLoc(), - HighlightingModifier::ConstructorOrDestructor); + if (auto *D = CE->getMethodDecl()) { + if (isa(D)) { + if (auto *ME = dyn_cast(CE->getCallee())) { + if (auto *TI = ME->getMemberNameInfo().getNamedTypeInfo()) { + H.addExtraModifier(TI->getTypeLoc().getBeginLoc(), + HighlightingModifier::ConstructorOrDestructor); + } } + } else if (D->isOverloadedOperator()) { + if (auto *ME = dyn_cast(CE->getCallee())) + H.addToken( + ME->getMemberNameInfo().getCXXOperatorNameRange().getBegin(), + HighlightingKind::Operator) + .addModifier(HighlightingModifier::UserDefined); } } return true; @@ -998,6 +1071,8 @@ return OS << "Macro"; case HighlightingKind::Modifier: return OS << "Modifier"; + case HighlightingKind::Operator: + return OS << "Operator"; case HighlightingKind::InactiveCode: return OS << "InactiveCode"; } @@ -1134,6 +1209,8 @@ return "macro"; case HighlightingKind::Modifier: return "modifier"; + case HighlightingKind::Operator: + return "operator"; case HighlightingKind::InactiveCode: return "comment"; } @@ -1168,6 +1245,8 @@ return "usedAsMutablePointer"; // nonstandard case HighlightingModifier::ConstructorOrDestructor: return "constructorOrDestructor"; // nonstandard + case HighlightingModifier::UserDefined: + return "userDefined"; // nonstandard case HighlightingModifier::FunctionScope: return "functionScope"; // nonstandard case HighlightingModifier::ClassScope: diff --git a/clang-tools-extra/clangd/test/initialize-params.test b/clang-tools-extra/clangd/test/initialize-params.test --- a/clang-tools-extra/clangd/test/initialize-params.test +++ b/clang-tools-extra/clangd/test/initialize-params.test @@ -70,6 +70,7 @@ # CHECK-NEXT: "usedAsMutableReference", # CHECK-NEXT: "usedAsMutablePointer", # CHECK-NEXT: "constructorOrDestructor", +# CHECK-NEXT: "userDefined", # CHECK-NEXT: "functionScope", # CHECK-NEXT: "classScope", # CHECK-NEXT: "fileScope", diff --git a/clang-tools-extra/clangd/test/semantic-tokens.test b/clang-tools-extra/clangd/test/semantic-tokens.test --- a/clang-tools-extra/clangd/test/semantic-tokens.test +++ b/clang-tools-extra/clangd/test/semantic-tokens.test @@ -23,7 +23,7 @@ # CHECK-NEXT: 4, # CHECK-NEXT: 1, # CHECK-NEXT: 0, -# CHECK-NEXT: 65539 +# CHECK-NEXT: 131075 # CHECK-NEXT: ], # CHECK-NEXT: "resultId": "1" # CHECK-NEXT: } @@ -49,7 +49,7 @@ # CHECK-NEXT: 4, # CHECK-NEXT: 1, # CHECK-NEXT: 0, -# CHECK-NEXT: 65539 +# CHECK-NEXT: 131075 # CHECK-NEXT: ], # Inserted at position 1 # CHECK-NEXT: "deleteCount": 0, @@ -72,12 +72,12 @@ # CHECK-NEXT: 4, # CHECK-NEXT: 1, # CHECK-NEXT: 0, -# CHECK-NEXT: 65539, +# CHECK-NEXT: 131075, # CHECK-NEXT: 1, # CHECK-NEXT: 4, # CHECK-NEXT: 1, # CHECK-NEXT: 0, -# CHECK-NEXT: 65539 +# CHECK-NEXT: 131075 # CHECK-NEXT: ], # CHECK-NEXT: "resultId": "3" # CHECK-NEXT: } diff --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp --- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -113,9 +113,9 @@ void $Function_def[[foo]](int $Parameter_def[[A]], $Class[[AS]] $Parameter_def[[As]]) { $Primitive_deduced_defaultLibrary[[auto]] $LocalVariable_def[[VeryLongVariableName]] = 12312; $Class[[AS]] $LocalVariable_def[[AA]]; - $Primitive_deduced_defaultLibrary[[auto]] $LocalVariable_def[[L]] = $LocalVariable[[AA]].$Field[[SomeMember]] + $Parameter[[A]]; + $Primitive_deduced_defaultLibrary[[auto]] $LocalVariable_def[[L]] = $LocalVariable[[AA]].$Field[[SomeMember]] $Operator[[+]] $Parameter[[A]]; auto $LocalVariable_def[[FN]] = [ $LocalVariable[[AA]]](int $Parameter_def[[A]]) -> void {}; - $LocalVariable[[FN]](12312); + $LocalVariable[[FN]]$Operator_userDefined[[(]]12312$Operator_userDefined[[)]]; } )cpp", R"cpp( @@ -144,7 +144,7 @@ struct $Class_def[[B]] { $Class_decl_constrDestr[[B]](); ~$Class_decl_constrDestr[[B]](); - void operator<<($Class[[B]]); + void operator$Operator_decl[[<<]]($Class[[B]]); $Class[[AAA]] $Field_decl[[AA]]; }; $Class[[B]]::$Class_def_constrDestr[[B]]() {} @@ -203,20 +203,20 @@ static double $StaticField_decl_static[[S]]; static void $StaticMethod_def_static[[bar]]() {} void $Method_def[[foo]]() { - $Field[[B]] = 123; - this->$Field[[B]] = 156; + $Field[[B]] $Operator[[=]] 123; + this->$Field[[B]] $Operator[[=]] 156; this->$Method[[foo]](); $Method[[foo]](); $StaticMethod_static[[bar]](); - $StaticField_static[[S]] = 90.1; + $StaticField_static[[S]] $Operator[[=]] 90.1; } }; void $Function_def[[foo]]() { $Class[[A]] $LocalVariable_def[[AA]]; - $LocalVariable[[AA]].$Field[[B]] += 2; + $LocalVariable[[AA]].$Field[[B]] $Operator[[+=]] 2; $LocalVariable[[AA]].$Method[[foo]](); $LocalVariable[[AA]].$Field[[E]].$Field[[C]]; - $Class[[A]]::$StaticField_static[[S]] = 90; + $Class[[A]]::$StaticField_static[[S]] $Operator[[=]] 90; } )cpp", R"cpp( @@ -295,10 +295,10 @@ struct $Class_def[[B]] {}; struct $Class_def[[A]] { $Class[[B]] $Field_decl[[BB]]; - $Class[[A]] &operator=($Class[[A]] &&$Parameter_def[[O]]); + $Class[[A]] &operator$Operator_decl[[=]]($Class[[A]] &&$Parameter_def[[O]]); }; - $Class[[A]] &$Class[[A]]::operator=($Class[[A]] &&$Parameter_def[[O]]) = default; + $Class[[A]] &$Class[[A]]::operator$Operator_def[[=]]($Class[[A]] &&$Parameter_def[[O]]) = default; )cpp", R"cpp( enum $Enum_decl[[En]] { @@ -327,9 +327,9 @@ $Enum_deduced[[auto]] $Variable_def[[AE]] = $Enum[[E]]::$EnumConstant_readonly[[E]]; $Class_deduced[[auto]] $Variable_def[[AF]] = $Class[[Foo]](); $Class_deduced[[decltype]](auto) $Variable_def[[AF2]] = $Class[[Foo]](); - $Class_deduced[[auto]] *$Variable_def[[AFP]] = &$Variable[[AF]]; + $Class_deduced[[auto]] *$Variable_def[[AFP]] = $Operator[[&]]$Variable[[AF]]; $Enum_deduced[[auto]] &$Variable_def[[AER]] = $Variable[[AE]]; - $Primitive_deduced_defaultLibrary[[auto]] $Variable_def[[Form]] = 10.2 + 2 * 4; + $Primitive_deduced_defaultLibrary[[auto]] $Variable_def[[Form]] = 10.2 $Operator[[+]] 2 $Operator[[*]] 4; $Primitive_deduced_defaultLibrary[[decltype]]($Variable[[Form]]) $Variable_def[[F]] = 10; auto $Variable_def[[Fun]] = []()->void{}; )cpp", @@ -342,21 +342,21 @@ template class $Class_def[[IP]] { void $Method_def[[f]]() { - *$TemplateParameter_readonly[[U]] += 5; + $Operator[[*]]$TemplateParameter_readonly[[U]] $Operator[[+=]] 5; } }; template class $Class_def[[Foo]] { void $Method_def[[f]]() { for(int $LocalVariable_def[[I]] = 0; - $LocalVariable[[I]] < $TemplateParameter_readonly[[U]];) {} + $LocalVariable[[I]] $Operator[[<]] $TemplateParameter_readonly[[U]];) {} } }; $Class[[G]] $Variable_def[[L]]; void $Function_def[[f]]() { $Class[[Foo]]<123> $LocalVariable_def[[F]]; - $Class[[GP]]<&$Variable[[L]]> $LocalVariable_def[[LL]]; + $Class[[GP]]<$Operator[[&]]$Variable[[L]]> $LocalVariable_def[[LL]]; $Class[[GR]]<$Variable[[L]]> $LocalVariable_def[[LLL]]; } )cpp", @@ -366,7 +366,8 @@ struct $Class_def[[G]] { void $Method_def[[foo]]( $TemplateParameter[[T]] *$Parameter_def[[O]]) { - ($Parameter[[O]]->*$TemplateParameter_readonly[[method]])(10); + ($Parameter[[O]]$Operator_userDefined[[->*]]$TemplateParameter_readonly[[method]])(10); + } }; struct $Class_def[[F]] { @@ -375,14 +376,14 @@ template struct $Class_def[[A]] { void $Method_def[[f]]() { - (*$TemplateParameter_readonly[[Func]])(); + ($Operator[[*]]$TemplateParameter_readonly[[Func]])(); } }; void $Function_def[[foo]]() { $Class[[F]] $LocalVariable_def[[FF]]; - $Class[[G]]<$Class[[F]], &$Class[[F]]::$Method[[f]]> $LocalVariable_def[[GG]]; - $LocalVariable[[GG]].$Method[[foo]](&$LocalVariable_usedAsMutablePointer[[FF]]); + $Class[[G]]<$Class[[F]], $Operator[[&]]$Class[[F]]::$Method[[f]]> $LocalVariable_def[[GG]]; + $LocalVariable[[GG]].$Method[[foo]]($Operator[[&]]$LocalVariable_usedAsMutablePointer[[FF]]); $Class[[A]]<$Function[[foo]]> $LocalVariable_def[[AA]]; } )cpp", @@ -411,7 +412,7 @@ $Macro[[DEF_VAR_TYPE]]($Class[[A]], $LocalVariable_def[[AA]]); double $Macro[[SOME_NAME]]; int $Macro[[SOME_NAME_SET]]; - $LocalVariable[[variable]] = 20.1; + $LocalVariable[[variable]] $Operator[[=]] 20.1; $Macro[[MACRO_CONCAT]](var, 2, float); $Macro[[DEF_VAR_T]]($Class[[A]], $Macro[[CPY]]( $Macro[[CPY]]($LocalVariable_def[[Nested]])), @@ -436,8 +437,8 @@ int $Variable_def[[y]]; int $Function_decl[[f]](); void $Function_def[[foo]]() { - $Macro[[assert]]($Variable[[x]] != $Variable[[y]]); - $Macro[[assert]]($Variable[[x]] != $Function[[f]]()); + $Macro[[assert]]($Variable[[x]] $Operator[[!=]] $Variable[[y]]); + $Macro[[assert]]($Variable[[x]] $Operator[[!=]] $Function[[f]]()); } )cpp", // highlighting all macro references @@ -467,7 +468,7 @@ auto [$LocalVariable_decl[[G1]], $LocalVariable_decl[[G2]]] = $Variable[[Global]]; $Class_deduced[[auto]] [$LocalVariable_decl[[P1]], $LocalVariable_decl[[P2]]] = $Parameter[[P]]; // Highlights references to BindingDecls. - $LocalVariable[[B1]]++; + $LocalVariable[[B1]]$Operator[[++]]; } )cpp", R"cpp( @@ -724,9 +725,9 @@ return 0; } - (int)$Method_def[[doSomething]] { - $Class[[Foo]].$Field_static[[sharedInstance]].$Field[[someProperty]] = 1; - self.$Field[[someProperty]] = self.$Field[[someProperty]] + self.$Field[[otherMethod]] + 1; - self->$Field[[_someProperty]] = $Field[[_someProperty]] + 1; + $Class[[Foo]].$Field_static[[sharedInstance]].$Field[[someProperty]] $Operator[[=]] 1; + self.$Field[[someProperty]] $Operator[[=]] self.$Field[[someProperty]] $Operator[[+]] self.$Field[[otherMethod]] $Operator[[+]] 1; + self->$Field[[_someProperty]] $Operator[[=]] $Field[[_someProperty]] $Operator[[+]] 1; } @end )cpp", @@ -747,11 +748,11 @@ // Modifier for variables passed as non-const references R"cpp( struct $Class_def[[ClassWithOp]] { - void operator()(int); - void operator()(int, int &); - void operator()(int, int, const int &); - int &operator[](int &); - int operator[](int) const; + void operator$Operator_decl[[(]]$Operator_decl[[)]](int); + void operator$Operator_decl[[(]]$Operator_decl[[)]](int, int &); + void operator$Operator_decl[[(]]$Operator_decl[[)]](int, int, const int &); + int &operator$Operator_decl[[[]]$Operator_decl[[]]](int &); + int operator$Operator_decl[[[]]$Operator_decl[[]]](int) const; }; struct $Class_def[[ClassWithStaticMember]] { static inline int $StaticField_def_static[[j]] = 0; @@ -791,16 +792,16 @@ $LocalVariable_usedAsMutablePointer[[array]], $LocalVariable_usedAsMutableReference[[array]], $LocalVariable[[array]] ); - [](int){}($LocalVariable[[val]]); - [](int&){}($LocalVariable_usedAsMutableReference[[val]]); - [](const int&){}($LocalVariable[[val]]); + [](int){}$Operator_userDefined[[(]]$LocalVariable[[val]]$Operator_userDefined[[)]]; + [](int&){}$Operator_userDefined[[(]]$LocalVariable_usedAsMutableReference[[val]]$Operator_userDefined[[)]]; + [](const int&){}$Operator_userDefined[[(]]$LocalVariable[[val]]$Operator_userDefined[[)]]; $Class[[ClassWithOp]] $LocalVariable_def[[c]]; const $Class[[ClassWithOp]] $LocalVariable_def_readonly[[c2]]; - $LocalVariable[[c]]($LocalVariable[[val]]); - $LocalVariable[[c]](0, $LocalVariable_usedAsMutableReference[[val]]); - $LocalVariable[[c]](0, 0, $LocalVariable[[val]]); - $LocalVariable[[c]][$LocalVariable_usedAsMutableReference[[val]]]; - $LocalVariable_readonly[[c2]][$LocalVariable[[val]]]; + $LocalVariable[[c]]$Operator_userDefined[[(]]$LocalVariable[[val]]$Operator_userDefined[[)]]; + $LocalVariable[[c]]$Operator_userDefined[[(]]0, $LocalVariable_usedAsMutableReference[[val]]$Operator_userDefined[[)]]; + $LocalVariable[[c]]$Operator_userDefined[[(]]0, 0, $LocalVariable[[val]]$Operator_userDefined[[)]]; + $LocalVariable[[c]]$Operator_userDefined[[[]]$LocalVariable_usedAsMutableReference[[val]]$Operator_userDefined[[]]]; + $LocalVariable_readonly[[c2]]$Operator_userDefined[[[]]$LocalVariable[[val]]$Operator_userDefined[[]]]; } struct $Class_def[[S]] { $Class_def_constrDestr[[S]](int&) { @@ -824,7 +825,7 @@ void $Function_def[[foo]]() { int $LocalVariable_def[[a]], $LocalVariable_def[[b]]; [ $LocalVariable_def[[c]] = $LocalVariable[[a]], - $LocalVariable_def[[d]]($LocalVariable[[b]]) ]() {}(); + $LocalVariable_def[[d]]($LocalVariable[[b]]) ]() {}$Operator_userDefined[[(]]$Operator_userDefined[[)]]; } )cpp", // Enum base specifier @@ -877,8 +878,8 @@ const $TemplateParameter[[auto]] $Parameter_def_readonly[[auto_type]], const int $Parameter_def_readonly[[explicit_type]]) { return $Parameter_readonly[[template_type]] - + $Parameter_readonly[[auto_type]] - + $Parameter_readonly[[explicit_type]]; + $Operator_userDefined[[+]] $Parameter_readonly[[auto_type]] + $Operator_userDefined[[+]] $Parameter_readonly[[explicit_type]]; } )cpp", // Explicit template specialization @@ -894,6 +895,33 @@ template <> int $Variable_def[[x]] = (int)sizeof($Class[[Base]]); )cpp", + // operator calls in template + R"cpp( + template class $Class_def[[C]] { + bool $Method_def[[compare]]($TemplateParameter[[T]] $Parameter_def[[t1]], $TemplateParameter[[T]] $Parameter_def[[t2]]) { return $Parameter[[t1]] $Operator_userDefined[[==]] $Parameter[[t2]]; } + $TemplateParameter[[T]] $Method_def[[deref]]($TemplateParameter[[T]] *$Parameter_def[[t]]) { return $Operator_userDefined[[*]]$Parameter[[t]]; } + }; + )cpp", + // new and delete + R"cpp( + struct $Class_def[[S]] { int *$Field_decl[[a]]; }; + void $Function_def[[f]]() { + $Class[[S]] *$LocalVariable_def[[s]] = $Operator[[new]] $Class[[S]]; + $LocalVariable[[s]]->$Field[[a]] $Operator[[=]] $Operator[[new]] int[10]; + $Operator[[delete]][] $LocalVariable[[s]]->$Field[[a]]; + $Operator[[delete]] $LocalVariable[[s]]; + } + )cpp", + // explicit operator invocation + R"cpp( + struct $Class_def[[S]] { + $Class[[S]] operator$Operator_decl[[+]](const $Class[[S]] &$Parameter_def_readonly[[other]]); + }; + void $Function_def[[f]]() { + $Class[[S]] $LocalVariable_def[[s]]; + $Class[[S]] $LocalVariable_def[[s2]] = $LocalVariable[[s]].operator$Operator_userDefined[[+]]($LocalVariable[[s]]); + } + )cpp", // no crash R"cpp( struct $Class_def[[Foo]] { @@ -901,8 +929,8 @@ }; void $Function_def[[s]]($Class[[Foo]] $Parameter_def[[f]]) { - auto $LocalVariable_def[[k]] = &$Class[[Foo]]::$Method[[foo]]; - ($Parameter[[f]].*$LocalVariable[[k]])(); // no crash on VisitCXXMemberCallExpr + auto $LocalVariable_def[[k]] = $Operator[[&]]$Class[[Foo]]::$Method[[foo]]; + ($Parameter[[f]]$Operator[[.*]]$LocalVariable[[k]])(); // no crash on VisitCXXMemberCallExpr } )cpp"}; for (const auto &TestCase : TestCases) @@ -942,7 +970,7 @@ @end int $Function_def[[somethingUsingSystemSymbols]]() { $Class_defaultLibrary[[SYSObject]] *$LocalVariable_def[[obj]] = [$Class_defaultLibrary[[SYSObject]] $StaticMethod_static_defaultLibrary[[new]]]; - return $LocalVariable[[obj]].$Field_defaultLibrary[[value]] + $LocalVariable[[obj]].$Field_readonly[[user_property]]; + return $LocalVariable[[obj]].$Field_defaultLibrary[[value]] $Operator[[+]] $LocalVariable[[obj]].$Field_readonly[[user_property]]; } )cpp", {{"SystemSDK/SYSObject.h", R"cpp(