18#include "clang/AST/ASTContext.h"
19#include "clang/AST/Decl.h"
20#include "clang/AST/DeclCXX.h"
21#include "clang/AST/DeclObjC.h"
22#include "clang/AST/DeclTemplate.h"
23#include "clang/AST/DeclarationName.h"
24#include "clang/AST/ExprCXX.h"
25#include "clang/AST/RecursiveASTVisitor.h"
26#include "clang/AST/TypeLoc.h"
27#include "clang/Basic/SourceLocation.h"
28#include "clang/Basic/SourceManager.h"
29#include "clang/Sema/HeuristicResolver.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"
44llvm::Expected<Position> endOfLine(llvm::StringRef Code,
int Line) {
47 return StartOfLine.takeError();
48 StringRef LineText = Code.drop_front(*StartOfLine).take_until([](
char C) {
56bool canHighlightName(DeclarationName Name) {
57 switch (Name.getNameKind()) {
58 case DeclarationName::Identifier: {
59 auto *II = Name.getAsIdentifierInfo();
60 return II && !II->getName().empty();
62 case DeclarationName::CXXConstructorName:
63 case DeclarationName::CXXDestructorName:
65 case DeclarationName::ObjCZeroArgSelector:
66 case DeclarationName::ObjCOneArgSelector:
67 case DeclarationName::ObjCMultiArgSelector:
71 case DeclarationName::CXXConversionFunctionName:
72 case DeclarationName::CXXOperatorName:
73 case DeclarationName::CXXDeductionGuideName:
74 case DeclarationName::CXXLiteralOperatorName:
75 case DeclarationName::CXXUsingDirective:
78 llvm_unreachable(
"invalid name kind");
81std::optional<HighlightingKind> kindForType(
const Type *TP,
82 const HeuristicResolver *Resolver);
83std::optional<HighlightingKind> kindForDecl(
const NamedDecl *D,
84 const HeuristicResolver *Resolver) {
85 if (
auto *USD = dyn_cast<UsingShadowDecl>(D)) {
86 if (
auto *Target = USD->getTargetDecl())
89 if (
auto *TD = dyn_cast<TemplateDecl>(D)) {
90 if (
auto *Templated = TD->getTemplatedDecl())
93 if (
auto *TD = dyn_cast<TypedefNameDecl>(D)) {
96 kindForType(TD->getUnderlyingType().getTypePtrOrNull(), Resolver))
104 if (
auto *RD = llvm::dyn_cast<RecordDecl>(D)) {
110 if (isa<ClassTemplateDecl, RecordDecl, CXXConstructorDecl, ObjCInterfaceDecl,
111 ObjCImplementationDecl>(D))
113 if (isa<ObjCProtocolDecl>(D))
115 if (isa<ObjCCategoryDecl, ObjCCategoryImplDecl>(D))
117 if (
auto *MD = dyn_cast<CXXMethodDecl>(D))
120 if (
auto *OMD = dyn_cast<ObjCMethodDecl>(D))
123 if (isa<FieldDecl, IndirectFieldDecl, ObjCPropertyDecl>(D))
125 if (isa<EnumDecl>(D))
127 if (isa<EnumConstantDecl>(D))
129 if (isa<ParmVarDecl>(D))
131 if (
auto *VD = dyn_cast<VarDecl>(D)) {
132 if (isa<ImplicitParamDecl>(VD))
138 if (
const auto *BD = dyn_cast<BindingDecl>(D))
139 return BD->getDeclContext()->isFunctionOrMethod()
142 if (isa<FunctionDecl>(D))
144 if (isa<NamespaceDecl>(D) || isa<NamespaceAliasDecl>(D) ||
145 isa<UsingDirectiveDecl>(D))
147 if (isa<TemplateTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
148 isa<NonTypeTemplateParmDecl>(D))
150 if (isa<ConceptDecl>(D))
152 if (isa<LabelDecl>(D))
154 if (
const auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(D)) {
155 auto Targets = Resolver->resolveUsingValueDecl(UUVD);
156 if (!Targets.empty() && Targets[0] != UUVD) {
157 return kindForDecl(Targets[0], Resolver);
163std::optional<HighlightingKind> kindForType(
const Type *TP,
164 const HeuristicResolver *Resolver) {
167 if (TP->isBuiltinType())
169 if (
auto *TD = dyn_cast<TemplateTypeParmType>(TP))
170 return kindForDecl(TD->getDecl(), Resolver);
171 if (isa<ObjCObjectPointerType>(TP))
173 if (
auto *TD = TP->getAsTagDecl())
174 return kindForDecl(TD, Resolver);
178bool isDependent(
const Decl *D) {
179 if (isa<UnresolvedUsingValueDecl>(D))
187bool isDefaultLibrary(
const Decl *D) {
188 SourceLocation Loc =
D->getLocation();
191 return D->getASTContext().getSourceManager().isInSystemHeader(Loc);
194bool isDefaultLibrary(
const Type *T) {
200 if (
auto *TD = dyn_cast<TemplateTypeParmType>(
Underlying))
201 return isDefaultLibrary(TD->getDecl());
203 return isDefaultLibrary(TD);
210SourceLocation getHighlightableSpellingToken(SourceLocation L,
211 const SourceManager &SM) {
213 return SM.isWrittenInMainFile(L) ? L : SourceLocation{};
215 if (!SM.isMacroArgExpansion(L))
218 return getHighlightableSpellingToken(SM.getImmediateSpellingLoc(L), SM);
222 enum HighlightPriority { Dependent = 0, Resolved = 1 };
248 unsigned Priority1 = evaluateHighlightPriority(A);
249 unsigned Priority2 = evaluateHighlightPriority(B);
250 if (Priority1 == Priority2 &&
A.Kind !=
B.Kind)
252 auto Result = Priority1 > Priority2 ?
A :
B;
253 Result.Modifiers =
A.Modifiers |
B.Modifiers;
256std::optional<HighlightingToken>
257resolveConflict(ArrayRef<HighlightingToken> Tokens) {
258 if (Tokens.size() == 1)
261 assert(Tokens.size() >= 2);
262 std::optional<HighlightingToken> Winner =
263 resolveConflict(Tokens[0], Tokens[1]);
264 for (
size_t I = 2; Winner && I < Tokens.size(); ++I)
265 Winner = resolveConflict(*Winner, Tokens[I]);
271class HighlightingFilter {
273 HighlightingFilter() {
274 for (
auto &Active : ActiveKindLookup)
277 ActiveModifiersMask = ~0;
281 ActiveKindLookup[
static_cast<size_t>(Kind)] =
false;
285 ActiveModifiersMask &= ~(1 <<
static_cast<uint32_t
>(
Modifier));
289 return ActiveKindLookup[
static_cast<size_t>(Kind)];
292 uint32_t maskModifiers(uint32_t Modifiers)
const {
293 return Modifiers & ActiveModifiersMask;
296 static HighlightingFilter fromCurrentConfig() {
298 HighlightingFilter Filter;
299 for (
const auto &Kind :
C.SemanticTokens.DisabledKinds)
301 Filter.disableKind(*K);
302 for (
const auto &
Modifier :
C.SemanticTokens.DisabledModifiers)
304 Filter.disableModifier(*M);
311 uint32_t ActiveModifiersMask;
315class HighlightingsBuilder {
317 HighlightingsBuilder(
const ParsedAST &
AST,
const HighlightingFilter &Filter)
318 : TB(
AST.getTokens()), SourceMgr(
AST.getSourceManager()),
319 LangOpts(
AST.getLangOpts()), Filter(Filter),
320 Resolver(
AST.getHeuristicResolver()) {}
323 auto Range = getRangeForSourceLocation(Loc);
325 return InvalidHighlightingToken;
327 return addToken(*Range, Kind);
332 void addAngleBracketTokens(SourceLocation LLoc, SourceLocation RLoc) {
333 if (!LLoc.isValid() || !RLoc.isValid())
336 auto LRange = getRangeForSourceLocation(LLoc);
342 RLoc = SourceMgr.getFileLoc(RLoc);
344 RLoc = getHighlightableSpellingToken(RLoc, SourceMgr);
348 const auto *RTok = TB.spelledTokenContaining(RLoc);
352 if (!RTok || RTok->kind() == tok::greatergreater) {
361 if (RTok->kind() == tok::greater) {
362 if (
auto RRange = getRangeForSourceLocation(RLoc)) {
371 if (!Filter.isHighlightKindActive(Kind))
372 return InvalidHighlightingToken;
374 HighlightingToken HT;
377 Tokens.push_back(std::move(HT));
378 return Tokens.back();
382 if (
auto Range = getRangeForSourceLocation(Loc))
383 ExtraModifiers[*Range].push_back(
Modifier);
386 std::vector<HighlightingToken> collect(ParsedAST &
AST) && {
390 auto Last = llvm::unique(Tokens);
391 Tokens.erase(Last, Tokens.end());
396 std::vector<HighlightingToken> NonConflicting;
397 NonConflicting.reserve(Tokens.size());
398 for (ArrayRef<HighlightingToken> TokRef = Tokens; !TokRef.empty();) {
399 ArrayRef<HighlightingToken> Conflicting =
400 TokRef.take_while([&](
const HighlightingToken &T) {
403 return T.R == TokRef.front().R;
405 if (
auto Resolved = resolveConflict(Conflicting)) {
407 auto Modifiers = ExtraModifiers.find(Resolved->R);
408 if (Modifiers != ExtraModifiers.end()) {
410 Resolved->addModifier(Mod);
414 Resolved->Modifiers = Filter.maskModifiers(Resolved->Modifiers);
415 NonConflicting.push_back(*Resolved);
419 TokRef = TokRef.drop_front(Conflicting.size());
423 return NonConflicting;
425 const auto &SM =
AST.getSourceManager();
426 StringRef MainCode = SM.getBufferOrFake(SM.getMainFileID()).getBuffer();
429 std::vector<HighlightingToken> WithInactiveLines;
431 llvm::sort(SortedInactiveRegions);
432 auto It = NonConflicting.begin();
433 for (
const Range &R : SortedInactiveRegions) {
436 assert(R.start.line <= R.end.line);
437 for (
int Line = R.start.line; Line <= R.end.line; ++Line) {
439 for (; It != NonConflicting.end() && It->R.start.line < Line; ++It)
440 WithInactiveLines.push_back(std::move(*It));
442 auto EndOfLine = endOfLine(MainCode, Line);
444 HighlightingToken HT;
445 WithInactiveLines.emplace_back();
447 WithInactiveLines.back().R.start.line = Line;
448 WithInactiveLines.back().R.end = *EndOfLine;
450 elog(
"Failed to determine end of line: {0}", EndOfLine.takeError());
458 while (It != NonConflicting.end() && It->R.start.line == Line)
463 for (; It != NonConflicting.end(); ++It)
464 WithInactiveLines.push_back(std::move(*It));
465 return WithInactiveLines;
468 const HeuristicResolver *getResolver()
const {
return Resolver; }
471 std::optional<Range> getRangeForSourceLocation(SourceLocation Loc) {
472 Loc = getHighlightableSpellingToken(Loc, SourceMgr);
477 const auto *Tok = TB.spelledTokenContaining(Loc);
481 Tok->range(SourceMgr).toCharRange(SourceMgr));
484 const syntax::TokenBuffer &TB;
485 const SourceManager &SourceMgr;
486 const LangOptions &LangOpts;
487 HighlightingFilter Filter;
488 std::vector<HighlightingToken> Tokens;
489 std::map<Range, llvm::SmallVector<HighlightingModifier, 1>> ExtraModifiers;
490 const HeuristicResolver *Resolver;
492 HighlightingToken InvalidHighlightingToken;
495std::optional<HighlightingModifier> scopeModifier(
const NamedDecl *D) {
496 const DeclContext *DC =
D->getDeclContext();
498 if (
auto *R = dyn_cast_or_null<CXXRecordDecl>(D))
499 if (R->isInjectedClassName())
500 DC = DC->getParent();
502 if (llvm::isa<FieldDecl>(D))
503 if (
const auto *RD = llvm::dyn_cast<RecordDecl>(DC))
507 for (; !DC->isFileContext(); DC = DC->getParent()) {
508 if (DC->isFunctionOrMethod())
515 if (DC->isTranslationUnit() &&
D->isTemplateParameter())
518 if (llvm::to_underlying(
D->getLinkageInternal()) <
519 llvm::to_underlying(Linkage::External))
524std::optional<HighlightingModifier> scopeModifier(
const Type *T) {
527 if (
T->isBuiltinType())
529 if (
auto *TD = dyn_cast<TemplateTypeParmType>(T))
530 return scopeModifier(TD->getDecl());
531 if (
auto *TD =
T->getAsTagDecl())
532 return scopeModifier(TD);
538class CollectExtraHighlightings
539 :
public RecursiveASTVisitor<CollectExtraHighlightings> {
540 using Base = RecursiveASTVisitor<CollectExtraHighlightings>;
543 CollectExtraHighlightings(HighlightingsBuilder &H) : H(H) {}
545 bool VisitCXXConstructExpr(CXXConstructExpr *E) {
546 highlightMutableReferenceArguments(E->getConstructor(),
547 {E->getArgs(), E->getNumArgs()});
552 bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
553 if (Init->isMemberInitializer())
554 if (
auto *Member = Init->getMember())
555 highlightMutableReferenceArgument(Member->getType(), Init->getInit());
556 return Base::TraverseConstructorInitializer(Init);
559 bool TraverseTypeConstraint(
const TypeConstraint *C) {
560 if (
auto *Args =
C->getTemplateArgsAsWritten())
561 H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
562 return Base::TraverseTypeConstraint(C);
565 bool VisitPredefinedExpr(PredefinedExpr *E) {
573 bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
574 if (
auto *Args = E->getTemplateArgsAsWritten())
575 H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
579 bool VisitTemplateDecl(TemplateDecl *D) {
580 if (
auto *TPL =
D->getTemplateParameters())
581 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
585 bool VisitTagDecl(TagDecl *D) {
586 for (TemplateParameterList *TPL :
D->getTemplateParameterLists())
587 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
592 VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D) {
593 if (
auto *Args =
D->getTemplateArgsAsWritten())
594 H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
598 bool VisitClassTemplatePartialSpecializationDecl(
599 ClassTemplatePartialSpecializationDecl *D) {
600 if (
auto *TPL =
D->getTemplateParameters())
601 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
605 bool VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) {
606 if (
auto *Args =
D->getTemplateArgsAsWritten())
607 H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
611 bool VisitVarTemplatePartialSpecializationDecl(
612 VarTemplatePartialSpecializationDecl *D) {
613 if (
auto *TPL =
D->getTemplateParameters())
614 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
618 bool VisitDeclRefExpr(DeclRefExpr *E) {
619 H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
622 bool VisitMemberExpr(MemberExpr *E) {
623 H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
627 bool VisitFunctionDecl(FunctionDecl *D) {
628 if (
D->isOverloadedOperator()) {
629 const auto AddOpDeclToken = [&](SourceLocation Loc) {
632 if (
D->isThisDeclarationADefinition())
635 const auto Range =
D->getNameInfo().getCXXOperatorNameRange();
636 AddOpDeclToken(Range.getBegin());
637 const auto Kind =
D->getOverloadedOperator();
638 if (Kind == OO_Call || Kind == OO_Subscript)
639 AddOpDeclToken(Range.getEnd());
641 if (
auto *Args =
D->getTemplateSpecializationArgsAsWritten())
642 H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
646 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
647 const auto AddOpToken = [&](SourceLocation Loc) {
651 AddOpToken(E->getOperatorLoc());
652 const auto Kind = E->getOperator();
653 if (Kind == OO_Call || Kind == OO_Subscript) {
654 if (
auto *Callee = E->getCallee())
655 AddOpToken(Callee->getBeginLoc());
660 bool VisitUnaryOperator(UnaryOperator *Op) {
662 if (Op->getSubExpr()->isTypeDependent())
667 bool VisitBinaryOperator(BinaryOperator *Op) {
669 if (Op->getLHS()->isTypeDependent() || Op->getRHS()->isTypeDependent())
674 bool VisitConditionalOperator(ConditionalOperator *Op) {
680 bool VisitCXXNewExpr(CXXNewExpr *E) {
682 if (isa_and_present<CXXMethodDecl>(E->getOperatorNew()))
687 bool VisitCXXDeleteExpr(CXXDeleteExpr *E) {
689 if (isa_and_present<CXXMethodDecl>(E->getOperatorDelete()))
694 bool VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
695 const auto &
B = E->getAngleBrackets();
696 H.addAngleBracketTokens(
B.getBegin(),
B.getEnd());
700 bool VisitCallExpr(CallExpr *E) {
703 if (isa<UserDefinedLiteral>(E))
708 llvm::ArrayRef<const Expr *> Args = {E->getArgs(), E->getNumArgs()};
709 if (
auto *CallOp = dyn_cast<CXXOperatorCallExpr>(E)) {
710 switch (CallOp->getOperator()) {
713 Args = Args.drop_front();
720 highlightMutableReferenceArguments(
721 dyn_cast_or_null<FunctionDecl>(E->getCalleeDecl()), Args);
726 void highlightMutableReferenceArgument(QualType T,
const Expr *Arg) {
733 bool IsRef =
T->isLValueReferenceType();
734 bool IsPtr =
T->isPointerType();
735 if ((!IsRef && !IsPtr) ||
T->getPointeeType().isConstQualified() ||
736 T->isDependentType()) {
740 std::optional<SourceLocation> Location;
745 if (
auto *IC = dyn_cast<ImplicitCastExpr>(Arg))
746 Arg = IC->getSubExprAsWritten();
747 if (
auto *UO = dyn_cast<UnaryOperator>(Arg)) {
748 if (UO->getOpcode() == UO_AddrOf)
749 Arg = UO->getSubExpr();
751 if (
auto *DR = dyn_cast<DeclRefExpr>(Arg))
752 Location = DR->getLocation();
753 else if (
auto *M = dyn_cast<MemberExpr>(Arg))
754 Location = M->getMemberLoc();
757 H.addExtraModifier(*Location,
763 highlightMutableReferenceArguments(
const FunctionDecl *FD,
764 llvm::ArrayRef<const Expr *const> Args) {
768 if (
auto *ProtoType = FD->getType()->getAs<FunctionProtoType>()) {
773 I < std::min(
size_t(ProtoType->getNumParams()), Args.size()); ++I) {
774 highlightMutableReferenceArgument(ProtoType->getParamType(I), Args[I]);
779 bool VisitDecltypeTypeLoc(DecltypeTypeLoc L) {
780 if (
auto K = kindForType(L.getTypePtr(), H.getResolver())) {
781 auto &Tok = H.addToken(L.getBeginLoc(), *K)
783 if (
auto Mod = scopeModifier(L.getTypePtr()))
784 Tok.addModifier(*Mod);
785 if (isDefaultLibrary(L.getTypePtr()))
791 bool VisitCXXDestructorDecl(CXXDestructorDecl *D) {
792 if (
auto *TI =
D->getNameInfo().getNamedTypeInfo()) {
793 SourceLocation Loc = TI->getTypeLoc().getBeginLoc();
796 if (
D->isThisDeclarationADefinition())
802 bool VisitCXXMemberCallExpr(CXXMemberCallExpr *CE) {
805 if (
auto *D = CE->getMethodDecl()) {
806 if (isa<CXXDestructorDecl>(D)) {
807 if (
auto *ME = dyn_cast<MemberExpr>(CE->getCallee())) {
808 if (
auto *TI = ME->getMemberNameInfo().getNamedTypeInfo()) {
809 H.addExtraModifier(TI->getTypeLoc().getBeginLoc(),
813 }
else if (
D->isOverloadedOperator()) {
814 if (
auto *ME = dyn_cast<MemberExpr>(CE->getCallee()))
816 ME->getMemberNameInfo().getCXXOperatorNameRange().getBegin(),
824 bool VisitDeclaratorDecl(DeclaratorDecl *D) {
825 for (TemplateParameterList *TPL :
D->getTemplateParameterLists())
826 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
827 auto *AT =
D->getType()->getContainedAutoType();
831 kindForType(AT->getDeducedType().getTypePtrOrNull(), H.getResolver());
834 auto *TSI =
D->getTypeSourceInfo();
837 SourceLocation StartLoc =
838 TSI->getTypeLoc().getContainedAutoTypeLoc().getNameLoc();
843 if (StartLoc ==
D->getLocation())
848 const Type *
Deduced = AT->getDeducedType().getTypePtrOrNull();
849 if (
auto Mod = scopeModifier(
Deduced))
850 Tok.addModifier(*Mod);
858 void highlightObjCSelector(
const ArrayRef<SourceLocation> &Locs,
bool Decl,
862 for (SourceLocation Part : Locs) {
876 bool VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
877 llvm::SmallVector<SourceLocation> Locs;
878 OMD->getSelectorLocs(Locs);
879 highlightObjCSelector(Locs,
true,
880 OMD->isThisDeclarationADefinition(),
881 OMD->isClassMethod(), isDefaultLibrary(OMD));
885 bool VisitObjCMessageExpr(ObjCMessageExpr *OME) {
886 llvm::SmallVector<SourceLocation> Locs;
887 OME->getSelectorLocs(Locs);
889 if (ObjCMethodDecl *OMD = OME->getMethodDecl())
891 highlightObjCSelector(Locs,
false,
false,
900 void highlightObjCImplicitPropertyRef(
const ObjCMethodDecl *OMD,
901 SourceLocation Loc) {
904 if (OMD->isClassMethod())
906 if (isDefaultLibrary(OMD))
910 bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *OPRE) {
914 if (!OPRE->isImplicitProperty())
920 if (OPRE->isMessagingGetter()) {
921 highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertyGetter(),
922 OPRE->getLocation());
925 if (OPRE->isMessagingSetter()) {
926 highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertySetter(),
927 OPRE->getLocation());
932 bool VisitOverloadExpr(OverloadExpr *E) {
933 H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
934 if (!E->decls().empty())
938 if (llvm::isa<UnresolvedMemberExpr>(E))
944 bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
948 H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
952 bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
956 H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
960 bool VisitAttr(Attr *A) {
961 switch (
A->getKind()) {
972 bool VisitDependentNameTypeLoc(DependentNameTypeLoc L) {
979 bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc L) {
980 if (!L.getTypePtr()->getTemplateName().getAsTemplateDecl(
985 H.addAngleBracketTokens(L.getLAngleLoc(), L.getRAngleLoc());
989 bool TraverseTemplateArgumentLoc(TemplateArgumentLoc L) {
992 if (L.getArgument().getKind() != TemplateArgument::Template &&
993 L.getArgument().getKind() != TemplateArgument::TemplateExpansion)
994 return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
996 TemplateName N = L.getArgument().getAsTemplateOrTemplatePattern();
997 switch (N.getKind()) {
998 case TemplateName::OverloadedTemplate:
1003 case TemplateName::DependentTemplate:
1004 case TemplateName::AssumedTemplate:
1008 case TemplateName::Template:
1009 case TemplateName::QualifiedTemplate:
1010 case TemplateName::SubstTemplateTemplateParm:
1011 case TemplateName::SubstTemplateTemplateParmPack:
1012 case TemplateName::UsingTemplate:
1013 case TemplateName::DeducedTemplate:
1017 return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
1021 HighlightingsBuilder &H;
1025std::vector<HighlightingToken>
1027 auto &C =
AST.getASTContext();
1028 HighlightingFilter Filter = HighlightingFilter::fromCurrentConfig();
1029 if (!IncludeInactiveRegionTokens)
1032 HighlightingsBuilder Builder(
AST, Filter);
1034 CollectExtraHighlightings(Builder).TraverseAST(C);
1039 for (
const NamedDecl *Decl : R.
Targets) {
1040 if (!canHighlightName(Decl->getDeclName()))
1042 auto Kind = kindForDecl(Decl,
AST.getHeuristicResolver());
1045 auto &Tok = Builder.addToken(R.
NameLoc, *Kind);
1048 if (
auto *TD = dyn_cast<TemplateDecl>(Decl)) {
1049 if (
auto *Templated = TD->getTemplatedDecl())
1052 if (
auto Mod = scopeModifier(Decl))
1053 Tok.addModifier(*Mod);
1057 static const thread_local llvm::DenseMap<
SymbolTag,
1068 for (
const auto &[Tag,
Modifier] : TagModifierMap) {
1081 if (isDependent(Decl))
1084 if (isDefaultLibrary(Decl))
1087 if (isa<CXXConstructorDecl>(Decl))
1091 AST.getHeuristicResolver());
1094 auto &T = Builder.addToken(M.toRange(C.getSourceManager()),
1100 for (
const auto &SIDToRefs :
AST.getMacros().MacroRefs)
1101 for (
const auto &M : SIDToRefs.second)
1103 for (
const auto &M :
AST.getMacros().UnknownMacros)
1106 return std::move(Builder).collect(
AST);
1112 return OS <<
"Variable";
1114 return OS <<
"LocalVariable";
1116 return OS <<
"Parameter";
1118 return OS <<
"Function";
1120 return OS <<
"Method";
1122 return OS <<
"StaticMethod";
1124 return OS <<
"Field";
1126 return OS <<
"StaticField";
1128 return OS <<
"Class";
1130 return OS <<
"Interface";
1132 return OS <<
"Enum";
1134 return OS <<
"EnumConstant";
1136 return OS <<
"Typedef";
1138 return OS <<
"Type";
1140 return OS <<
"Unknown";
1142 return OS <<
"Namespace";
1144 return OS <<
"TemplateParameter";
1146 return OS <<
"Concept";
1148 return OS <<
"Primitive";
1150 return OS <<
"Macro";
1152 return OS <<
"Modifier";
1154 return OS <<
"Operator";
1156 return OS <<
"Bracket";
1158 return OS <<
"Label";
1160 return OS <<
"InactiveCode";
1162 llvm_unreachable(
"invalid HighlightingKind");
1164std::optional<HighlightingKind>
1166 static llvm::StringMap<HighlightingKind> Lookup = {
1193 auto It = Lookup.find(Name);
1194 return It != Lookup.end() ? std::make_optional(It->getValue()) : std::nullopt;
1199 return OS <<
"decl";
1203 return OS <<
"constrDestr";
1208std::optional<HighlightingModifier>
1210 static llvm::StringMap<HighlightingModifier> Lookup = {
1223 {
"ConstructorOrDestructor",
1232 auto It = Lookup.find(Name);
1233 return It != Lookup.end() ? std::make_optional(It->getValue()) : std::nullopt;
1245std::vector<SemanticToken>
1247 llvm::StringRef Code) {
1248 assert(llvm::is_sorted(Tokens));
1249 std::vector<SemanticToken> Result;
1256 Result.emplace_back();
1260 assert(Tok.R.start.line >= Last->
R.
end.
line);
1272 Out->
tokenType =
static_cast<unsigned>(Tok.Kind);
1276 if (Tok.R.end.line == Tok.R.start.line) {
1277 Out->
length = Tok.R.end.character - Tok.R.start.character;
1287 for (
int I = Tok.R.start.line; I < Tok.R.end.line; ++I) {
1288 auto LineEnd = Code.find(
'\n', TokStartOffset);
1289 assert(LineEnd != Code.npos);
1290 Out->
length = LineEnd - TokStartOffset;
1292 TokStartOffset = LineEnd + 1;
1293 Result.emplace_back();
1294 Out = &Result.back();
1295 *Out = Result[Result.size() - 2];
1301 Out->
length = Tok.R.end.character;
1336 return "enumMember";
1345 return "typeParameter";
1363 llvm_unreachable(
"unhandled HighlightingKind");
1369 return "declaration";
1371 return "definition";
1373 return "deprecated";
1385 return "dependentName";
1387 return "defaultLibrary";
1389 return "usedAsMutableReference";
1391 return "usedAsMutablePointer";
1393 return "constructorOrDestructor";
1395 return "userDefined";
1397 return "functionScope";
1399 return "classScope";
1403 return "globalScope";
1405 llvm_unreachable(
"unhandled HighlightingModifier");
1408std::vector<SemanticTokensEdit>
diffTokens(llvm::ArrayRef<SemanticToken> Old,
1409 llvm::ArrayRef<SemanticToken> New) {
1413 unsigned Offset = 0;
1414 while (!Old.empty() && !New.empty() && Old.front() == New.front()) {
1416 Old = Old.drop_front();
1417 New = New.drop_front();
1419 while (!Old.empty() && !New.empty() && Old.back() == New.back()) {
1420 Old = Old.drop_back();
1421 New = New.drop_back();
1424 if (Old.empty() && New.empty())
1427 Edit.startToken = Offset;
1428 Edit.deleteTokens = Old.size();
1430 return {std::move(
Edit)};
1434 std::vector<Range> SkippedRanges(std::move(
AST.getMacros().SkippedRanges));
1435 const auto &SM =
AST.getSourceManager();
1436 StringRef MainCode = SM.getBufferOrFake(SM.getMainFileID()).getBuffer();
1437 std::vector<Range> InactiveRegions;
1438 for (
const Range &Skipped : SkippedRanges) {
1439 Range Inactive = Skipped;
1457 if (
auto EndOfLine = endOfLine(MainCode, Inactive.
end.
line)) {
1458 Inactive.
end = *EndOfLine;
1460 elog(
"Failed to determine end of line: {0}", EndOfLine.takeError());
1463 InactiveRegions.push_back(Inactive);
1465 return InactiveRegions;
static cl::opt< std::string > Config("config", desc(R"(
Specifies a configuration in YAML/JSON format:
-config="{Checks:' *', CheckOptions:{x:y}}"
When the value is empty, clang-tidy will
attempt to find a file named .clang-tidy for
each source file in its parent directories.
)"), cl::init(""), cl::cat(ClangTidyCategory))
Stores and provides access to parsed AST.
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
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)
uint32_t SymbolTags
A bitmask type representing symbol tags supported by LSP.
Range halfOpenToRange(const SourceManager &SM, CharSourceRange R)
llvm::StringRef toSemanticTokenType(HighlightingKind Kind)
size_t lspLength(llvm::StringRef Code)
SymbolTag
Symbol tags are extra annotations that can be attached to a symbol.
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.
SymbolTags toSymbolTagBitmask(const SymbolTag ST)
Converts a single SymbolTag to a bitmask.
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
SymbolTags computeSymbolTags(const NamedDecl &ND)
Computes symbol tags for a given NamedDecl.
===– 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;.
SourceLocation NameLoc
Start location of the last name part, i.e. 'foo' in 'ns::foo<int>'.
llvm::SmallVector< const NamedDecl *, 1 > Targets
A list of targets referenced by this name.
Specifies a single semantic token in the document.
unsigned length
the length of the token. A token cannot be multiline
unsigned deltaStart
token start character, relative to the previous token (relative to 0 or the previous token's start if...
unsigned deltaLine
token line number, relative to the previous token
unsigned tokenType
will be looked up in SemanticTokensLegend.tokenTypes
unsigned tokenModifiers
each set bit will be looked up in SemanticTokensLegend.tokenModifiers
Describes a replacement of a contiguous range of semanticTokens.