//===--- SemanticHighlighting.cpp - ------------------------- ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "SemanticHighlighting.h"
#include "Config.h"
#include "FindTarget.h"
#include "HeuristicResolver.h"
#include "ParsedAST.h"
#include "Protocol.h"
#include "SourceCode.h"
#include "support/Logger.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Tooling/Syntax/Tokens.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Error.h"
#include <algorithm>
#include <optional>

namespace clang {
namespace clangd {
namespace {

/// Get the last Position on a given line.
llvm::Expected<Position> endOfLine(llvm::StringRef Code, int Line) {
  auto StartOfLine = positionToOffset(Code, Position{Line, 0});
  if (!StartOfLine)
    return StartOfLine.takeError();
  StringRef LineText = Code.drop_front(*StartOfLine).take_until([](char C) {
    return C == '\n';
  });
  return Position{Line, static_cast<int>(lspLength(LineText))};
}

/// Some names are not written in the source code and cannot be highlighted,
/// e.g. anonymous classes. This function detects those cases.
bool canHighlightName(DeclarationName Name) {
  switch (Name.getNameKind()) {
  case DeclarationName::Identifier: {
    auto *II = Name.getAsIdentifierInfo();
    return II && !II->getName().empty();
  }
  case DeclarationName::CXXConstructorName:
  case DeclarationName::CXXDestructorName:
    return true;
  case DeclarationName::ObjCZeroArgSelector:
  case DeclarationName::ObjCOneArgSelector:
  case DeclarationName::ObjCMultiArgSelector:
    // Multi-arg selectors need special handling, and we handle 0/1 arg
    // selectors there too.
    return false;
  case DeclarationName::CXXConversionFunctionName:
  case DeclarationName::CXXOperatorName:
  case DeclarationName::CXXDeductionGuideName:
  case DeclarationName::CXXLiteralOperatorName:
  case DeclarationName::CXXUsingDirective:
    return false;
  }
  llvm_unreachable("invalid name kind");
}

bool isUniqueDefinition(const NamedDecl *Decl) {
  if (auto *Func = dyn_cast<FunctionDecl>(Decl))
    return Func->isThisDeclarationADefinition();
  if (auto *Klass = dyn_cast<CXXRecordDecl>(Decl))
    return Klass->isThisDeclarationADefinition();
  if (auto *Iface = dyn_cast<ObjCInterfaceDecl>(Decl))
    return Iface->isThisDeclarationADefinition();
  if (auto *Proto = dyn_cast<ObjCProtocolDecl>(Decl))
    return Proto->isThisDeclarationADefinition();
  if (auto *Var = dyn_cast<VarDecl>(Decl))
    return Var->isThisDeclarationADefinition();
  return isa<TemplateTypeParmDecl>(Decl) ||
         isa<NonTypeTemplateParmDecl>(Decl) ||
         isa<TemplateTemplateParmDecl>(Decl) || isa<ObjCCategoryDecl>(Decl) ||
         isa<ObjCImplDecl>(Decl);
}

std::optional<HighlightingKind> kindForType(const Type *TP,
                                            const HeuristicResolver *Resolver);
std::optional<HighlightingKind> kindForDecl(const NamedDecl *D,
                                            const HeuristicResolver *Resolver) {
  if (auto *USD = dyn_cast<UsingShadowDecl>(D)) {
    if (auto *Target = USD->getTargetDecl())
      D = Target;
  }
  if (auto *TD = dyn_cast<TemplateDecl>(D)) {
    if (auto *Templated = TD->getTemplatedDecl())
      D = Templated;
  }
  if (auto *TD = dyn_cast<TypedefNameDecl>(D)) {
    // We try to highlight typedefs as their underlying type.
    if (auto K =
            kindForType(TD->getUnderlyingType().getTypePtrOrNull(), Resolver))
      return K;
    // And fallback to a generic kind if this fails.
    return HighlightingKind::Typedef;
  }
  // We highlight class decls, constructor decls and destructor decls as
  // `Class` type. The destructor decls are handled in `VisitTagTypeLoc` (we
  // will visit a TypeLoc where the underlying Type is a CXXRecordDecl).
  if (auto *RD = llvm::dyn_cast<RecordDecl>(D)) {
    // We don't want to highlight lambdas like classes.
    if (RD->isLambda())
      return std::nullopt;
    return HighlightingKind::Class;
  }
  if (isa<ClassTemplateDecl, RecordDecl, CXXConstructorDecl, ObjCInterfaceDecl,
          ObjCImplementationDecl>(D))
    return HighlightingKind::Class;
  if (isa<ObjCProtocolDecl>(D))
    return HighlightingKind::Interface;
  if (isa<ObjCCategoryDecl, ObjCCategoryImplDecl>(D))
    return HighlightingKind::Namespace;
  if (auto *MD = dyn_cast<CXXMethodDecl>(D))
    return MD->isStatic() ? HighlightingKind::StaticMethod
                          : HighlightingKind::Method;
  if (auto *OMD = dyn_cast<ObjCMethodDecl>(D))
    return OMD->isClassMethod() ? HighlightingKind::StaticMethod
                                : HighlightingKind::Method;
  if (isa<FieldDecl, ObjCPropertyDecl>(D))
    return HighlightingKind::Field;
  if (isa<EnumDecl>(D))
    return HighlightingKind::Enum;
  if (isa<EnumConstantDecl>(D))
    return HighlightingKind::EnumConstant;
  if (isa<ParmVarDecl>(D))
    return HighlightingKind::Parameter;
  if (auto *VD = dyn_cast<VarDecl>(D)) {
    if (isa<ImplicitParamDecl>(VD)) // e.g. ObjC Self
      return std::nullopt;
    return VD->isStaticDataMember()
               ? HighlightingKind::StaticField
               : VD->isLocalVarDecl() ? HighlightingKind::LocalVariable
                                      : HighlightingKind::Variable;
  }
  if (const auto *BD = dyn_cast<BindingDecl>(D))
    return BD->getDeclContext()->isFunctionOrMethod()
               ? HighlightingKind::LocalVariable
               : HighlightingKind::Variable;
  if (isa<FunctionDecl>(D))
    return HighlightingKind::Function;
  if (isa<NamespaceDecl>(D) || isa<NamespaceAliasDecl>(D) ||
      isa<UsingDirectiveDecl>(D))
    return HighlightingKind::Namespace;
  if (isa<TemplateTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
      isa<NonTypeTemplateParmDecl>(D))
    return HighlightingKind::TemplateParameter;
  if (isa<ConceptDecl>(D))
    return HighlightingKind::Concept;
  if (isa<LabelDecl>(D))
    return HighlightingKind::Label;
  if (const auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(D)) {
    auto Targets = Resolver->resolveUsingValueDecl(UUVD);
    if (!Targets.empty() && Targets[0] != UUVD) {
      return kindForDecl(Targets[0], Resolver);
    }
    return HighlightingKind::Unknown;
  }
  return std::nullopt;
}
std::optional<HighlightingKind> kindForType(const Type *TP,
                                            const HeuristicResolver *Resolver) {
  if (!TP)
    return std::nullopt;
  if (TP->isBuiltinType()) // Builtins are special, they do not have decls.
    return HighlightingKind::Primitive;
  if (auto *TD = dyn_cast<TemplateTypeParmType>(TP))
    return kindForDecl(TD->getDecl(), Resolver);
  if (isa<ObjCObjectPointerType>(TP))
    return HighlightingKind::Class;
  if (auto *TD = TP->getAsTagDecl())
    return kindForDecl(TD, Resolver);
  return std::nullopt;
}

// Whether T is const in a loose sense - is a variable with this type readonly?
bool isConst(QualType T) {
  if (T.isNull())
    return false;
  T = T.getNonReferenceType();
  if (T.isConstQualified())
    return true;
  if (const auto *AT = T->getAsArrayTypeUnsafe())
    return isConst(AT->getElementType());
  if (isConst(T->getPointeeType()))
    return true;
  return false;
}

// Whether D is const in a loose sense (should it be highlighted as such?)
// FIXME: This is separate from whether *a particular usage* can mutate D.
//        We may want V in V.size() to be readonly even if V is mutable.
bool isConst(const Decl *D) {
  if (llvm::isa<EnumConstantDecl>(D) || llvm::isa<NonTypeTemplateParmDecl>(D))
    return true;
  if (llvm::isa<FieldDecl>(D) || llvm::isa<VarDecl>(D) ||
      llvm::isa<MSPropertyDecl>(D) || llvm::isa<BindingDecl>(D)) {
    if (isConst(llvm::cast<ValueDecl>(D)->getType()))
      return true;
  }
  if (const auto *OCPD = llvm::dyn_cast<ObjCPropertyDecl>(D)) {
    if (OCPD->isReadOnly())
      return true;
  }
  if (const auto *MPD = llvm::dyn_cast<MSPropertyDecl>(D)) {
    if (!MPD->hasSetter())
      return true;
  }
  if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D)) {
    if (CMD->isConst())
      return true;
  }
  return false;
}

// "Static" means many things in C++, only some get the "static" modifier.
//
// Meanings that do:
// - Members associated with the class rather than the instance.
//   This is what 'static' most often means across languages.
// - static local variables
//   These are similarly "detached from their context" by the static keyword.
//   In practice, these are rarely used inside classes, reducing confusion.
//
// Meanings that don't:
// - Namespace-scoped variables, which have static storage class.
//   This is implicit, so the keyword "static" isn't so strongly associated.
//   If we want a modifier for these, "global scope" is probably the concept.
// - Namespace-scoped variables/functions explicitly marked "static".
//   There the keyword changes *linkage* , which is a totally different concept.
//   If we want to model this, "file scope" would be a nice modifier.
//
// This is confusing, and maybe we should use another name, but because "static"
// is a standard LSP modifier, having one with that name has advantages.
bool isStatic(const Decl *D) {
  if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
    return CMD->isStatic();
  if (const VarDecl *VD = llvm::dyn_cast<VarDecl>(D))
    return VD->isStaticDataMember() || VD->isStaticLocal();
  if (const auto *OPD = llvm::dyn_cast<ObjCPropertyDecl>(D))
    return OPD->isClassProperty();
  if (const auto *OMD = llvm::dyn_cast<ObjCMethodDecl>(D))
    return OMD->isClassMethod();
  return false;
}

bool isAbstract(const Decl *D) {
  if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
    return CMD->isPureVirtual();
  if (const auto *CRD = llvm::dyn_cast<CXXRecordDecl>(D))
    return CRD->hasDefinition() && CRD->isAbstract();
  return false;
}

bool isVirtual(const Decl *D) {
  if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
    return CMD->isVirtual();
  return false;
}

bool isDependent(const Decl *D) {
  if (isa<UnresolvedUsingValueDecl>(D))
    return true;
  return false;
}

/// Returns true if `Decl` is considered to be from a default/system library.
/// This currently checks the systemness of the file by include type, although
/// different heuristics may be used in the future (e.g. sysroot paths).
bool isDefaultLibrary(const Decl *D) {
  SourceLocation Loc = D->getLocation();
  if (!Loc.isValid())
    return false;
  return D->getASTContext().getSourceManager().isInSystemHeader(Loc);
}

bool isDefaultLibrary(const Type *T) {
  if (!T)
    return false;
  const Type *Underlying = T->getPointeeOrArrayElementType();
  if (Underlying->isBuiltinType())
    return true;
  if (auto *TD = dyn_cast<TemplateTypeParmType>(Underlying))
    return isDefaultLibrary(TD->getDecl());
  if (auto *TD = Underlying->getAsTagDecl())
    return isDefaultLibrary(TD);
  return false;
}

// For a macro usage `DUMP(foo)`, we want:
//  - DUMP --> "macro"
//  - foo --> "variable".
SourceLocation getHighlightableSpellingToken(SourceLocation L,
                                             const SourceManager &SM) {
  if (L.isFileID())
    return SM.isWrittenInMainFile(L) ? L : SourceLocation{};
  // Tokens expanded from the macro body contribute no highlightings.
  if (!SM.isMacroArgExpansion(L))
    return {};
  // Tokens expanded from macro args are potentially highlightable.
  return getHighlightableSpellingToken(SM.getImmediateSpellingLoc(L), SM);
}

unsigned evaluateHighlightPriority(const HighlightingToken &Tok) {
  enum HighlightPriority { Dependent = 0, Resolved = 1 };
  return (Tok.Modifiers & (1 << uint32_t(HighlightingModifier::DependentName)))
             ? Dependent
             : Resolved;
}

// Sometimes we get multiple tokens at the same location:
//
// - findExplicitReferences() returns a heuristic result for a dependent name
//   (e.g. Method) and CollectExtraHighlighting returning a fallback dependent
//   highlighting (e.g. Unknown+Dependent).
// - macro arguments are expanded multiple times and have different roles
// - broken code recovery produces several AST nodes at the same location
//
// We should either resolve these to a single token, or drop them all.
// Our heuristics are:
//
// - token kinds that come with "dependent-name" modifiers are less reliable
//   (these tend to be vague, like Type or Unknown)
// - if we have multiple equally reliable kinds, drop token rather than guess
// - take the union of modifiers from all tokens
//
// In particular, heuristically resolved dependent names get their heuristic
// kind, plus the dependent modifier.
std::optional<HighlightingToken> resolveConflict(const HighlightingToken &A,
                                                 const HighlightingToken &B) {
  unsigned Priority1 = evaluateHighlightPriority(A);
  unsigned Priority2 = evaluateHighlightPriority(B);
  if (Priority1 == Priority2 && A.Kind != B.Kind)
    return std::nullopt;
  auto Result = Priority1 > Priority2 ? A : B;
  Result.Modifiers = A.Modifiers | B.Modifiers;
  return Result;
}
std::optional<HighlightingToken>
resolveConflict(ArrayRef<HighlightingToken> Tokens) {
  if (Tokens.size() == 1)
    return Tokens[0];

  assert(Tokens.size() >= 2);
  std::optional<HighlightingToken> Winner =
      resolveConflict(Tokens[0], Tokens[1]);
  for (size_t I = 2; Winner && I < Tokens.size(); ++I)
    Winner = resolveConflict(*Winner, Tokens[I]);
  return Winner;
}

/// Filter to remove particular kinds of highlighting tokens and modifiers from
/// the output.
class HighlightingFilter {
public:
  HighlightingFilter() {
    for (auto &Active : ActiveKindLookup)
      Active = true;

    ActiveModifiersMask = ~0;
  }

  void disableKind(HighlightingKind Kind) {
    ActiveKindLookup[static_cast<size_t>(Kind)] = false;
  }

  void disableModifier(HighlightingModifier Modifier) {
    ActiveModifiersMask &= ~(1 << static_cast<uint32_t>(Modifier));
  }

  bool isHighlightKindActive(HighlightingKind Kind) const {
    return ActiveKindLookup[static_cast<size_t>(Kind)];
  }

  uint32_t maskModifiers(uint32_t Modifiers) const {
    return Modifiers & ActiveModifiersMask;
  }

  static HighlightingFilter fromCurrentConfig() {
    const Config &C = Config::current();
    HighlightingFilter Filter;
    for (const auto &Kind : C.SemanticTokens.DisabledKinds)
      if (auto K = highlightingKindFromString(Kind))
        Filter.disableKind(*K);
    for (const auto &Modifier : C.SemanticTokens.DisabledModifiers)
      if (auto M = highlightingModifierFromString(Modifier))
        Filter.disableModifier(*M);

    return Filter;
  }

private:
  bool ActiveKindLookup[static_cast<size_t>(HighlightingKind::LastKind) + 1];
  uint32_t ActiveModifiersMask;
};

/// Consumes source locations and maps them to text ranges for highlightings.
class HighlightingsBuilder {
public:
  HighlightingsBuilder(const ParsedAST &AST, const HighlightingFilter &Filter)
      : TB(AST.getTokens()), SourceMgr(AST.getSourceManager()),
        LangOpts(AST.getLangOpts()), Filter(Filter),
        Resolver(AST.getHeuristicResolver()) {}

  HighlightingToken &addToken(SourceLocation Loc, HighlightingKind Kind) {
    auto Range = getRangeForSourceLocation(Loc);
    if (!Range)
      return InvalidHighlightingToken;

    return addToken(*Range, Kind);
  }

  // Most of this function works around
  // https://github.com/clangd/clangd/issues/871.
  void addAngleBracketTokens(SourceLocation LLoc, SourceLocation RLoc) {
    if (!LLoc.isValid() || !RLoc.isValid())
      return;

    auto LRange = getRangeForSourceLocation(LLoc);
    if (!LRange)
      return;

    // RLoc might be pointing at a virtual buffer when it's part of a `>>`
    // token.
    RLoc = SourceMgr.getFileLoc(RLoc);
    // Make sure token is part of the main file.
    RLoc = getHighlightableSpellingToken(RLoc, SourceMgr);
    if (!RLoc.isValid())
      return;

    const auto *RTok = TB.spelledTokenAt(RLoc);
    // Handle `>>`. RLoc is always pointing at the right location, just change
    // the end to be offset by 1.
    // We'll either point at the beginning of `>>`, hence get a proper spelled
    // or point in the middle of `>>` hence get no spelled tok.
    if (!RTok || RTok->kind() == tok::greatergreater) {
      Position Begin = sourceLocToPosition(SourceMgr, RLoc);
      Position End = sourceLocToPosition(SourceMgr, RLoc.getLocWithOffset(1));
      addToken(*LRange, HighlightingKind::Bracket);
      addToken({Begin, End}, HighlightingKind::Bracket);
      return;
    }

    // Easy case, we have the `>` token directly available.
    if (RTok->kind() == tok::greater) {
      if (auto RRange = getRangeForSourceLocation(RLoc)) {
        addToken(*LRange, HighlightingKind::Bracket);
        addToken(*RRange, HighlightingKind::Bracket);
      }
      return;
    }
  }

  HighlightingToken &addToken(Range R, HighlightingKind Kind) {
    if (!Filter.isHighlightKindActive(Kind))
      return InvalidHighlightingToken;

    HighlightingToken HT;
    HT.R = std::move(R);
    HT.Kind = Kind;
    Tokens.push_back(std::move(HT));
    return Tokens.back();
  }

  void addExtraModifier(SourceLocation Loc, HighlightingModifier Modifier) {
    if (auto Range = getRangeForSourceLocation(Loc))
      ExtraModifiers[*Range].push_back(Modifier);
  }

  std::vector<HighlightingToken> collect(ParsedAST &AST) && {
    // Initializer lists can give duplicates of tokens, therefore all tokens
    // must be deduplicated.
    llvm::sort(Tokens);
    auto Last = std::unique(Tokens.begin(), Tokens.end());
    Tokens.erase(Last, Tokens.end());

    // Macros can give tokens that have the same source range but conflicting
    // kinds. In this case all tokens sharing this source range should be
    // removed.
    std::vector<HighlightingToken> NonConflicting;
    NonConflicting.reserve(Tokens.size());
    for (ArrayRef<HighlightingToken> TokRef = Tokens; !TokRef.empty();) {
      ArrayRef<HighlightingToken> Conflicting =
          TokRef.take_while([&](const HighlightingToken &T) {
            // TokRef is guaranteed at least one element here because otherwise
            // this predicate would never fire.
            return T.R == TokRef.front().R;
          });
      if (auto Resolved = resolveConflict(Conflicting)) {
        // Apply extra collected highlighting modifiers
        auto Modifiers = ExtraModifiers.find(Resolved->R);
        if (Modifiers != ExtraModifiers.end()) {
          for (HighlightingModifier Mod : Modifiers->second) {
            Resolved->addModifier(Mod);
          }
        }

        Resolved->Modifiers = Filter.maskModifiers(Resolved->Modifiers);
        NonConflicting.push_back(*Resolved);
      }
      // TokRef[Conflicting.size()] is the next token with a different range (or
      // the end of the Tokens).
      TokRef = TokRef.drop_front(Conflicting.size());
    }

    if (!Filter.isHighlightKindActive(HighlightingKind::InactiveCode))
      return NonConflicting;

    const auto &SM = AST.getSourceManager();
    StringRef MainCode = SM.getBufferOrFake(SM.getMainFileID()).getBuffer();

    // Merge token stream with "inactive line" markers.
    std::vector<HighlightingToken> WithInactiveLines;
    auto SortedInactiveRegions = getInactiveRegions(AST);
    llvm::sort(SortedInactiveRegions);
    auto It = NonConflicting.begin();
    for (const Range &R : SortedInactiveRegions) {
      // Create one token for each line in the inactive range, so it works
      // with line-based diffing.
      assert(R.start.line <= R.end.line);
      for (int Line = R.start.line; Line <= R.end.line; ++Line) {
        // Copy tokens before the inactive line
        for (; It != NonConflicting.end() && It->R.start.line < Line; ++It)
          WithInactiveLines.push_back(std::move(*It));
        // Add a token for the inactive line itself.
        auto EndOfLine = endOfLine(MainCode, Line);
        if (EndOfLine) {
          HighlightingToken HT;
          WithInactiveLines.emplace_back();
          WithInactiveLines.back().Kind = HighlightingKind::InactiveCode;
          WithInactiveLines.back().R.start.line = Line;
          WithInactiveLines.back().R.end = *EndOfLine;
        } else {
          elog("Failed to determine end of line: {0}", EndOfLine.takeError());
        }

        // Skip any other tokens on the inactive line. e.g.
        // `#ifndef Foo` is considered as part of an inactive region when Foo is
        // defined, and there is a Foo macro token.
        // FIXME: we should reduce the scope of the inactive region to not
        // include the directive itself.
        while (It != NonConflicting.end() && It->R.start.line == Line)
          ++It;
      }
    }
    // Copy tokens after the last inactive line
    for (; It != NonConflicting.end(); ++It)
      WithInactiveLines.push_back(std::move(*It));
    return WithInactiveLines;
  }

  const HeuristicResolver *getResolver() const { return Resolver; }

private:
  std::optional<Range> getRangeForSourceLocation(SourceLocation Loc) {
    Loc = getHighlightableSpellingToken(Loc, SourceMgr);
    if (Loc.isInvalid())
      return std::nullopt;
    // We might have offsets in the main file that don't correspond to any
    // spelled tokens.
    const auto *Tok = TB.spelledTokenAt(Loc);
    if (!Tok)
      return std::nullopt;
    return halfOpenToRange(SourceMgr,
                           Tok->range(SourceMgr).toCharRange(SourceMgr));
  }

  const syntax::TokenBuffer &TB;
  const SourceManager &SourceMgr;
  const LangOptions &LangOpts;
  HighlightingFilter Filter;
  std::vector<HighlightingToken> Tokens;
  std::map<Range, llvm::SmallVector<HighlightingModifier, 1>> ExtraModifiers;
  const HeuristicResolver *Resolver;
  // returned from addToken(InvalidLoc)
  HighlightingToken InvalidHighlightingToken;
};

std::optional<HighlightingModifier> scopeModifier(const NamedDecl *D) {
  const DeclContext *DC = D->getDeclContext();
  // Injected "Foo" within the class "Foo" has file scope, not class scope.
  if (auto *R = dyn_cast_or_null<RecordDecl>(D))
    if (R->isInjectedClassName())
      DC = DC->getParent();
  // Lambda captures are considered function scope, not class scope.
  if (llvm::isa<FieldDecl>(D))
    if (const auto *RD = llvm::dyn_cast<RecordDecl>(DC))
      if (RD->isLambda())
        return HighlightingModifier::FunctionScope;
  // Walk up the DeclContext hierarchy until we find something interesting.
  for (; !DC->isFileContext(); DC = DC->getParent()) {
    if (DC->isFunctionOrMethod())
      return HighlightingModifier::FunctionScope;
    if (DC->isRecord())
      return HighlightingModifier::ClassScope;
  }
  // Some template parameters (e.g. those for variable templates) don't have
  // meaningful DeclContexts. That doesn't mean they're global!
  if (DC->isTranslationUnit() && D->isTemplateParameter())
    return std::nullopt;
  // ExternalLinkage threshold could be tweaked, e.g. module-visible as global.
  if (llvm::to_underlying(D->getLinkageInternal()) <
      llvm::to_underlying(Linkage::External))
    return HighlightingModifier::FileScope;
  return HighlightingModifier::GlobalScope;
}

std::optional<HighlightingModifier> scopeModifier(const Type *T) {
  if (!T)
    return std::nullopt;
  if (T->isBuiltinType())
    return HighlightingModifier::GlobalScope;
  if (auto *TD = dyn_cast<TemplateTypeParmType>(T))
    return scopeModifier(TD->getDecl());
  if (auto *TD = T->getAsTagDecl())
    return scopeModifier(TD);
  return std::nullopt;
}

/// Produces highlightings, which are not captured by findExplicitReferences,
/// e.g. highlights dependent names and 'auto' as the underlying type.
class CollectExtraHighlightings
    : public RecursiveASTVisitor<CollectExtraHighlightings> {
  using Base = RecursiveASTVisitor<CollectExtraHighlightings>;

public:
  CollectExtraHighlightings(HighlightingsBuilder &H) : H(H) {}

  bool VisitCXXConstructExpr(CXXConstructExpr *E) {
    highlightMutableReferenceArguments(E->getConstructor(),
                                       {E->getArgs(), E->getNumArgs()});

    return true;
  }

  bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
    if (Init->isMemberInitializer())
      if (auto *Member = Init->getMember())
        highlightMutableReferenceArgument(Member->getType(), Init->getInit());
    return Base::TraverseConstructorInitializer(Init);
  }

  bool TraverseTypeConstraint(const TypeConstraint *C) {
    if (auto *Args = C->getTemplateArgsAsWritten())
      H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
    return Base::TraverseTypeConstraint(C);
  }

  bool VisitPredefinedExpr(PredefinedExpr *E) {
    H.addToken(E->getLocation(), HighlightingKind::LocalVariable)
        .addModifier(HighlightingModifier::Static)
        .addModifier(HighlightingModifier::Readonly)
        .addModifier(HighlightingModifier::FunctionScope);
    return true;
  }

  bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
    if (auto *Args = E->getTemplateArgsAsWritten())
      H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
    return true;
  }

  bool VisitTemplateDecl(TemplateDecl *D) {
    if (auto *TPL = D->getTemplateParameters())
      H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
    return true;
  }

  bool VisitTagDecl(TagDecl *D) {
    for (unsigned i = 0; i < D->getNumTemplateParameterLists(); ++i) {
      if (auto *TPL = D->getTemplateParameterList(i))
        H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
    }
    return true;
  }

  bool VisitClassTemplatePartialSpecializationDecl(
      ClassTemplatePartialSpecializationDecl *D) {
    if (auto *TPL = D->getTemplateParameters())
      H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
    if (auto *Args = D->getTemplateArgsAsWritten())
      H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
    return true;
  }

  bool VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) {
    if (auto *Args = D->getTemplateArgsInfo())
      H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
    return true;
  }

  bool VisitVarTemplatePartialSpecializationDecl(
      VarTemplatePartialSpecializationDecl *D) {
    if (auto *TPL = D->getTemplateParameters())
      H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
    if (auto *Args = D->getTemplateArgsAsWritten())
      H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
    return true;
  }

  bool VisitDeclRefExpr(DeclRefExpr *E) {
    H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
    return true;
  }
  bool VisitMemberExpr(MemberExpr *E) {
    H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
    return true;
  }

  bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc L) {
    H.addAngleBracketTokens(L.getLAngleLoc(), L.getRAngleLoc());
    return true;
  }

  bool VisitFunctionDecl(FunctionDecl *D) {
    if (D->isOverloadedOperator()) {
      const auto AddOpDeclToken = [&](SourceLocation Loc) {
        auto &Token = H.addToken(Loc, HighlightingKind::Operator)
                          .addModifier(HighlightingModifier::Declaration);
        if (D->isThisDeclarationADefinition())
          Token.addModifier(HighlightingModifier::Definition);
      };
      const auto Range = D->getNameInfo().getCXXOperatorNameRange();
      AddOpDeclToken(Range.getBegin());
      const auto Kind = D->getOverloadedOperator();
      if (Kind == OO_Call || Kind == OO_Subscript)
        AddOpDeclToken(Range.getEnd());
    }
    if (auto *Args = D->getTemplateSpecializationArgsAsWritten())
      H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
    return true;
  }

  bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
    const auto AddOpToken = [&](SourceLocation Loc) {
      H.addToken(Loc, HighlightingKind::Operator)
          .addModifier(HighlightingModifier::UserDefined);
    };
    AddOpToken(E->getOperatorLoc());
    const auto Kind = E->getOperator();
    if (Kind == OO_Call || Kind == OO_Subscript) {
      if (auto *Callee = E->getCallee())
        AddOpToken(Callee->getBeginLoc());
    }
    return true;
  }

  bool VisitUnaryOperator(UnaryOperator *Op) {
    auto &Token = H.addToken(Op->getOperatorLoc(), HighlightingKind::Operator);
    if (Op->getSubExpr()->isTypeDependent())
      Token.addModifier(HighlightingModifier::UserDefined);
    return true;
  }

  bool VisitBinaryOperator(BinaryOperator *Op) {
    auto &Token = H.addToken(Op->getOperatorLoc(), HighlightingKind::Operator);
    if (Op->getLHS()->isTypeDependent() || Op->getRHS()->isTypeDependent())
      Token.addModifier(HighlightingModifier::UserDefined);
    return true;
  }

  bool VisitConditionalOperator(ConditionalOperator *Op) {
    H.addToken(Op->getQuestionLoc(), HighlightingKind::Operator);
    H.addToken(Op->getColonLoc(), HighlightingKind::Operator);
    return true;
  }

  bool VisitCXXNewExpr(CXXNewExpr *E) {
    auto &Token = H.addToken(E->getBeginLoc(), HighlightingKind::Operator);
    if (isa_and_present<CXXMethodDecl>(E->getOperatorNew()))
      Token.addModifier(HighlightingModifier::UserDefined);
    return true;
  }

  bool VisitCXXDeleteExpr(CXXDeleteExpr *E) {
    auto &Token = H.addToken(E->getBeginLoc(), HighlightingKind::Operator);
    if (isa_and_present<CXXMethodDecl>(E->getOperatorDelete()))
      Token.addModifier(HighlightingModifier::UserDefined);
    return true;
  }

  bool VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
    const auto &B = E->getAngleBrackets();
    H.addAngleBracketTokens(B.getBegin(), B.getEnd());
    return true;
  }

  bool VisitCallExpr(CallExpr *E) {
    // Highlighting parameters passed by non-const reference does not really
    // make sense for literals...
    if (isa<UserDefinedLiteral>(E))
      return true;

    // FIXME: consider highlighting parameters of some other overloaded
    // operators as well
    llvm::ArrayRef<const Expr *> Args = {E->getArgs(), E->getNumArgs()};
    if (auto *CallOp = dyn_cast<CXXOperatorCallExpr>(E)) {
      switch (CallOp->getOperator()) {
      case OO_Call:
      case OO_Subscript:
        Args = Args.drop_front(); // Drop object parameter
        break;
      default:
        return true;
      }
    }

    highlightMutableReferenceArguments(
        dyn_cast_or_null<FunctionDecl>(E->getCalleeDecl()), Args);

    return true;
  }

  void highlightMutableReferenceArgument(QualType T, const Expr *Arg) {
    if (!Arg)
      return;

    // Is this parameter passed by non-const pointer or reference?
    // FIXME The condition T->idDependentType() could be relaxed a bit,
    // e.g. std::vector<T>& is dependent but we would want to highlight it
    bool IsRef = T->isLValueReferenceType();
    bool IsPtr = T->isPointerType();
    if ((!IsRef && !IsPtr) || T->getPointeeType().isConstQualified() ||
        T->isDependentType()) {
      return;
    }

    std::optional<SourceLocation> Location;

    // FIXME Add "unwrapping" for ArraySubscriptExpr,
    //  e.g. highlight `a` in `a[i]`
    // FIXME Handle dependent expression types
    if (auto *IC = dyn_cast<ImplicitCastExpr>(Arg))
      Arg = IC->getSubExprAsWritten();
    if (auto *UO = dyn_cast<UnaryOperator>(Arg)) {
      if (UO->getOpcode() == UO_AddrOf)
        Arg = UO->getSubExpr();
    }
    if (auto *DR = dyn_cast<DeclRefExpr>(Arg))
      Location = DR->getLocation();
    else if (auto *M = dyn_cast<MemberExpr>(Arg))
      Location = M->getMemberLoc();

    if (Location)
      H.addExtraModifier(*Location,
                         IsRef ? HighlightingModifier::UsedAsMutableReference
                               : HighlightingModifier::UsedAsMutablePointer);
  }

  void
  highlightMutableReferenceArguments(const FunctionDecl *FD,
                                     llvm::ArrayRef<const Expr *const> Args) {
    if (!FD)
      return;

    if (auto *ProtoType = FD->getType()->getAs<FunctionProtoType>()) {
      // Iterate over the types of the function parameters.
      // If any of them are non-const reference paramteres, add it as a
      // highlighting modifier to the corresponding expression
      for (size_t I = 0;
           I < std::min(size_t(ProtoType->getNumParams()), Args.size()); ++I) {
        highlightMutableReferenceArgument(ProtoType->getParamType(I), Args[I]);
      }
    }
  }

  bool VisitDecltypeTypeLoc(DecltypeTypeLoc L) {
    if (auto K = kindForType(L.getTypePtr(), H.getResolver())) {
      auto &Tok = H.addToken(L.getBeginLoc(), *K)
                      .addModifier(HighlightingModifier::Deduced);
      if (auto Mod = scopeModifier(L.getTypePtr()))
        Tok.addModifier(*Mod);
      if (isDefaultLibrary(L.getTypePtr()))
        Tok.addModifier(HighlightingModifier::DefaultLibrary);
    }
    return true;
  }

  bool VisitCXXDestructorDecl(CXXDestructorDecl *D) {
    if (auto *TI = D->getNameInfo().getNamedTypeInfo()) {
      SourceLocation Loc = TI->getTypeLoc().getBeginLoc();
      H.addExtraModifier(Loc, HighlightingModifier::ConstructorOrDestructor);
      H.addExtraModifier(Loc, HighlightingModifier::Declaration);
      if (D->isThisDeclarationADefinition())
        H.addExtraModifier(Loc, HighlightingModifier::Definition);
    }
    return true;
  }

  bool VisitCXXMemberCallExpr(CXXMemberCallExpr *CE) {
    // getMethodDecl can return nullptr with member pointers, e.g.
    // `(foo.*pointer_to_member_fun)(arg);`
    if (auto *D = CE->getMethodDecl()) {
      if (isa<CXXDestructorDecl>(D)) {
        if (auto *ME = dyn_cast<MemberExpr>(CE->getCallee())) {
          if (auto *TI = ME->getMemberNameInfo().getNamedTypeInfo()) {
            H.addExtraModifier(TI->getTypeLoc().getBeginLoc(),
                               HighlightingModifier::ConstructorOrDestructor);
          }
        }
      } else if (D->isOverloadedOperator()) {
        if (auto *ME = dyn_cast<MemberExpr>(CE->getCallee()))
          H.addToken(
               ME->getMemberNameInfo().getCXXOperatorNameRange().getBegin(),
               HighlightingKind::Operator)
              .addModifier(HighlightingModifier::UserDefined);
      }
    }
    return true;
  }

  bool VisitDeclaratorDecl(DeclaratorDecl *D) {
    for (unsigned i = 0; i < D->getNumTemplateParameterLists(); ++i) {
      if (auto *TPL = D->getTemplateParameterList(i))
        H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
    }
    auto *AT = D->getType()->getContainedAutoType();
    if (!AT)
      return true;
    auto K =
        kindForType(AT->getDeducedType().getTypePtrOrNull(), H.getResolver());
    if (!K)
      return true;
    auto *TSI = D->getTypeSourceInfo();
    if (!TSI)
      return true;
    SourceLocation StartLoc =
        TSI->getTypeLoc().getContainedAutoTypeLoc().getNameLoc();
    // The AutoType may not have a corresponding token, e.g. in the case of
    // init-captures. In this case, StartLoc overlaps with the location
    // of the decl itself, and producing a token for the type here would result
    // in both it and the token for the decl being dropped due to conflict.
    if (StartLoc == D->getLocation())
      return true;

    auto &Tok =
        H.addToken(StartLoc, *K).addModifier(HighlightingModifier::Deduced);
    const Type *Deduced = AT->getDeducedType().getTypePtrOrNull();
    if (auto Mod = scopeModifier(Deduced))
      Tok.addModifier(*Mod);
    if (isDefaultLibrary(Deduced))
      Tok.addModifier(HighlightingModifier::DefaultLibrary);
    return true;
  }

  // We handle objective-C selectors specially, because one reference can
  // cover several non-contiguous tokens.
  void highlightObjCSelector(const ArrayRef<SourceLocation> &Locs, bool Decl,
                             bool Def, bool Class, bool DefaultLibrary) {
    HighlightingKind Kind =
        Class ? HighlightingKind::StaticMethod : HighlightingKind::Method;
    for (SourceLocation Part : Locs) {
      auto &Tok =
          H.addToken(Part, Kind).addModifier(HighlightingModifier::ClassScope);
      if (Decl)
        Tok.addModifier(HighlightingModifier::Declaration);
      if (Def)
        Tok.addModifier(HighlightingModifier::Definition);
      if (Class)
        Tok.addModifier(HighlightingModifier::Static);
      if (DefaultLibrary)
        Tok.addModifier(HighlightingModifier::DefaultLibrary);
    }
  }

  bool VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
    llvm::SmallVector<SourceLocation> Locs;
    OMD->getSelectorLocs(Locs);
    highlightObjCSelector(Locs, /*Decl=*/true,
                          OMD->isThisDeclarationADefinition(),
                          OMD->isClassMethod(), isDefaultLibrary(OMD));
    return true;
  }

  bool VisitObjCMessageExpr(ObjCMessageExpr *OME) {
    llvm::SmallVector<SourceLocation> Locs;
    OME->getSelectorLocs(Locs);
    bool DefaultLibrary = false;
    if (ObjCMethodDecl *OMD = OME->getMethodDecl())
      DefaultLibrary = isDefaultLibrary(OMD);
    highlightObjCSelector(Locs, /*Decl=*/false, /*Def=*/false,
                          OME->isClassMessage(), DefaultLibrary);
    return true;
  }

  // Objective-C allows you to use property syntax `self.prop` as sugar for
  // `[self prop]` and `[self setProp:]` when there's no explicit `@property`
  // for `prop` as well as for class properties. We treat this like a property
  // even though semantically it's equivalent to a method expression.
  void highlightObjCImplicitPropertyRef(const ObjCMethodDecl *OMD,
                                        SourceLocation Loc) {
    auto &Tok = H.addToken(Loc, HighlightingKind::Field)
                    .addModifier(HighlightingModifier::ClassScope);
    if (OMD->isClassMethod())
      Tok.addModifier(HighlightingModifier::Static);
    if (isDefaultLibrary(OMD))
      Tok.addModifier(HighlightingModifier::DefaultLibrary);
  }

  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *OPRE) {
    // We need to handle implicit properties here since they will appear to
    // reference `ObjCMethodDecl` via an implicit `ObjCMessageExpr`, so normal
    // highlighting will not work.
    if (!OPRE->isImplicitProperty())
      return true;
    // A single property expr can reference both a getter and setter, but we can
    // only provide a single semantic token, so prefer the getter. In most cases
    // the end result should be the same, although it's technically possible
    // that the user defines a setter for a system SDK.
    if (OPRE->isMessagingGetter()) {
      highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertyGetter(),
                                       OPRE->getLocation());
      return true;
    }
    if (OPRE->isMessagingSetter()) {
      highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertySetter(),
                                       OPRE->getLocation());
    }
    return true;
  }

  bool VisitOverloadExpr(OverloadExpr *E) {
    H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
    if (!E->decls().empty())
      return true; // handled by findExplicitReferences.
    auto &Tok = H.addToken(E->getNameLoc(), HighlightingKind::Unknown)
                    .addModifier(HighlightingModifier::DependentName);
    if (llvm::isa<UnresolvedMemberExpr>(E))
      Tok.addModifier(HighlightingModifier::ClassScope);
    // other case is UnresolvedLookupExpr, scope is unknown.
    return true;
  }

  bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
    H.addToken(E->getMemberNameInfo().getLoc(), HighlightingKind::Unknown)
        .addModifier(HighlightingModifier::DependentName)
        .addModifier(HighlightingModifier::ClassScope);
    H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
    return true;
  }

  bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
    H.addToken(E->getNameInfo().getLoc(), HighlightingKind::Unknown)
        .addModifier(HighlightingModifier::DependentName)
        .addModifier(HighlightingModifier::ClassScope);
    H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
    return true;
  }

  bool VisitAttr(Attr *A) {
    switch (A->getKind()) {
    case attr::Override:
    case attr::Final:
      H.addToken(A->getLocation(), HighlightingKind::Modifier);
      break;
    default:
      break;
    }
    return true;
  }

  bool VisitDependentNameTypeLoc(DependentNameTypeLoc L) {
    H.addToken(L.getNameLoc(), HighlightingKind::Type)
        .addModifier(HighlightingModifier::DependentName)
        .addModifier(HighlightingModifier::ClassScope);
    return true;
  }

  bool VisitDependentTemplateSpecializationTypeLoc(
      DependentTemplateSpecializationTypeLoc L) {
    H.addToken(L.getTemplateNameLoc(), HighlightingKind::Type)
        .addModifier(HighlightingModifier::DependentName)
        .addModifier(HighlightingModifier::ClassScope);
    H.addAngleBracketTokens(L.getLAngleLoc(), L.getRAngleLoc());
    return true;
  }

  bool TraverseTemplateArgumentLoc(TemplateArgumentLoc L) {
    // Handle template template arguments only (other arguments are handled by
    // their Expr, TypeLoc etc values).
    if (L.getArgument().getKind() != TemplateArgument::Template &&
        L.getArgument().getKind() != TemplateArgument::TemplateExpansion)
      return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);

    TemplateName N = L.getArgument().getAsTemplateOrTemplatePattern();
    switch (N.getKind()) {
    case TemplateName::OverloadedTemplate:
      // Template template params must always be class templates.
      // Don't bother to try to work out the scope here.
      H.addToken(L.getTemplateNameLoc(), HighlightingKind::Class);
      break;
    case TemplateName::DependentTemplate:
    case TemplateName::AssumedTemplate:
      H.addToken(L.getTemplateNameLoc(), HighlightingKind::Class)
          .addModifier(HighlightingModifier::DependentName);
      break;
    case TemplateName::Template:
    case TemplateName::QualifiedTemplate:
    case TemplateName::SubstTemplateTemplateParm:
    case TemplateName::SubstTemplateTemplateParmPack:
    case TemplateName::UsingTemplate:
      // Names that could be resolved to a TemplateDecl are handled elsewhere.
      break;
    }
    return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L);
  }

  // findExplicitReferences will walk nested-name-specifiers and
  // find anything that can be resolved to a Decl. However, non-leaf
  // components of nested-name-specifiers which are dependent names
  // (kind "Identifier") cannot be resolved to a decl, so we visit
  // them here.
  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc Q) {
    if (NestedNameSpecifier *NNS = Q.getNestedNameSpecifier()) {
      if (NNS->getKind() == NestedNameSpecifier::Identifier)
        H.addToken(Q.getLocalBeginLoc(), HighlightingKind::Type)
            .addModifier(HighlightingModifier::DependentName)
            .addModifier(HighlightingModifier::ClassScope);
    }
    return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(Q);
  }

private:
  HighlightingsBuilder &H;
};
} // namespace

std::vector<HighlightingToken>
getSemanticHighlightings(ParsedAST &AST, bool IncludeInactiveRegionTokens) {
  auto &C = AST.getASTContext();
  HighlightingFilter Filter = HighlightingFilter::fromCurrentConfig();
  if (!IncludeInactiveRegionTokens)
    Filter.disableKind(HighlightingKind::InactiveCode);
  // Add highlightings for AST nodes.
  HighlightingsBuilder Builder(AST, Filter);
  // Highlight 'decltype' and 'auto' as their underlying types.
  CollectExtraHighlightings(Builder).TraverseAST(C);
  // Highlight all decls and references coming from the AST.
  findExplicitReferences(
      C,
      [&](ReferenceLoc R) {
        for (const NamedDecl *Decl : R.Targets) {
          if (!canHighlightName(Decl->getDeclName()))
            continue;
          auto Kind = kindForDecl(Decl, AST.getHeuristicResolver());
          if (!Kind)
            continue;
          auto &Tok = Builder.addToken(R.NameLoc, *Kind);

          // The attribute tests don't want to look at the template.
          if (auto *TD = dyn_cast<TemplateDecl>(Decl)) {
            if (auto *Templated = TD->getTemplatedDecl())
              Decl = Templated;
          }
          if (auto Mod = scopeModifier(Decl))
            Tok.addModifier(*Mod);
          if (isConst(Decl))
            Tok.addModifier(HighlightingModifier::Readonly);
          if (isStatic(Decl))
            Tok.addModifier(HighlightingModifier::Static);
          if (isAbstract(Decl))
            Tok.addModifier(HighlightingModifier::Abstract);
          if (isVirtual(Decl))
            Tok.addModifier(HighlightingModifier::Virtual);
          if (isDependent(Decl))
            Tok.addModifier(HighlightingModifier::DependentName);
          if (isDefaultLibrary(Decl))
            Tok.addModifier(HighlightingModifier::DefaultLibrary);
          if (Decl->isDeprecated())
            Tok.addModifier(HighlightingModifier::Deprecated);
          if (isa<CXXConstructorDecl>(Decl))
            Tok.addModifier(HighlightingModifier::ConstructorOrDestructor);
          if (R.IsDecl) {
            // Do not treat an UnresolvedUsingValueDecl as a declaration.
            // It's more common to think of it as a reference to the
            // underlying declaration.
            if (!isa<UnresolvedUsingValueDecl>(Decl))
              Tok.addModifier(HighlightingModifier::Declaration);
            if (isUniqueDefinition(Decl))
              Tok.addModifier(HighlightingModifier::Definition);
          }
        }
      },
      AST.getHeuristicResolver());
  // Add highlightings for macro references.
  auto AddMacro = [&](const MacroOccurrence &M) {
    auto &T = Builder.addToken(M.toRange(C.getSourceManager()),
                               HighlightingKind::Macro);
    T.addModifier(HighlightingModifier::GlobalScope);
    if (M.IsDefinition)
      T.addModifier(HighlightingModifier::Declaration);
  };
  for (const auto &SIDToRefs : AST.getMacros().MacroRefs)
    for (const auto &M : SIDToRefs.second)
      AddMacro(M);
  for (const auto &M : AST.getMacros().UnknownMacros)
    AddMacro(M);

  return std::move(Builder).collect(AST);
}

llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingKind K) {
  switch (K) {
  case HighlightingKind::Variable:
    return OS << "Variable";
  case HighlightingKind::LocalVariable:
    return OS << "LocalVariable";
  case HighlightingKind::Parameter:
    return OS << "Parameter";
  case HighlightingKind::Function:
    return OS << "Function";
  case HighlightingKind::Method:
    return OS << "Method";
  case HighlightingKind::StaticMethod:
    return OS << "StaticMethod";
  case HighlightingKind::Field:
    return OS << "Field";
  case HighlightingKind::StaticField:
    return OS << "StaticField";
  case HighlightingKind::Class:
    return OS << "Class";
  case HighlightingKind::Interface:
    return OS << "Interface";
  case HighlightingKind::Enum:
    return OS << "Enum";
  case HighlightingKind::EnumConstant:
    return OS << "EnumConstant";
  case HighlightingKind::Typedef:
    return OS << "Typedef";
  case HighlightingKind::Type:
    return OS << "Type";
  case HighlightingKind::Unknown:
    return OS << "Unknown";
  case HighlightingKind::Namespace:
    return OS << "Namespace";
  case HighlightingKind::TemplateParameter:
    return OS << "TemplateParameter";
  case HighlightingKind::Concept:
    return OS << "Concept";
  case HighlightingKind::Primitive:
    return OS << "Primitive";
  case HighlightingKind::Macro:
    return OS << "Macro";
  case HighlightingKind::Modifier:
    return OS << "Modifier";
  case HighlightingKind::Operator:
    return OS << "Operator";
  case HighlightingKind::Bracket:
    return OS << "Bracket";
  case HighlightingKind::Label:
    return OS << "Label";
  case HighlightingKind::InactiveCode:
    return OS << "InactiveCode";
  }
  llvm_unreachable("invalid HighlightingKind");
}
std::optional<HighlightingKind>
highlightingKindFromString(llvm::StringRef Name) {
  static llvm::StringMap<HighlightingKind> Lookup = {
      {"Variable", HighlightingKind::Variable},
      {"LocalVariable", HighlightingKind::LocalVariable},
      {"Parameter", HighlightingKind::Parameter},
      {"Function", HighlightingKind::Function},
      {"Method", HighlightingKind::Method},
      {"StaticMethod", HighlightingKind::StaticMethod},
      {"Field", HighlightingKind::Field},
      {"StaticField", HighlightingKind::StaticField},
      {"Class", HighlightingKind::Class},
      {"Interface", HighlightingKind::Interface},
      {"Enum", HighlightingKind::Enum},
      {"EnumConstant", HighlightingKind::EnumConstant},
      {"Typedef", HighlightingKind::Typedef},
      {"Type", HighlightingKind::Type},
      {"Unknown", HighlightingKind::Unknown},
      {"Namespace", HighlightingKind::Namespace},
      {"TemplateParameter", HighlightingKind::TemplateParameter},
      {"Concept", HighlightingKind::Concept},
      {"Primitive", HighlightingKind::Primitive},
      {"Macro", HighlightingKind::Macro},
      {"Modifier", HighlightingKind::Modifier},
      {"Operator", HighlightingKind::Operator},
      {"Bracket", HighlightingKind::Bracket},
      {"InactiveCode", HighlightingKind::InactiveCode},
  };

  auto It = Lookup.find(Name);
  return It != Lookup.end() ? std::make_optional(It->getValue()) : std::nullopt;
}
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingModifier K) {
  switch (K) {
  case HighlightingModifier::Declaration:
    return OS << "decl"; // abbreviation for common case
  case HighlightingModifier::Definition:
    return OS << "def"; // abbrevation for common case
  case HighlightingModifier::ConstructorOrDestructor:
    return OS << "constrDestr";
  default:
    return OS << toSemanticTokenModifier(K);
  }
}
std::optional<HighlightingModifier>
highlightingModifierFromString(llvm::StringRef Name) {
  static llvm::StringMap<HighlightingModifier> Lookup = {
      {"Declaration", HighlightingModifier::Declaration},
      {"Definition", HighlightingModifier::Definition},
      {"Deprecated", HighlightingModifier::Deprecated},
      {"Deduced", HighlightingModifier::Deduced},
      {"Readonly", HighlightingModifier::Readonly},
      {"Static", HighlightingModifier::Static},
      {"Abstract", HighlightingModifier::Abstract},
      {"Virtual", HighlightingModifier::Virtual},
      {"DependentName", HighlightingModifier::DependentName},
      {"DefaultLibrary", HighlightingModifier::DefaultLibrary},
      {"UsedAsMutableReference", HighlightingModifier::UsedAsMutableReference},
      {"UsedAsMutablePointer", HighlightingModifier::UsedAsMutablePointer},
      {"ConstructorOrDestructor",
       HighlightingModifier::ConstructorOrDestructor},
      {"UserDefined", HighlightingModifier::UserDefined},
      {"FunctionScope", HighlightingModifier::FunctionScope},
      {"ClassScope", HighlightingModifier::ClassScope},
      {"FileScope", HighlightingModifier::FileScope},
      {"GlobalScope", HighlightingModifier::GlobalScope},
  };

  auto It = Lookup.find(Name);
  return It != Lookup.end() ? std::make_optional(It->getValue()) : std::nullopt;
}

bool operator==(const HighlightingToken &L, const HighlightingToken &R) {
  return std::tie(L.R, L.Kind, L.Modifiers) ==
         std::tie(R.R, R.Kind, R.Modifiers);
}
bool operator<(const HighlightingToken &L, const HighlightingToken &R) {
  return std::tie(L.R, L.Kind, L.Modifiers) <
         std::tie(R.R, R.Kind, R.Modifiers);
}

std::vector<SemanticToken>
toSemanticTokens(llvm::ArrayRef<HighlightingToken> Tokens,
                 llvm::StringRef Code) {
  assert(llvm::is_sorted(Tokens));
  std::vector<SemanticToken> Result;
  // In case we split a HighlightingToken into multiple tokens (e.g. because it
  // was spanning multiple lines), this tracks the last one. This prevents
  // having a copy all the time.
  HighlightingToken Scratch;
  const HighlightingToken *Last = nullptr;
  for (const HighlightingToken &Tok : Tokens) {
    Result.emplace_back();
    SemanticToken *Out = &Result.back();
    // deltaStart/deltaLine are relative if possible.
    if (Last) {
      assert(Tok.R.start.line >= Last->R.end.line);
      Out->deltaLine = Tok.R.start.line - Last->R.end.line;
      if (Out->deltaLine == 0) {
        assert(Tok.R.start.character >= Last->R.start.character);
        Out->deltaStart = Tok.R.start.character - Last->R.start.character;
      } else {
        Out->deltaStart = Tok.R.start.character;
      }
    } else {
      Out->deltaLine = Tok.R.start.line;
      Out->deltaStart = Tok.R.start.character;
    }
    Out->tokenType = static_cast<unsigned>(Tok.Kind);
    Out->tokenModifiers = Tok.Modifiers;
    Last = &Tok;

    if (Tok.R.end.line == Tok.R.start.line) {
      Out->length = Tok.R.end.character - Tok.R.start.character;
    } else {
      // If the token spans a line break, split it into multiple pieces for each
      // line.
      // This is slow, but multiline tokens are rare.
      // FIXME: There's a client capability for supporting multiline tokens,
      // respect that.
      auto TokStartOffset = llvm::cantFail(positionToOffset(Code, Tok.R.start));
      // Note that the loop doesn't cover the last line, which has a special
      // length.
      for (int I = Tok.R.start.line; I < Tok.R.end.line; ++I) {
        auto LineEnd = Code.find('\n', TokStartOffset);
        assert(LineEnd != Code.npos);
        Out->length = LineEnd - TokStartOffset;
        // Token continues on next line, right after the line break.
        TokStartOffset = LineEnd + 1;
        Result.emplace_back();
        Out = &Result.back();
        *Out = Result[Result.size() - 2];
        // New token starts at the first column of the next line.
        Out->deltaLine = 1;
        Out->deltaStart = 0;
      }
      // This is the token on last line.
      Out->length = Tok.R.end.character;
      // Update the start location for last token, as that's used in the
      // relative delta calculation for following tokens.
      Scratch = *Last;
      Scratch.R.start.line = Tok.R.end.line;
      Scratch.R.start.character = 0;
      Last = &Scratch;
    }
  }
  return Result;
}
llvm::StringRef toSemanticTokenType(HighlightingKind Kind) {
  switch (Kind) {
  case HighlightingKind::Variable:
  case HighlightingKind::LocalVariable:
  case HighlightingKind::StaticField:
    return "variable";
  case HighlightingKind::Parameter:
    return "parameter";
  case HighlightingKind::Function:
    return "function";
  case HighlightingKind::Method:
    return "method";
  case HighlightingKind::StaticMethod:
    // FIXME: better method with static modifier?
    return "function";
  case HighlightingKind::Field:
    return "property";
  case HighlightingKind::Class:
    return "class";
  case HighlightingKind::Interface:
    return "interface";
  case HighlightingKind::Enum:
    return "enum";
  case HighlightingKind::EnumConstant:
    return "enumMember";
  case HighlightingKind::Typedef:
  case HighlightingKind::Type:
    return "type";
  case HighlightingKind::Unknown:
    return "unknown"; // nonstandard
  case HighlightingKind::Namespace:
    return "namespace";
  case HighlightingKind::TemplateParameter:
    return "typeParameter";
  case HighlightingKind::Concept:
    return "concept"; // nonstandard
  case HighlightingKind::Primitive:
    return "type";
  case HighlightingKind::Macro:
    return "macro";
  case HighlightingKind::Modifier:
    return "modifier";
  case HighlightingKind::Operator:
    return "operator";
  case HighlightingKind::Bracket:
    return "bracket";
  case HighlightingKind::Label:
    return "label";
  case HighlightingKind::InactiveCode:
    return "comment";
  }
  llvm_unreachable("unhandled HighlightingKind");
}

llvm::StringRef toSemanticTokenModifier(HighlightingModifier Modifier) {
  switch (Modifier) {
  case HighlightingModifier::Declaration:
    return "declaration";
  case HighlightingModifier::Definition:
    return "definition";
  case HighlightingModifier::Deprecated:
    return "deprecated";
  case HighlightingModifier::Readonly:
    return "readonly";
  case HighlightingModifier::Static:
    return "static";
  case HighlightingModifier::Deduced:
    return "deduced"; // nonstandard
  case HighlightingModifier::Abstract:
    return "abstract";
  case HighlightingModifier::Virtual:
    return "virtual";
  case HighlightingModifier::DependentName:
    return "dependentName"; // nonstandard
  case HighlightingModifier::DefaultLibrary:
    return "defaultLibrary";
  case HighlightingModifier::UsedAsMutableReference:
    return "usedAsMutableReference"; // nonstandard
  case HighlightingModifier::UsedAsMutablePointer:
    return "usedAsMutablePointer"; // nonstandard
  case HighlightingModifier::ConstructorOrDestructor:
    return "constructorOrDestructor"; // nonstandard
  case HighlightingModifier::UserDefined:
    return "userDefined"; // nonstandard
  case HighlightingModifier::FunctionScope:
    return "functionScope"; // nonstandard
  case HighlightingModifier::ClassScope:
    return "classScope"; // nonstandard
  case HighlightingModifier::FileScope:
    return "fileScope"; // nonstandard
  case HighlightingModifier::GlobalScope:
    return "globalScope"; // nonstandard
  }
  llvm_unreachable("unhandled HighlightingModifier");
}

std::vector<SemanticTokensEdit>
diffTokens(llvm::ArrayRef<SemanticToken> Old,
           llvm::ArrayRef<SemanticToken> New) {
  // For now, just replace everything from the first-last modification.
  // FIXME: use a real diff instead, this is bad with include-insertion.

  unsigned Offset = 0;
  while (!Old.empty() && !New.empty() && Old.front() == New.front()) {
    ++Offset;
    Old = Old.drop_front();
    New = New.drop_front();
  }
  while (!Old.empty() && !New.empty() && Old.back() == New.back()) {
    Old = Old.drop_back();
    New = New.drop_back();
  }

  if (Old.empty() && New.empty())
    return {};
  SemanticTokensEdit Edit;
  Edit.startToken = Offset;
  Edit.deleteTokens = Old.size();
  Edit.tokens = New;
  return {std::move(Edit)};
}

std::vector<Range> getInactiveRegions(ParsedAST &AST) {
  std::vector<Range> SkippedRanges(std::move(AST.getMacros().SkippedRanges));
  const auto &SM = AST.getSourceManager();
  StringRef MainCode = SM.getBufferOrFake(SM.getMainFileID()).getBuffer();
  std::vector<Range> InactiveRegions;
  for (const Range &Skipped : SkippedRanges) {
    Range Inactive = Skipped;
    // Sometimes, SkippedRanges contains a range ending at position 0
    // of a line. Clients that apply whole-line styles will treat that
    // line as inactive which is not desirable, so adjust the ending
    // position to be the end of the previous line.
    if (Inactive.end.character == 0 && Inactive.end.line > 0) {
      --Inactive.end.line;
    }
    // Exclude the directive lines themselves from the range.
    if (Inactive.end.line >= Inactive.start.line + 2) {
      ++Inactive.start.line;
      --Inactive.end.line;
    } else {
      // range would be empty, e.g. #endif on next line after #ifdef
      continue;
    }
    // Since we've adjusted the ending line, we need to recompute the
    // column to reflect the end of that line.
    if (auto EndOfLine = endOfLine(MainCode, Inactive.end.line)) {
      Inactive.end = *EndOfLine;
    } else {
      elog("Failed to determine end of line: {0}", EndOfLine.takeError());
      continue;
    }
    InactiveRegions.push_back(Inactive);
  }
  return InactiveRegions;
}

} // namespace clangd
} // namespace clang
