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 (
unsigned i = 0; i <
D->getNumTemplateParameterLists(); ++i) {
587 if (
auto *TPL =
D->getTemplateParameterList(i))
588 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
594 VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D) {
595 if (
auto *Args =
D->getTemplateArgsAsWritten())
596 H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
600 bool VisitClassTemplatePartialSpecializationDecl(
601 ClassTemplatePartialSpecializationDecl *D) {
602 if (
auto *TPL =
D->getTemplateParameters())
603 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
607 bool VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) {
608 if (
auto *Args =
D->getTemplateArgsAsWritten())
609 H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
613 bool VisitVarTemplatePartialSpecializationDecl(
614 VarTemplatePartialSpecializationDecl *D) {
615 if (
auto *TPL =
D->getTemplateParameters())
616 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
620 bool VisitDeclRefExpr(DeclRefExpr *E) {
621 H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
624 bool VisitMemberExpr(MemberExpr *E) {
625 H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
629 bool VisitFunctionDecl(FunctionDecl *D) {
630 if (
D->isOverloadedOperator()) {
631 const auto AddOpDeclToken = [&](SourceLocation Loc) {
634 if (
D->isThisDeclarationADefinition())
637 const auto Range =
D->getNameInfo().getCXXOperatorNameRange();
638 AddOpDeclToken(Range.getBegin());
639 const auto Kind =
D->getOverloadedOperator();
640 if (Kind == OO_Call || Kind == OO_Subscript)
641 AddOpDeclToken(Range.getEnd());
643 if (
auto *Args =
D->getTemplateSpecializationArgsAsWritten())
644 H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
648 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
649 const auto AddOpToken = [&](SourceLocation Loc) {
653 AddOpToken(E->getOperatorLoc());
654 const auto Kind = E->getOperator();
655 if (Kind == OO_Call || Kind == OO_Subscript) {
656 if (
auto *Callee = E->getCallee())
657 AddOpToken(Callee->getBeginLoc());
662 bool VisitUnaryOperator(UnaryOperator *Op) {
664 if (Op->getSubExpr()->isTypeDependent())
669 bool VisitBinaryOperator(BinaryOperator *Op) {
671 if (Op->getLHS()->isTypeDependent() || Op->getRHS()->isTypeDependent())
676 bool VisitConditionalOperator(ConditionalOperator *Op) {
682 bool VisitCXXNewExpr(CXXNewExpr *E) {
684 if (isa_and_present<CXXMethodDecl>(E->getOperatorNew()))
689 bool VisitCXXDeleteExpr(CXXDeleteExpr *E) {
691 if (isa_and_present<CXXMethodDecl>(E->getOperatorDelete()))
696 bool VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
697 const auto &
B = E->getAngleBrackets();
698 H.addAngleBracketTokens(
B.getBegin(),
B.getEnd());
702 bool VisitCallExpr(CallExpr *E) {
705 if (isa<UserDefinedLiteral>(E))
710 llvm::ArrayRef<const Expr *> Args = {E->getArgs(), E->getNumArgs()};
711 if (
auto *CallOp = dyn_cast<CXXOperatorCallExpr>(E)) {
712 switch (CallOp->getOperator()) {
715 Args = Args.drop_front();
722 highlightMutableReferenceArguments(
723 dyn_cast_or_null<FunctionDecl>(E->getCalleeDecl()), Args);
728 void highlightMutableReferenceArgument(QualType T,
const Expr *Arg) {
735 bool IsRef =
T->isLValueReferenceType();
736 bool IsPtr =
T->isPointerType();
737 if ((!IsRef && !IsPtr) ||
T->getPointeeType().isConstQualified() ||
738 T->isDependentType()) {
742 std::optional<SourceLocation> Location;
747 if (
auto *IC = dyn_cast<ImplicitCastExpr>(Arg))
748 Arg = IC->getSubExprAsWritten();
749 if (
auto *UO = dyn_cast<UnaryOperator>(Arg)) {
750 if (UO->getOpcode() == UO_AddrOf)
751 Arg = UO->getSubExpr();
753 if (
auto *DR = dyn_cast<DeclRefExpr>(Arg))
754 Location = DR->getLocation();
755 else if (
auto *M = dyn_cast<MemberExpr>(Arg))
756 Location = M->getMemberLoc();
759 H.addExtraModifier(*Location,
765 highlightMutableReferenceArguments(
const FunctionDecl *FD,
766 llvm::ArrayRef<const Expr *const> Args) {
770 if (
auto *ProtoType = FD->getType()->getAs<FunctionProtoType>()) {
775 I < std::min(
size_t(ProtoType->getNumParams()), Args.size()); ++I) {
776 highlightMutableReferenceArgument(ProtoType->getParamType(I), Args[I]);
781 bool VisitDecltypeTypeLoc(DecltypeTypeLoc L) {
782 if (
auto K = kindForType(L.getTypePtr(), H.getResolver())) {
783 auto &Tok = H.addToken(L.getBeginLoc(), *K)
785 if (
auto Mod = scopeModifier(L.getTypePtr()))
786 Tok.addModifier(*Mod);
787 if (isDefaultLibrary(L.getTypePtr()))
793 bool VisitCXXDestructorDecl(CXXDestructorDecl *D) {
794 if (
auto *TI =
D->getNameInfo().getNamedTypeInfo()) {
795 SourceLocation Loc = TI->getTypeLoc().getBeginLoc();
798 if (
D->isThisDeclarationADefinition())
804 bool VisitCXXMemberCallExpr(CXXMemberCallExpr *CE) {
807 if (
auto *D = CE->getMethodDecl()) {
808 if (isa<CXXDestructorDecl>(D)) {
809 if (
auto *ME = dyn_cast<MemberExpr>(CE->getCallee())) {
810 if (
auto *TI = ME->getMemberNameInfo().getNamedTypeInfo()) {
811 H.addExtraModifier(TI->getTypeLoc().getBeginLoc(),
815 }
else if (
D->isOverloadedOperator()) {
816 if (
auto *ME = dyn_cast<MemberExpr>(CE->getCallee()))
818 ME->getMemberNameInfo().getCXXOperatorNameRange().getBegin(),
826 bool VisitDeclaratorDecl(DeclaratorDecl *D) {
827 for (
unsigned i = 0; i <
D->getNumTemplateParameterLists(); ++i) {
828 if (
auto *TPL =
D->getTemplateParameterList(i))
829 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
831 auto *AT =
D->getType()->getContainedAutoType();
835 kindForType(AT->getDeducedType().getTypePtrOrNull(), H.getResolver());
838 auto *TSI =
D->getTypeSourceInfo();
841 SourceLocation StartLoc =
842 TSI->getTypeLoc().getContainedAutoTypeLoc().getNameLoc();
847 if (StartLoc ==
D->getLocation())
852 const Type *
Deduced = AT->getDeducedType().getTypePtrOrNull();
853 if (
auto Mod = scopeModifier(
Deduced))
854 Tok.addModifier(*Mod);
862 void highlightObjCSelector(
const ArrayRef<SourceLocation> &Locs,
bool Decl,
866 for (SourceLocation Part : Locs) {
880 bool VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
881 llvm::SmallVector<SourceLocation> Locs;
882 OMD->getSelectorLocs(Locs);
883 highlightObjCSelector(Locs,
true,
884 OMD->isThisDeclarationADefinition(),
885 OMD->isClassMethod(), isDefaultLibrary(OMD));
889 bool VisitObjCMessageExpr(ObjCMessageExpr *OME) {
890 llvm::SmallVector<SourceLocation> Locs;
891 OME->getSelectorLocs(Locs);
893 if (ObjCMethodDecl *OMD = OME->getMethodDecl())
895 highlightObjCSelector(Locs,
false,
false,
904 void highlightObjCImplicitPropertyRef(
const ObjCMethodDecl *OMD,
905 SourceLocation Loc) {
908 if (OMD->isClassMethod())
910 if (isDefaultLibrary(OMD))
914 bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *OPRE) {
918 if (!OPRE->isImplicitProperty())
924 if (OPRE->isMessagingGetter()) {
925 highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertyGetter(),
926 OPRE->getLocation());
929 if (OPRE->isMessagingSetter()) {
930 highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertySetter(),
931 OPRE->getLocation());
936 bool VisitOverloadExpr(OverloadExpr *E) {
937 H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
938 if (!E->decls().empty())
942 if (llvm::isa<UnresolvedMemberExpr>(E))
948 bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
952 H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
956 bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
960 H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
964 bool VisitAttr(Attr *A) {
965 switch (
A->getKind()) {
976 bool VisitDependentNameTypeLoc(DependentNameTypeLoc L) {
983 bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc L) {
984 if (!L.getTypePtr()->getTemplateName().getAsTemplateDecl(
989 H.addAngleBracketTokens(L.getLAngleLoc(), L.getRAngleLoc());
993 bool TraverseTemplateArgumentLoc(TemplateArgumentLoc L) {
996 if (L.getArgument().getKind() != TemplateArgument::Template &&
997 L.getArgument().getKind() != TemplateArgument::TemplateExpansion)
998 return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
1000 TemplateName N = L.getArgument().getAsTemplateOrTemplatePattern();
1001 switch (N.getKind()) {
1002 case TemplateName::OverloadedTemplate:
1007 case TemplateName::DependentTemplate:
1008 case TemplateName::AssumedTemplate:
1012 case TemplateName::Template:
1013 case TemplateName::QualifiedTemplate:
1014 case TemplateName::SubstTemplateTemplateParm:
1015 case TemplateName::SubstTemplateTemplateParmPack:
1016 case TemplateName::UsingTemplate:
1017 case TemplateName::DeducedTemplate:
1021 return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
1025 HighlightingsBuilder &H;
1029std::vector<HighlightingToken>
1031 auto &C =
AST.getASTContext();
1032 HighlightingFilter Filter = HighlightingFilter::fromCurrentConfig();
1033 if (!IncludeInactiveRegionTokens)
1036 HighlightingsBuilder Builder(
AST, Filter);
1038 CollectExtraHighlightings(Builder).TraverseAST(C);
1043 for (
const NamedDecl *Decl : R.
Targets) {
1044 if (!canHighlightName(Decl->getDeclName()))
1046 auto Kind = kindForDecl(Decl,
AST.getHeuristicResolver());
1049 auto &Tok = Builder.addToken(R.
NameLoc, *Kind);
1052 if (
auto *TD = dyn_cast<TemplateDecl>(Decl)) {
1053 if (
auto *Templated = TD->getTemplatedDecl())
1056 if (
auto Mod = scopeModifier(Decl))
1057 Tok.addModifier(*Mod);
1061 static const thread_local llvm::DenseMap<
SymbolTag,
1072 for (
const auto &[Tag,
Modifier] : TagModifierMap) {
1085 if (isDependent(Decl))
1088 if (isDefaultLibrary(Decl))
1091 if (isa<CXXConstructorDecl>(Decl))
1095 AST.getHeuristicResolver());
1098 auto &T = Builder.addToken(M.toRange(C.getSourceManager()),
1104 for (
const auto &SIDToRefs :
AST.getMacros().MacroRefs)
1105 for (
const auto &M : SIDToRefs.second)
1107 for (
const auto &M :
AST.getMacros().UnknownMacros)
1110 return std::move(Builder).collect(
AST);
1116 return OS <<
"Variable";
1118 return OS <<
"LocalVariable";
1120 return OS <<
"Parameter";
1122 return OS <<
"Function";
1124 return OS <<
"Method";
1126 return OS <<
"StaticMethod";
1128 return OS <<
"Field";
1130 return OS <<
"StaticField";
1132 return OS <<
"Class";
1134 return OS <<
"Interface";
1136 return OS <<
"Enum";
1138 return OS <<
"EnumConstant";
1140 return OS <<
"Typedef";
1142 return OS <<
"Type";
1144 return OS <<
"Unknown";
1146 return OS <<
"Namespace";
1148 return OS <<
"TemplateParameter";
1150 return OS <<
"Concept";
1152 return OS <<
"Primitive";
1154 return OS <<
"Macro";
1156 return OS <<
"Modifier";
1158 return OS <<
"Operator";
1160 return OS <<
"Bracket";
1162 return OS <<
"Label";
1164 return OS <<
"InactiveCode";
1166 llvm_unreachable(
"invalid HighlightingKind");
1168std::optional<HighlightingKind>
1170 static llvm::StringMap<HighlightingKind> Lookup = {
1197 auto It = Lookup.find(Name);
1198 return It != Lookup.end() ? std::make_optional(It->getValue()) : std::nullopt;
1203 return OS <<
"decl";
1207 return OS <<
"constrDestr";
1212std::optional<HighlightingModifier>
1214 static llvm::StringMap<HighlightingModifier> Lookup = {
1227 {
"ConstructorOrDestructor",
1236 auto It = Lookup.find(Name);
1237 return It != Lookup.end() ? std::make_optional(It->getValue()) : std::nullopt;
1249std::vector<SemanticToken>
1251 llvm::StringRef Code) {
1252 assert(llvm::is_sorted(Tokens));
1253 std::vector<SemanticToken> Result;
1260 Result.emplace_back();
1264 assert(Tok.R.start.line >= Last->
R.
end.
line);
1276 Out->
tokenType =
static_cast<unsigned>(Tok.Kind);
1280 if (Tok.R.end.line == Tok.R.start.line) {
1281 Out->
length = Tok.R.end.character - Tok.R.start.character;
1291 for (
int I = Tok.R.start.line; I < Tok.R.end.line; ++I) {
1292 auto LineEnd = Code.find(
'\n', TokStartOffset);
1293 assert(LineEnd != Code.npos);
1294 Out->
length = LineEnd - TokStartOffset;
1296 TokStartOffset = LineEnd + 1;
1297 Result.emplace_back();
1298 Out = &Result.back();
1299 *Out = Result[Result.size() - 2];
1305 Out->
length = Tok.R.end.character;
1340 return "enumMember";
1349 return "typeParameter";
1367 llvm_unreachable(
"unhandled HighlightingKind");
1373 return "declaration";
1375 return "definition";
1377 return "deprecated";
1389 return "dependentName";
1391 return "defaultLibrary";
1393 return "usedAsMutableReference";
1395 return "usedAsMutablePointer";
1397 return "constructorOrDestructor";
1399 return "userDefined";
1401 return "functionScope";
1403 return "classScope";
1407 return "globalScope";
1409 llvm_unreachable(
"unhandled HighlightingModifier");
1412std::vector<SemanticTokensEdit>
diffTokens(llvm::ArrayRef<SemanticToken> Old,
1413 llvm::ArrayRef<SemanticToken> New) {
1417 unsigned Offset = 0;
1418 while (!Old.empty() && !New.empty() && Old.front() == New.front()) {
1420 Old = Old.drop_front();
1421 New = New.drop_front();
1423 while (!Old.empty() && !New.empty() && Old.back() == New.back()) {
1424 Old = Old.drop_back();
1425 New = New.drop_back();
1428 if (Old.empty() && New.empty())
1431 Edit.startToken = Offset;
1432 Edit.deleteTokens = Old.size();
1434 return {std::move(
Edit)};
1438 std::vector<Range> SkippedRanges(std::move(
AST.getMacros().SkippedRanges));
1439 const auto &SM =
AST.getSourceManager();
1440 StringRef MainCode = SM.getBufferOrFake(SM.getMainFileID()).getBuffer();
1441 std::vector<Range> InactiveRegions;
1442 for (
const Range &Skipped : SkippedRanges) {
1443 Range Inactive = Skipped;
1461 if (
auto EndOfLine = endOfLine(MainCode, Inactive.
end.
line)) {
1462 Inactive.
end = *EndOfLine;
1464 elog(
"Failed to determine end of line: {0}", EndOfLine.takeError());
1467 InactiveRegions.push_back(Inactive);
1469 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.