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) {
793 D->getNameInfo().getNamedTypeInfo()->getTypeLoc().getBeginLoc();
796 if (
D->isThisDeclarationADefinition())
801 bool VisitCXXMemberCallExpr(CXXMemberCallExpr *CE) {
804 if (
auto *D = CE->getMethodDecl()) {
805 if (isa<CXXDestructorDecl>(D)) {
806 if (
auto *ME = dyn_cast<MemberExpr>(CE->getCallee()))
807 H.addExtraModifier(ME->getMemberNameInfo()
812 }
else if (
D->isOverloadedOperator()) {
813 if (
auto *ME = dyn_cast<MemberExpr>(CE->getCallee()))
815 ME->getMemberNameInfo().getCXXOperatorNameRange().getBegin(),
823 bool VisitDeclaratorDecl(DeclaratorDecl *D) {
824 for (TemplateParameterList *TPL :
D->getTemplateParameterLists())
825 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
826 auto *AT =
D->getType()->getContainedAutoType();
830 kindForType(AT->getDeducedType().getTypePtrOrNull(), H.getResolver());
833 auto *TSI =
D->getTypeSourceInfo();
836 SourceLocation StartLoc =
837 TSI->getTypeLoc().getContainedAutoTypeLoc().getNameLoc();
842 if (StartLoc ==
D->getLocation())
847 const Type *
Deduced = AT->getDeducedType().getTypePtrOrNull();
848 if (
auto Mod = scopeModifier(
Deduced))
849 Tok.addModifier(*Mod);
857 void highlightObjCSelector(
const ArrayRef<SourceLocation> &Locs,
bool Decl,
861 for (SourceLocation Part : Locs) {
875 bool VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
876 llvm::SmallVector<SourceLocation> Locs;
877 OMD->getSelectorLocs(Locs);
878 highlightObjCSelector(Locs,
true,
879 OMD->isThisDeclarationADefinition(),
880 OMD->isClassMethod(), isDefaultLibrary(OMD));
884 bool VisitObjCMessageExpr(ObjCMessageExpr *OME) {
885 llvm::SmallVector<SourceLocation> Locs;
886 OME->getSelectorLocs(Locs);
888 if (ObjCMethodDecl *OMD = OME->getMethodDecl())
890 highlightObjCSelector(Locs,
false,
false,
899 void highlightObjCImplicitPropertyRef(
const ObjCMethodDecl *OMD,
900 SourceLocation Loc) {
903 if (OMD->isClassMethod())
905 if (isDefaultLibrary(OMD))
909 bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *OPRE) {
913 if (!OPRE->isImplicitProperty())
919 if (OPRE->isMessagingGetter()) {
920 highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertyGetter(),
921 OPRE->getLocation());
924 if (OPRE->isMessagingSetter()) {
925 highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertySetter(),
926 OPRE->getLocation());
931 bool VisitOverloadExpr(OverloadExpr *E) {
932 H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
933 if (!E->decls().empty())
937 if (llvm::isa<UnresolvedMemberExpr>(E))
943 bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
947 H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
951 bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
955 H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
959 bool VisitAttr(Attr *A) {
960 switch (
A->getKind()) {
971 bool VisitDependentNameTypeLoc(DependentNameTypeLoc L) {
978 bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc L) {
979 if (!L.getTypePtr()->getTemplateName().getAsTemplateDecl(
984 H.addAngleBracketTokens(L.getLAngleLoc(), L.getRAngleLoc());
988 bool TraverseTemplateArgumentLoc(TemplateArgumentLoc L) {
991 if (L.getArgument().getKind() != TemplateArgument::Template &&
992 L.getArgument().getKind() != TemplateArgument::TemplateExpansion)
993 return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
995 TemplateName N = L.getArgument().getAsTemplateOrTemplatePattern();
996 switch (N.getKind()) {
997 case TemplateName::OverloadedTemplate:
1002 case TemplateName::DependentTemplate:
1003 case TemplateName::AssumedTemplate:
1007 case TemplateName::Template:
1008 case TemplateName::QualifiedTemplate:
1009 case TemplateName::SubstTemplateTemplateParm:
1010 case TemplateName::SubstTemplateTemplateParmPack:
1011 case TemplateName::UsingTemplate:
1012 case TemplateName::DeducedTemplate:
1016 return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
1020 HighlightingsBuilder &H;
1024std::vector<HighlightingToken>
1026 auto &C =
AST.getASTContext();
1027 HighlightingFilter Filter = HighlightingFilter::fromCurrentConfig();
1028 if (!IncludeInactiveRegionTokens)
1031 HighlightingsBuilder Builder(
AST, Filter);
1033 CollectExtraHighlightings(Builder).TraverseAST(C);
1038 for (
const NamedDecl *Decl : R.
Targets) {
1039 if (!canHighlightName(Decl->getDeclName()))
1041 auto Kind = kindForDecl(Decl,
AST.getHeuristicResolver());
1044 auto &Tok = Builder.addToken(R.
NameLoc, *Kind);
1047 if (
auto *TD = dyn_cast<TemplateDecl>(Decl)) {
1048 if (
auto *Templated = TD->getTemplatedDecl())
1051 if (
auto Mod = scopeModifier(Decl))
1052 Tok.addModifier(*Mod);
1056 static const thread_local llvm::DenseMap<
SymbolTag,
1067 for (
const auto &[Tag,
Modifier] : TagModifierMap) {
1080 if (isDependent(Decl))
1083 if (isDefaultLibrary(Decl))
1086 if (isa<CXXConstructorDecl>(Decl))
1090 AST.getHeuristicResolver());
1093 auto &T = Builder.addToken(M.toRange(C.getSourceManager()),
1099 for (
const auto &SIDToRefs :
AST.getMacros().MacroRefs)
1100 for (
const auto &M : SIDToRefs.second)
1102 for (
const auto &M :
AST.getMacros().UnknownMacros)
1105 return std::move(Builder).collect(
AST);
1111 return OS <<
"Variable";
1113 return OS <<
"LocalVariable";
1115 return OS <<
"Parameter";
1117 return OS <<
"Function";
1119 return OS <<
"Method";
1121 return OS <<
"StaticMethod";
1123 return OS <<
"Field";
1125 return OS <<
"StaticField";
1127 return OS <<
"Class";
1129 return OS <<
"Interface";
1131 return OS <<
"Enum";
1133 return OS <<
"EnumConstant";
1135 return OS <<
"Typedef";
1137 return OS <<
"Type";
1139 return OS <<
"Unknown";
1141 return OS <<
"Namespace";
1143 return OS <<
"TemplateParameter";
1145 return OS <<
"Concept";
1147 return OS <<
"Primitive";
1149 return OS <<
"Macro";
1151 return OS <<
"Modifier";
1153 return OS <<
"Operator";
1155 return OS <<
"Bracket";
1157 return OS <<
"Label";
1159 return OS <<
"InactiveCode";
1161 llvm_unreachable(
"invalid HighlightingKind");
1163std::optional<HighlightingKind>
1165 static llvm::StringMap<HighlightingKind> Lookup = {
1192 auto It = Lookup.find(Name);
1193 return It != Lookup.end() ? std::make_optional(It->getValue()) : std::nullopt;
1198 return OS <<
"decl";
1202 return OS <<
"constrDestr";
1207std::optional<HighlightingModifier>
1209 static llvm::StringMap<HighlightingModifier> Lookup = {
1222 {
"ConstructorOrDestructor",
1231 auto It = Lookup.find(Name);
1232 return It != Lookup.end() ? std::make_optional(It->getValue()) : std::nullopt;
1244std::vector<SemanticToken>
1246 llvm::StringRef Code) {
1247 assert(llvm::is_sorted(Tokens));
1248 std::vector<SemanticToken> Result;
1255 Result.emplace_back();
1259 assert(Tok.R.start.line >= Last->
R.
end.
line);
1271 Out->
tokenType =
static_cast<unsigned>(Tok.Kind);
1275 if (Tok.R.end.line == Tok.R.start.line) {
1276 Out->
length = Tok.R.end.character - Tok.R.start.character;
1286 for (
int I = Tok.R.start.line; I < Tok.R.end.line; ++I) {
1287 auto LineEnd = Code.find(
'\n', TokStartOffset);
1288 assert(LineEnd != Code.npos);
1289 Out->
length = LineEnd - TokStartOffset;
1291 TokStartOffset = LineEnd + 1;
1292 Result.emplace_back();
1293 Out = &Result.back();
1294 *Out = Result[Result.size() - 2];
1300 Out->
length = Tok.R.end.character;
1335 return "enumMember";
1344 return "typeParameter";
1362 llvm_unreachable(
"unhandled HighlightingKind");
1368 return "declaration";
1370 return "definition";
1372 return "deprecated";
1384 return "dependentName";
1386 return "defaultLibrary";
1388 return "usedAsMutableReference";
1390 return "usedAsMutablePointer";
1392 return "constructorOrDestructor";
1394 return "userDefined";
1396 return "functionScope";
1398 return "classScope";
1402 return "globalScope";
1404 llvm_unreachable(
"unhandled HighlightingModifier");
1407std::vector<SemanticTokensEdit>
diffTokens(llvm::ArrayRef<SemanticToken> Old,
1408 llvm::ArrayRef<SemanticToken> New) {
1412 unsigned Offset = 0;
1413 while (!Old.empty() && !New.empty() && Old.front() == New.front()) {
1415 Old = Old.drop_front();
1416 New = New.drop_front();
1418 while (!Old.empty() && !New.empty() && Old.back() == New.back()) {
1419 Old = Old.drop_back();
1420 New = New.drop_back();
1423 if (Old.empty() && New.empty())
1426 Edit.startToken = Offset;
1427 Edit.deleteTokens = Old.size();
1429 return {std::move(
Edit)};
1433 std::vector<Range> SkippedRanges(std::move(
AST.getMacros().SkippedRanges));
1434 const auto &SM =
AST.getSourceManager();
1435 StringRef MainCode = SM.getBufferOrFake(SM.getMainFileID()).getBuffer();
1436 std::vector<Range> InactiveRegions;
1437 for (
const Range &Skipped : SkippedRanges) {
1438 Range Inactive = Skipped;
1456 if (
auto EndOfLine = endOfLine(MainCode, Inactive.
end.
line)) {
1457 Inactive.
end = *EndOfLine;
1459 elog(
"Failed to determine end of line: {0}", EndOfLine.takeError());
1462 InactiveRegions.push_back(Inactive);
1464 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.
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 bool operator==(const llvm::simple_ilist< T > &LHS, const llvm::simple_ilist< T > &RHS)
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.