17#include "clang/AST/ASTContext.h"
18#include "clang/AST/Decl.h"
19#include "clang/AST/DeclCXX.h"
20#include "clang/AST/DeclObjC.h"
21#include "clang/AST/DeclTemplate.h"
22#include "clang/AST/DeclarationName.h"
23#include "clang/AST/ExprCXX.h"
24#include "clang/AST/RecursiveASTVisitor.h"
25#include "clang/AST/Type.h"
26#include "clang/AST/TypeLoc.h"
27#include "clang/Basic/LangOptions.h"
28#include "clang/Basic/SourceLocation.h"
29#include "clang/Basic/SourceManager.h"
30#include "clang/Tooling/Syntax/Tokens.h"
31#include "llvm/ADT/STLExtras.h"
32#include "llvm/ADT/StringRef.h"
33#include "llvm/Support/Casting.h"
34#include "llvm/Support/Error.h"
43llvm::Expected<Position> endOfLine(llvm::StringRef
Code,
int Line) {
46 return StartOfLine.takeError();
47 StringRef LineText =
Code.drop_front(*StartOfLine).take_until([](
char C) {
55bool canHighlightName(DeclarationName
Name) {
56 switch (
Name.getNameKind()) {
57 case DeclarationName::Identifier: {
58 auto *II =
Name.getAsIdentifierInfo();
59 return II && !II->getName().empty();
61 case DeclarationName::CXXConstructorName:
62 case DeclarationName::CXXDestructorName:
64 case DeclarationName::ObjCZeroArgSelector:
65 case DeclarationName::ObjCOneArgSelector:
66 case DeclarationName::ObjCMultiArgSelector:
70 case DeclarationName::CXXConversionFunctionName:
71 case DeclarationName::CXXOperatorName:
72 case DeclarationName::CXXDeductionGuideName:
73 case DeclarationName::CXXLiteralOperatorName:
74 case DeclarationName::CXXUsingDirective:
77 llvm_unreachable(
"invalid name kind");
80bool isUniqueDefinition(
const NamedDecl *
Decl) {
81 if (
auto *Func = dyn_cast<FunctionDecl>(
Decl))
82 return Func->isThisDeclarationADefinition();
83 if (
auto *Klass = dyn_cast<CXXRecordDecl>(
Decl))
84 return Klass->isThisDeclarationADefinition();
85 if (
auto *Iface = dyn_cast<ObjCInterfaceDecl>(
Decl))
86 return Iface->isThisDeclarationADefinition();
87 if (
auto *Proto = dyn_cast<ObjCProtocolDecl>(
Decl))
88 return Proto->isThisDeclarationADefinition();
89 if (
auto *Var = dyn_cast<VarDecl>(
Decl))
90 return Var->isThisDeclarationADefinition();
91 return isa<TemplateTypeParmDecl>(
Decl) ||
92 isa<NonTypeTemplateParmDecl>(
Decl) ||
93 isa<TemplateTemplateParmDecl>(
Decl) || isa<ObjCCategoryDecl>(
Decl) ||
94 isa<ObjCImplDecl>(
Decl);
97std::optional<HighlightingKind> kindForType(
const Type *TP,
98 const HeuristicResolver *Resolver);
99std::optional<HighlightingKind> kindForDecl(
const NamedDecl *D,
100 const HeuristicResolver *Resolver) {
101 if (
auto *USD = dyn_cast<UsingShadowDecl>(D)) {
102 if (
auto *Target = USD->getTargetDecl())
105 if (
auto *TD = dyn_cast<TemplateDecl>(D)) {
106 if (
auto *Templated = TD->getTemplatedDecl())
109 if (
auto *TD = dyn_cast<TypedefNameDecl>(D)) {
112 kindForType(TD->getUnderlyingType().getTypePtrOrNull(), Resolver))
120 if (
auto *RD = llvm::dyn_cast<RecordDecl>(D)) {
126 if (isa<ClassTemplateDecl, RecordDecl, CXXConstructorDecl, ObjCInterfaceDecl,
127 ObjCImplementationDecl>(D))
129 if (isa<ObjCProtocolDecl>(D))
131 if (isa<ObjCCategoryDecl, ObjCCategoryImplDecl>(D))
133 if (
auto *MD = dyn_cast<CXXMethodDecl>(D))
136 if (
auto *OMD = dyn_cast<ObjCMethodDecl>(D))
139 if (isa<FieldDecl, ObjCPropertyDecl>(D))
141 if (isa<EnumDecl>(D))
143 if (isa<EnumConstantDecl>(D))
145 if (isa<ParmVarDecl>(D))
147 if (
auto *VD = dyn_cast<VarDecl>(D)) {
148 if (isa<ImplicitParamDecl>(VD))
150 return VD->isStaticDataMember()
155 if (
const auto *BD = dyn_cast<BindingDecl>(D))
156 return BD->getDeclContext()->isFunctionOrMethod()
159 if (isa<FunctionDecl>(D))
161 if (isa<NamespaceDecl>(D) || isa<NamespaceAliasDecl>(D) ||
162 isa<UsingDirectiveDecl>(D))
164 if (isa<TemplateTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
165 isa<NonTypeTemplateParmDecl>(D))
167 if (isa<ConceptDecl>(D))
169 if (isa<LabelDecl>(D))
171 if (
const auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(D)) {
173 if (!Targets.empty() && Targets[0] != UUVD) {
174 return kindForDecl(Targets[0], Resolver);
180std::optional<HighlightingKind> kindForType(
const Type *TP,
181 const HeuristicResolver *Resolver) {
184 if (TP->isBuiltinType())
186 if (
auto *TD = dyn_cast<TemplateTypeParmType>(TP))
187 return kindForDecl(TD->getDecl(), Resolver);
188 if (isa<ObjCObjectPointerType>(TP))
190 if (
auto *TD = TP->getAsTagDecl())
191 return kindForDecl(TD, Resolver);
196bool isConst(QualType T) {
199 T = T.getNonReferenceType();
200 if (T.isConstQualified())
202 if (
const auto *AT = T->getAsArrayTypeUnsafe())
203 return isConst(AT->getElementType());
204 if (isConst(T->getPointeeType()))
212bool isConst(
const Decl *D) {
213 if (llvm::isa<EnumConstantDecl>(D) || llvm::isa<NonTypeTemplateParmDecl>(D))
215 if (llvm::isa<FieldDecl>(D) || llvm::isa<VarDecl>(D) ||
216 llvm::isa<MSPropertyDecl>(D) || llvm::isa<BindingDecl>(D)) {
217 if (isConst(llvm::cast<ValueDecl>(D)->getType()))
220 if (
const auto *OCPD = llvm::dyn_cast<ObjCPropertyDecl>(D)) {
221 if (OCPD->isReadOnly())
224 if (
const auto *MPD = llvm::dyn_cast<MSPropertyDecl>(D)) {
225 if (!MPD->hasSetter())
228 if (
const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D)) {
254bool isStatic(
const Decl *D) {
255 if (
const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
256 return CMD->isStatic();
257 if (
const VarDecl *VD = llvm::dyn_cast<VarDecl>(D))
258 return VD->isStaticDataMember() || VD->isStaticLocal();
259 if (
const auto *OPD = llvm::dyn_cast<ObjCPropertyDecl>(D))
260 return OPD->isClassProperty();
261 if (
const auto *OMD = llvm::dyn_cast<ObjCMethodDecl>(D))
262 return OMD->isClassMethod();
266bool isAbstract(
const Decl *D) {
267 if (
const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
268 return CMD->isPure();
269 if (
const auto *CRD = llvm::dyn_cast<CXXRecordDecl>(D))
270 return CRD->hasDefinition() && CRD->isAbstract();
274bool isVirtual(
const Decl *D) {
275 if (
const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
276 return CMD->isVirtual();
280bool isDependent(
const Decl *D) {
281 if (isa<UnresolvedUsingValueDecl>(D))
289bool isDefaultLibrary(
const Decl *D) {
290 SourceLocation
Loc =
D->getLocation();
293 return D->getASTContext().getSourceManager().isInSystemHeader(
Loc);
296bool isDefaultLibrary(
const Type *T) {
302 if (
auto *TD = dyn_cast<TemplateTypeParmType>(
Underlying))
303 return isDefaultLibrary(TD->getDecl());
305 return isDefaultLibrary(TD);
312SourceLocation getHighlightableSpellingToken(SourceLocation L,
313 const SourceManager &SM) {
315 return SM.isWrittenInMainFile(L) ? L : SourceLocation{};
317 if (!SM.isMacroArgExpansion(L))
320 return getHighlightableSpellingToken(SM.getImmediateSpellingLoc(L), SM);
323unsigned evaluateHighlightPriority(
const HighlightingToken &Tok) {
324 enum HighlightPriority { Dependent = 0, Resolved = 1 };
348std::optional<HighlightingToken> resolveConflict(
const HighlightingToken &A,
349 const HighlightingToken &B) {
350 unsigned Priority1 = evaluateHighlightPriority(A);
351 unsigned Priority2 = evaluateHighlightPriority(B);
352 if (Priority1 == Priority2 &&
A.Kind !=
B.Kind)
354 auto Result = Priority1 > Priority2 ?
A :
B;
355 Result.Modifiers =
A.Modifiers |
B.Modifiers;
358std::optional<HighlightingToken>
359resolveConflict(ArrayRef<HighlightingToken> Tokens) {
360 if (Tokens.size() == 1)
363 assert(Tokens.size() >= 2);
364 std::optional<HighlightingToken> Winner =
365 resolveConflict(Tokens[0], Tokens[1]);
366 for (
size_t I = 2; Winner && I < Tokens.size(); ++I)
367 Winner = resolveConflict(*Winner, Tokens[I]);
373class HighlightingFilter {
375 HighlightingFilter() {
376 for (
auto &Active : ActiveKindLookup)
379 ActiveModifiersMask = ~0;
383 ActiveKindLookup[
static_cast<size_t>(
Kind)] =
false;
387 ActiveModifiersMask &= ~(1 <<
static_cast<uint32_t
>(
Modifier));
391 return ActiveKindLookup[
static_cast<size_t>(
Kind)];
394 uint32_t maskModifiers(uint32_t Modifiers)
const {
395 return Modifiers & ActiveModifiersMask;
398 static HighlightingFilter fromCurrentConfig() {
400 HighlightingFilter Filter;
401 for (
const auto &
Kind :
C.SemanticTokens.DisabledKinds)
403 Filter.disableKind(*
K);
404 for (
const auto &
Modifier :
C.SemanticTokens.DisabledModifiers)
406 Filter.disableModifier(*
M);
413 uint32_t ActiveModifiersMask;
417class HighlightingsBuilder {
419 HighlightingsBuilder(
const ParsedAST &
AST,
const HighlightingFilter &Filter)
420 : TB(
AST.getTokens()), SourceMgr(
AST.getSourceManager()),
421 LangOpts(
AST.getLangOpts()), Filter(Filter) {}
424 auto Range = getRangeForSourceLocation(
Loc);
426 return InvalidHighlightingToken;
428 return addToken(*Range,
Kind);
433 void addAngleBracketTokens(SourceLocation LLoc, SourceLocation RLoc) {
434 if (!LLoc.isValid() || !RLoc.isValid())
437 auto LRange = getRangeForSourceLocation(LLoc);
443 RLoc = SourceMgr.getFileLoc(RLoc);
445 RLoc = getHighlightableSpellingToken(RLoc, SourceMgr);
449 const auto *RTok = TB.spelledTokenAt(RLoc);
454 if (!RTok || RTok->kind() == tok::greatergreater) {
463 if (RTok->kind() == tok::greater) {
464 if (
auto RRange = getRangeForSourceLocation(RLoc)) {
473 if (!Filter.isHighlightKindActive(
Kind))
474 return InvalidHighlightingToken;
476 HighlightingToken HT;
479 Tokens.push_back(std::move(HT));
480 return Tokens.back();
484 if (
auto Range = getRangeForSourceLocation(
Loc))
488 std::vector<HighlightingToken> collect(ParsedAST &
AST) && {
492 auto Last = std::unique(Tokens.begin(), Tokens.end());
493 Tokens.erase(Last, Tokens.end());
498 std::vector<HighlightingToken> NonConflicting;
499 NonConflicting.reserve(Tokens.size());
500 for (ArrayRef<HighlightingToken> TokRef = Tokens; !TokRef.empty();) {
501 ArrayRef<HighlightingToken> Conflicting =
502 TokRef.take_while([&](
const HighlightingToken &T) {
505 return T.R == TokRef.front().R;
507 if (
auto Resolved = resolveConflict(Conflicting)) {
509 auto Modifiers = ExtraModifiers.find(Resolved->R);
510 if (Modifiers != ExtraModifiers.end()) {
512 Resolved->addModifier(Mod);
516 Resolved->Modifiers = Filter.maskModifiers(Resolved->Modifiers);
517 NonConflicting.push_back(*Resolved);
521 TokRef = TokRef.drop_front(Conflicting.size());
525 return NonConflicting;
527 const auto &SM =
AST.getSourceManager();
528 StringRef MainCode = SM.getBufferOrFake(SM.getMainFileID()).getBuffer();
531 std::vector<HighlightingToken> WithInactiveLines;
533 llvm::sort(SortedInactiveRegions);
534 auto It = NonConflicting.begin();
535 for (
const Range &R : SortedInactiveRegions) {
538 assert(R.start.line <= R.end.line);
539 for (
int Line = R.start.line; Line <= R.end.line; ++Line) {
541 for (; It != NonConflicting.end() && It->R.start.line < Line; ++It)
542 WithInactiveLines.push_back(std::move(*It));
544 auto EndOfLine = endOfLine(MainCode, Line);
546 HighlightingToken HT;
547 WithInactiveLines.emplace_back();
549 WithInactiveLines.back().R.start.line =
Line;
550 WithInactiveLines.back().R.end = *EndOfLine;
552 elog(
"Failed to determine end of line: {0}", EndOfLine.takeError());
560 while (It != NonConflicting.end() && It->R.start.line == Line)
565 for (; It != NonConflicting.end(); ++It)
566 WithInactiveLines.push_back(std::move(*It));
567 return WithInactiveLines;
570 const HeuristicResolver *getResolver()
const {
return Resolver; }
573 std::optional<Range> getRangeForSourceLocation(SourceLocation
Loc) {
574 Loc = getHighlightableSpellingToken(
Loc, SourceMgr);
579 const auto *Tok = TB.spelledTokenAt(
Loc);
583 Tok->range(SourceMgr).toCharRange(SourceMgr));
586 const syntax::TokenBuffer &TB;
587 const SourceManager &SourceMgr;
588 const LangOptions &LangOpts;
589 HighlightingFilter Filter;
590 std::vector<HighlightingToken> Tokens;
591 std::map<Range, llvm::SmallVector<HighlightingModifier, 1>> ExtraModifiers;
592 const HeuristicResolver *Resolver =
nullptr;
594 HighlightingToken InvalidHighlightingToken;
597std::optional<HighlightingModifier> scopeModifier(
const NamedDecl *D) {
598 const DeclContext *DC =
D->getDeclContext();
600 if (
auto *R = dyn_cast_or_null<RecordDecl>(D))
601 if (R->isInjectedClassName())
602 DC = DC->getParent();
604 if (llvm::isa<FieldDecl>(D))
605 if (
const auto *RD = llvm::dyn_cast<RecordDecl>(DC))
609 for (; !DC->isFileContext(); DC = DC->getParent()) {
610 if (DC->isFunctionOrMethod())
617 if (DC->isTranslationUnit() &&
D->isTemplateParameter())
620 if (
D->getLinkageInternal() < ExternalLinkage)
625std::optional<HighlightingModifier> scopeModifier(
const Type *T) {
628 if (T->isBuiltinType())
630 if (
auto *TD = dyn_cast<TemplateTypeParmType>(T))
631 return scopeModifier(TD->getDecl());
632 if (
auto *TD = T->getAsTagDecl())
633 return scopeModifier(TD);
639class CollectExtraHighlightings
644 CollectExtraHighlightings(HighlightingsBuilder &H) : H(H) {}
646 bool VisitCXXConstructExpr(CXXConstructExpr *
E) {
647 highlightMutableReferenceArguments(
E->getConstructor(),
648 {E->getArgs(), E->getNumArgs()});
653 bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
654 if (Init->isMemberInitializer())
655 if (
auto *Member = Init->getMember())
656 highlightMutableReferenceArgument(Member->getType(), Init->getInit());
657 return Base::TraverseConstructorInitializer(Init);
660 bool TraverseTypeConstraint(
const TypeConstraint *
C) {
661 if (
auto *
Args =
C->getTemplateArgsAsWritten())
662 H.addAngleBracketTokens(
Args->getLAngleLoc(),
Args->getRAngleLoc());
663 return Base::TraverseTypeConstraint(
C);
666 bool VisitPredefinedExpr(PredefinedExpr *
E) {
674 bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *
E) {
675 if (
auto *
Args =
E->getTemplateArgsAsWritten())
676 H.addAngleBracketTokens(
Args->getLAngleLoc(),
Args->getRAngleLoc());
680 bool VisitTemplateDecl(TemplateDecl *D) {
681 if (
auto *TPL =
D->getTemplateParameters())
682 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
686 bool VisitTagDecl(TagDecl *D) {
687 for (
unsigned i = 0; i <
D->getNumTemplateParameterLists(); ++i) {
688 if (
auto *TPL =
D->getTemplateParameterList(i))
689 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
694 bool VisitClassTemplatePartialSpecializationDecl(
695 ClassTemplatePartialSpecializationDecl *D) {
696 if (
auto *TPL =
D->getTemplateParameters())
697 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
698 if (
auto *
Args =
D->getTemplateArgsAsWritten())
699 H.addAngleBracketTokens(
Args->getLAngleLoc(),
Args->getRAngleLoc());
703 bool VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) {
704 if (
auto *
Args =
D->getTemplateArgsInfo())
705 H.addAngleBracketTokens(
Args->getLAngleLoc(),
Args->getRAngleLoc());
709 bool VisitVarTemplatePartialSpecializationDecl(
710 VarTemplatePartialSpecializationDecl *D) {
711 if (
auto *TPL =
D->getTemplateParameters())
712 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
713 if (
auto *
Args =
D->getTemplateArgsAsWritten())
714 H.addAngleBracketTokens(
Args->getLAngleLoc(),
Args->getRAngleLoc());
718 bool VisitClassScopeFunctionSpecializationDecl(
719 ClassScopeFunctionSpecializationDecl *D) {
720 if (
auto *
Args =
D->getTemplateArgsAsWritten())
721 H.addAngleBracketTokens(
Args->getLAngleLoc(),
Args->getRAngleLoc());
725 bool VisitDeclRefExpr(DeclRefExpr *
E) {
726 H.addAngleBracketTokens(
E->getLAngleLoc(),
E->getRAngleLoc());
729 bool VisitMemberExpr(MemberExpr *
E) {
730 H.addAngleBracketTokens(
E->getLAngleLoc(),
E->getRAngleLoc());
734 bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc L) {
735 H.addAngleBracketTokens(L.getLAngleLoc(), L.getRAngleLoc());
739 bool VisitFunctionDecl(FunctionDecl *D) {
740 if (
D->isOverloadedOperator()) {
741 const auto AddOpDeclToken = [&](SourceLocation
Loc) {
744 if (
D->isThisDeclarationADefinition())
747 const auto Range =
D->getNameInfo().getCXXOperatorNameRange();
748 AddOpDeclToken(
Range.getBegin());
749 const auto Kind =
D->getOverloadedOperator();
750 if (
Kind == OO_Call ||
Kind == OO_Subscript)
751 AddOpDeclToken(
Range.getEnd());
753 if (
auto *
Args =
D->getTemplateSpecializationArgsAsWritten())
754 H.addAngleBracketTokens(
Args->getLAngleLoc(),
Args->getRAngleLoc());
755 if (
auto *I =
D->getDependentSpecializationInfo())
756 H.addAngleBracketTokens(I->getLAngleLoc(), I->getRAngleLoc());
760 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *
E) {
761 const auto AddOpToken = [&](SourceLocation
Loc) {
765 AddOpToken(
E->getOperatorLoc());
766 const auto Kind =
E->getOperator();
767 if (
Kind == OO_Call ||
Kind == OO_Subscript) {
768 if (
auto *Callee =
E->getCallee())
769 AddOpToken(Callee->getBeginLoc());
774 bool VisitUnaryOperator(UnaryOperator *Op) {
776 if (Op->getSubExpr()->isTypeDependent())
781 bool VisitBinaryOperator(BinaryOperator *Op) {
783 if (Op->getLHS()->isTypeDependent() || Op->getRHS()->isTypeDependent())
788 bool VisitConditionalOperator(ConditionalOperator *Op) {
794 bool VisitCXXNewExpr(CXXNewExpr *
E) {
796 if (isa_and_present<CXXMethodDecl>(
E->getOperatorNew()))
801 bool VisitCXXDeleteExpr(CXXDeleteExpr *
E) {
803 if (isa_and_present<CXXMethodDecl>(
E->getOperatorDelete()))
808 bool VisitCXXNamedCastExpr(CXXNamedCastExpr *
E) {
809 const auto &
B =
E->getAngleBrackets();
810 H.addAngleBracketTokens(
B.getBegin(),
B.getEnd());
814 bool VisitCallExpr(CallExpr *
E) {
817 if (isa<UserDefinedLiteral>(
E))
822 llvm::ArrayRef<const Expr *>
Args = {
E->getArgs(),
E->getNumArgs()};
823 if (
auto *CallOp = dyn_cast<CXXOperatorCallExpr>(
E)) {
824 switch (CallOp->getOperator()) {
834 highlightMutableReferenceArguments(
835 dyn_cast_or_null<FunctionDecl>(
E->getCalleeDecl()),
Args);
840 void highlightMutableReferenceArgument(QualType T,
const Expr *Arg) {
847 bool IsRef = T->isLValueReferenceType();
848 bool IsPtr = T->isPointerType();
849 if ((!IsRef && !IsPtr) || T->getPointeeType().isConstQualified() ||
850 T->isDependentType()) {
854 std::optional<SourceLocation>
Location;
859 if (
auto *IC = dyn_cast<ImplicitCastExpr>(Arg))
860 Arg = IC->getSubExprAsWritten();
861 if (
auto *UO = dyn_cast<UnaryOperator>(Arg)) {
862 if (UO->getOpcode() == UO_AddrOf)
863 Arg = UO->getSubExpr();
865 if (
auto *DR = dyn_cast<DeclRefExpr>(Arg))
867 else if (
auto *
M = dyn_cast<MemberExpr>(Arg))
877 highlightMutableReferenceArguments(
const FunctionDecl *FD,
878 llvm::ArrayRef<const Expr *const>
Args) {
882 if (
auto *ProtoType = FD->getType()->getAs<FunctionProtoType>()) {
887 I < std::min(
size_t(ProtoType->getNumParams()),
Args.size()); ++I) {
888 highlightMutableReferenceArgument(ProtoType->getParamType(I),
Args[I]);
893 bool VisitDecltypeTypeLoc(DecltypeTypeLoc L) {
894 if (
auto K = kindForType(L.getTypePtr(), H.getResolver())) {
895 auto &Tok = H.addToken(L.getBeginLoc(), *
K)
897 if (
auto Mod = scopeModifier(L.getTypePtr()))
898 Tok.addModifier(*Mod);
899 if (isDefaultLibrary(L.getTypePtr()))
905 bool VisitCXXDestructorDecl(CXXDestructorDecl *D) {
906 if (
auto *TI =
D->getNameInfo().getNamedTypeInfo()) {
907 SourceLocation
Loc = TI->getTypeLoc().getBeginLoc();
910 if (
D->isThisDeclarationADefinition())
916 bool VisitCXXMemberCallExpr(CXXMemberCallExpr *
CE) {
919 if (
auto *D =
CE->getMethodDecl()) {
920 if (isa<CXXDestructorDecl>(D)) {
921 if (
auto *ME = dyn_cast<MemberExpr>(
CE->getCallee())) {
922 if (
auto *TI = ME->getMemberNameInfo().getNamedTypeInfo()) {
923 H.addExtraModifier(TI->getTypeLoc().getBeginLoc(),
927 }
else if (
D->isOverloadedOperator()) {
928 if (
auto *ME = dyn_cast<MemberExpr>(
CE->getCallee()))
930 ME->getMemberNameInfo().getCXXOperatorNameRange().getBegin(),
938 bool VisitDeclaratorDecl(DeclaratorDecl *D) {
939 for (
unsigned i = 0; i <
D->getNumTemplateParameterLists(); ++i) {
940 if (
auto *TPL =
D->getTemplateParameterList(i))
941 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
943 auto *AT =
D->getType()->getContainedAutoType();
947 kindForType(AT->getDeducedType().getTypePtrOrNull(), H.getResolver());
950 auto *TSI =
D->getTypeSourceInfo();
953 SourceLocation StartLoc =
954 TSI->getTypeLoc().getContainedAutoTypeLoc().getNameLoc();
959 if (StartLoc ==
D->getLocation())
964 const Type *
Deduced = AT->getDeducedType().getTypePtrOrNull();
965 if (
auto Mod = scopeModifier(
Deduced))
966 Tok.addModifier(*Mod);
974 void highlightObjCSelector(
const ArrayRef<SourceLocation> &Locs,
bool Decl,
978 for (SourceLocation Part : Locs) {
992 bool VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
993 llvm::SmallVector<SourceLocation> Locs;
994 OMD->getSelectorLocs(Locs);
995 highlightObjCSelector(Locs,
true,
996 OMD->isThisDeclarationADefinition(),
997 OMD->isClassMethod(), isDefaultLibrary(OMD));
1001 bool VisitObjCMessageExpr(ObjCMessageExpr *OME) {
1002 llvm::SmallVector<SourceLocation> Locs;
1003 OME->getSelectorLocs(Locs);
1005 if (ObjCMethodDecl *OMD = OME->getMethodDecl())
1007 highlightObjCSelector(Locs,
false,
false,
1016 void highlightObjCImplicitPropertyRef(
const ObjCMethodDecl *OMD,
1017 SourceLocation
Loc) {
1020 if (OMD->isClassMethod())
1022 if (isDefaultLibrary(OMD))
1026 bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *OPRE) {
1030 if (!OPRE->isImplicitProperty())
1036 if (OPRE->isMessagingGetter()) {
1037 highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertyGetter(),
1038 OPRE->getLocation());
1041 if (OPRE->isMessagingSetter()) {
1042 highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertySetter(),
1043 OPRE->getLocation());
1048 bool VisitOverloadExpr(OverloadExpr *
E) {
1049 H.addAngleBracketTokens(
E->getLAngleLoc(),
E->getRAngleLoc());
1050 if (!
E->decls().empty())
1054 if (llvm::isa<UnresolvedMemberExpr>(
E))
1060 bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *
E) {
1064 H.addAngleBracketTokens(
E->getLAngleLoc(),
E->getRAngleLoc());
1068 bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *
E) {
1072 H.addAngleBracketTokens(
E->getLAngleLoc(),
E->getRAngleLoc());
1076 bool VisitAttr(Attr *A) {
1077 switch (
A->getKind()) {
1078 case attr::Override:
1088 bool VisitDependentNameTypeLoc(DependentNameTypeLoc L) {
1095 bool VisitDependentTemplateSpecializationTypeLoc(
1096 DependentTemplateSpecializationTypeLoc L) {
1100 H.addAngleBracketTokens(L.getLAngleLoc(), L.getRAngleLoc());
1104 bool TraverseTemplateArgumentLoc(TemplateArgumentLoc L) {
1107 if (L.getArgument().getKind() != TemplateArgument::Template &&
1108 L.getArgument().getKind() != TemplateArgument::TemplateExpansion)
1109 return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
1111 TemplateName N = L.getArgument().getAsTemplateOrTemplatePattern();
1112 switch (N.getKind()) {
1113 case TemplateName::OverloadedTemplate:
1118 case TemplateName::DependentTemplate:
1119 case TemplateName::AssumedTemplate:
1123 case TemplateName::Template:
1124 case TemplateName::QualifiedTemplate:
1125 case TemplateName::SubstTemplateTemplateParm:
1126 case TemplateName::SubstTemplateTemplateParmPack:
1127 case TemplateName::UsingTemplate:
1131 return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
1139 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc Q) {
1140 if (NestedNameSpecifier *NNS = Q.getNestedNameSpecifier()) {
1141 if (NNS->getKind() == NestedNameSpecifier::Identifier)
1146 return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(Q);
1150 HighlightingsBuilder &H;
1154std::vector<HighlightingToken>
1156 auto &
C =
AST.getASTContext();
1157 HighlightingFilter Filter = HighlightingFilter::fromCurrentConfig();
1158 if (!IncludeInactiveRegionTokens)
1163 CollectExtraHighlightings(
Builder).TraverseAST(
C);
1169 if (!canHighlightName(Decl->getDeclName()))
1171 auto Kind = kindForDecl(Decl, AST.getHeuristicResolver());
1174 auto &Tok = Builder.addToken(R.NameLoc, *Kind);
1177 if (auto *TD = dyn_cast<TemplateDecl>(Decl)) {
1178 if (auto *Templated = TD->getTemplatedDecl())
1181 if (
auto Mod = scopeModifier(
Decl))
1182 Tok.addModifier(*Mod);
1187 if (isAbstract(
Decl))
1189 if (isVirtual(
Decl))
1191 if (isDependent(
Decl))
1193 if (isDefaultLibrary(
Decl))
1195 if (
Decl->isDeprecated())
1197 if (isa<CXXConstructorDecl>(
Decl))
1203 if (!isa<UnresolvedUsingValueDecl>(Decl))
1204 Tok.addModifier(HighlightingModifier::Declaration);
1205 if (isUniqueDefinition(Decl))
1206 Tok.addModifier(HighlightingModifier::Definition);
1210 AST.getHeuristicResolver());
1212 auto AddMacro = [&](
const MacroOccurrence &
M) {
1213 auto &T =
Builder.addToken(
M.toRange(
C.getSourceManager()),
1219 for (
const auto &SIDToRefs :
AST.getMacros().MacroRefs)
1220 for (
const auto &
M : SIDToRefs.second)
1222 for (
const auto &
M :
AST.getMacros().UnknownMacros)
1230 case HighlightingKind::Variable:
1231 return OS <<
"Variable";
1232 case HighlightingKind::LocalVariable:
1233 return OS <<
"LocalVariable";
1234 case HighlightingKind::Parameter:
1235 return OS <<
"Parameter";
1236 case HighlightingKind::Function:
1237 return OS <<
"Function";
1238 case HighlightingKind::Method:
1239 return OS <<
"Method";
1240 case HighlightingKind::StaticMethod:
1241 return OS <<
"StaticMethod";
1242 case HighlightingKind::Field:
1243 return OS <<
"Field";
1244 case HighlightingKind::StaticField:
1245 return OS <<
"StaticField";
1246 case HighlightingKind::Class:
1247 return OS <<
"Class";
1248 case HighlightingKind::Interface:
1249 return OS <<
"Interface";
1250 case HighlightingKind::Enum:
1251 return OS <<
"Enum";
1252 case HighlightingKind::EnumConstant:
1253 return OS <<
"EnumConstant";
1254 case HighlightingKind::Typedef:
1255 return OS <<
"Typedef";
1256 case HighlightingKind::Type:
1257 return OS <<
"Type";
1258 case HighlightingKind::Unknown:
1259 return OS <<
"Unknown";
1260 case HighlightingKind::Namespace:
1261 return OS <<
"Namespace";
1262 case HighlightingKind::TemplateParameter:
1263 return OS <<
"TemplateParameter";
1264 case HighlightingKind::Concept:
1265 return OS <<
"Concept";
1266 case HighlightingKind::Primitive:
1267 return OS <<
"Primitive";
1268 case HighlightingKind::Macro:
1269 return OS <<
"Macro";
1270 case HighlightingKind::Modifier:
1271 return OS <<
"Modifier";
1272 case HighlightingKind::Operator:
1273 return OS <<
"Operator";
1274 case HighlightingKind::Bracket:
1275 return OS <<
"Bracket";
1276 case HighlightingKind::Label:
1277 return OS <<
"Label";
1278 case HighlightingKind::InactiveCode:
1279 return OS <<
"InactiveCode";
1281 llvm_unreachable(
"invalid HighlightingKind");
1283std::optional<HighlightingKind>
1285 static llvm::StringMap<HighlightingKind> Lookup = {
1286 {
"Variable", HighlightingKind::Variable},
1287 {
"LocalVariable", HighlightingKind::LocalVariable},
1288 {
"Parameter", HighlightingKind::Parameter},
1289 {
"Function", HighlightingKind::Function},
1290 {
"Method", HighlightingKind::Method},
1291 {
"StaticMethod", HighlightingKind::StaticMethod},
1292 {
"Field", HighlightingKind::Field},
1293 {
"StaticField", HighlightingKind::StaticField},
1294 {
"Class", HighlightingKind::Class},
1295 {
"Interface", HighlightingKind::Interface},
1296 {
"Enum", HighlightingKind::Enum},
1297 {
"EnumConstant", HighlightingKind::EnumConstant},
1298 {
"Typedef", HighlightingKind::Typedef},
1299 {
"Type", HighlightingKind::Type},
1300 {
"Unknown", HighlightingKind::Unknown},
1301 {
"Namespace", HighlightingKind::Namespace},
1302 {
"TemplateParameter", HighlightingKind::TemplateParameter},
1303 {
"Concept", HighlightingKind::Concept},
1304 {
"Primitive", HighlightingKind::Primitive},
1305 {
"Macro", HighlightingKind::Macro},
1306 {
"Modifier", HighlightingKind::Modifier},
1307 {
"Operator", HighlightingKind::Operator},
1308 {
"Bracket", HighlightingKind::Bracket},
1309 {
"InactiveCode", HighlightingKind::InactiveCode},
1312 auto It = Lookup.find(
Name);
1313 return It != Lookup.end() ? std::make_optional(It->getValue()) : std::nullopt;
1317 case HighlightingModifier::Declaration:
1318 return OS <<
"decl";
1319 case HighlightingModifier::Definition:
1321 case HighlightingModifier::ConstructorOrDestructor:
1322 return OS <<
"constrDestr";
1327std::optional<HighlightingModifier>
1329 static llvm::StringMap<HighlightingModifier> Lookup = {
1330 {
"Declaration", HighlightingModifier::Declaration},
1331 {
"Definition", HighlightingModifier::Definition},
1332 {
"Deprecated", HighlightingModifier::Deprecated},
1333 {
"Deduced", HighlightingModifier::Deduced},
1334 {
"Readonly", HighlightingModifier::Readonly},
1335 {
"Static", HighlightingModifier::Static},
1336 {
"Abstract", HighlightingModifier::Abstract},
1337 {
"Virtual", HighlightingModifier::Virtual},
1338 {
"DependentName", HighlightingModifier::DependentName},
1339 {
"DefaultLibrary", HighlightingModifier::DefaultLibrary},
1340 {
"UsedAsMutableReference", HighlightingModifier::UsedAsMutableReference},
1341 {
"UsedAsMutablePointer", HighlightingModifier::UsedAsMutablePointer},
1342 {
"ConstructorOrDestructor",
1343 HighlightingModifier::ConstructorOrDestructor},
1344 {
"UserDefined", HighlightingModifier::UserDefined},
1345 {
"FunctionScope", HighlightingModifier::FunctionScope},
1346 {
"ClassScope", HighlightingModifier::ClassScope},
1347 {
"FileScope", HighlightingModifier::FileScope},
1348 {
"GlobalScope", HighlightingModifier::GlobalScope},
1351 auto It = Lookup.find(
Name);
1352 return It != Lookup.end() ? std::make_optional(It->getValue()) : std::nullopt;
1356 return std::tie(L.R, L.Kind, L.Modifiers) ==
1360 return std::tie(L.R, L.Kind, L.Modifiers) <
1364std::vector<SemanticToken>
1366 llvm::StringRef
Code) {
1367 assert(llvm::is_sorted(Tokens));
1368 std::vector<SemanticToken> Result;
1375 Result.emplace_back();
1379 assert(Tok.R.start.line >= Last->
R.
end.
line);
1380 Out->deltaLine = Tok.R.start.line - Last->
R.
end.
line;
1381 if (
Out->deltaLine == 0) {
1385 Out->deltaStart = Tok.R.start.character;
1388 Out->deltaLine = Tok.R.start.line;
1389 Out->deltaStart = Tok.R.start.character;
1391 Out->tokenType =
static_cast<unsigned>(Tok.Kind);
1392 Out->tokenModifiers = Tok.Modifiers;
1395 if (Tok.R.end.line == Tok.R.start.line) {
1396 Out->length = Tok.R.end.character - Tok.R.start.character;
1406 for (
int I = Tok.R.start.line; I < Tok.R.end.line; ++I) {
1407 auto LineEnd =
Code.find(
'\n', TokStartOffset);
1408 assert(LineEnd !=
Code.npos);
1409 Out->length = LineEnd - TokStartOffset;
1411 TokStartOffset = LineEnd + 1;
1412 Result.emplace_back();
1413 Out = &Result.back();
1414 *
Out = Result[Result.size() - 2];
1417 Out->deltaStart = 0;
1420 Out->length = Tok.R.end.character;
1433 case HighlightingKind::Variable:
1434 case HighlightingKind::LocalVariable:
1435 case HighlightingKind::StaticField:
1437 case HighlightingKind::Parameter:
1439 case HighlightingKind::Function:
1441 case HighlightingKind::Method:
1443 case HighlightingKind::StaticMethod:
1446 case HighlightingKind::Field:
1448 case HighlightingKind::Class:
1450 case HighlightingKind::Interface:
1452 case HighlightingKind::Enum:
1454 case HighlightingKind::EnumConstant:
1455 return "enumMember";
1456 case HighlightingKind::Typedef:
1457 case HighlightingKind::Type:
1459 case HighlightingKind::Unknown:
1461 case HighlightingKind::Namespace:
1463 case HighlightingKind::TemplateParameter:
1464 return "typeParameter";
1465 case HighlightingKind::Concept:
1467 case HighlightingKind::Primitive:
1469 case HighlightingKind::Macro:
1471 case HighlightingKind::Modifier:
1473 case HighlightingKind::Operator:
1475 case HighlightingKind::Bracket:
1477 case HighlightingKind::Label:
1479 case HighlightingKind::InactiveCode:
1482 llvm_unreachable(
"unhandled HighlightingKind");
1487 case HighlightingModifier::Declaration:
1488 return "declaration";
1489 case HighlightingModifier::Definition:
1490 return "definition";
1491 case HighlightingModifier::Deprecated:
1492 return "deprecated";
1493 case HighlightingModifier::Readonly:
1495 case HighlightingModifier::Static:
1497 case HighlightingModifier::Deduced:
1499 case HighlightingModifier::Abstract:
1501 case HighlightingModifier::Virtual:
1503 case HighlightingModifier::DependentName:
1504 return "dependentName";
1505 case HighlightingModifier::DefaultLibrary:
1506 return "defaultLibrary";
1507 case HighlightingModifier::UsedAsMutableReference:
1508 return "usedAsMutableReference";
1509 case HighlightingModifier::UsedAsMutablePointer:
1510 return "usedAsMutablePointer";
1511 case HighlightingModifier::ConstructorOrDestructor:
1512 return "constructorOrDestructor";
1513 case HighlightingModifier::UserDefined:
1514 return "userDefined";
1515 case HighlightingModifier::FunctionScope:
1516 return "functionScope";
1517 case HighlightingModifier::ClassScope:
1518 return "classScope";
1519 case HighlightingModifier::FileScope:
1521 case HighlightingModifier::GlobalScope:
1522 return "globalScope";
1524 llvm_unreachable(
"unhandled HighlightingModifier");
1527std::vector<SemanticTokensEdit>
1529 llvm::ArrayRef<SemanticToken> New) {
1534 while (!Old.empty() && !New.empty() && Old.front() == New.front()) {
1536 Old = Old.drop_front();
1537 New = New.drop_front();
1539 while (!Old.empty() && !New.empty() && Old.back() == New.back()) {
1540 Old = Old.drop_back();
1541 New = New.drop_back();
1544 if (Old.empty() && New.empty())
1548 Edit.deleteTokens = Old.size();
1550 return {std::move(
Edit)};
1554 std::vector<Range> SkippedRanges(std::move(AST.getMacros().SkippedRanges));
1555 const auto &SM = AST.getSourceManager();
1556 StringRef MainCode = SM.getBufferOrFake(SM.getMainFileID()).getBuffer();
1557 std::vector<Range> InactiveRegions;
1558 for (
const Range &Skipped : SkippedRanges) {
1559 Range Inactive = Skipped;
1577 if (
auto EndOfLine = endOfLine(MainCode, Inactive.
end.
line)) {
1578 Inactive.
end = *EndOfLine;
1580 elog(
"Failed to determine end of line: {0}", EndOfLine.takeError());
1583 InactiveRegions.push_back(Inactive);
1585 return InactiveRegions;
const FunctionDecl * Decl
CodeCompletionBuilder Builder
CompiledFragmentImpl & Out
CharSourceRange Range
SourceRange for the file name.
const google::protobuf::Message & M
llvm::raw_string_ostream OS
std::vector< const NamedDecl * > resolveUsingValueDecl(const UnresolvedUsingValueDecl *UUVD) const
Stores and provides access to parsed AST.
std::optional< HighlightingModifier > highlightingModifierFromString(llvm::StringRef Name)
llvm::StringRef toSemanticTokenModifier(HighlightingModifier Modifier)
std::vector< HighlightingToken > getSemanticHighlightings(ParsedAST &AST, bool IncludeInactiveRegionTokens)
std::optional< HighlightingKind > highlightingKindFromString(llvm::StringRef Name)
Range halfOpenToRange(const SourceManager &SM, CharSourceRange R)
llvm::StringRef toSemanticTokenType(HighlightingKind Kind)
size_t lspLength(llvm::StringRef Code)
std::vector< SemanticToken > toSemanticTokens(llvm::ArrayRef< HighlightingToken > Tokens, llvm::StringRef Code)
std::vector< SemanticTokensEdit > diffTokens(llvm::ArrayRef< SemanticToken > Old, llvm::ArrayRef< SemanticToken > New)
void findExplicitReferences(const Stmt *S, llvm::function_ref< void(ReferenceLoc)> Out, const HeuristicResolver *Resolver)
Recursively traverse S and report all references explicitly written in the code.
bool operator==(const Inclusion &LHS, const Inclusion &RHS)
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc)
Turn a SourceLocation into a [line, column] pair.
llvm::Expected< size_t > positionToOffset(llvm::StringRef Code, Position P, bool AllowColumnsBeyondLineLength)
Turn a [line, column] pair into an offset in Code.
bool operator<(const Ref &L, const Ref &R)
@ Type
An inlay hint that for a type annotation.
std::vector< Range > getInactiveRegions(ParsedAST &AST)
void elog(const char *Fmt, Ts &&... Vals)
@ Underlying
This is the underlying declaration for a renaming-alias, decltype etc.
@ ConstructorOrDestructor
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static const Config & current()
Returns the Config of the current Context, or an empty configuration.
A set of edits generated for a single file.
int line
Line position in a document (zero-based).
int character
Character offset on a line in a document (zero-based).
Position start
The range's start position.
Position end
The range's end position.
Information about a reference written in the source code, independent of the actual AST node that thi...
bool IsDecl
True if the reference is a declaration or definition;.
llvm::SmallVector< const NamedDecl *, 1 > Targets
A list of targets referenced by this name.
Specifies a single semantic token in the document.
Describes a replacement of a contiguous range of semanticTokens.