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 VisitImportDecl(
const ImportDecl *D) {
587 for (
const auto ModuleLoc :
D->getIdentifierLocs()) {
592 bool VisitExportDecl(
const ExportDecl *D) {
597 bool VisitTagDecl(TagDecl *D) {
598 for (TemplateParameterList *TPL :
D->getTemplateParameterLists())
599 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
604 VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D) {
605 if (
auto *Args =
D->getTemplateArgsAsWritten())
606 H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
610 bool VisitClassTemplatePartialSpecializationDecl(
611 ClassTemplatePartialSpecializationDecl *D) {
612 if (
auto *TPL =
D->getTemplateParameters())
613 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
617 bool VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) {
618 if (
auto *Args =
D->getTemplateArgsAsWritten())
619 H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
623 bool VisitVarTemplatePartialSpecializationDecl(
624 VarTemplatePartialSpecializationDecl *D) {
625 if (
auto *TPL =
D->getTemplateParameters())
626 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
630 bool VisitDeclRefExpr(DeclRefExpr *E) {
631 H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
634 bool VisitMemberExpr(MemberExpr *E) {
635 H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
639 bool VisitFunctionDecl(FunctionDecl *D) {
640 if (
D->isOverloadedOperator()) {
641 const auto AddOpDeclToken = [&](SourceLocation Loc) {
644 if (
D->isThisDeclarationADefinition())
647 const auto Range =
D->getNameInfo().getCXXOperatorNameRange();
648 AddOpDeclToken(Range.getBegin());
649 const auto Kind =
D->getOverloadedOperator();
650 if (Kind == OO_Call || Kind == OO_Subscript)
651 AddOpDeclToken(Range.getEnd());
653 if (
auto *Args =
D->getTemplateSpecializationArgsAsWritten())
654 H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
658 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
659 const auto AddOpToken = [&](SourceLocation Loc) {
663 AddOpToken(E->getOperatorLoc());
664 const auto Kind = E->getOperator();
665 if (Kind == OO_Call || Kind == OO_Subscript) {
666 if (
auto *Callee = E->getCallee())
667 AddOpToken(Callee->getBeginLoc());
672 bool VisitUnaryOperator(UnaryOperator *Op) {
674 if (Op->getSubExpr()->isTypeDependent())
679 bool VisitBinaryOperator(BinaryOperator *Op) {
681 if (Op->getLHS()->isTypeDependent() || Op->getRHS()->isTypeDependent())
686 bool VisitConditionalOperator(ConditionalOperator *Op) {
692 bool VisitCXXNewExpr(CXXNewExpr *E) {
694 if (isa_and_present<CXXMethodDecl>(E->getOperatorNew()))
699 bool VisitCXXDeleteExpr(CXXDeleteExpr *E) {
701 if (isa_and_present<CXXMethodDecl>(E->getOperatorDelete()))
706 bool VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
707 const auto &
B = E->getAngleBrackets();
708 H.addAngleBracketTokens(
B.getBegin(),
B.getEnd());
712 bool VisitCallExpr(CallExpr *E) {
715 if (isa<UserDefinedLiteral>(E))
720 llvm::ArrayRef<const Expr *> Args = {E->getArgs(), E->getNumArgs()};
721 if (
auto *CallOp = dyn_cast<CXXOperatorCallExpr>(E)) {
722 switch (CallOp->getOperator()) {
725 Args = Args.drop_front();
732 highlightMutableReferenceArguments(
733 dyn_cast_or_null<FunctionDecl>(E->getCalleeDecl()), Args);
738 void highlightMutableReferenceArgument(QualType T,
const Expr *Arg) {
745 bool IsRef =
T->isLValueReferenceType();
746 bool IsPtr =
T->isPointerType();
747 if ((!IsRef && !IsPtr) ||
T->getPointeeType().isConstQualified() ||
748 T->isDependentType()) {
752 std::optional<SourceLocation> Location;
757 if (
auto *IC = dyn_cast<ImplicitCastExpr>(Arg))
758 Arg = IC->getSubExprAsWritten();
759 if (
auto *UO = dyn_cast<UnaryOperator>(Arg)) {
760 if (UO->getOpcode() == UO_AddrOf)
761 Arg = UO->getSubExpr();
763 if (
auto *DR = dyn_cast<DeclRefExpr>(Arg))
764 Location = DR->getLocation();
765 else if (
auto *M = dyn_cast<MemberExpr>(Arg))
766 Location = M->getMemberLoc();
769 H.addExtraModifier(*Location,
775 highlightMutableReferenceArguments(
const FunctionDecl *FD,
776 llvm::ArrayRef<const Expr *const> Args) {
780 if (
auto *ProtoType = FD->getType()->getAs<FunctionProtoType>()) {
785 I < std::min(
size_t(ProtoType->getNumParams()), Args.size()); ++I) {
786 highlightMutableReferenceArgument(ProtoType->getParamType(I), Args[I]);
791 bool VisitDecltypeTypeLoc(DecltypeTypeLoc L) {
792 if (
auto K = kindForType(L.getTypePtr(), H.getResolver())) {
793 auto &Tok = H.addToken(L.getBeginLoc(), *K)
795 if (
auto Mod = scopeModifier(L.getTypePtr()))
796 Tok.addModifier(*Mod);
797 if (isDefaultLibrary(L.getTypePtr()))
803 bool VisitCXXDestructorDecl(CXXDestructorDecl *D) {
805 D->getNameInfo().getNamedTypeInfo()->getTypeLoc().getBeginLoc();
808 if (
D->isThisDeclarationADefinition())
813 bool VisitCXXMemberCallExpr(CXXMemberCallExpr *CE) {
816 if (
auto *D = CE->getMethodDecl()) {
817 if (isa<CXXDestructorDecl>(D)) {
818 if (
auto *ME = dyn_cast<MemberExpr>(CE->getCallee()))
819 H.addExtraModifier(ME->getMemberNameInfo()
824 }
else if (
D->isOverloadedOperator()) {
825 if (
auto *ME = dyn_cast<MemberExpr>(CE->getCallee()))
827 ME->getMemberNameInfo().getCXXOperatorNameRange().getBegin(),
835 bool VisitDeclaratorDecl(DeclaratorDecl *D) {
836 for (TemplateParameterList *TPL :
D->getTemplateParameterLists())
837 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
838 auto *AT =
D->getType()->getContainedAutoType();
842 kindForType(AT->getDeducedType().getTypePtrOrNull(), H.getResolver());
845 auto *TSI =
D->getTypeSourceInfo();
848 auto ATL = TSI->getTypeLoc().getContainedAutoTypeLoc();
851 SourceLocation StartLoc = ATL.getNameLoc();
856 if (StartLoc ==
D->getLocation())
861 const Type *
Deduced = AT->getDeducedType().getTypePtrOrNull();
862 if (
auto Mod = scopeModifier(
Deduced))
863 Tok.addModifier(*Mod);
871 void highlightObjCSelector(
const ArrayRef<SourceLocation> &Locs,
bool Decl,
875 for (SourceLocation Part : Locs) {
889 bool VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
890 llvm::SmallVector<SourceLocation> Locs;
891 OMD->getSelectorLocs(Locs);
892 highlightObjCSelector(Locs,
true,
893 OMD->isThisDeclarationADefinition(),
894 OMD->isClassMethod(), isDefaultLibrary(OMD));
898 bool VisitObjCMessageExpr(ObjCMessageExpr *OME) {
899 llvm::SmallVector<SourceLocation> Locs;
900 OME->getSelectorLocs(Locs);
902 if (ObjCMethodDecl *OMD = OME->getMethodDecl())
904 highlightObjCSelector(Locs,
false,
false,
913 void highlightObjCImplicitPropertyRef(
const ObjCMethodDecl *OMD,
914 SourceLocation Loc) {
917 if (OMD->isClassMethod())
919 if (isDefaultLibrary(OMD))
923 bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *OPRE) {
927 if (!OPRE->isImplicitProperty())
933 if (OPRE->isMessagingGetter()) {
934 highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertyGetter(),
935 OPRE->getLocation());
938 if (OPRE->isMessagingSetter()) {
939 highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertySetter(),
940 OPRE->getLocation());
945 bool VisitOverloadExpr(OverloadExpr *E) {
946 H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
947 if (!E->decls().empty())
951 if (llvm::isa<UnresolvedMemberExpr>(E))
957 bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
961 H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
965 bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
969 H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
973 bool VisitAttr(Attr *A) {
974 switch (
A->getKind()) {
985 bool VisitDependentNameTypeLoc(DependentNameTypeLoc L) {
992 bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc L) {
993 if (!L.getTypePtr()->getTemplateName().getAsTemplateDecl(
998 H.addAngleBracketTokens(L.getLAngleLoc(), L.getRAngleLoc());
1002 bool TraverseTemplateArgumentLoc(TemplateArgumentLoc L) {
1005 if (L.getArgument().getKind() != TemplateArgument::Template &&
1006 L.getArgument().getKind() != TemplateArgument::TemplateExpansion)
1007 return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
1009 TemplateName N = L.getArgument().getAsTemplateOrTemplatePattern();
1010 switch (N.getKind()) {
1011 case TemplateName::OverloadedTemplate:
1016 case TemplateName::DependentTemplate:
1017 case TemplateName::AssumedTemplate:
1021 case TemplateName::Template:
1022 case TemplateName::QualifiedTemplate:
1023 case TemplateName::SubstTemplateTemplateParm:
1024 case TemplateName::SubstTemplateTemplateParmPack:
1025 case TemplateName::UsingTemplate:
1026 case TemplateName::DeducedTemplate:
1030 return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
1034 HighlightingsBuilder &H;
1038std::vector<HighlightingToken>
1040 auto &C =
AST.getASTContext();
1041 HighlightingFilter Filter = HighlightingFilter::fromCurrentConfig();
1042 if (!IncludeInactiveRegionTokens)
1045 HighlightingsBuilder Builder(
AST, Filter);
1047 CollectExtraHighlightings(Builder).TraverseAST(C);
1052 for (
const NamedDecl *Decl : R.
Targets) {
1053 if (!canHighlightName(Decl->getDeclName()))
1055 auto Kind = kindForDecl(Decl,
AST.getHeuristicResolver());
1058 auto &Tok = Builder.addToken(R.
NameLoc, *Kind);
1061 if (
auto *TD = dyn_cast<TemplateDecl>(Decl)) {
1062 if (
auto *Templated = TD->getTemplatedDecl())
1065 if (
auto Mod = scopeModifier(Decl))
1066 Tok.addModifier(*Mod);
1070 static const thread_local llvm::DenseMap<
SymbolTag,
1081 for (
const auto &[Tag,
Modifier] : TagModifierMap) {
1094 if (isDependent(Decl))
1097 if (isDefaultLibrary(Decl))
1100 if (isa<CXXConstructorDecl>(Decl))
1104 AST.getHeuristicResolver());
1107 auto &T = Builder.addToken(M.toRange(C.getSourceManager()),
1113 for (
const auto &SIDToRefs :
AST.getMacros().MacroRefs)
1114 for (
const auto &M : SIDToRefs.second)
1116 for (
const auto &M :
AST.getMacros().UnknownMacros)
1119 return std::move(Builder).collect(
AST);
1125 return OS <<
"Variable";
1127 return OS <<
"LocalVariable";
1129 return OS <<
"Parameter";
1131 return OS <<
"Function";
1133 return OS <<
"Method";
1135 return OS <<
"StaticMethod";
1137 return OS <<
"Field";
1139 return OS <<
"StaticField";
1141 return OS <<
"Class";
1143 return OS <<
"Interface";
1145 return OS <<
"Enum";
1147 return OS <<
"EnumConstant";
1149 return OS <<
"Typedef";
1151 return OS <<
"Type";
1153 return OS <<
"Unknown";
1155 return OS <<
"Namespace";
1157 return OS <<
"TemplateParameter";
1159 return OS <<
"Concept";
1161 return OS <<
"Primitive";
1163 return OS <<
"Macro";
1165 return OS <<
"Modifier";
1167 return OS <<
"Operator";
1169 return OS <<
"Bracket";
1171 return OS <<
"Label";
1173 return OS <<
"InactiveCode";
1175 llvm_unreachable(
"invalid HighlightingKind");
1177std::optional<HighlightingKind>
1179 static llvm::StringMap<HighlightingKind> Lookup = {
1206 auto It = Lookup.find(Name);
1207 return It != Lookup.end() ? std::make_optional(It->getValue()) : std::nullopt;
1212 return OS <<
"decl";
1216 return OS <<
"constrDestr";
1221std::optional<HighlightingModifier>
1223 static llvm::StringMap<HighlightingModifier> Lookup = {
1236 {
"ConstructorOrDestructor",
1245 auto It = Lookup.find(Name);
1246 return It != Lookup.end() ? std::make_optional(It->getValue()) : std::nullopt;
1258std::vector<SemanticToken>
1260 llvm::StringRef Code) {
1261 assert(llvm::is_sorted(Tokens));
1262 std::vector<SemanticToken> Result;
1269 Result.emplace_back();
1273 assert(Tok.R.start.line >= Last->
R.
end.
line);
1285 Out->
tokenType =
static_cast<unsigned>(Tok.Kind);
1289 if (Tok.R.end.line == Tok.R.start.line) {
1290 Out->
length = Tok.R.end.character - Tok.R.start.character;
1300 for (
int I = Tok.R.start.line; I < Tok.R.end.line; ++I) {
1301 auto LineEnd = Code.find(
'\n', TokStartOffset);
1302 assert(LineEnd != Code.npos);
1303 Out->
length = LineEnd - TokStartOffset;
1305 TokStartOffset = LineEnd + 1;
1306 Result.emplace_back();
1307 Out = &Result.back();
1308 *Out = Result[Result.size() - 2];
1314 Out->
length = Tok.R.end.character;
1349 return "enumMember";
1358 return "typeParameter";
1376 llvm_unreachable(
"unhandled HighlightingKind");
1382 return "declaration";
1384 return "definition";
1386 return "deprecated";
1398 return "dependentName";
1400 return "defaultLibrary";
1402 return "usedAsMutableReference";
1404 return "usedAsMutablePointer";
1406 return "constructorOrDestructor";
1408 return "userDefined";
1410 return "functionScope";
1412 return "classScope";
1416 return "globalScope";
1418 llvm_unreachable(
"unhandled HighlightingModifier");
1421std::vector<SemanticTokensEdit>
diffTokens(llvm::ArrayRef<SemanticToken> Old,
1422 llvm::ArrayRef<SemanticToken> New) {
1426 unsigned Offset = 0;
1427 while (!Old.empty() && !New.empty() && Old.front() == New.front()) {
1429 Old = Old.drop_front();
1430 New = New.drop_front();
1432 while (!Old.empty() && !New.empty() && Old.back() == New.back()) {
1433 Old = Old.drop_back();
1434 New = New.drop_back();
1437 if (Old.empty() && New.empty())
1440 Edit.startToken = Offset;
1441 Edit.deleteTokens = Old.size();
1443 return {std::move(
Edit)};
1447 std::vector<Range> SkippedRanges(std::move(
AST.getMacros().SkippedRanges));
1448 const auto &SM =
AST.getSourceManager();
1449 StringRef MainCode = SM.getBufferOrFake(SM.getMainFileID()).getBuffer();
1450 std::vector<Range> InactiveRegions;
1451 for (
const Range &Skipped : SkippedRanges) {
1452 Range Inactive = Skipped;
1470 if (
auto EndOfLine = endOfLine(MainCode, Inactive.
end.
line)) {
1471 Inactive.
end = *EndOfLine;
1473 elog(
"Failed to determine end of line: {0}", EndOfLine.takeError());
1476 InactiveRegions.push_back(Inactive);
1478 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))
static GeneratorRegistry::Add< MDGenerator > MD(MDGenerator::Format, "Generator for Markdown output.")
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.