xref: /llvm-project/clang-tools-extra/clangd/SemanticHighlighting.cpp (revision ae932becb2c952876edbb3591bfa997bf4629a4d)
1 //===--- SemanticHighlighting.cpp - ------------------------- ---*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "SemanticHighlighting.h"
10 #include "Config.h"
11 #include "FindTarget.h"
12 #include "ParsedAST.h"
13 #include "Protocol.h"
14 #include "SourceCode.h"
15 #include "support/Logger.h"
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/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"
35 #include <algorithm>
36 #include <optional>
37 
38 namespace clang {
39 namespace clangd {
40 namespace {
41 
42 /// Get the last Position on a given line.
43 llvm::Expected<Position> endOfLine(llvm::StringRef Code, int Line) {
44   auto StartOfLine = positionToOffset(Code, Position{Line, 0});
45   if (!StartOfLine)
46     return StartOfLine.takeError();
47   StringRef LineText = Code.drop_front(*StartOfLine).take_until([](char C) {
48     return C == '\n';
49   });
50   return Position{Line, static_cast<int>(lspLength(LineText))};
51 }
52 
53 /// Some names are not written in the source code and cannot be highlighted,
54 /// e.g. anonymous classes. This function detects those cases.
55 bool canHighlightName(DeclarationName Name) {
56   switch (Name.getNameKind()) {
57   case DeclarationName::Identifier: {
58     auto *II = Name.getAsIdentifierInfo();
59     return II && !II->getName().empty();
60   }
61   case DeclarationName::CXXConstructorName:
62   case DeclarationName::CXXDestructorName:
63     return true;
64   case DeclarationName::ObjCZeroArgSelector:
65   case DeclarationName::ObjCOneArgSelector:
66   case DeclarationName::ObjCMultiArgSelector:
67     // Multi-arg selectors need special handling, and we handle 0/1 arg
68     // selectors there too.
69     return false;
70   case DeclarationName::CXXConversionFunctionName:
71   case DeclarationName::CXXOperatorName:
72   case DeclarationName::CXXDeductionGuideName:
73   case DeclarationName::CXXLiteralOperatorName:
74   case DeclarationName::CXXUsingDirective:
75     return false;
76   }
77   llvm_unreachable("invalid name kind");
78 }
79 
80 bool isUniqueDefinition(const NamedDecl *Decl) {
81   if (auto *Func = dyn_cast<FunctionDecl>(Decl))
82     return Func->isThisDeclarationADefinition();
83   if (auto *Klass = dyn_cast<CXXRecordDecl>(Decl))
84     return Klass->isThisDeclarationADefinition();
85   if (auto *Iface = dyn_cast<ObjCInterfaceDecl>(Decl))
86     return Iface->isThisDeclarationADefinition();
87   if (auto *Proto = dyn_cast<ObjCProtocolDecl>(Decl))
88     return Proto->isThisDeclarationADefinition();
89   if (auto *Var = dyn_cast<VarDecl>(Decl))
90     return Var->isThisDeclarationADefinition();
91   return isa<TemplateTypeParmDecl>(Decl) ||
92          isa<NonTypeTemplateParmDecl>(Decl) ||
93          isa<TemplateTemplateParmDecl>(Decl) || isa<ObjCCategoryDecl>(Decl) ||
94          isa<ObjCImplDecl>(Decl);
95 }
96 
97 std::optional<HighlightingKind> kindForType(const Type *TP,
98                                             const HeuristicResolver *Resolver);
99 std::optional<HighlightingKind> kindForDecl(const NamedDecl *D,
100                                             const HeuristicResolver *Resolver) {
101   if (auto *USD = dyn_cast<UsingShadowDecl>(D)) {
102     if (auto *Target = USD->getTargetDecl())
103       D = Target;
104   }
105   if (auto *TD = dyn_cast<TemplateDecl>(D)) {
106     if (auto *Templated = TD->getTemplatedDecl())
107       D = Templated;
108   }
109   if (auto *TD = dyn_cast<TypedefNameDecl>(D)) {
110     // We try to highlight typedefs as their underlying type.
111     if (auto K =
112             kindForType(TD->getUnderlyingType().getTypePtrOrNull(), Resolver))
113       return K;
114     // And fallback to a generic kind if this fails.
115     return HighlightingKind::Typedef;
116   }
117   // We highlight class decls, constructor decls and destructor decls as
118   // `Class` type. The destructor decls are handled in `VisitTagTypeLoc` (we
119   // will visit a TypeLoc where the underlying Type is a CXXRecordDecl).
120   if (auto *RD = llvm::dyn_cast<RecordDecl>(D)) {
121     // We don't want to highlight lambdas like classes.
122     if (RD->isLambda())
123       return std::nullopt;
124     return HighlightingKind::Class;
125   }
126   if (isa<ClassTemplateDecl, RecordDecl, CXXConstructorDecl, ObjCInterfaceDecl,
127           ObjCImplementationDecl>(D))
128     return HighlightingKind::Class;
129   if (isa<ObjCProtocolDecl>(D))
130     return HighlightingKind::Interface;
131   if (isa<ObjCCategoryDecl, ObjCCategoryImplDecl>(D))
132     return HighlightingKind::Namespace;
133   if (auto *MD = dyn_cast<CXXMethodDecl>(D))
134     return MD->isStatic() ? HighlightingKind::StaticMethod
135                           : HighlightingKind::Method;
136   if (auto *OMD = dyn_cast<ObjCMethodDecl>(D))
137     return OMD->isClassMethod() ? HighlightingKind::StaticMethod
138                                 : HighlightingKind::Method;
139   if (isa<FieldDecl, IndirectFieldDecl, ObjCPropertyDecl>(D))
140     return HighlightingKind::Field;
141   if (isa<EnumDecl>(D))
142     return HighlightingKind::Enum;
143   if (isa<EnumConstantDecl>(D))
144     return HighlightingKind::EnumConstant;
145   if (isa<ParmVarDecl>(D))
146     return HighlightingKind::Parameter;
147   if (auto *VD = dyn_cast<VarDecl>(D)) {
148     if (isa<ImplicitParamDecl>(VD)) // e.g. ObjC Self
149       return std::nullopt;
150     return VD->isStaticDataMember()
151                ? HighlightingKind::StaticField
152                : VD->isLocalVarDecl() ? HighlightingKind::LocalVariable
153                                       : HighlightingKind::Variable;
154   }
155   if (const auto *BD = dyn_cast<BindingDecl>(D))
156     return BD->getDeclContext()->isFunctionOrMethod()
157                ? HighlightingKind::LocalVariable
158                : HighlightingKind::Variable;
159   if (isa<FunctionDecl>(D))
160     return HighlightingKind::Function;
161   if (isa<NamespaceDecl>(D) || isa<NamespaceAliasDecl>(D) ||
162       isa<UsingDirectiveDecl>(D))
163     return HighlightingKind::Namespace;
164   if (isa<TemplateTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
165       isa<NonTypeTemplateParmDecl>(D))
166     return HighlightingKind::TemplateParameter;
167   if (isa<ConceptDecl>(D))
168     return HighlightingKind::Concept;
169   if (isa<LabelDecl>(D))
170     return HighlightingKind::Label;
171   if (const auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(D)) {
172     auto Targets = Resolver->resolveUsingValueDecl(UUVD);
173     if (!Targets.empty() && Targets[0] != UUVD) {
174       return kindForDecl(Targets[0], Resolver);
175     }
176     return HighlightingKind::Unknown;
177   }
178   return std::nullopt;
179 }
180 std::optional<HighlightingKind> kindForType(const Type *TP,
181                                             const HeuristicResolver *Resolver) {
182   if (!TP)
183     return std::nullopt;
184   if (TP->isBuiltinType()) // Builtins are special, they do not have decls.
185     return HighlightingKind::Primitive;
186   if (auto *TD = dyn_cast<TemplateTypeParmType>(TP))
187     return kindForDecl(TD->getDecl(), Resolver);
188   if (isa<ObjCObjectPointerType>(TP))
189     return HighlightingKind::Class;
190   if (auto *TD = TP->getAsTagDecl())
191     return kindForDecl(TD, Resolver);
192   return std::nullopt;
193 }
194 
195 // Whether T is const in a loose sense - is a variable with this type readonly?
196 bool isConst(QualType T) {
197   if (T.isNull())
198     return false;
199   T = T.getNonReferenceType();
200   if (T.isConstQualified())
201     return true;
202   if (const auto *AT = T->getAsArrayTypeUnsafe())
203     return isConst(AT->getElementType());
204   if (isConst(T->getPointeeType()))
205     return true;
206   return false;
207 }
208 
209 // Whether D is const in a loose sense (should it be highlighted as such?)
210 // FIXME: This is separate from whether *a particular usage* can mutate D.
211 //        We may want V in V.size() to be readonly even if V is mutable.
212 bool isConst(const Decl *D) {
213   if (llvm::isa<EnumConstantDecl>(D) || llvm::isa<NonTypeTemplateParmDecl>(D))
214     return true;
215   if (llvm::isa<FieldDecl>(D) || llvm::isa<VarDecl>(D) ||
216       llvm::isa<MSPropertyDecl>(D) || llvm::isa<BindingDecl>(D)) {
217     if (isConst(llvm::cast<ValueDecl>(D)->getType()))
218       return true;
219   }
220   if (const auto *OCPD = llvm::dyn_cast<ObjCPropertyDecl>(D)) {
221     if (OCPD->isReadOnly())
222       return true;
223   }
224   if (const auto *MPD = llvm::dyn_cast<MSPropertyDecl>(D)) {
225     if (!MPD->hasSetter())
226       return true;
227   }
228   if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D)) {
229     if (CMD->isConst())
230       return true;
231   }
232   return false;
233 }
234 
235 // "Static" means many things in C++, only some get the "static" modifier.
236 //
237 // Meanings that do:
238 // - Members associated with the class rather than the instance.
239 //   This is what 'static' most often means across languages.
240 // - static local variables
241 //   These are similarly "detached from their context" by the static keyword.
242 //   In practice, these are rarely used inside classes, reducing confusion.
243 //
244 // Meanings that don't:
245 // - Namespace-scoped variables, which have static storage class.
246 //   This is implicit, so the keyword "static" isn't so strongly associated.
247 //   If we want a modifier for these, "global scope" is probably the concept.
248 // - Namespace-scoped variables/functions explicitly marked "static".
249 //   There the keyword changes *linkage* , which is a totally different concept.
250 //   If we want to model this, "file scope" would be a nice modifier.
251 //
252 // This is confusing, and maybe we should use another name, but because "static"
253 // is a standard LSP modifier, having one with that name has advantages.
254 bool isStatic(const Decl *D) {
255   if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
256     return CMD->isStatic();
257   if (const VarDecl *VD = llvm::dyn_cast<VarDecl>(D))
258     return VD->isStaticDataMember() || VD->isStaticLocal();
259   if (const auto *OPD = llvm::dyn_cast<ObjCPropertyDecl>(D))
260     return OPD->isClassProperty();
261   if (const auto *OMD = llvm::dyn_cast<ObjCMethodDecl>(D))
262     return OMD->isClassMethod();
263   return false;
264 }
265 
266 bool isAbstract(const Decl *D) {
267   if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
268     return CMD->isPureVirtual();
269   if (const auto *CRD = llvm::dyn_cast<CXXRecordDecl>(D))
270     return CRD->hasDefinition() && CRD->isAbstract();
271   return false;
272 }
273 
274 bool isVirtual(const Decl *D) {
275   if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
276     return CMD->isVirtual();
277   return false;
278 }
279 
280 bool isDependent(const Decl *D) {
281   if (isa<UnresolvedUsingValueDecl>(D))
282     return true;
283   return false;
284 }
285 
286 /// Returns true if `Decl` is considered to be from a default/system library.
287 /// This currently checks the systemness of the file by include type, although
288 /// different heuristics may be used in the future (e.g. sysroot paths).
289 bool isDefaultLibrary(const Decl *D) {
290   SourceLocation Loc = D->getLocation();
291   if (!Loc.isValid())
292     return false;
293   return D->getASTContext().getSourceManager().isInSystemHeader(Loc);
294 }
295 
296 bool isDefaultLibrary(const Type *T) {
297   if (!T)
298     return false;
299   const Type *Underlying = T->getPointeeOrArrayElementType();
300   if (Underlying->isBuiltinType())
301     return true;
302   if (auto *TD = dyn_cast<TemplateTypeParmType>(Underlying))
303     return isDefaultLibrary(TD->getDecl());
304   if (auto *TD = Underlying->getAsTagDecl())
305     return isDefaultLibrary(TD);
306   return false;
307 }
308 
309 // For a macro usage `DUMP(foo)`, we want:
310 //  - DUMP --> "macro"
311 //  - foo --> "variable".
312 SourceLocation getHighlightableSpellingToken(SourceLocation L,
313                                              const SourceManager &SM) {
314   if (L.isFileID())
315     return SM.isWrittenInMainFile(L) ? L : SourceLocation{};
316   // Tokens expanded from the macro body contribute no highlightings.
317   if (!SM.isMacroArgExpansion(L))
318     return {};
319   // Tokens expanded from macro args are potentially highlightable.
320   return getHighlightableSpellingToken(SM.getImmediateSpellingLoc(L), SM);
321 }
322 
323 unsigned evaluateHighlightPriority(const HighlightingToken &Tok) {
324   enum HighlightPriority { Dependent = 0, Resolved = 1 };
325   return (Tok.Modifiers & (1 << uint32_t(HighlightingModifier::DependentName)))
326              ? Dependent
327              : Resolved;
328 }
329 
330 // Sometimes we get multiple tokens at the same location:
331 //
332 // - findExplicitReferences() returns a heuristic result for a dependent name
333 //   (e.g. Method) and CollectExtraHighlighting returning a fallback dependent
334 //   highlighting (e.g. Unknown+Dependent).
335 // - macro arguments are expanded multiple times and have different roles
336 // - broken code recovery produces several AST nodes at the same location
337 //
338 // We should either resolve these to a single token, or drop them all.
339 // Our heuristics are:
340 //
341 // - token kinds that come with "dependent-name" modifiers are less reliable
342 //   (these tend to be vague, like Type or Unknown)
343 // - if we have multiple equally reliable kinds, drop token rather than guess
344 // - take the union of modifiers from all tokens
345 //
346 // In particular, heuristically resolved dependent names get their heuristic
347 // kind, plus the dependent modifier.
348 std::optional<HighlightingToken> resolveConflict(const HighlightingToken &A,
349                                                  const HighlightingToken &B) {
350   unsigned Priority1 = evaluateHighlightPriority(A);
351   unsigned Priority2 = evaluateHighlightPriority(B);
352   if (Priority1 == Priority2 && A.Kind != B.Kind)
353     return std::nullopt;
354   auto Result = Priority1 > Priority2 ? A : B;
355   Result.Modifiers = A.Modifiers | B.Modifiers;
356   return Result;
357 }
358 std::optional<HighlightingToken>
359 resolveConflict(ArrayRef<HighlightingToken> Tokens) {
360   if (Tokens.size() == 1)
361     return Tokens[0];
362 
363   assert(Tokens.size() >= 2);
364   std::optional<HighlightingToken> Winner =
365       resolveConflict(Tokens[0], Tokens[1]);
366   for (size_t I = 2; Winner && I < Tokens.size(); ++I)
367     Winner = resolveConflict(*Winner, Tokens[I]);
368   return Winner;
369 }
370 
371 /// Filter to remove particular kinds of highlighting tokens and modifiers from
372 /// the output.
373 class HighlightingFilter {
374 public:
375   HighlightingFilter() {
376     for (auto &Active : ActiveKindLookup)
377       Active = true;
378 
379     ActiveModifiersMask = ~0;
380   }
381 
382   void disableKind(HighlightingKind Kind) {
383     ActiveKindLookup[static_cast<size_t>(Kind)] = false;
384   }
385 
386   void disableModifier(HighlightingModifier Modifier) {
387     ActiveModifiersMask &= ~(1 << static_cast<uint32_t>(Modifier));
388   }
389 
390   bool isHighlightKindActive(HighlightingKind Kind) const {
391     return ActiveKindLookup[static_cast<size_t>(Kind)];
392   }
393 
394   uint32_t maskModifiers(uint32_t Modifiers) const {
395     return Modifiers & ActiveModifiersMask;
396   }
397 
398   static HighlightingFilter fromCurrentConfig() {
399     const Config &C = Config::current();
400     HighlightingFilter Filter;
401     for (const auto &Kind : C.SemanticTokens.DisabledKinds)
402       if (auto K = highlightingKindFromString(Kind))
403         Filter.disableKind(*K);
404     for (const auto &Modifier : C.SemanticTokens.DisabledModifiers)
405       if (auto M = highlightingModifierFromString(Modifier))
406         Filter.disableModifier(*M);
407 
408     return Filter;
409   }
410 
411 private:
412   bool ActiveKindLookup[static_cast<size_t>(HighlightingKind::LastKind) + 1];
413   uint32_t ActiveModifiersMask;
414 };
415 
416 /// Consumes source locations and maps them to text ranges for highlightings.
417 class HighlightingsBuilder {
418 public:
419   HighlightingsBuilder(const ParsedAST &AST, const HighlightingFilter &Filter)
420       : TB(AST.getTokens()), SourceMgr(AST.getSourceManager()),
421         LangOpts(AST.getLangOpts()), Filter(Filter),
422         Resolver(AST.getHeuristicResolver()) {}
423 
424   HighlightingToken &addToken(SourceLocation Loc, HighlightingKind Kind) {
425     auto Range = getRangeForSourceLocation(Loc);
426     if (!Range)
427       return InvalidHighlightingToken;
428 
429     return addToken(*Range, Kind);
430   }
431 
432   // Most of this function works around
433   // https://github.com/clangd/clangd/issues/871.
434   void addAngleBracketTokens(SourceLocation LLoc, SourceLocation RLoc) {
435     if (!LLoc.isValid() || !RLoc.isValid())
436       return;
437 
438     auto LRange = getRangeForSourceLocation(LLoc);
439     if (!LRange)
440       return;
441 
442     // RLoc might be pointing at a virtual buffer when it's part of a `>>`
443     // token.
444     RLoc = SourceMgr.getFileLoc(RLoc);
445     // Make sure token is part of the main file.
446     RLoc = getHighlightableSpellingToken(RLoc, SourceMgr);
447     if (!RLoc.isValid())
448       return;
449 
450     const auto *RTok = TB.spelledTokenContaining(RLoc);
451     // Handle `>>`. RLoc is either part of `>>` or a spelled token on its own
452     // `>`. If it's the former, slice to have length of 1, if latter use the
453     // token as-is.
454     if (!RTok || RTok->kind() == tok::greatergreater) {
455       Position Begin = sourceLocToPosition(SourceMgr, RLoc);
456       Position End = sourceLocToPosition(SourceMgr, RLoc.getLocWithOffset(1));
457       addToken(*LRange, HighlightingKind::Bracket);
458       addToken({Begin, End}, HighlightingKind::Bracket);
459       return;
460     }
461 
462     // Easy case, we have the `>` token directly available.
463     if (RTok->kind() == tok::greater) {
464       if (auto RRange = getRangeForSourceLocation(RLoc)) {
465         addToken(*LRange, HighlightingKind::Bracket);
466         addToken(*RRange, HighlightingKind::Bracket);
467       }
468       return;
469     }
470   }
471 
472   HighlightingToken &addToken(Range R, HighlightingKind Kind) {
473     if (!Filter.isHighlightKindActive(Kind))
474       return InvalidHighlightingToken;
475 
476     HighlightingToken HT;
477     HT.R = std::move(R);
478     HT.Kind = Kind;
479     Tokens.push_back(std::move(HT));
480     return Tokens.back();
481   }
482 
483   void addExtraModifier(SourceLocation Loc, HighlightingModifier Modifier) {
484     if (auto Range = getRangeForSourceLocation(Loc))
485       ExtraModifiers[*Range].push_back(Modifier);
486   }
487 
488   std::vector<HighlightingToken> collect(ParsedAST &AST) && {
489     // Initializer lists can give duplicates of tokens, therefore all tokens
490     // must be deduplicated.
491     llvm::sort(Tokens);
492     auto Last = std::unique(Tokens.begin(), Tokens.end());
493     Tokens.erase(Last, Tokens.end());
494 
495     // Macros can give tokens that have the same source range but conflicting
496     // kinds. In this case all tokens sharing this source range should be
497     // removed.
498     std::vector<HighlightingToken> NonConflicting;
499     NonConflicting.reserve(Tokens.size());
500     for (ArrayRef<HighlightingToken> TokRef = Tokens; !TokRef.empty();) {
501       ArrayRef<HighlightingToken> Conflicting =
502           TokRef.take_while([&](const HighlightingToken &T) {
503             // TokRef is guaranteed at least one element here because otherwise
504             // this predicate would never fire.
505             return T.R == TokRef.front().R;
506           });
507       if (auto Resolved = resolveConflict(Conflicting)) {
508         // Apply extra collected highlighting modifiers
509         auto Modifiers = ExtraModifiers.find(Resolved->R);
510         if (Modifiers != ExtraModifiers.end()) {
511           for (HighlightingModifier Mod : Modifiers->second) {
512             Resolved->addModifier(Mod);
513           }
514         }
515 
516         Resolved->Modifiers = Filter.maskModifiers(Resolved->Modifiers);
517         NonConflicting.push_back(*Resolved);
518       }
519       // TokRef[Conflicting.size()] is the next token with a different range (or
520       // the end of the Tokens).
521       TokRef = TokRef.drop_front(Conflicting.size());
522     }
523 
524     if (!Filter.isHighlightKindActive(HighlightingKind::InactiveCode))
525       return NonConflicting;
526 
527     const auto &SM = AST.getSourceManager();
528     StringRef MainCode = SM.getBufferOrFake(SM.getMainFileID()).getBuffer();
529 
530     // Merge token stream with "inactive line" markers.
531     std::vector<HighlightingToken> WithInactiveLines;
532     auto SortedInactiveRegions = getInactiveRegions(AST);
533     llvm::sort(SortedInactiveRegions);
534     auto It = NonConflicting.begin();
535     for (const Range &R : SortedInactiveRegions) {
536       // Create one token for each line in the inactive range, so it works
537       // with line-based diffing.
538       assert(R.start.line <= R.end.line);
539       for (int Line = R.start.line; Line <= R.end.line; ++Line) {
540         // Copy tokens before the inactive line
541         for (; It != NonConflicting.end() && It->R.start.line < Line; ++It)
542           WithInactiveLines.push_back(std::move(*It));
543         // Add a token for the inactive line itself.
544         auto EndOfLine = endOfLine(MainCode, Line);
545         if (EndOfLine) {
546           HighlightingToken HT;
547           WithInactiveLines.emplace_back();
548           WithInactiveLines.back().Kind = HighlightingKind::InactiveCode;
549           WithInactiveLines.back().R.start.line = Line;
550           WithInactiveLines.back().R.end = *EndOfLine;
551         } else {
552           elog("Failed to determine end of line: {0}", EndOfLine.takeError());
553         }
554 
555         // Skip any other tokens on the inactive line. e.g.
556         // `#ifndef Foo` is considered as part of an inactive region when Foo is
557         // defined, and there is a Foo macro token.
558         // FIXME: we should reduce the scope of the inactive region to not
559         // include the directive itself.
560         while (It != NonConflicting.end() && It->R.start.line == Line)
561           ++It;
562       }
563     }
564     // Copy tokens after the last inactive line
565     for (; It != NonConflicting.end(); ++It)
566       WithInactiveLines.push_back(std::move(*It));
567     return WithInactiveLines;
568   }
569 
570   const HeuristicResolver *getResolver() const { return Resolver; }
571 
572 private:
573   std::optional<Range> getRangeForSourceLocation(SourceLocation Loc) {
574     Loc = getHighlightableSpellingToken(Loc, SourceMgr);
575     if (Loc.isInvalid())
576       return std::nullopt;
577     // We might have offsets in the main file that don't correspond to any
578     // spelled tokens.
579     const auto *Tok = TB.spelledTokenContaining(Loc);
580     if (!Tok)
581       return std::nullopt;
582     return halfOpenToRange(SourceMgr,
583                            Tok->range(SourceMgr).toCharRange(SourceMgr));
584   }
585 
586   const syntax::TokenBuffer &TB;
587   const SourceManager &SourceMgr;
588   const LangOptions &LangOpts;
589   HighlightingFilter Filter;
590   std::vector<HighlightingToken> Tokens;
591   std::map<Range, llvm::SmallVector<HighlightingModifier, 1>> ExtraModifiers;
592   const HeuristicResolver *Resolver;
593   // returned from addToken(InvalidLoc)
594   HighlightingToken InvalidHighlightingToken;
595 };
596 
597 std::optional<HighlightingModifier> scopeModifier(const NamedDecl *D) {
598   const DeclContext *DC = D->getDeclContext();
599   // Injected "Foo" within the class "Foo" has file scope, not class scope.
600   if (auto *R = dyn_cast_or_null<RecordDecl>(D))
601     if (R->isInjectedClassName())
602       DC = DC->getParent();
603   // Lambda captures are considered function scope, not class scope.
604   if (llvm::isa<FieldDecl>(D))
605     if (const auto *RD = llvm::dyn_cast<RecordDecl>(DC))
606       if (RD->isLambda())
607         return HighlightingModifier::FunctionScope;
608   // Walk up the DeclContext hierarchy until we find something interesting.
609   for (; !DC->isFileContext(); DC = DC->getParent()) {
610     if (DC->isFunctionOrMethod())
611       return HighlightingModifier::FunctionScope;
612     if (DC->isRecord())
613       return HighlightingModifier::ClassScope;
614   }
615   // Some template parameters (e.g. those for variable templates) don't have
616   // meaningful DeclContexts. That doesn't mean they're global!
617   if (DC->isTranslationUnit() && D->isTemplateParameter())
618     return std::nullopt;
619   // ExternalLinkage threshold could be tweaked, e.g. module-visible as global.
620   if (llvm::to_underlying(D->getLinkageInternal()) <
621       llvm::to_underlying(Linkage::External))
622     return HighlightingModifier::FileScope;
623   return HighlightingModifier::GlobalScope;
624 }
625 
626 std::optional<HighlightingModifier> scopeModifier(const Type *T) {
627   if (!T)
628     return std::nullopt;
629   if (T->isBuiltinType())
630     return HighlightingModifier::GlobalScope;
631   if (auto *TD = dyn_cast<TemplateTypeParmType>(T))
632     return scopeModifier(TD->getDecl());
633   if (auto *TD = T->getAsTagDecl())
634     return scopeModifier(TD);
635   return std::nullopt;
636 }
637 
638 /// Produces highlightings, which are not captured by findExplicitReferences,
639 /// e.g. highlights dependent names and 'auto' as the underlying type.
640 class CollectExtraHighlightings
641     : public RecursiveASTVisitor<CollectExtraHighlightings> {
642   using Base = RecursiveASTVisitor<CollectExtraHighlightings>;
643 
644 public:
645   CollectExtraHighlightings(HighlightingsBuilder &H) : H(H) {}
646 
647   bool VisitCXXConstructExpr(CXXConstructExpr *E) {
648     highlightMutableReferenceArguments(E->getConstructor(),
649                                        {E->getArgs(), E->getNumArgs()});
650 
651     return true;
652   }
653 
654   bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
655     if (Init->isMemberInitializer())
656       if (auto *Member = Init->getMember())
657         highlightMutableReferenceArgument(Member->getType(), Init->getInit());
658     return Base::TraverseConstructorInitializer(Init);
659   }
660 
661   bool TraverseTypeConstraint(const TypeConstraint *C) {
662     if (auto *Args = C->getTemplateArgsAsWritten())
663       H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
664     return Base::TraverseTypeConstraint(C);
665   }
666 
667   bool VisitPredefinedExpr(PredefinedExpr *E) {
668     H.addToken(E->getLocation(), HighlightingKind::LocalVariable)
669         .addModifier(HighlightingModifier::Static)
670         .addModifier(HighlightingModifier::Readonly)
671         .addModifier(HighlightingModifier::FunctionScope);
672     return true;
673   }
674 
675   bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
676     if (auto *Args = E->getTemplateArgsAsWritten())
677       H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
678     return true;
679   }
680 
681   bool VisitTemplateDecl(TemplateDecl *D) {
682     if (auto *TPL = D->getTemplateParameters())
683       H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
684     return true;
685   }
686 
687   bool VisitTagDecl(TagDecl *D) {
688     for (unsigned i = 0; i < D->getNumTemplateParameterLists(); ++i) {
689       if (auto *TPL = D->getTemplateParameterList(i))
690         H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
691     }
692     return true;
693   }
694 
695   bool
696   VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D) {
697     if (auto *Args = D->getTemplateArgsAsWritten())
698       H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
699     return true;
700   }
701 
702   bool VisitClassTemplatePartialSpecializationDecl(
703       ClassTemplatePartialSpecializationDecl *D) {
704     if (auto *TPL = D->getTemplateParameters())
705       H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
706     return true;
707   }
708 
709   bool VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) {
710     if (auto *Args = D->getTemplateArgsAsWritten())
711       H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
712     return true;
713   }
714 
715   bool VisitVarTemplatePartialSpecializationDecl(
716       VarTemplatePartialSpecializationDecl *D) {
717     if (auto *TPL = D->getTemplateParameters())
718       H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
719     return true;
720   }
721 
722   bool VisitDeclRefExpr(DeclRefExpr *E) {
723     H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
724     return true;
725   }
726   bool VisitMemberExpr(MemberExpr *E) {
727     H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
728     return true;
729   }
730 
731   bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc L) {
732     H.addAngleBracketTokens(L.getLAngleLoc(), L.getRAngleLoc());
733     return true;
734   }
735 
736   bool VisitFunctionDecl(FunctionDecl *D) {
737     if (D->isOverloadedOperator()) {
738       const auto AddOpDeclToken = [&](SourceLocation Loc) {
739         auto &Token = H.addToken(Loc, HighlightingKind::Operator)
740                           .addModifier(HighlightingModifier::Declaration);
741         if (D->isThisDeclarationADefinition())
742           Token.addModifier(HighlightingModifier::Definition);
743       };
744       const auto Range = D->getNameInfo().getCXXOperatorNameRange();
745       AddOpDeclToken(Range.getBegin());
746       const auto Kind = D->getOverloadedOperator();
747       if (Kind == OO_Call || Kind == OO_Subscript)
748         AddOpDeclToken(Range.getEnd());
749     }
750     if (auto *Args = D->getTemplateSpecializationArgsAsWritten())
751       H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
752     return true;
753   }
754 
755   bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
756     const auto AddOpToken = [&](SourceLocation Loc) {
757       H.addToken(Loc, HighlightingKind::Operator)
758           .addModifier(HighlightingModifier::UserDefined);
759     };
760     AddOpToken(E->getOperatorLoc());
761     const auto Kind = E->getOperator();
762     if (Kind == OO_Call || Kind == OO_Subscript) {
763       if (auto *Callee = E->getCallee())
764         AddOpToken(Callee->getBeginLoc());
765     }
766     return true;
767   }
768 
769   bool VisitUnaryOperator(UnaryOperator *Op) {
770     auto &Token = H.addToken(Op->getOperatorLoc(), HighlightingKind::Operator);
771     if (Op->getSubExpr()->isTypeDependent())
772       Token.addModifier(HighlightingModifier::UserDefined);
773     return true;
774   }
775 
776   bool VisitBinaryOperator(BinaryOperator *Op) {
777     auto &Token = H.addToken(Op->getOperatorLoc(), HighlightingKind::Operator);
778     if (Op->getLHS()->isTypeDependent() || Op->getRHS()->isTypeDependent())
779       Token.addModifier(HighlightingModifier::UserDefined);
780     return true;
781   }
782 
783   bool VisitConditionalOperator(ConditionalOperator *Op) {
784     H.addToken(Op->getQuestionLoc(), HighlightingKind::Operator);
785     H.addToken(Op->getColonLoc(), HighlightingKind::Operator);
786     return true;
787   }
788 
789   bool VisitCXXNewExpr(CXXNewExpr *E) {
790     auto &Token = H.addToken(E->getBeginLoc(), HighlightingKind::Operator);
791     if (isa_and_present<CXXMethodDecl>(E->getOperatorNew()))
792       Token.addModifier(HighlightingModifier::UserDefined);
793     return true;
794   }
795 
796   bool VisitCXXDeleteExpr(CXXDeleteExpr *E) {
797     auto &Token = H.addToken(E->getBeginLoc(), HighlightingKind::Operator);
798     if (isa_and_present<CXXMethodDecl>(E->getOperatorDelete()))
799       Token.addModifier(HighlightingModifier::UserDefined);
800     return true;
801   }
802 
803   bool VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
804     const auto &B = E->getAngleBrackets();
805     H.addAngleBracketTokens(B.getBegin(), B.getEnd());
806     return true;
807   }
808 
809   bool VisitCallExpr(CallExpr *E) {
810     // Highlighting parameters passed by non-const reference does not really
811     // make sense for literals...
812     if (isa<UserDefinedLiteral>(E))
813       return true;
814 
815     // FIXME: consider highlighting parameters of some other overloaded
816     // operators as well
817     llvm::ArrayRef<const Expr *> Args = {E->getArgs(), E->getNumArgs()};
818     if (auto *CallOp = dyn_cast<CXXOperatorCallExpr>(E)) {
819       switch (CallOp->getOperator()) {
820       case OO_Call:
821       case OO_Subscript:
822         Args = Args.drop_front(); // Drop object parameter
823         break;
824       default:
825         return true;
826       }
827     }
828 
829     highlightMutableReferenceArguments(
830         dyn_cast_or_null<FunctionDecl>(E->getCalleeDecl()), Args);
831 
832     return true;
833   }
834 
835   void highlightMutableReferenceArgument(QualType T, const Expr *Arg) {
836     if (!Arg)
837       return;
838 
839     // Is this parameter passed by non-const pointer or reference?
840     // FIXME The condition T->idDependentType() could be relaxed a bit,
841     // e.g. std::vector<T>& is dependent but we would want to highlight it
842     bool IsRef = T->isLValueReferenceType();
843     bool IsPtr = T->isPointerType();
844     if ((!IsRef && !IsPtr) || T->getPointeeType().isConstQualified() ||
845         T->isDependentType()) {
846       return;
847     }
848 
849     std::optional<SourceLocation> Location;
850 
851     // FIXME Add "unwrapping" for ArraySubscriptExpr,
852     //  e.g. highlight `a` in `a[i]`
853     // FIXME Handle dependent expression types
854     if (auto *IC = dyn_cast<ImplicitCastExpr>(Arg))
855       Arg = IC->getSubExprAsWritten();
856     if (auto *UO = dyn_cast<UnaryOperator>(Arg)) {
857       if (UO->getOpcode() == UO_AddrOf)
858         Arg = UO->getSubExpr();
859     }
860     if (auto *DR = dyn_cast<DeclRefExpr>(Arg))
861       Location = DR->getLocation();
862     else if (auto *M = dyn_cast<MemberExpr>(Arg))
863       Location = M->getMemberLoc();
864 
865     if (Location)
866       H.addExtraModifier(*Location,
867                          IsRef ? HighlightingModifier::UsedAsMutableReference
868                                : HighlightingModifier::UsedAsMutablePointer);
869   }
870 
871   void
872   highlightMutableReferenceArguments(const FunctionDecl *FD,
873                                      llvm::ArrayRef<const Expr *const> Args) {
874     if (!FD)
875       return;
876 
877     if (auto *ProtoType = FD->getType()->getAs<FunctionProtoType>()) {
878       // Iterate over the types of the function parameters.
879       // If any of them are non-const reference paramteres, add it as a
880       // highlighting modifier to the corresponding expression
881       for (size_t I = 0;
882            I < std::min(size_t(ProtoType->getNumParams()), Args.size()); ++I) {
883         highlightMutableReferenceArgument(ProtoType->getParamType(I), Args[I]);
884       }
885     }
886   }
887 
888   bool VisitDecltypeTypeLoc(DecltypeTypeLoc L) {
889     if (auto K = kindForType(L.getTypePtr(), H.getResolver())) {
890       auto &Tok = H.addToken(L.getBeginLoc(), *K)
891                       .addModifier(HighlightingModifier::Deduced);
892       if (auto Mod = scopeModifier(L.getTypePtr()))
893         Tok.addModifier(*Mod);
894       if (isDefaultLibrary(L.getTypePtr()))
895         Tok.addModifier(HighlightingModifier::DefaultLibrary);
896     }
897     return true;
898   }
899 
900   bool VisitCXXDestructorDecl(CXXDestructorDecl *D) {
901     if (auto *TI = D->getNameInfo().getNamedTypeInfo()) {
902       SourceLocation Loc = TI->getTypeLoc().getBeginLoc();
903       H.addExtraModifier(Loc, HighlightingModifier::ConstructorOrDestructor);
904       H.addExtraModifier(Loc, HighlightingModifier::Declaration);
905       if (D->isThisDeclarationADefinition())
906         H.addExtraModifier(Loc, HighlightingModifier::Definition);
907     }
908     return true;
909   }
910 
911   bool VisitCXXMemberCallExpr(CXXMemberCallExpr *CE) {
912     // getMethodDecl can return nullptr with member pointers, e.g.
913     // `(foo.*pointer_to_member_fun)(arg);`
914     if (auto *D = CE->getMethodDecl()) {
915       if (isa<CXXDestructorDecl>(D)) {
916         if (auto *ME = dyn_cast<MemberExpr>(CE->getCallee())) {
917           if (auto *TI = ME->getMemberNameInfo().getNamedTypeInfo()) {
918             H.addExtraModifier(TI->getTypeLoc().getBeginLoc(),
919                                HighlightingModifier::ConstructorOrDestructor);
920           }
921         }
922       } else if (D->isOverloadedOperator()) {
923         if (auto *ME = dyn_cast<MemberExpr>(CE->getCallee()))
924           H.addToken(
925                ME->getMemberNameInfo().getCXXOperatorNameRange().getBegin(),
926                HighlightingKind::Operator)
927               .addModifier(HighlightingModifier::UserDefined);
928       }
929     }
930     return true;
931   }
932 
933   bool VisitDeclaratorDecl(DeclaratorDecl *D) {
934     for (unsigned i = 0; i < D->getNumTemplateParameterLists(); ++i) {
935       if (auto *TPL = D->getTemplateParameterList(i))
936         H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
937     }
938     auto *AT = D->getType()->getContainedAutoType();
939     if (!AT)
940       return true;
941     auto K =
942         kindForType(AT->getDeducedType().getTypePtrOrNull(), H.getResolver());
943     if (!K)
944       return true;
945     auto *TSI = D->getTypeSourceInfo();
946     if (!TSI)
947       return true;
948     SourceLocation StartLoc =
949         TSI->getTypeLoc().getContainedAutoTypeLoc().getNameLoc();
950     // The AutoType may not have a corresponding token, e.g. in the case of
951     // init-captures. In this case, StartLoc overlaps with the location
952     // of the decl itself, and producing a token for the type here would result
953     // in both it and the token for the decl being dropped due to conflict.
954     if (StartLoc == D->getLocation())
955       return true;
956 
957     auto &Tok =
958         H.addToken(StartLoc, *K).addModifier(HighlightingModifier::Deduced);
959     const Type *Deduced = AT->getDeducedType().getTypePtrOrNull();
960     if (auto Mod = scopeModifier(Deduced))
961       Tok.addModifier(*Mod);
962     if (isDefaultLibrary(Deduced))
963       Tok.addModifier(HighlightingModifier::DefaultLibrary);
964     return true;
965   }
966 
967   // We handle objective-C selectors specially, because one reference can
968   // cover several non-contiguous tokens.
969   void highlightObjCSelector(const ArrayRef<SourceLocation> &Locs, bool Decl,
970                              bool Def, bool Class, bool DefaultLibrary) {
971     HighlightingKind Kind =
972         Class ? HighlightingKind::StaticMethod : HighlightingKind::Method;
973     for (SourceLocation Part : Locs) {
974       auto &Tok =
975           H.addToken(Part, Kind).addModifier(HighlightingModifier::ClassScope);
976       if (Decl)
977         Tok.addModifier(HighlightingModifier::Declaration);
978       if (Def)
979         Tok.addModifier(HighlightingModifier::Definition);
980       if (Class)
981         Tok.addModifier(HighlightingModifier::Static);
982       if (DefaultLibrary)
983         Tok.addModifier(HighlightingModifier::DefaultLibrary);
984     }
985   }
986 
987   bool VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
988     llvm::SmallVector<SourceLocation> Locs;
989     OMD->getSelectorLocs(Locs);
990     highlightObjCSelector(Locs, /*Decl=*/true,
991                           OMD->isThisDeclarationADefinition(),
992                           OMD->isClassMethod(), isDefaultLibrary(OMD));
993     return true;
994   }
995 
996   bool VisitObjCMessageExpr(ObjCMessageExpr *OME) {
997     llvm::SmallVector<SourceLocation> Locs;
998     OME->getSelectorLocs(Locs);
999     bool DefaultLibrary = false;
1000     if (ObjCMethodDecl *OMD = OME->getMethodDecl())
1001       DefaultLibrary = isDefaultLibrary(OMD);
1002     highlightObjCSelector(Locs, /*Decl=*/false, /*Def=*/false,
1003                           OME->isClassMessage(), DefaultLibrary);
1004     return true;
1005   }
1006 
1007   // Objective-C allows you to use property syntax `self.prop` as sugar for
1008   // `[self prop]` and `[self setProp:]` when there's no explicit `@property`
1009   // for `prop` as well as for class properties. We treat this like a property
1010   // even though semantically it's equivalent to a method expression.
1011   void highlightObjCImplicitPropertyRef(const ObjCMethodDecl *OMD,
1012                                         SourceLocation Loc) {
1013     auto &Tok = H.addToken(Loc, HighlightingKind::Field)
1014                     .addModifier(HighlightingModifier::ClassScope);
1015     if (OMD->isClassMethod())
1016       Tok.addModifier(HighlightingModifier::Static);
1017     if (isDefaultLibrary(OMD))
1018       Tok.addModifier(HighlightingModifier::DefaultLibrary);
1019   }
1020 
1021   bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *OPRE) {
1022     // We need to handle implicit properties here since they will appear to
1023     // reference `ObjCMethodDecl` via an implicit `ObjCMessageExpr`, so normal
1024     // highlighting will not work.
1025     if (!OPRE->isImplicitProperty())
1026       return true;
1027     // A single property expr can reference both a getter and setter, but we can
1028     // only provide a single semantic token, so prefer the getter. In most cases
1029     // the end result should be the same, although it's technically possible
1030     // that the user defines a setter for a system SDK.
1031     if (OPRE->isMessagingGetter()) {
1032       highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertyGetter(),
1033                                        OPRE->getLocation());
1034       return true;
1035     }
1036     if (OPRE->isMessagingSetter()) {
1037       highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertySetter(),
1038                                        OPRE->getLocation());
1039     }
1040     return true;
1041   }
1042 
1043   bool VisitOverloadExpr(OverloadExpr *E) {
1044     H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
1045     if (!E->decls().empty())
1046       return true; // handled by findExplicitReferences.
1047     auto &Tok = H.addToken(E->getNameLoc(), HighlightingKind::Unknown)
1048                     .addModifier(HighlightingModifier::DependentName);
1049     if (llvm::isa<UnresolvedMemberExpr>(E))
1050       Tok.addModifier(HighlightingModifier::ClassScope);
1051     // other case is UnresolvedLookupExpr, scope is unknown.
1052     return true;
1053   }
1054 
1055   bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
1056     H.addToken(E->getMemberNameInfo().getLoc(), HighlightingKind::Unknown)
1057         .addModifier(HighlightingModifier::DependentName)
1058         .addModifier(HighlightingModifier::ClassScope);
1059     H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
1060     return true;
1061   }
1062 
1063   bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
1064     H.addToken(E->getNameInfo().getLoc(), HighlightingKind::Unknown)
1065         .addModifier(HighlightingModifier::DependentName)
1066         .addModifier(HighlightingModifier::ClassScope);
1067     H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
1068     return true;
1069   }
1070 
1071   bool VisitAttr(Attr *A) {
1072     switch (A->getKind()) {
1073     case attr::Override:
1074     case attr::Final:
1075       H.addToken(A->getLocation(), HighlightingKind::Modifier);
1076       break;
1077     default:
1078       break;
1079     }
1080     return true;
1081   }
1082 
1083   bool VisitDependentNameTypeLoc(DependentNameTypeLoc L) {
1084     H.addToken(L.getNameLoc(), HighlightingKind::Type)
1085         .addModifier(HighlightingModifier::DependentName)
1086         .addModifier(HighlightingModifier::ClassScope);
1087     return true;
1088   }
1089 
1090   bool VisitDependentTemplateSpecializationTypeLoc(
1091       DependentTemplateSpecializationTypeLoc L) {
1092     H.addToken(L.getTemplateNameLoc(), HighlightingKind::Type)
1093         .addModifier(HighlightingModifier::DependentName)
1094         .addModifier(HighlightingModifier::ClassScope);
1095     H.addAngleBracketTokens(L.getLAngleLoc(), L.getRAngleLoc());
1096     return true;
1097   }
1098 
1099   bool TraverseTemplateArgumentLoc(TemplateArgumentLoc L) {
1100     // Handle template template arguments only (other arguments are handled by
1101     // their Expr, TypeLoc etc values).
1102     if (L.getArgument().getKind() != TemplateArgument::Template &&
1103         L.getArgument().getKind() != TemplateArgument::TemplateExpansion)
1104       return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
1105 
1106     TemplateName N = L.getArgument().getAsTemplateOrTemplatePattern();
1107     switch (N.getKind()) {
1108     case TemplateName::OverloadedTemplate:
1109       // Template template params must always be class templates.
1110       // Don't bother to try to work out the scope here.
1111       H.addToken(L.getTemplateNameLoc(), HighlightingKind::Class);
1112       break;
1113     case TemplateName::DependentTemplate:
1114     case TemplateName::AssumedTemplate:
1115       H.addToken(L.getTemplateNameLoc(), HighlightingKind::Class)
1116           .addModifier(HighlightingModifier::DependentName);
1117       break;
1118     case TemplateName::Template:
1119     case TemplateName::QualifiedTemplate:
1120     case TemplateName::SubstTemplateTemplateParm:
1121     case TemplateName::SubstTemplateTemplateParmPack:
1122     case TemplateName::UsingTemplate:
1123     case TemplateName::DeducedTemplate:
1124       // Names that could be resolved to a TemplateDecl are handled elsewhere.
1125       break;
1126     }
1127     return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
1128   }
1129 
1130   // findExplicitReferences will walk nested-name-specifiers and
1131   // find anything that can be resolved to a Decl. However, non-leaf
1132   // components of nested-name-specifiers which are dependent names
1133   // (kind "Identifier") cannot be resolved to a decl, so we visit
1134   // them here.
1135   bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc Q) {
1136     if (NestedNameSpecifier *NNS = Q.getNestedNameSpecifier()) {
1137       if (NNS->getKind() == NestedNameSpecifier::Identifier)
1138         H.addToken(Q.getLocalBeginLoc(), HighlightingKind::Type)
1139             .addModifier(HighlightingModifier::DependentName)
1140             .addModifier(HighlightingModifier::ClassScope);
1141     }
1142     return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(Q);
1143   }
1144 
1145 private:
1146   HighlightingsBuilder &H;
1147 };
1148 } // namespace
1149 
1150 std::vector<HighlightingToken>
1151 getSemanticHighlightings(ParsedAST &AST, bool IncludeInactiveRegionTokens) {
1152   auto &C = AST.getASTContext();
1153   HighlightingFilter Filter = HighlightingFilter::fromCurrentConfig();
1154   if (!IncludeInactiveRegionTokens)
1155     Filter.disableKind(HighlightingKind::InactiveCode);
1156   // Add highlightings for AST nodes.
1157   HighlightingsBuilder Builder(AST, Filter);
1158   // Highlight 'decltype' and 'auto' as their underlying types.
1159   CollectExtraHighlightings(Builder).TraverseAST(C);
1160   // Highlight all decls and references coming from the AST.
1161   findExplicitReferences(
1162       C,
1163       [&](ReferenceLoc R) {
1164         for (const NamedDecl *Decl : R.Targets) {
1165           if (!canHighlightName(Decl->getDeclName()))
1166             continue;
1167           auto Kind = kindForDecl(Decl, AST.getHeuristicResolver());
1168           if (!Kind)
1169             continue;
1170           auto &Tok = Builder.addToken(R.NameLoc, *Kind);
1171 
1172           // The attribute tests don't want to look at the template.
1173           if (auto *TD = dyn_cast<TemplateDecl>(Decl)) {
1174             if (auto *Templated = TD->getTemplatedDecl())
1175               Decl = Templated;
1176           }
1177           if (auto Mod = scopeModifier(Decl))
1178             Tok.addModifier(*Mod);
1179           if (isConst(Decl))
1180             Tok.addModifier(HighlightingModifier::Readonly);
1181           if (isStatic(Decl))
1182             Tok.addModifier(HighlightingModifier::Static);
1183           if (isAbstract(Decl))
1184             Tok.addModifier(HighlightingModifier::Abstract);
1185           if (isVirtual(Decl))
1186             Tok.addModifier(HighlightingModifier::Virtual);
1187           if (isDependent(Decl))
1188             Tok.addModifier(HighlightingModifier::DependentName);
1189           if (isDefaultLibrary(Decl))
1190             Tok.addModifier(HighlightingModifier::DefaultLibrary);
1191           if (Decl->isDeprecated())
1192             Tok.addModifier(HighlightingModifier::Deprecated);
1193           if (isa<CXXConstructorDecl>(Decl))
1194             Tok.addModifier(HighlightingModifier::ConstructorOrDestructor);
1195           if (R.IsDecl) {
1196             // Do not treat an UnresolvedUsingValueDecl as a declaration.
1197             // It's more common to think of it as a reference to the
1198             // underlying declaration.
1199             if (!isa<UnresolvedUsingValueDecl>(Decl))
1200               Tok.addModifier(HighlightingModifier::Declaration);
1201             if (isUniqueDefinition(Decl))
1202               Tok.addModifier(HighlightingModifier::Definition);
1203           }
1204         }
1205       },
1206       AST.getHeuristicResolver());
1207   // Add highlightings for macro references.
1208   auto AddMacro = [&](const MacroOccurrence &M) {
1209     auto &T = Builder.addToken(M.toRange(C.getSourceManager()),
1210                                HighlightingKind::Macro);
1211     T.addModifier(HighlightingModifier::GlobalScope);
1212     if (M.IsDefinition)
1213       T.addModifier(HighlightingModifier::Declaration);
1214   };
1215   for (const auto &SIDToRefs : AST.getMacros().MacroRefs)
1216     for (const auto &M : SIDToRefs.second)
1217       AddMacro(M);
1218   for (const auto &M : AST.getMacros().UnknownMacros)
1219     AddMacro(M);
1220 
1221   return std::move(Builder).collect(AST);
1222 }
1223 
1224 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingKind K) {
1225   switch (K) {
1226   case HighlightingKind::Variable:
1227     return OS << "Variable";
1228   case HighlightingKind::LocalVariable:
1229     return OS << "LocalVariable";
1230   case HighlightingKind::Parameter:
1231     return OS << "Parameter";
1232   case HighlightingKind::Function:
1233     return OS << "Function";
1234   case HighlightingKind::Method:
1235     return OS << "Method";
1236   case HighlightingKind::StaticMethod:
1237     return OS << "StaticMethod";
1238   case HighlightingKind::Field:
1239     return OS << "Field";
1240   case HighlightingKind::StaticField:
1241     return OS << "StaticField";
1242   case HighlightingKind::Class:
1243     return OS << "Class";
1244   case HighlightingKind::Interface:
1245     return OS << "Interface";
1246   case HighlightingKind::Enum:
1247     return OS << "Enum";
1248   case HighlightingKind::EnumConstant:
1249     return OS << "EnumConstant";
1250   case HighlightingKind::Typedef:
1251     return OS << "Typedef";
1252   case HighlightingKind::Type:
1253     return OS << "Type";
1254   case HighlightingKind::Unknown:
1255     return OS << "Unknown";
1256   case HighlightingKind::Namespace:
1257     return OS << "Namespace";
1258   case HighlightingKind::TemplateParameter:
1259     return OS << "TemplateParameter";
1260   case HighlightingKind::Concept:
1261     return OS << "Concept";
1262   case HighlightingKind::Primitive:
1263     return OS << "Primitive";
1264   case HighlightingKind::Macro:
1265     return OS << "Macro";
1266   case HighlightingKind::Modifier:
1267     return OS << "Modifier";
1268   case HighlightingKind::Operator:
1269     return OS << "Operator";
1270   case HighlightingKind::Bracket:
1271     return OS << "Bracket";
1272   case HighlightingKind::Label:
1273     return OS << "Label";
1274   case HighlightingKind::InactiveCode:
1275     return OS << "InactiveCode";
1276   }
1277   llvm_unreachable("invalid HighlightingKind");
1278 }
1279 std::optional<HighlightingKind>
1280 highlightingKindFromString(llvm::StringRef Name) {
1281   static llvm::StringMap<HighlightingKind> Lookup = {
1282       {"Variable", HighlightingKind::Variable},
1283       {"LocalVariable", HighlightingKind::LocalVariable},
1284       {"Parameter", HighlightingKind::Parameter},
1285       {"Function", HighlightingKind::Function},
1286       {"Method", HighlightingKind::Method},
1287       {"StaticMethod", HighlightingKind::StaticMethod},
1288       {"Field", HighlightingKind::Field},
1289       {"StaticField", HighlightingKind::StaticField},
1290       {"Class", HighlightingKind::Class},
1291       {"Interface", HighlightingKind::Interface},
1292       {"Enum", HighlightingKind::Enum},
1293       {"EnumConstant", HighlightingKind::EnumConstant},
1294       {"Typedef", HighlightingKind::Typedef},
1295       {"Type", HighlightingKind::Type},
1296       {"Unknown", HighlightingKind::Unknown},
1297       {"Namespace", HighlightingKind::Namespace},
1298       {"TemplateParameter", HighlightingKind::TemplateParameter},
1299       {"Concept", HighlightingKind::Concept},
1300       {"Primitive", HighlightingKind::Primitive},
1301       {"Macro", HighlightingKind::Macro},
1302       {"Modifier", HighlightingKind::Modifier},
1303       {"Operator", HighlightingKind::Operator},
1304       {"Bracket", HighlightingKind::Bracket},
1305       {"InactiveCode", HighlightingKind::InactiveCode},
1306   };
1307 
1308   auto It = Lookup.find(Name);
1309   return It != Lookup.end() ? std::make_optional(It->getValue()) : std::nullopt;
1310 }
1311 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingModifier K) {
1312   switch (K) {
1313   case HighlightingModifier::Declaration:
1314     return OS << "decl"; // abbreviation for common case
1315   case HighlightingModifier::Definition:
1316     return OS << "def"; // abbrevation for common case
1317   case HighlightingModifier::ConstructorOrDestructor:
1318     return OS << "constrDestr";
1319   default:
1320     return OS << toSemanticTokenModifier(K);
1321   }
1322 }
1323 std::optional<HighlightingModifier>
1324 highlightingModifierFromString(llvm::StringRef Name) {
1325   static llvm::StringMap<HighlightingModifier> Lookup = {
1326       {"Declaration", HighlightingModifier::Declaration},
1327       {"Definition", HighlightingModifier::Definition},
1328       {"Deprecated", HighlightingModifier::Deprecated},
1329       {"Deduced", HighlightingModifier::Deduced},
1330       {"Readonly", HighlightingModifier::Readonly},
1331       {"Static", HighlightingModifier::Static},
1332       {"Abstract", HighlightingModifier::Abstract},
1333       {"Virtual", HighlightingModifier::Virtual},
1334       {"DependentName", HighlightingModifier::DependentName},
1335       {"DefaultLibrary", HighlightingModifier::DefaultLibrary},
1336       {"UsedAsMutableReference", HighlightingModifier::UsedAsMutableReference},
1337       {"UsedAsMutablePointer", HighlightingModifier::UsedAsMutablePointer},
1338       {"ConstructorOrDestructor",
1339        HighlightingModifier::ConstructorOrDestructor},
1340       {"UserDefined", HighlightingModifier::UserDefined},
1341       {"FunctionScope", HighlightingModifier::FunctionScope},
1342       {"ClassScope", HighlightingModifier::ClassScope},
1343       {"FileScope", HighlightingModifier::FileScope},
1344       {"GlobalScope", HighlightingModifier::GlobalScope},
1345   };
1346 
1347   auto It = Lookup.find(Name);
1348   return It != Lookup.end() ? std::make_optional(It->getValue()) : std::nullopt;
1349 }
1350 
1351 bool operator==(const HighlightingToken &L, const HighlightingToken &R) {
1352   return std::tie(L.R, L.Kind, L.Modifiers) ==
1353          std::tie(R.R, R.Kind, R.Modifiers);
1354 }
1355 bool operator<(const HighlightingToken &L, const HighlightingToken &R) {
1356   return std::tie(L.R, L.Kind, L.Modifiers) <
1357          std::tie(R.R, R.Kind, R.Modifiers);
1358 }
1359 
1360 std::vector<SemanticToken>
1361 toSemanticTokens(llvm::ArrayRef<HighlightingToken> Tokens,
1362                  llvm::StringRef Code) {
1363   assert(llvm::is_sorted(Tokens));
1364   std::vector<SemanticToken> Result;
1365   // In case we split a HighlightingToken into multiple tokens (e.g. because it
1366   // was spanning multiple lines), this tracks the last one. This prevents
1367   // having a copy all the time.
1368   HighlightingToken Scratch;
1369   const HighlightingToken *Last = nullptr;
1370   for (const HighlightingToken &Tok : Tokens) {
1371     Result.emplace_back();
1372     SemanticToken *Out = &Result.back();
1373     // deltaStart/deltaLine are relative if possible.
1374     if (Last) {
1375       assert(Tok.R.start.line >= Last->R.end.line);
1376       Out->deltaLine = Tok.R.start.line - Last->R.end.line;
1377       if (Out->deltaLine == 0) {
1378         assert(Tok.R.start.character >= Last->R.start.character);
1379         Out->deltaStart = Tok.R.start.character - Last->R.start.character;
1380       } else {
1381         Out->deltaStart = Tok.R.start.character;
1382       }
1383     } else {
1384       Out->deltaLine = Tok.R.start.line;
1385       Out->deltaStart = Tok.R.start.character;
1386     }
1387     Out->tokenType = static_cast<unsigned>(Tok.Kind);
1388     Out->tokenModifiers = Tok.Modifiers;
1389     Last = &Tok;
1390 
1391     if (Tok.R.end.line == Tok.R.start.line) {
1392       Out->length = Tok.R.end.character - Tok.R.start.character;
1393     } else {
1394       // If the token spans a line break, split it into multiple pieces for each
1395       // line.
1396       // This is slow, but multiline tokens are rare.
1397       // FIXME: There's a client capability for supporting multiline tokens,
1398       // respect that.
1399       auto TokStartOffset = llvm::cantFail(positionToOffset(Code, Tok.R.start));
1400       // Note that the loop doesn't cover the last line, which has a special
1401       // length.
1402       for (int I = Tok.R.start.line; I < Tok.R.end.line; ++I) {
1403         auto LineEnd = Code.find('\n', TokStartOffset);
1404         assert(LineEnd != Code.npos);
1405         Out->length = LineEnd - TokStartOffset;
1406         // Token continues on next line, right after the line break.
1407         TokStartOffset = LineEnd + 1;
1408         Result.emplace_back();
1409         Out = &Result.back();
1410         *Out = Result[Result.size() - 2];
1411         // New token starts at the first column of the next line.
1412         Out->deltaLine = 1;
1413         Out->deltaStart = 0;
1414       }
1415       // This is the token on last line.
1416       Out->length = Tok.R.end.character;
1417       // Update the start location for last token, as that's used in the
1418       // relative delta calculation for following tokens.
1419       Scratch = *Last;
1420       Scratch.R.start.line = Tok.R.end.line;
1421       Scratch.R.start.character = 0;
1422       Last = &Scratch;
1423     }
1424   }
1425   return Result;
1426 }
1427 llvm::StringRef toSemanticTokenType(HighlightingKind Kind) {
1428   switch (Kind) {
1429   case HighlightingKind::Variable:
1430   case HighlightingKind::LocalVariable:
1431   case HighlightingKind::StaticField:
1432     return "variable";
1433   case HighlightingKind::Parameter:
1434     return "parameter";
1435   case HighlightingKind::Function:
1436     return "function";
1437   case HighlightingKind::Method:
1438     return "method";
1439   case HighlightingKind::StaticMethod:
1440     // FIXME: better method with static modifier?
1441     return "function";
1442   case HighlightingKind::Field:
1443     return "property";
1444   case HighlightingKind::Class:
1445     return "class";
1446   case HighlightingKind::Interface:
1447     return "interface";
1448   case HighlightingKind::Enum:
1449     return "enum";
1450   case HighlightingKind::EnumConstant:
1451     return "enumMember";
1452   case HighlightingKind::Typedef:
1453   case HighlightingKind::Type:
1454     return "type";
1455   case HighlightingKind::Unknown:
1456     return "unknown"; // nonstandard
1457   case HighlightingKind::Namespace:
1458     return "namespace";
1459   case HighlightingKind::TemplateParameter:
1460     return "typeParameter";
1461   case HighlightingKind::Concept:
1462     return "concept"; // nonstandard
1463   case HighlightingKind::Primitive:
1464     return "type";
1465   case HighlightingKind::Macro:
1466     return "macro";
1467   case HighlightingKind::Modifier:
1468     return "modifier";
1469   case HighlightingKind::Operator:
1470     return "operator";
1471   case HighlightingKind::Bracket:
1472     return "bracket";
1473   case HighlightingKind::Label:
1474     return "label";
1475   case HighlightingKind::InactiveCode:
1476     return "comment";
1477   }
1478   llvm_unreachable("unhandled HighlightingKind");
1479 }
1480 
1481 llvm::StringRef toSemanticTokenModifier(HighlightingModifier Modifier) {
1482   switch (Modifier) {
1483   case HighlightingModifier::Declaration:
1484     return "declaration";
1485   case HighlightingModifier::Definition:
1486     return "definition";
1487   case HighlightingModifier::Deprecated:
1488     return "deprecated";
1489   case HighlightingModifier::Readonly:
1490     return "readonly";
1491   case HighlightingModifier::Static:
1492     return "static";
1493   case HighlightingModifier::Deduced:
1494     return "deduced"; // nonstandard
1495   case HighlightingModifier::Abstract:
1496     return "abstract";
1497   case HighlightingModifier::Virtual:
1498     return "virtual";
1499   case HighlightingModifier::DependentName:
1500     return "dependentName"; // nonstandard
1501   case HighlightingModifier::DefaultLibrary:
1502     return "defaultLibrary";
1503   case HighlightingModifier::UsedAsMutableReference:
1504     return "usedAsMutableReference"; // nonstandard
1505   case HighlightingModifier::UsedAsMutablePointer:
1506     return "usedAsMutablePointer"; // nonstandard
1507   case HighlightingModifier::ConstructorOrDestructor:
1508     return "constructorOrDestructor"; // nonstandard
1509   case HighlightingModifier::UserDefined:
1510     return "userDefined"; // nonstandard
1511   case HighlightingModifier::FunctionScope:
1512     return "functionScope"; // nonstandard
1513   case HighlightingModifier::ClassScope:
1514     return "classScope"; // nonstandard
1515   case HighlightingModifier::FileScope:
1516     return "fileScope"; // nonstandard
1517   case HighlightingModifier::GlobalScope:
1518     return "globalScope"; // nonstandard
1519   }
1520   llvm_unreachable("unhandled HighlightingModifier");
1521 }
1522 
1523 std::vector<SemanticTokensEdit>
1524 diffTokens(llvm::ArrayRef<SemanticToken> Old,
1525            llvm::ArrayRef<SemanticToken> New) {
1526   // For now, just replace everything from the first-last modification.
1527   // FIXME: use a real diff instead, this is bad with include-insertion.
1528 
1529   unsigned Offset = 0;
1530   while (!Old.empty() && !New.empty() && Old.front() == New.front()) {
1531     ++Offset;
1532     Old = Old.drop_front();
1533     New = New.drop_front();
1534   }
1535   while (!Old.empty() && !New.empty() && Old.back() == New.back()) {
1536     Old = Old.drop_back();
1537     New = New.drop_back();
1538   }
1539 
1540   if (Old.empty() && New.empty())
1541     return {};
1542   SemanticTokensEdit Edit;
1543   Edit.startToken = Offset;
1544   Edit.deleteTokens = Old.size();
1545   Edit.tokens = New;
1546   return {std::move(Edit)};
1547 }
1548 
1549 std::vector<Range> getInactiveRegions(ParsedAST &AST) {
1550   std::vector<Range> SkippedRanges(std::move(AST.getMacros().SkippedRanges));
1551   const auto &SM = AST.getSourceManager();
1552   StringRef MainCode = SM.getBufferOrFake(SM.getMainFileID()).getBuffer();
1553   std::vector<Range> InactiveRegions;
1554   for (const Range &Skipped : SkippedRanges) {
1555     Range Inactive = Skipped;
1556     // Sometimes, SkippedRanges contains a range ending at position 0
1557     // of a line. Clients that apply whole-line styles will treat that
1558     // line as inactive which is not desirable, so adjust the ending
1559     // position to be the end of the previous line.
1560     if (Inactive.end.character == 0 && Inactive.end.line > 0) {
1561       --Inactive.end.line;
1562     }
1563     // Exclude the directive lines themselves from the range.
1564     if (Inactive.end.line >= Inactive.start.line + 2) {
1565       ++Inactive.start.line;
1566       --Inactive.end.line;
1567     } else {
1568       // range would be empty, e.g. #endif on next line after #ifdef
1569       continue;
1570     }
1571     // Since we've adjusted the ending line, we need to recompute the
1572     // column to reflect the end of that line.
1573     if (auto EndOfLine = endOfLine(MainCode, Inactive.end.line)) {
1574       Inactive.end = *EndOfLine;
1575     } else {
1576       elog("Failed to determine end of line: {0}", EndOfLine.takeError());
1577       continue;
1578     }
1579     InactiveRegions.push_back(Inactive);
1580   }
1581   return InactiveRegions;
1582 }
1583 
1584 } // namespace clangd
1585 } // namespace clang
1586