16#include "clang/AST/ASTContext.h"
17#include "clang/AST/Decl.h"
18#include "clang/AST/DeclCXX.h"
19#include "clang/AST/DeclObjC.h"
20#include "clang/AST/DeclTemplate.h"
21#include "clang/AST/DeclarationName.h"
22#include "clang/AST/ExprCXX.h"
23#include "clang/AST/RecursiveASTVisitor.h"
24#include "clang/AST/Type.h"
25#include "clang/AST/TypeLoc.h"
26#include "clang/Basic/LangOptions.h"
27#include "clang/Basic/SourceLocation.h"
28#include "clang/Basic/SourceManager.h"
29#include "clang/Tooling/Syntax/Tokens.h"
30#include "llvm/ADT/STLExtras.h"
31#include "llvm/ADT/StringRef.h"
32#include "llvm/Support/Casting.h"
33#include "llvm/Support/Error.h"
43bool canHighlightName(DeclarationName
Name) {
44 switch (
Name.getNameKind()) {
45 case DeclarationName::Identifier: {
46 auto *II =
Name.getAsIdentifierInfo();
47 return II && !II->getName().empty();
49 case DeclarationName::CXXConstructorName:
50 case DeclarationName::CXXDestructorName:
52 case DeclarationName::ObjCZeroArgSelector:
53 case DeclarationName::ObjCOneArgSelector:
54 case DeclarationName::ObjCMultiArgSelector:
58 case DeclarationName::CXXConversionFunctionName:
59 case DeclarationName::CXXOperatorName:
60 case DeclarationName::CXXDeductionGuideName:
61 case DeclarationName::CXXLiteralOperatorName:
62 case DeclarationName::CXXUsingDirective:
65 llvm_unreachable(
"invalid name kind");
68bool isUniqueDefinition(
const NamedDecl *
Decl) {
69 if (
auto *Func = dyn_cast<FunctionDecl>(
Decl))
70 return Func->isThisDeclarationADefinition();
71 if (
auto *Klass = dyn_cast<CXXRecordDecl>(
Decl))
72 return Klass->isThisDeclarationADefinition();
73 if (
auto *Iface = dyn_cast<ObjCInterfaceDecl>(
Decl))
74 return Iface->isThisDeclarationADefinition();
75 if (
auto *Proto = dyn_cast<ObjCProtocolDecl>(
Decl))
76 return Proto->isThisDeclarationADefinition();
77 if (
auto *Var = dyn_cast<VarDecl>(
Decl))
78 return Var->isThisDeclarationADefinition();
79 return isa<TemplateTypeParmDecl>(
Decl) ||
80 isa<NonTypeTemplateParmDecl>(
Decl) ||
81 isa<TemplateTemplateParmDecl>(
Decl) || isa<ObjCCategoryDecl>(
Decl) ||
82 isa<ObjCImplDecl>(
Decl);
85std::optional<HighlightingKind> kindForType(
const Type *TP,
86 const HeuristicResolver *Resolver);
87std::optional<HighlightingKind> kindForDecl(
const NamedDecl *D,
88 const HeuristicResolver *Resolver) {
89 if (
auto *USD = dyn_cast<UsingShadowDecl>(D)) {
90 if (
auto *Target = USD->getTargetDecl())
93 if (
auto *TD = dyn_cast<TemplateDecl>(D)) {
94 if (
auto *Templated = TD->getTemplatedDecl())
97 if (
auto *TD = dyn_cast<TypedefNameDecl>(D)) {
100 kindForType(TD->getUnderlyingType().getTypePtrOrNull(), Resolver))
108 if (
auto *RD = llvm::dyn_cast<RecordDecl>(D)) {
114 if (isa<ClassTemplateDecl, RecordDecl, CXXConstructorDecl, ObjCInterfaceDecl,
115 ObjCImplementationDecl>(D))
117 if (isa<ObjCProtocolDecl>(D))
119 if (isa<ObjCCategoryDecl>(D))
121 if (
auto *MD = dyn_cast<CXXMethodDecl>(D))
124 if (
auto *OMD = dyn_cast<ObjCMethodDecl>(D))
127 if (isa<FieldDecl, ObjCPropertyDecl>(D))
129 if (isa<EnumDecl>(D))
131 if (isa<EnumConstantDecl>(D))
133 if (isa<ParmVarDecl>(D))
135 if (
auto *VD = dyn_cast<VarDecl>(D)) {
136 if (isa<ImplicitParamDecl>(VD))
138 return VD->isStaticDataMember()
143 if (
const auto *BD = dyn_cast<BindingDecl>(D))
144 return BD->getDeclContext()->isFunctionOrMethod()
147 if (isa<FunctionDecl>(D))
149 if (isa<NamespaceDecl>(D) || isa<NamespaceAliasDecl>(D) ||
150 isa<UsingDirectiveDecl>(D))
152 if (isa<TemplateTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
153 isa<NonTypeTemplateParmDecl>(D))
155 if (isa<ConceptDecl>(D))
157 if (
const auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(D)) {
159 if (!Targets.empty() && Targets[0] != UUVD) {
160 return kindForDecl(Targets[0], Resolver);
166std::optional<HighlightingKind> kindForType(
const Type *TP,
167 const HeuristicResolver *Resolver) {
170 if (TP->isBuiltinType())
172 if (
auto *TD = dyn_cast<TemplateTypeParmType>(TP))
173 return kindForDecl(TD->getDecl(), Resolver);
174 if (isa<ObjCObjectPointerType>(TP))
176 if (
auto *TD = TP->getAsTagDecl())
177 return kindForDecl(TD, Resolver);
182bool isConst(QualType T) {
185 T = T.getNonReferenceType();
186 if (T.isConstQualified())
188 if (
const auto *AT = T->getAsArrayTypeUnsafe())
189 return isConst(AT->getElementType());
190 if (isConst(T->getPointeeType()))
198bool isConst(
const Decl *D) {
199 if (llvm::isa<EnumConstantDecl>(D) || llvm::isa<NonTypeTemplateParmDecl>(D))
201 if (llvm::isa<FieldDecl>(D) || llvm::isa<VarDecl>(D) ||
202 llvm::isa<MSPropertyDecl>(D) || llvm::isa<BindingDecl>(D)) {
203 if (isConst(llvm::cast<ValueDecl>(D)->getType()))
206 if (
const auto *OCPD = llvm::dyn_cast<ObjCPropertyDecl>(D)) {
207 if (OCPD->isReadOnly())
210 if (
const auto *MPD = llvm::dyn_cast<MSPropertyDecl>(D)) {
211 if (!MPD->hasSetter())
214 if (
const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D)) {
240bool isStatic(
const Decl *D) {
241 if (
const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
242 return CMD->isStatic();
243 if (
const VarDecl *VD = llvm::dyn_cast<VarDecl>(D))
244 return VD->isStaticDataMember() || VD->isStaticLocal();
245 if (
const auto *OPD = llvm::dyn_cast<ObjCPropertyDecl>(D))
246 return OPD->isClassProperty();
247 if (
const auto *OMD = llvm::dyn_cast<ObjCMethodDecl>(D))
248 return OMD->isClassMethod();
252bool isAbstract(
const Decl *D) {
253 if (
const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
254 return CMD->isPure();
255 if (
const auto *CRD = llvm::dyn_cast<CXXRecordDecl>(D))
256 return CRD->hasDefinition() && CRD->isAbstract();
260bool isVirtual(
const Decl *D) {
261 if (
const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
262 return CMD->isVirtual();
266bool isDependent(
const Decl *D) {
267 if (isa<UnresolvedUsingValueDecl>(D))
275bool isDefaultLibrary(
const Decl *D) {
276 SourceLocation
Loc =
D->getLocation();
279 return D->getASTContext().getSourceManager().isInSystemHeader(
Loc);
282bool isDefaultLibrary(
const Type *T) {
288 if (
auto *TD = dyn_cast<TemplateTypeParmType>(
Underlying))
289 return isDefaultLibrary(TD->getDecl());
291 return isDefaultLibrary(TD);
298SourceLocation getHighlightableSpellingToken(SourceLocation L,
299 const SourceManager &SM) {
301 return SM.isWrittenInMainFile(L) ? L : SourceLocation{};
303 if (!SM.isMacroArgExpansion(L))
306 return getHighlightableSpellingToken(SM.getImmediateSpellingLoc(L), SM);
309unsigned evaluateHighlightPriority(
const HighlightingToken &Tok) {
310 enum HighlightPriority { Dependent = 0, Resolved = 1 };
334std::optional<HighlightingToken> resolveConflict(
const HighlightingToken &A,
335 const HighlightingToken &B) {
336 unsigned Priority1 = evaluateHighlightPriority(A);
337 unsigned Priority2 = evaluateHighlightPriority(B);
338 if (Priority1 == Priority2 &&
A.Kind !=
B.Kind)
340 auto Result = Priority1 > Priority2 ?
A :
B;
341 Result.Modifiers =
A.Modifiers |
B.Modifiers;
344std::optional<HighlightingToken>
345resolveConflict(ArrayRef<HighlightingToken> Tokens) {
346 if (Tokens.size() == 1)
349 assert(Tokens.size() >= 2);
350 std::optional<HighlightingToken> Winner =
351 resolveConflict(Tokens[0], Tokens[1]);
352 for (
size_t I = 2; Winner && I < Tokens.size(); ++I)
353 Winner = resolveConflict(*Winner, Tokens[I]);
358class HighlightingsBuilder {
360 HighlightingsBuilder(
const ParsedAST &
AST)
361 : TB(
AST.getTokens()), SourceMgr(
AST.getSourceManager()),
362 LangOpts(
AST.getLangOpts()) {}
365 auto Range = getRangeForSourceLocation(
Loc);
367 return InvalidHighlightingToken;
369 return addToken(*Range,
Kind);
374 void addAngleBracketTokens(SourceLocation LLoc, SourceLocation RLoc) {
375 if (!LLoc.isValid() || !RLoc.isValid())
378 auto LRange = getRangeForSourceLocation(LLoc);
384 RLoc = SourceMgr.getFileLoc(RLoc);
386 RLoc = getHighlightableSpellingToken(RLoc, SourceMgr);
390 const auto *RTok = TB.spelledTokenAt(RLoc);
395 if (!RTok || RTok->kind() == tok::greatergreater) {
404 if (RTok->kind() == tok::greater) {
405 if (
auto RRange = getRangeForSourceLocation(RLoc)) {
414 HighlightingToken HT;
417 Tokens.push_back(std::move(HT));
418 return Tokens.back();
422 if (
auto Range = getRangeForSourceLocation(
Loc))
426 std::vector<HighlightingToken> collect(ParsedAST &
AST) && {
430 auto Last = std::unique(Tokens.begin(), Tokens.end());
431 Tokens.erase(Last, Tokens.end());
436 std::vector<HighlightingToken> NonConflicting;
437 NonConflicting.reserve(Tokens.size());
438 for (ArrayRef<HighlightingToken> TokRef = Tokens; !TokRef.empty();) {
439 ArrayRef<HighlightingToken> Conflicting =
440 TokRef.take_while([&](
const HighlightingToken &T) {
443 return T.R == TokRef.front().R;
445 if (
auto Resolved = resolveConflict(Conflicting)) {
447 auto Modifiers = ExtraModifiers.find(Resolved->R);
448 if (Modifiers != ExtraModifiers.end()) {
450 Resolved->addModifier(Mod);
454 NonConflicting.push_back(*Resolved);
458 TokRef = TokRef.drop_front(Conflicting.size());
461 const auto &SM =
AST.getSourceManager();
462 StringRef MainCode = SM.getBufferOrFake(SM.getMainFileID()).getBuffer();
465 std::vector<HighlightingToken> WithInactiveLines;
466 auto SortedSkippedRanges =
AST.getMacros().SkippedRanges;
467 llvm::sort(SortedSkippedRanges);
468 auto It = NonConflicting.begin();
469 for (
const Range &R : SortedSkippedRanges) {
472 assert(R.start.line <= R.end.line);
473 for (
int Line = R.start.line; Line <= R.end.line; ++Line) {
476 if (Line == R.end.line && R.end.character == 0)
479 for (; It != NonConflicting.end() && It->R.start.line < Line; ++It)
480 WithInactiveLines.push_back(std::move(*It));
485 MainCode.drop_front(*StartOfLine).take_until([](
char C) {
488 HighlightingToken HT;
489 WithInactiveLines.emplace_back();
491 WithInactiveLines.back().R.start.line =
Line;
492 WithInactiveLines.back().R.end.line =
Line;
493 WithInactiveLines.back().R.end.character =
496 elog(
"Failed to convert position to offset: {0}",
497 StartOfLine.takeError());
505 while (It != NonConflicting.end() && It->R.start.line == Line)
510 for (; It != NonConflicting.end(); ++It)
511 WithInactiveLines.push_back(std::move(*It));
512 return WithInactiveLines;
515 const HeuristicResolver *getResolver()
const {
return Resolver; }
518 std::optional<Range> getRangeForSourceLocation(SourceLocation
Loc) {
519 Loc = getHighlightableSpellingToken(
Loc, SourceMgr);
524 const auto *Tok = TB.spelledTokenAt(
Loc);
528 Tok->range(SourceMgr).toCharRange(SourceMgr));
531 const syntax::TokenBuffer &TB;
532 const SourceManager &SourceMgr;
533 const LangOptions &LangOpts;
534 std::vector<HighlightingToken> Tokens;
535 std::map<Range, llvm::SmallVector<HighlightingModifier, 1>> ExtraModifiers;
536 const HeuristicResolver *Resolver =
nullptr;
538 HighlightingToken InvalidHighlightingToken;
541std::optional<HighlightingModifier> scopeModifier(
const NamedDecl *D) {
542 const DeclContext *DC =
D->getDeclContext();
544 if (
auto *R = dyn_cast_or_null<RecordDecl>(D))
545 if (R->isInjectedClassName())
546 DC = DC->getParent();
548 if (llvm::isa<FieldDecl>(D))
549 if (
const auto *RD = llvm::dyn_cast<RecordDecl>(DC))
553 for (; !DC->isFileContext(); DC = DC->getParent()) {
554 if (DC->isFunctionOrMethod())
561 if (DC->isTranslationUnit() &&
D->isTemplateParameter())
564 if (
D->getLinkageInternal() < ExternalLinkage)
569std::optional<HighlightingModifier> scopeModifier(
const Type *T) {
572 if (T->isBuiltinType())
574 if (
auto *TD = dyn_cast<TemplateTypeParmType>(T))
575 return scopeModifier(TD->getDecl());
576 if (
auto *TD = T->getAsTagDecl())
577 return scopeModifier(TD);
583class CollectExtraHighlightings
588 CollectExtraHighlightings(HighlightingsBuilder &H) : H(H) {}
590 bool VisitCXXConstructExpr(CXXConstructExpr *
E) {
591 highlightMutableReferenceArguments(
E->getConstructor(),
592 {E->getArgs(), E->getNumArgs()});
597 bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
598 if (Init->isMemberInitializer())
599 if (
auto *Member = Init->getMember())
600 highlightMutableReferenceArgument(Member->getType(), Init->getInit());
601 return Base::TraverseConstructorInitializer(Init);
604 bool TraverseTypeConstraint(
const TypeConstraint *
C) {
605 if (
auto *
Args =
C->getTemplateArgsAsWritten())
606 H.addAngleBracketTokens(
Args->getLAngleLoc(),
Args->getRAngleLoc());
607 return Base::TraverseTypeConstraint(
C);
610 bool VisitPredefinedExpr(PredefinedExpr *
E) {
618 bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *
E) {
619 if (
auto *
Args =
E->getTemplateArgsAsWritten())
620 H.addAngleBracketTokens(
Args->getLAngleLoc(),
Args->getRAngleLoc());
624 bool VisitTemplateDecl(TemplateDecl *D) {
625 if (
auto *TPL =
D->getTemplateParameters())
626 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
630 bool VisitTagDecl(TagDecl *D) {
631 for (
unsigned i = 0; i <
D->getNumTemplateParameterLists(); ++i) {
632 if (
auto *TPL =
D->getTemplateParameterList(i))
633 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
638 bool VisitClassTemplatePartialSpecializationDecl(
639 ClassTemplatePartialSpecializationDecl *D) {
640 if (
auto *TPL =
D->getTemplateParameters())
641 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
642 if (
auto *
Args =
D->getTemplateArgsAsWritten())
643 H.addAngleBracketTokens(
Args->getLAngleLoc(),
Args->getRAngleLoc());
647 bool VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) {
648 if (
auto *
Args =
D->getTemplateArgsInfo())
649 H.addAngleBracketTokens(
Args->getLAngleLoc(),
Args->getRAngleLoc());
653 bool VisitVarTemplatePartialSpecializationDecl(
654 VarTemplatePartialSpecializationDecl *D) {
655 if (
auto *TPL =
D->getTemplateParameters())
656 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
657 if (
auto *
Args =
D->getTemplateArgsAsWritten())
658 H.addAngleBracketTokens(
Args->getLAngleLoc(),
Args->getRAngleLoc());
662 bool VisitClassScopeFunctionSpecializationDecl(
663 ClassScopeFunctionSpecializationDecl *D) {
664 if (
auto *
Args =
D->getTemplateArgsAsWritten())
665 H.addAngleBracketTokens(
Args->getLAngleLoc(),
Args->getRAngleLoc());
669 bool VisitDeclRefExpr(DeclRefExpr *
E) {
670 H.addAngleBracketTokens(
E->getLAngleLoc(),
E->getRAngleLoc());
673 bool VisitMemberExpr(MemberExpr *
E) {
674 H.addAngleBracketTokens(
E->getLAngleLoc(),
E->getRAngleLoc());
678 bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc L) {
679 H.addAngleBracketTokens(L.getLAngleLoc(), L.getRAngleLoc());
683 bool VisitAutoTypeLoc(AutoTypeLoc L) {
684 if (L.isConstrained())
685 H.addAngleBracketTokens(L.getLAngleLoc(), L.getRAngleLoc());
689 bool VisitFunctionDecl(FunctionDecl *D) {
690 if (
D->isOverloadedOperator()) {
691 const auto AddOpDeclToken = [&](SourceLocation
Loc) {
694 if (
D->isThisDeclarationADefinition())
697 const auto Range =
D->getNameInfo().getCXXOperatorNameRange();
698 AddOpDeclToken(
Range.getBegin());
699 const auto Kind =
D->getOverloadedOperator();
700 if (
Kind == OO_Call ||
Kind == OO_Subscript)
701 AddOpDeclToken(
Range.getEnd());
703 if (
auto *
Args =
D->getTemplateSpecializationArgsAsWritten())
704 H.addAngleBracketTokens(
Args->getLAngleLoc(),
Args->getRAngleLoc());
705 if (
auto *I =
D->getDependentSpecializationInfo())
706 H.addAngleBracketTokens(I->getLAngleLoc(), I->getRAngleLoc());
710 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *
E) {
711 const auto AddOpToken = [&](SourceLocation
Loc) {
715 AddOpToken(
E->getOperatorLoc());
716 const auto Kind =
E->getOperator();
717 if (
Kind == OO_Call ||
Kind == OO_Subscript) {
718 if (
auto *Callee =
E->getCallee())
719 AddOpToken(Callee->getBeginLoc());
724 bool VisitUnaryOperator(UnaryOperator *Op) {
726 if (Op->getSubExpr()->isTypeDependent())
731 bool VisitBinaryOperator(BinaryOperator *Op) {
733 if (Op->getLHS()->isTypeDependent() || Op->getRHS()->isTypeDependent())
738 bool VisitConditionalOperator(ConditionalOperator *Op) {
744 bool VisitCXXNewExpr(CXXNewExpr *
E) {
746 if (isa_and_present<CXXMethodDecl>(
E->getOperatorNew()))
751 bool VisitCXXDeleteExpr(CXXDeleteExpr *
E) {
753 if (isa_and_present<CXXMethodDecl>(
E->getOperatorDelete()))
758 bool VisitCXXNamedCastExpr(CXXNamedCastExpr *
E) {
759 const auto &
B =
E->getAngleBrackets();
760 H.addAngleBracketTokens(
B.getBegin(),
B.getEnd());
764 bool VisitCallExpr(CallExpr *
E) {
767 if (isa<UserDefinedLiteral>(
E))
772 llvm::ArrayRef<const Expr *>
Args = {
E->getArgs(),
E->getNumArgs()};
773 if (
auto *CallOp = dyn_cast<CXXOperatorCallExpr>(
E)) {
774 switch (CallOp->getOperator()) {
784 highlightMutableReferenceArguments(
785 dyn_cast_or_null<FunctionDecl>(
E->getCalleeDecl()),
Args);
790 void highlightMutableReferenceArgument(QualType T,
const Expr *Arg) {
797 bool IsRef = T->isLValueReferenceType();
798 bool IsPtr = T->isPointerType();
799 if ((!IsRef && !IsPtr) || T->getPointeeType().isConstQualified() ||
800 T->isDependentType()) {
804 std::optional<SourceLocation>
Location;
809 if (
auto *IC = dyn_cast<ImplicitCastExpr>(Arg))
810 Arg = IC->getSubExprAsWritten();
811 if (
auto *UO = dyn_cast<UnaryOperator>(Arg)) {
812 if (UO->getOpcode() == UO_AddrOf)
813 Arg = UO->getSubExpr();
815 if (
auto *DR = dyn_cast<DeclRefExpr>(Arg))
817 else if (
auto *
M = dyn_cast<MemberExpr>(Arg))
827 highlightMutableReferenceArguments(
const FunctionDecl *FD,
828 llvm::ArrayRef<const Expr *const>
Args) {
832 if (
auto *ProtoType = FD->getType()->getAs<FunctionProtoType>()) {
837 I < std::min(
size_t(ProtoType->getNumParams()),
Args.size()); ++I) {
838 highlightMutableReferenceArgument(ProtoType->getParamType(I),
Args[I]);
843 bool VisitDecltypeTypeLoc(DecltypeTypeLoc L) {
844 if (
auto K = kindForType(L.getTypePtr(), H.getResolver())) {
845 auto &Tok = H.addToken(L.getBeginLoc(), *
K)
847 if (
auto Mod = scopeModifier(L.getTypePtr()))
848 Tok.addModifier(*Mod);
849 if (isDefaultLibrary(L.getTypePtr()))
855 bool VisitCXXDestructorDecl(CXXDestructorDecl *D) {
856 if (
auto *TI =
D->getNameInfo().getNamedTypeInfo()) {
857 SourceLocation
Loc = TI->getTypeLoc().getBeginLoc();
860 if (
D->isThisDeclarationADefinition())
866 bool VisitCXXMemberCallExpr(CXXMemberCallExpr *
CE) {
869 if (
auto *D =
CE->getMethodDecl()) {
870 if (isa<CXXDestructorDecl>(D)) {
871 if (
auto *ME = dyn_cast<MemberExpr>(
CE->getCallee())) {
872 if (
auto *TI = ME->getMemberNameInfo().getNamedTypeInfo()) {
873 H.addExtraModifier(TI->getTypeLoc().getBeginLoc(),
877 }
else if (
D->isOverloadedOperator()) {
878 if (
auto *ME = dyn_cast<MemberExpr>(
CE->getCallee()))
880 ME->getMemberNameInfo().getCXXOperatorNameRange().getBegin(),
888 bool VisitDeclaratorDecl(DeclaratorDecl *D) {
889 for (
unsigned i = 0; i <
D->getNumTemplateParameterLists(); ++i) {
890 if (
auto *TPL =
D->getTemplateParameterList(i))
891 H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
893 auto *AT =
D->getType()->getContainedAutoType();
897 kindForType(AT->getDeducedType().getTypePtrOrNull(), H.getResolver());
900 SourceLocation StartLoc =
D->getTypeSpecStartLoc();
905 if (StartLoc ==
D->getLocation())
909 const Type *
Deduced = AT->getDeducedType().getTypePtrOrNull();
910 if (
auto Mod = scopeModifier(
Deduced))
911 Tok.addModifier(*Mod);
919 void highlightObjCSelector(
const ArrayRef<SourceLocation> &Locs,
bool Decl,
923 for (SourceLocation Part : Locs) {
937 bool VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
938 llvm::SmallVector<SourceLocation> Locs;
939 OMD->getSelectorLocs(Locs);
940 highlightObjCSelector(Locs,
true,
941 OMD->isThisDeclarationADefinition(),
942 OMD->isClassMethod(), isDefaultLibrary(OMD));
946 bool VisitObjCMessageExpr(ObjCMessageExpr *OME) {
947 llvm::SmallVector<SourceLocation> Locs;
948 OME->getSelectorLocs(Locs);
950 if (ObjCMethodDecl *OMD = OME->getMethodDecl())
952 highlightObjCSelector(Locs,
false,
false,
961 void highlightObjCImplicitPropertyRef(
const ObjCMethodDecl *OMD,
962 SourceLocation
Loc) {
965 if (OMD->isClassMethod())
967 if (isDefaultLibrary(OMD))
971 bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *OPRE) {
975 if (!OPRE->isImplicitProperty())
981 if (OPRE->isMessagingGetter()) {
982 highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertyGetter(),
983 OPRE->getLocation());
986 if (OPRE->isMessagingSetter()) {
987 highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertySetter(),
988 OPRE->getLocation());
993 bool VisitOverloadExpr(OverloadExpr *
E) {
994 H.addAngleBracketTokens(
E->getLAngleLoc(),
E->getRAngleLoc());
995 if (!
E->decls().empty())
999 if (llvm::isa<UnresolvedMemberExpr>(
E))
1005 bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *
E) {
1009 H.addAngleBracketTokens(
E->getLAngleLoc(),
E->getRAngleLoc());
1013 bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *
E) {
1017 H.addAngleBracketTokens(
E->getLAngleLoc(),
E->getRAngleLoc());
1021 bool VisitAttr(Attr *A) {
1022 switch (
A->getKind()) {
1023 case attr::Override:
1033 bool VisitDependentNameTypeLoc(DependentNameTypeLoc L) {
1040 bool VisitDependentTemplateSpecializationTypeLoc(
1041 DependentTemplateSpecializationTypeLoc L) {
1045 H.addAngleBracketTokens(L.getLAngleLoc(), L.getRAngleLoc());
1049 bool TraverseTemplateArgumentLoc(TemplateArgumentLoc L) {
1052 if (L.getArgument().getKind() != TemplateArgument::Template &&
1053 L.getArgument().getKind() != TemplateArgument::TemplateExpansion)
1054 return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
1056 TemplateName N = L.getArgument().getAsTemplateOrTemplatePattern();
1057 switch (N.getKind()) {
1058 case TemplateName::OverloadedTemplate:
1063 case TemplateName::DependentTemplate:
1064 case TemplateName::AssumedTemplate:
1068 case TemplateName::Template:
1069 case TemplateName::QualifiedTemplate:
1070 case TemplateName::SubstTemplateTemplateParm:
1071 case TemplateName::SubstTemplateTemplateParmPack:
1072 case TemplateName::UsingTemplate:
1076 return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
1084 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc Q) {
1085 if (NestedNameSpecifier *NNS = Q.getNestedNameSpecifier()) {
1086 if (NNS->getKind() == NestedNameSpecifier::Identifier)
1091 return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(Q);
1095 HighlightingsBuilder &H;
1100 auto &
C =
AST.getASTContext();
1104 CollectExtraHighlightings(
Builder).TraverseAST(
C);
1110 if (!canHighlightName(Decl->getDeclName()))
1112 auto Kind = kindForDecl(Decl, AST.getHeuristicResolver());
1115 auto &Tok = Builder.addToken(R.NameLoc, *Kind);
1118 if (auto *TD = dyn_cast<TemplateDecl>(Decl)) {
1119 if (auto *Templated = TD->getTemplatedDecl())
1122 if (
auto Mod = scopeModifier(
Decl))
1123 Tok.addModifier(*Mod);
1128 if (isAbstract(
Decl))
1130 if (isVirtual(
Decl))
1132 if (isDependent(
Decl))
1134 if (isDefaultLibrary(
Decl))
1136 if (
Decl->isDeprecated())
1138 if (isa<CXXConstructorDecl>(
Decl))
1144 if (!isa<UnresolvedUsingValueDecl>(Decl))
1145 Tok.addModifier(HighlightingModifier::Declaration);
1146 if (isUniqueDefinition(Decl))
1147 Tok.addModifier(HighlightingModifier::Definition);
1151 AST.getHeuristicResolver());
1153 auto AddMacro = [&](
const MacroOccurrence &
M) {
1159 for (
const auto &SIDToRefs :
AST.getMacros().MacroRefs)
1160 for (
const auto &
M : SIDToRefs.second)
1162 for (
const auto &
M :
AST.getMacros().UnknownMacros)
1170 case HighlightingKind::Variable:
1171 return OS <<
"Variable";
1172 case HighlightingKind::LocalVariable:
1173 return OS <<
"LocalVariable";
1174 case HighlightingKind::Parameter:
1175 return OS <<
"Parameter";
1176 case HighlightingKind::Function:
1177 return OS <<
"Function";
1178 case HighlightingKind::Method:
1179 return OS <<
"Method";
1180 case HighlightingKind::StaticMethod:
1181 return OS <<
"StaticMethod";
1182 case HighlightingKind::Field:
1183 return OS <<
"Field";
1184 case HighlightingKind::StaticField:
1185 return OS <<
"StaticField";
1186 case HighlightingKind::Class:
1187 return OS <<
"Class";
1188 case HighlightingKind::Interface:
1189 return OS <<
"Interface";
1190 case HighlightingKind::Enum:
1191 return OS <<
"Enum";
1192 case HighlightingKind::EnumConstant:
1193 return OS <<
"EnumConstant";
1194 case HighlightingKind::Typedef:
1195 return OS <<
"Typedef";
1196 case HighlightingKind::Type:
1197 return OS <<
"Type";
1198 case HighlightingKind::Unknown:
1199 return OS <<
"Unknown";
1200 case HighlightingKind::Namespace:
1201 return OS <<
"Namespace";
1202 case HighlightingKind::TemplateParameter:
1203 return OS <<
"TemplateParameter";
1204 case HighlightingKind::Concept:
1205 return OS <<
"Concept";
1206 case HighlightingKind::Primitive:
1207 return OS <<
"Primitive";
1208 case HighlightingKind::Macro:
1209 return OS <<
"Macro";
1210 case HighlightingKind::Modifier:
1211 return OS <<
"Modifier";
1212 case HighlightingKind::Operator:
1213 return OS <<
"Operator";
1214 case HighlightingKind::Bracket:
1215 return OS <<
"Bracket";
1216 case HighlightingKind::InactiveCode:
1217 return OS <<
"InactiveCode";
1219 llvm_unreachable(
"invalid HighlightingKind");
1223 case HighlightingModifier::Declaration:
1224 return OS <<
"decl";
1225 case HighlightingModifier::Definition:
1227 case HighlightingModifier::ConstructorOrDestructor:
1228 return OS <<
"constrDestr";
1235 return std::tie(L.R, L.Kind, L.Modifiers) ==
1239 return std::tie(L.R, L.Kind, L.Modifiers) <
1243std::vector<SemanticToken>
1245 llvm::StringRef
Code) {
1246 assert(llvm::is_sorted(Tokens));
1247 std::vector<SemanticToken> Result;
1254 Result.emplace_back();
1258 assert(Tok.R.start.line >= Last->
R.
end.
line);
1259 Out->deltaLine = Tok.R.start.line - Last->
R.
end.
line;
1260 if (
Out->deltaLine == 0) {
1264 Out->deltaStart = Tok.R.start.character;
1267 Out->deltaLine = Tok.R.start.line;
1268 Out->deltaStart = Tok.R.start.character;
1270 Out->tokenType =
static_cast<unsigned>(Tok.Kind);
1271 Out->tokenModifiers = Tok.Modifiers;
1274 if (Tok.R.end.line == Tok.R.start.line) {
1275 Out->length = Tok.R.end.character - Tok.R.start.character;
1285 for (
int I = Tok.R.start.line; I < Tok.R.end.line; ++I) {
1286 auto LineEnd =
Code.find(
'\n', TokStartOffset);
1287 assert(LineEnd !=
Code.npos);
1288 Out->length = LineEnd - TokStartOffset;
1290 TokStartOffset = LineEnd + 1;
1291 Result.emplace_back();
1292 Out = &Result.back();
1293 *
Out = Result[Result.size() - 2];
1296 Out->deltaStart = 0;
1299 Out->length = Tok.R.end.character;
1312 case HighlightingKind::Variable:
1313 case HighlightingKind::LocalVariable:
1314 case HighlightingKind::StaticField:
1316 case HighlightingKind::Parameter:
1318 case HighlightingKind::Function:
1320 case HighlightingKind::Method:
1322 case HighlightingKind::StaticMethod:
1325 case HighlightingKind::Field:
1327 case HighlightingKind::Class:
1329 case HighlightingKind::Interface:
1331 case HighlightingKind::Enum:
1333 case HighlightingKind::EnumConstant:
1334 return "enumMember";
1335 case HighlightingKind::Typedef:
1336 case HighlightingKind::Type:
1338 case HighlightingKind::Unknown:
1340 case HighlightingKind::Namespace:
1342 case HighlightingKind::TemplateParameter:
1343 return "typeParameter";
1344 case HighlightingKind::Concept:
1346 case HighlightingKind::Primitive:
1348 case HighlightingKind::Macro:
1350 case HighlightingKind::Modifier:
1352 case HighlightingKind::Operator:
1354 case HighlightingKind::Bracket:
1356 case HighlightingKind::InactiveCode:
1359 llvm_unreachable(
"unhandled HighlightingKind");
1364 case HighlightingModifier::Declaration:
1365 return "declaration";
1366 case HighlightingModifier::Definition:
1367 return "definition";
1368 case HighlightingModifier::Deprecated:
1369 return "deprecated";
1370 case HighlightingModifier::Readonly:
1372 case HighlightingModifier::Static:
1374 case HighlightingModifier::Deduced:
1376 case HighlightingModifier::Abstract:
1378 case HighlightingModifier::Virtual:
1380 case HighlightingModifier::DependentName:
1381 return "dependentName";
1382 case HighlightingModifier::DefaultLibrary:
1383 return "defaultLibrary";
1384 case HighlightingModifier::UsedAsMutableReference:
1385 return "usedAsMutableReference";
1386 case HighlightingModifier::UsedAsMutablePointer:
1387 return "usedAsMutablePointer";
1388 case HighlightingModifier::ConstructorOrDestructor:
1389 return "constructorOrDestructor";
1390 case HighlightingModifier::UserDefined:
1391 return "userDefined";
1392 case HighlightingModifier::FunctionScope:
1393 return "functionScope";
1394 case HighlightingModifier::ClassScope:
1395 return "classScope";
1396 case HighlightingModifier::FileScope:
1398 case HighlightingModifier::GlobalScope:
1399 return "globalScope";
1401 llvm_unreachable(
"unhandled HighlightingModifier");
1404std::vector<SemanticTokensEdit>
1406 llvm::ArrayRef<SemanticToken> New) {
1411 while (!Old.empty() && !New.empty() && Old.front() == New.front()) {
1413 Old = Old.drop_front();
1414 New = New.drop_front();
1416 while (!Old.empty() && !New.empty() && Old.back() == New.back()) {
1417 Old = Old.drop_back();
1418 New = New.drop_back();
1421 if (Old.empty() && New.empty())
1425 Edit.deleteTokens = Old.size();
1427 return {std::move(
Edit)};
const FunctionDecl * Decl
CodeCompletionBuilder Builder
CompiledFragmentImpl & Out
CharSourceRange Range
SourceRange for the file name.
const google::protobuf::Message & M
llvm::raw_string_ostream OS
std::vector< const NamedDecl * > resolveUsingValueDecl(const UnresolvedUsingValueDecl *UUVD) const
Stores and provides access to parsed AST.
llvm::StringRef toSemanticTokenModifier(HighlightingModifier Modifier)
Range halfOpenToRange(const SourceManager &SM, CharSourceRange R)
llvm::StringRef toSemanticTokenType(HighlightingKind Kind)
size_t lspLength(llvm::StringRef Code)
std::vector< SemanticToken > toSemanticTokens(llvm::ArrayRef< HighlightingToken > Tokens, llvm::StringRef Code)
std::vector< SemanticTokensEdit > diffTokens(llvm::ArrayRef< SemanticToken > Old, llvm::ArrayRef< SemanticToken > New)
void findExplicitReferences(const Stmt *S, llvm::function_ref< void(ReferenceLoc)> Out, const HeuristicResolver *Resolver)
Recursively traverse S and report all references explicitly written in the code.
bool operator==(const Inclusion &LHS, const Inclusion &RHS)
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc)
Turn a SourceLocation into a [line, column] pair.
llvm::Expected< size_t > positionToOffset(llvm::StringRef Code, Position P, bool AllowColumnsBeyondLineLength)
Turn a [line, column] pair into an offset in Code.
bool operator<(const Ref &L, const Ref &R)
@ Type
An inlay hint that for a type annotation.
void elog(const char *Fmt, Ts &&... Vals)
@ Underlying
This is the underlying declaration for a renaming-alias, decltype etc.
std::vector< HighlightingToken > getSemanticHighlightings(ParsedAST &AST)
@ ConstructorOrDestructor
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
A set of edits generated for a single file.
int line
Line position in a document (zero-based).
int character
Character offset on a line in a document (zero-based).
Position start
The range's start position.
Position end
The range's end position.
Information about a reference written in the source code, independent of the actual AST node that thi...
bool IsDecl
True if the reference is a declaration or definition;.
llvm::SmallVector< const NamedDecl *, 1 > Targets
A list of targets referenced by this name.
Specifies a single semantic token in the document.
Describes a replacement of a contiguous range of semanticTokens.